Icde25 revision submission (#13974)

Co-authored-by: gzh0806 <gzh23@mails.tsinghua.edu.cn>
diff --git a/iotdb-core/tsfile/pom.xml b/iotdb-core/tsfile/pom.xml
index 0a09da5..39f45ce 100644
--- a/iotdb-core/tsfile/pom.xml
+++ b/iotdb-core/tsfile/pom.xml
@@ -103,6 +103,14 @@
                     <runOrder>random</runOrder>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>16</source>
+                    <target>16</target>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
     <dependencies>
@@ -181,6 +189,16 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+            <version>1.21</version> <!-- 请检查是否有更新的版本 -->
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-math3</artifactId>
+            <version>3.6.1</version>
+        </dependency>
+        <dependency>
             <groupId>org.jetbrains</groupId>
             <artifactId>annotations</artifactId>
             <version>24.0.1</version>
@@ -196,6 +214,11 @@
             <artifactId>JavaFastPFOR</artifactId>
             <version>[0.1,)</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
     <profiles>
         <profile>
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/EncodeTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/EncodeTest.java
index e3bc4b9..db3877a 100644
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/EncodeTest.java
+++ b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/EncodeTest.java
@@ -27,9 +27,9 @@
 
   public static void main(@NotNull String[] args) throws IOException {
 
-    //String parent_dir = "/Users/xiaojinzhao/Desktop/encoding-outlier/";
-    String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
-    String output_parent_dir = parent_dir + "vldb/compression_ratio/sota_ratio/";
+    String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";
+//    String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+    String output_parent_dir = parent_dir + "icde0802/compression_ratio/sota_ratio/";
     String input_parent_dir = parent_dir + "trans_data/";
     ArrayList<String> input_path_list = new ArrayList<>();
     ArrayList<String> output_path_list = new ArrayList<>();
@@ -82,7 +82,7 @@
       String Output = output_path_list.get(file_i);
 
       // speed
-      int repeatTime = 100; // set repeat time
+      int repeatTime = 10; // set repeat time
       String dataTypeName = "int"; // set dataType
 
       File file = new File(inputPath);
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/GroupL.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/GroupL.java
deleted file mode 100644
index 3141984..0000000
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/GroupL.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.apache.iotdb.tsfile.encoding;
-
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.Arrays;
-
-import static java.lang.Math.pow;
-
-public class GroupL {
-    public int[] number;
-    public int count;
-    public int[] count_array;
-    public int range;
-    public long[] sorted_value_list;
-    public int unique_number;
-    public int mask;
-    public int left_shift;
-
-    public int getCount(long long1) {
-        return ((int) (long1 & this.mask));
-    }
-    public int getUniqueValue(long long1) {
-        return ((int) ((long1) >> this.left_shift));
-    }
-
-    public static int getBitWith(int num) {
-        if (num == 0) return 1;
-        else return 32 - Integer.numberOfLeadingZeros(num);
-    }
-    public GroupL(int[] number, int count, int i) {
-        this.number = number;
-        this.count = count;
-        this.range = (int) pow(2,i-1);
-        this.count_array = new int[range];
-    }
-
-    public int[] getNumber() {
-        return number;
-    }
-
-
-    public int getCount() {
-        return count;
-    }
-
-    public void addNumber(int number) {
-        this.number[this.count] = number;
-        this.count++;
-    }
-
-    public void setCount(int count) {
-        this.count = count;
-    }
-
-    public void setCount_array(){
-        double par = this.range/(count*Math.log(this.count));
-        int k1_start = this.range;
-        this.left_shift = getBitWith(this.count);
-        this.mask = (1 << left_shift) - 1;
-        if (par > 3) {
-            int[] value_list = new int[this.count];
-            for (int i = 0; i < this.count; i++) {
-                int value = this.number[i];
-                count_array[value - k1_start]++;
-                if (count_array[value - k1_start] == 1) {
-                    value_list[unique_number] = value;
-                    unique_number++;
-                }
-            }
-            sorted_value_list = new long[unique_number];
-            for (int i = 0; i < unique_number; i++) {
-                int value = value_list[i];
-                sorted_value_list[i] = (((long) (value - k1_start)) << left_shift) + count_array[value - k1_start];
-            }
-            Arrays.sort(sorted_value_list);
-
-            int cdf_count = 0;
-            for (int i = 0; i < unique_number; i++) {
-                cdf_count += getCount(sorted_value_list[i]);
-                sorted_value_list[i] = (((long) getUniqueValue(sorted_value_list[i])) << left_shift) + cdf_count;//new_value_list[i]
-            }
-        }else{
-            int[] hash = new int[this.range];
-            for (int i = 0; i < this.count; i++) {
-                int value = this.number[i];
-                if (hash[value - k1_start] == 0){
-                    this.unique_number++;
-                }
-                hash[value - k1_start]++;
-            }
-            sorted_value_list = new long[unique_number];
-            int ccount = 0;
-            int index = 0;
-            for(int i=0;i<this.range;i++){
-                if (hash[i] >0) {
-                    ccount += hash[i];
-                    sorted_value_list[index] = (((long) i) << left_shift) + ccount;
-                    index++;
-                }
-            }
-        }
-    }
-
-    public void incrementCount() {
-        count++;
-    }
-
-    @Override
-    public String toString() {
-        return "Number: " + number + ", Count: " + count;
-    }
-
-}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/GroupU.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/GroupU.java
deleted file mode 100644
index 4e375ef..0000000
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/GroupU.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package org.apache.iotdb.tsfile.encoding;
-
-import java.util.Arrays;
-
-import static java.lang.Math.pow;
-
-public class GroupU{
-
-    public int[] number;
-    public int count;
-    public int[] count_array;
-    public int range;
-    public int unique_number;
-    public int mask;
-    public int left_shift;
-    public long[] sorted_value_list; // cdf
-    public int[] invert;
-    public int[] invert2;
-
-    public int getCount(long long1) {
-        return ((int) (long1 & this.mask));
-    }
-    public int getUniqueValue(long long1) {
-        return ((int) ((long1) >> this.left_shift));
-    }
-
-    public static int getBitWith(int num) {
-        if (num == 0) return 1;
-        else return 32 - Integer.numberOfLeadingZeros(num);
-    }
-
-    public GroupU(int[] number, int count, int i) {
-        this.number = number;
-        this.count = count;
-        this.range = (int) pow(2,i-1);
-        this.count_array = new int[range];
-    }
-
-    public int[] getNumber() {
-        return number;
-    }
-
-
-    public int getCount() {
-        return count;
-    }
-
-    public void addNumber(int number) {
-        this.number[this.count] = number;
-        this.count++;
-    }
-
-    public void setCount(int count) {
-        this.count = count;
-    }
-
-    public void setCount_array(int max_){
-        int k2_end = max_ - this.range;
-        double par = this.range/(count*Math.log(this.count));
-        this.left_shift = getBitWith(this.count);
-        this.mask = (1 << left_shift) - 1;
-        invert = new int[this.range+1];
-        if (par > 3) {
-            int[] value_list = new int[this.count];
-            for (int i = 0; i < this.count; i++) {
-                int value = this.number[i];
-                count_array[k2_end - value]++;
-                if (count_array[k2_end - value] == 1) {
-                    value_list[unique_number] = value;
-                    unique_number++;
-                }
-            }
-            sorted_value_list = new long[unique_number];
-            for (int i = 0; i < unique_number; i++) {
-                int value = value_list[i];
-                sorted_value_list[i] = (((long) (k2_end - value)) << left_shift) + count_array[k2_end - value];
-            }
-            Arrays.sort(sorted_value_list);
-
-            int cdf_count = 0;
-            for (int i = 0; i < unique_number; i++) {
-                cdf_count += getCount(sorted_value_list[i]);
-                sorted_value_list[i] = (((long) getUniqueValue(sorted_value_list[i])) << left_shift) + cdf_count;//new_value_list[i]
-            }
-        }else {
-            int[] hash = new int[this.range];
-            for (int i = 0; i < this.count; i++) {
-                int value = this.number[i];
-                if (hash[k2_end - value] == 0) {
-                    this.unique_number++;
-                }
-                hash[k2_end - value]++;
-            }
-            sorted_value_list = new long[unique_number];
-            int ccount = 0;
-            int index = 0;
-            for (int i = 0; i < this.range; i++) {
-                if (hash[i] > 0) {
-                    ccount += hash[i];
-                    sorted_value_list[index] = (((long) i) << left_shift) + ccount;
-                    index++;
-                }
-            }
-        }
-    }
-
-    public void setinvert(){
-        int count = 0;
-        for (int i = 0; i < this.range; i++) {
-            invert[i] = count;
-            if (count < unique_number && getUniqueValue(sorted_value_list[count]) == i){
-                count ++;
-            }
-        }
-        invert[this.range] = count;
-    }
-
-    public void incrementCount() {
-        count++;
-    }
-
-    @Override
-    public String toString() {
-        return "Number: " + number + ", Count: " + count;
-    }
-
-}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/PFORTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/PFORTest.java
deleted file mode 100644
index a695fbd..0000000
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/PFORTest.java
+++ /dev/null
@@ -1,1063 +0,0 @@
-package org.apache.iotdb.tsfile.encoding;
-
-import com.csvreader.CsvReader;
-import com.csvreader.CsvWriter;
-import me.lemire.integercompression.*;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.*;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.util.*;
-
-import static org.apache.iotdb.tsfile.encoding.myPFOR.compressOneBlockOpt;
-import static org.apache.iotdb.tsfile.encoding.myPFOR.decompressOneBlock;
-
-public class PFORTest {
-
-    public static int[] getAbsDeltaTsBlock(
-            int[] ts_block,
-            ArrayList<Integer> min_delta) {
-        int[] ts_block_delta = new int[ts_block.length - 1];
-
-
-        int value_delta_min = Integer.MAX_VALUE;
-        for (int i = 1; i < ts_block.length; i++) {
-
-            int epsilon_v = ts_block[i] - ts_block[i - 1];
-
-            if (epsilon_v < value_delta_min) {
-                value_delta_min = epsilon_v;
-            }
-
-        }
-        min_delta.add(ts_block[0]);
-        min_delta.add(value_delta_min);
-
-        for (int i = 1; i < ts_block.length; i++) {
-            int epsilon_v = ts_block[i] - value_delta_min - ts_block[i - 1];
-            ts_block_delta[i - 1] = epsilon_v;
-        }
-        return ts_block_delta;
-    }
-
-    public static int zigzag(int num) {
-        if (num < 0) return ((-num) << 1) - 1;
-        else return num << 1;
-    }
-
-    public static int deZigzag(int num) {
-        if (num % 2 == 0) return num >> 1;
-        else return -((num + 1) >> 1);
-    }
-
-    public static int[] getAbsDeltaTsBlockSPRINTZ(
-            int[] ts_block,
-            ArrayList<Integer> min_delta) {
-        int[] ts_block_delta = new int[ts_block.length - 1];
-
-        for (int i = 1; i < ts_block.length; i++) {
-
-            int epsilon_v = ts_block[i] - ts_block[i - 1];
-            epsilon_v = zigzag(epsilon_v);
-            ts_block_delta[i - 1] = epsilon_v;
-
-        }
-        min_delta.add(ts_block[0]);
-
-        return ts_block_delta;
-    }
-
-    public static ArrayList<Integer> getAbsDeltaTsBlockRLE(
-            int[] ts_block,
-            ArrayList<Integer> min_delta,
-            ArrayList<Integer> repeat_count) {
-        ArrayList<Integer> ts_block_delta = new ArrayList<>();
-
-        int value_delta_min = Integer.MAX_VALUE;
-        for (Integer integer : ts_block) {
-            if (integer < value_delta_min) value_delta_min = integer;
-        }
-        int repeat_i = 0;
-        int pre_delta = ts_block[0] - value_delta_min;
-        int pre_count = 1;
-        min_delta.add(value_delta_min);
-        int block_size = ts_block.length;
-
-        for (int i = 1; i < block_size; i++) {
-            int delta = ts_block[i] - value_delta_min;
-            if (delta == pre_delta) {
-                pre_count++;
-            } else {
-                if (pre_count > 7) {
-                    repeat_count.add(repeat_i); // index_repeat
-                    repeat_count.add(pre_count); // repeat_count
-                    ts_block_delta.add(pre_delta);
-                } else {
-                    for (int j = 0; j < pre_count; j++)
-                        ts_block_delta.add(pre_delta);
-                }
-                pre_count = 1;
-                repeat_i = i;
-            }
-            pre_delta = delta;
-        }
-        for (int j = 0; j < pre_count; j++)
-            ts_block_delta.add(pre_delta);
-        return ts_block_delta;
-    }
-
-
-    public static void main(@NotNull String[] args) throws IOException {
-        //String parent_dir = "iotdb/iotdb-core/tsfile/src/test/resources/"; // your data path
-        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
-        String output_parent_dir = parent_dir + "vldb/compression_ratio/pfor_ratio/";
-        //String output_parent_dir = parent_dir + "pfor_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<String> encoding_list = new ArrayList<>();
-        ArrayList<String> encoding_list0 = new ArrayList<>();
-        int blocksize = 2048;
-
-        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");
-
-        encoding_list0.add("TS_2DIFF");
-        encoding_list0.add("RLE");
-        encoding_list0.add("SPRINTZ");
-
-        encoding_list.add("NEWPFOR");
-        encoding_list.add("OPTPFOR");
-        encoding_list.add("FASTPFOR");
-        encoding_list.add("PFOR");
-
-        for (String item : dataset_name) {
-            input_path_list.add(input_parent_dir + item);
-        }
-
-        output_path_list.add(output_parent_dir + "CS-Sensors_ratio.csv"); // 0
-
-        output_path_list.add(output_parent_dir + "Metro-Traffic_ratio.csv");// 1
-
-        output_path_list.add(output_parent_dir + "USGS-Earthquakes_ratio.csv");// 2
-
-        output_path_list.add(output_parent_dir + "YZ-Electricity_ratio.csv"); // 3
-
-        output_path_list.add(output_parent_dir + "GW-Magnetic_ratio.csv"); //4
-
-        output_path_list.add(output_parent_dir + "TY-Fuel_ratio.csv");//5
-
-        output_path_list.add(output_parent_dir + "Cyber-Vehicle_ratio.csv"); //6
-
-        output_path_list.add(output_parent_dir + "Vehicle-Charge_ratio.csv");//7
-
-        output_path_list.add(output_parent_dir + "Nifty-Stocks_ratio.csv");//8
-
-        output_path_list.add(output_parent_dir + "TH-Climate_ratio.csv");//9
-
-        output_path_list.add(output_parent_dir + "TY-Transport_ratio.csv");//10
-
-        output_path_list.add(output_parent_dir + "EPM-Education_ratio.csv");//11
-
-//        for (int file_i = 8; file_i < 9; file_i++) {
-        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
-            String inputPath = input_path_list.get(file_i);
-            String Output = output_path_list.get(file_i);
-
-            File file = new File(inputPath);
-            File[] tempList = file.listFiles();
-
-            CsvWriter writer = new CsvWriter(Output, ',', StandardCharsets.UTF_8);
-            String[] head = {
-                    "Input Direction",
-                    "Column Index",
-                    "Encoding Algorithm",
-                    "Compress Algorithm",
-                    "Encoding Time",
-                    "Decoding Time",
-                    "Compress Time",
-                    "Uncompress Time",
-                    "Points",
-                    "Compressed Size",
-                    "Compression Ratio"
-            };
-            writer.writeRecord(head); // write header to output file
-
-            assert tempList != null;
-            int fileRepeat;
-            ArrayList<Integer> columnIndexes = new ArrayList<>(); // set the column indexes of compressed
-            for (int i = 0; i < 2; i++) {
-                columnIndexes.add(i, i);
-            }
-            int points = 0;
-            IntegerCODEC codec = new Composition(new JustCopy(), new VariableByte());
-            IntWrapper inputoffset;
-            IntWrapper outputoffset;
-            int[] compressed;
-            for (String encoding : encoding_list) {
-                if (Objects.equals(encoding, "FASTPFOR")) {
-                    codec = new Composition(new FastPFOR(), new VariableByte());
-                } else if (Objects.equals(encoding, "NEWPFOR")) {
-                    codec = new Composition(new NewPFDS16(), new VariableByte());
-                } else if (Objects.equals(encoding, "OPTPFOR")) {
-                    codec = new Composition(new OptPFDS16(), new VariableByte());
-                } else if (Objects.equals(encoding, "PFOR")) {
-                    for (File f : tempList) {
-                        for (String encoding0 : encoding_list0) {
-                            fileRepeat = 0;
-                            double final_ratio = 0;
-                            int final_compressed_size = 0;
-                            System.out.println(f);
-                            long encodeTime = 0;
-                            long decodeTime = 0;
-                            while (fileRepeat < 1) {
-                                fileRepeat += 1;
-                                InputStream inputStream = Files.newInputStream(f.toPath());
-                                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
-                                ArrayList<String> data = new ArrayList<>();
-                                for (int index : columnIndexes) {
-                                    if (index == 0) {
-                                        continue;
-                                    }
-                                    loader.readHeaders();
-                                    data.clear();
-                                    while (loader.readRecord()) {
-                                        String v = loader.getValues()[index];
-                                        data.add(v);
-                                    }
-                                    points = data.size();
-                                    inputStream.close();
-
-                                    int[] origin = new int[data.size()];
-                                    int i = 0;
-                                    for (String value : data) {
-                                        origin[i] = Integer.parseInt(value);
-                                        i++;
-                                    }
-                                    switch (encoding0) {
-                                        case "TS_2DIFF": {
-                                            //TS_2DIFF+PFOR
-                                            ArrayList<Integer> min = new ArrayList<>();
-                                            ArrayList<Integer> outBlock = new ArrayList<>();
-                                            long s = System.nanoTime();
-                                            int offset = 0;
-                                            while (offset < data.size()) {
-                                                int endindex = offset + blocksize;
-                                                if (endindex >= data.size()) {
-                                                    endindex = data.size();
-                                                }
-                                                int[] slice = Arrays.copyOfRange(origin, offset, endindex);
-                                                int[] new_slice = getAbsDeltaTsBlock(slice, min);
-                                                int[] sliceoutBlock = compressOneBlockOpt(new_slice, new_slice.length);
-                                                outBlock.add(sliceoutBlock.length);
-                                                outBlock.add(endindex - offset - 1);
-                                                for (i = 0; i < sliceoutBlock.length; i++) {
-                                                    outBlock.add(sliceoutBlock[i]);
-                                                }
-                                                offset = endindex;
-                                            }
-                                            int[] minList = new int[min.size()];
-                                            i = 0;
-                                            for (int value : min) {
-                                                minList[i] = value;
-                                                i++;
-                                            }
-                                            int[] sliceoutBlock = compressOneBlockOpt(minList, minList.length);
-                                            for (i = sliceoutBlock.length - 1; i >= 0; i--) {
-                                                outBlock.add(0, sliceoutBlock[i]);
-                                            }
-                                            outBlock.add(0, minList.length);
-                                            outBlock.add(0, sliceoutBlock.length);
-                                            int[] outBlock2 = new int[outBlock.size()];
-                                            i = 0;
-                                            for (int value : outBlock) {
-                                                outBlock2[i] = value;
-                                                i++;
-                                            }
-                                            encodeTime += System.nanoTime() - s;
-                                            s = System.nanoTime();
-                                            offset = 0;
-                                            int[] uncompressed = new int[data.size()];
-                                            int j = 0;
-                                            int k = 0;
-                                            int first_slice_size = outBlock.get(offset);
-                                            int first_endindex = offset + 2 + first_slice_size;
-                                            int min_origin_size = outBlock.get(offset + 1);
-                                            int[] new_min = new int[min_origin_size];
-                                            int[] min_sliceBlock = Arrays.copyOfRange(outBlock2, offset + 2, first_endindex);
-                                            decompressOneBlock(new_min, min_sliceBlock, min_origin_size);
-                                            offset = first_endindex;
-                                            while (offset != outBlock.size()) {
-                                                int slice_size = outBlock.get(offset);
-                                                int endindex = offset + 2 + slice_size;
-                                                int origin_size = outBlock.get(offset + 1);
-                                                int[] sliceUncompressed = new int[origin_size];
-                                                int[] sliceBlock = Arrays.copyOfRange(outBlock2, offset + 2, endindex);
-                                                decompressOneBlock(sliceUncompressed, sliceBlock, origin_size);
-                                                uncompressed[j] = new_min[k];
-                                                j++;
-                                                k++;
-                                                for (i = 0; i < origin_size; i++) {
-                                                    uncompressed[j] = sliceUncompressed[i] + new_min[k] + uncompressed[j - 1];
-                                                    j++;
-                                                }
-                                                k++;
-                                                offset = endindex;
-                                            }
-                                            decodeTime += System.nanoTime() - s;
-                                            final_ratio += 1.0 * outBlock.size() / origin.length;
-                                            final_compressed_size += outBlock.size() * 4;
-                                            break;
-                                        }
-                                        case "SPRINTZ": {
-                                            //TS_2DIFF+SPRINTZ
-                                            ArrayList<Integer> min = new ArrayList<>();
-                                            ArrayList<Integer> outBlock = new ArrayList<>();
-                                            long s = System.nanoTime();
-                                            int offset = 0;
-                                            while (offset < data.size()) {
-                                                int endindex = offset + blocksize;
-                                                if (endindex >= data.size()) {
-                                                    endindex = data.size();
-                                                }
-                                                int[] slice = Arrays.copyOfRange(origin, offset, endindex);
-                                                int[] new_slice = getAbsDeltaTsBlockSPRINTZ(slice, min);
-                                                int[] sliceoutBlock = compressOneBlockOpt(new_slice, new_slice.length);
-                                                outBlock.add(sliceoutBlock.length);
-                                                outBlock.add(endindex - offset - 1);
-                                                for (i = 0; i < sliceoutBlock.length; i++) {
-                                                    outBlock.add(sliceoutBlock[i]);
-                                                }
-                                                offset = endindex;
-                                            }
-                                            int[] minList = new int[min.size()];
-                                            i = 0;
-                                            for (int value : min) {
-                                                minList[i] = value;
-                                                i++;
-                                            }
-                                            int[] sliceoutBlock = compressOneBlockOpt(minList, minList.length);
-                                            for (i = sliceoutBlock.length - 1; i >= 0; i--) {
-                                                outBlock.add(0, sliceoutBlock[i]);
-                                            }
-                                            outBlock.add(0, minList.length);
-                                            outBlock.add(0, sliceoutBlock.length);
-                                            int[] outBlock2 = new int[outBlock.size()];
-                                            i = 0;
-                                            for (int value : outBlock) {
-                                                outBlock2[i] = value;
-                                                i++;
-                                            }
-                                            encodeTime += System.nanoTime() - s;
-                                            s = System.nanoTime();
-                                            offset = 0;
-                                            int[] uncompressed = new int[data.size()];
-                                            int j = 0;
-                                            int k = 0;
-                                            int first_slice_size = outBlock.get(offset);
-                                            int first_endindex = offset + 2 + first_slice_size;
-                                            int min_origin_size = outBlock.get(offset + 1);
-                                            int[] new_min = new int[min_origin_size];
-                                            int[] min_sliceBlock = Arrays.copyOfRange(outBlock2, offset + 2, first_endindex);
-                                            decompressOneBlock(new_min, min_sliceBlock, min_origin_size);
-                                            offset = first_endindex;
-                                            while (offset != outBlock.size()) {
-                                                int slice_size = outBlock.get(offset);
-                                                int endindex = offset + 2 + slice_size;
-                                                int origin_size = outBlock.get(offset + 1);
-                                                int[] sliceUncompressed = new int[origin_size];
-                                                int[] sliceBlock = Arrays.copyOfRange(outBlock2, offset + 2, endindex);
-                                                decompressOneBlock(sliceUncompressed, sliceBlock, origin_size);
-
-                                                uncompressed[j] = new_min[k];
-                                                j++;
-                                                k++;
-                                                for (i = 0; i < origin_size; i++) {
-                                                    uncompressed[j] = deZigzag(sliceUncompressed[i]) + uncompressed[j - 1];
-                                                    j++;
-                                                }
-                                                offset = endindex;
-                                            }
-                                            decodeTime += System.nanoTime() - s;
-                                            final_ratio += 1.0 * outBlock.size() / origin.length;
-                                            final_compressed_size += outBlock.size() * 4;
-                                            break;
-                                        }
-                                        case "RLE": {
-                                            //TS_2DIFF+RLE+++
-                                            ArrayList<Integer> min = new ArrayList<>();
-                                            ArrayList<Integer> outBlock = new ArrayList<>();
-                                            long s = System.nanoTime();
-                                            int offset = 0;
-                                            while (offset < data.size()) {
-                                                int endindex = offset + blocksize;
-                                                if (endindex >= data.size()) {
-                                                    endindex = data.size();
-                                                }
-                                                int[] slice = Arrays.copyOfRange(origin, offset, endindex);
-                                                ArrayList<Integer> repeat_list = new ArrayList<>();
-                                                ArrayList<Integer> new_slice_list = getAbsDeltaTsBlockRLE(slice, min, repeat_list);
-                                                int[] new_slice = new int[new_slice_list.size()];
-                                                i = 0;
-                                                for (int value : new_slice_list) {
-                                                    new_slice[i++] = value;
-                                                }
-                                                int[] repeat = new int[repeat_list.size()];
-                                                i = 0;
-                                                for (int value : repeat_list) {
-                                                    repeat[i++] = value;
-                                                }
-                                                int[] sliceoutBlock = compressOneBlockOpt(new_slice, new_slice.length);
-                                                outBlock.add(sliceoutBlock.length);
-                                                outBlock.add(new_slice.length);
-                                                for (i = 0; i < sliceoutBlock.length; i++) {
-                                                    outBlock.add(sliceoutBlock[i]);
-                                                }
-                                                int[] sliceoutBlock2 = compressOneBlockOpt(repeat, repeat.length);
-                                                outBlock.add(sliceoutBlock2.length);
-                                                outBlock.add(repeat.length);
-                                                for (i = 0; i < sliceoutBlock2.length; i++) {
-                                                    outBlock.add(sliceoutBlock2[i]);
-                                                }
-                                                offset = endindex;
-                                            }
-                                            int[] minList = new int[min.size()];
-                                            i = 0;
-                                            for (int value : min) {
-                                                minList[i] = value;
-                                                i++;
-                                            }
-                                            int[] sliceoutBlock = compressOneBlockOpt(minList, minList.length);
-                                            for (i = sliceoutBlock.length - 1; i >= 0; i--) {
-                                                outBlock.add(0, sliceoutBlock[i]);
-                                            }
-                                            outBlock.add(0, minList.length);
-                                            outBlock.add(0, sliceoutBlock.length);
-                                            int[] outBlock2 = new int[outBlock.size()];
-                                            i = 0;
-                                            for (int value : outBlock) {
-                                                outBlock2[i] = value;
-                                                i++;
-                                            }
-                                            encodeTime += System.nanoTime() - s;
-                                            s = System.nanoTime();
-                                            offset = 0;
-                                            int[] uncompressed = new int[data.size()];
-                                            int j = 0;
-                                            int k = 0;
-                                            int first_slice_size = outBlock.get(offset);
-                                            int first_endindex = offset + 2 + first_slice_size;
-                                            int min_origin_size = outBlock.get(offset + 1);
-                                            int[] new_min = new int[min_origin_size];
-                                            int[] min_sliceBlock = Arrays.copyOfRange(outBlock2, offset + 2, first_endindex);
-                                            decompressOneBlock(new_min, min_sliceBlock, min_origin_size);
-                                            offset = first_endindex;
-                                            while (offset != outBlock.size()) {
-                                                //RLE---
-                                                int slice_size = outBlock.get(offset);
-                                                int endindex = offset + 2 + slice_size;
-                                                int origin_size = outBlock.get(offset + 1);
-                                                int[] sliceUncompressed = new int[origin_size];
-                                                int[] sliceBlock = Arrays.copyOfRange(outBlock2, offset + 2, endindex);
-                                                decompressOneBlock(sliceUncompressed, sliceBlock, origin_size);
-                                                offset = endindex;
-                                                slice_size = outBlock.get(offset);
-                                                endindex = offset + 2 + slice_size;
-                                                int origin_size2 = outBlock.get(offset + 1);
-                                                int[] sliceUncompressed2 = new int[origin_size2];//
-                                                int[] sliceBlock2 = Arrays.copyOfRange(outBlock2, offset + 2, endindex);
-                                                decompressOneBlock(sliceUncompressed2, sliceBlock2, origin_size2);
-
-                                                int index2 = 0;
-                                                int index1;
-                                                int fake_index = 0;
-                                                for (index1 = 0; index1 < origin_size; index1++) {
-                                                    if (index2 < sliceUncompressed2.length && fake_index == sliceUncompressed2[index2]) {
-                                                        //repeat
-                                                        int times = sliceUncompressed2[index2 + 1];
-                                                        for (i = 0; i < times; i++) {
-                                                            uncompressed[j] = sliceUncompressed[index1] + new_min[k];
-                                                            j++;
-                                                        }
-                                                        fake_index += sliceUncompressed2[index2 + 1];
-                                                        index2 += 2;
-                                                    } else {
-                                                        uncompressed[j] = sliceUncompressed[index1] + new_min[k];
-                                                        j++;
-                                                        fake_index++;
-                                                    }
-                                                }
-                                                offset = endindex;
-                                                k++;
-                                            }
-                                            decodeTime += System.nanoTime() - s;
-                                            final_ratio += 1.0 * outBlock.size() / origin.length;
-                                            final_compressed_size += outBlock.size() * 4;
-                                            break;
-                                        }
-                                    }
-                                }
-                            }
-                            String[] record = {
-                                    f.toString(),
-                                    "1",
-                                    encoding0 + "+" + encoding,
-                                    "NOCOMPRESSION",
-                                    String.valueOf(1.0 * encodeTime / fileRepeat),
-                                    String.valueOf(1.0 * decodeTime / fileRepeat),
-                                    "0",
-                                    "0",
-                                    String.valueOf(points),
-                                    String.valueOf(final_compressed_size / fileRepeat),
-                                    String.valueOf(final_ratio / fileRepeat)
-                            };
-
-                            writer.writeRecord(record);
-                        }
-                    }
-                    continue;
-                }
-                for (File f : tempList) {
-                    for (String encoding0 : encoding_list0) {
-                        switch (encoding0) {
-                            case "TS_2DIFF": {
-                                fileRepeat = 0;
-                                double final_ratio = 0;
-                                int final_compressed_size = 0;
-                                System.out.println(f);
-                                long encodeTime = 0;
-                                long decodeTime = 0;
-
-                                while (fileRepeat < 1) {
-                                    fileRepeat += 1;
-                                    InputStream inputStream = Files.newInputStream(f.toPath());
-                                    CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
-                                    ArrayList<String> data = new ArrayList<>();
-
-                                    for (int index : columnIndexes) {
-                                        if (index == 0) {
-                                            continue;
-                                        }
-                                        loader.readHeaders();
-                                        data.clear();
-                                        while (loader.readRecord()) {
-                                            String v = loader.getValues()[index];
-                                            data.add(v);
-                                        }
-                                        points = data.size();
-                                        inputStream.close();
-
-                                        int[] origin = new int[data.size()];
-                                        int i = 0;
-                                        for (String value : data) {
-                                            origin[i++] = Integer.parseInt(value);
-                                        }
-                                        // TS_2DIFF
-                                        ArrayList<Integer> min = new ArrayList<>();
-                                        ArrayList<Integer> outBlock = new ArrayList<>();
-                                        long s = System.nanoTime();
-                                        int offset = 0;
-                                        while (offset < data.size()) {
-                                            int endindex = offset + blocksize;
-                                            if (endindex >= data.size()) {
-                                                endindex = data.size();
-                                            }
-                                            int[] slice = Arrays.copyOfRange(origin, offset, endindex);
-                                            int[] tmp = getAbsDeltaTsBlock(slice, min);
-                                            compressed = new int[tmp.length + 1024];
-                                            inputoffset = new IntWrapper(0);
-                                            outputoffset = new IntWrapper(0);
-                                            codec.compress(tmp, inputoffset, tmp.length, compressed, outputoffset);
-                                            compressed = Arrays.copyOf(compressed, outputoffset.intValue());
-                                            outBlock.add(compressed.length);
-                                            outBlock.add(endindex - offset - 1);
-                                            for (i = 0; i < compressed.length; i++) {
-                                                outBlock.add(compressed[i]);
-                                            }
-                                            offset = endindex;
-                                        }
-                                        int[] minList = new int[min.size()];
-                                        i = 0;
-                                        for (int value : min) {
-                                            minList[i] = value;
-                                            i++;
-                                        }
-                                        compressed = new int[minList.length + 1024];
-                                        inputoffset = new IntWrapper(0);
-                                        outputoffset = new IntWrapper(0);
-                                        codec.compress(minList, inputoffset, minList.length, compressed, outputoffset);
-                                        compressed = Arrays.copyOf(compressed, outputoffset.intValue());
-                                        for (i = compressed.length - 1; i >= 0; i--) {
-                                            outBlock.add(0, compressed[i]);
-                                        }
-                                        outBlock.add(0, minList.length);
-                                        outBlock.add(0, compressed.length);
-                                        int[] outBlock2 = new int[outBlock.size()];
-                                        i = 0;
-                                        for (int value : outBlock) {
-                                            outBlock2[i] = value;
-                                            i++;
-                                        }
-                                        encodeTime += System.nanoTime() - s;
-                                        s = System.nanoTime();
-                                        offset = 0;
-                                        int[] uncompressed = new int[data.size()];
-                                        int j = 0;
-                                        int k = 0;
-                                        int first_slice_size = outBlock.get(offset);
-                                        int first_endindex = offset + 2 + first_slice_size;
-                                        int min_origin_size = outBlock.get(offset + 1);
-                                        int[] new_min = new int[min_origin_size];
-                                        int[] min_sliceBlock = Arrays.copyOfRange(outBlock2, offset + 2, first_endindex);
-                                        IntWrapper recoffset = new IntWrapper(0);
-                                        codec.uncompress(min_sliceBlock, new IntWrapper(0), min_sliceBlock.length,
-                                                new_min, recoffset);
-                                        offset = first_endindex;
-                                        while (offset != outBlock.size()) {
-                                            int slice_size = outBlock.get(offset);
-                                            int endindex = offset + 2 + slice_size;
-                                            int origin_size = outBlock.get(offset + 1);
-                                            int[] sliceBlock = Arrays.copyOfRange(outBlock2, offset + 2, endindex);
-                                            int[] recovered = new int[origin_size];
-                                            recoffset = new IntWrapper(0);
-                                            codec.uncompress(sliceBlock, new IntWrapper(0), sliceBlock.length,
-                                                    recovered, recoffset);
-                                            uncompressed[j] = new_min[k];
-                                            j++;
-                                            k++;
-                                            for (i = 0; i < origin_size; i++) {
-                                                uncompressed[j] = recovered[i] + new_min[k] + uncompressed[j - 1];
-                                                j++;
-                                            }
-                                            k++;
-                                            offset = endindex;
-                                        }
-                                        decodeTime += System.nanoTime() - s;
-
-
-                                        final_ratio += 1.0 * outBlock.size() / origin.length;
-                                        final_compressed_size += outBlock.size() * 4;
-                                    }
-                                }
-
-                                String[] record = {
-                                        f.toString(),
-                                        "1",
-                                        encoding0 + "+" + encoding,
-                                        "NOCOMPRESSION",
-                                        String.valueOf(1.0 * encodeTime / fileRepeat),
-                                        String.valueOf(1.0 * decodeTime / fileRepeat),
-                                        "0",
-                                        "0",
-                                        String.valueOf(points),
-                                        String.valueOf(final_compressed_size / fileRepeat),
-                                        String.valueOf(final_ratio / fileRepeat)
-                                };
-                                writer.writeRecord(record);
-                                break;
-                            }
-                            case "SPRINTZ": {
-                                fileRepeat = 0;
-                                double final_ratio = 0;
-                                int final_compressed_size = 0;
-                                System.out.println(f);
-                                long encodeTime = 0;
-                                long decodeTime = 0;
-
-                                while (fileRepeat < 1) {
-                                    fileRepeat += 1;
-                                    InputStream inputStream = Files.newInputStream(f.toPath());
-                                    CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
-                                    ArrayList<String> data = new ArrayList<>();
-
-                                    for (int index : columnIndexes) {
-                                        if (index == 0) {
-                                            continue;
-                                        }
-                                        loader.readHeaders();
-                                        data.clear();
-                                        while (loader.readRecord()) {
-                                            String v = loader.getValues()[index];
-                                            data.add(v);
-                                        }
-                                        points = data.size();
-                                        inputStream.close();
-
-                                        int[] origin = new int[data.size()];
-                                        int i = 0;
-                                        for (String value : data) {
-                                            origin[i++] = Integer.parseInt(value);
-                                        }
-                                        // SPRINTZ
-                                        ArrayList<Integer> min = new ArrayList<>();
-                                        ArrayList<Integer> outBlock = new ArrayList<>();
-                                        long s = System.nanoTime();
-                                        int offset = 0;
-                                        while (offset < data.size()) {
-                                            int endindex = offset + blocksize;
-                                            if (endindex >= data.size()) {
-                                                endindex = data.size();
-                                            }
-                                            int[] slice = Arrays.copyOfRange(origin, offset, endindex);
-                                            int[] tmp = getAbsDeltaTsBlockSPRINTZ(slice, min);
-                                            compressed = new int[tmp.length + 1024];
-                                            inputoffset = new IntWrapper(0);
-                                            outputoffset = new IntWrapper(0);
-                                            codec.compress(tmp, inputoffset, tmp.length, compressed, outputoffset);
-                                            compressed = Arrays.copyOf(compressed, outputoffset.intValue());
-                                            outBlock.add(compressed.length);
-                                            outBlock.add(endindex - offset - 1);
-                                            for (i = 0; i < compressed.length; i++) {
-                                                outBlock.add(compressed[i]);
-                                            }
-                                            offset = endindex;
-                                        }
-                                        int[] minList = new int[min.size()];
-                                        i = 0;
-                                        for (int value : min) {
-                                            minList[i] = value;
-                                            i++;
-                                        }
-                                        compressed = new int[minList.length + 1024];
-                                        inputoffset = new IntWrapper(0);
-                                        outputoffset = new IntWrapper(0);
-                                        codec.compress(minList, inputoffset, minList.length, compressed, outputoffset);
-                                        compressed = Arrays.copyOf(compressed, outputoffset.intValue());
-                                        for (i = compressed.length - 1; i >= 0; i--) {
-                                            outBlock.add(0, compressed[i]);
-                                        }
-                                        outBlock.add(0, minList.length);
-                                        outBlock.add(0, compressed.length);
-                                        int[] outBlock2 = new int[outBlock.size()];
-                                        i = 0;
-                                        for (int value : outBlock) {
-                                            outBlock2[i] = value;
-                                            i++;
-                                        }
-                                        encodeTime += System.nanoTime() - s;
-                                        s = System.nanoTime();
-                                        offset = 0;
-                                        int[] uncompressed = new int[data.size()];
-                                        int j = 0;
-                                        int k = 0;
-                                        int first_slice_size = outBlock.get(offset);
-                                        int first_endindex = offset + 2 + first_slice_size;
-                                        int min_origin_size = outBlock.get(offset + 1);
-                                        int[] new_min = new int[min_origin_size];
-                                        int[] min_sliceBlock = Arrays.copyOfRange(outBlock2, offset + 2, first_endindex);
-                                        IntWrapper recoffset = new IntWrapper(0);
-                                        codec.uncompress(min_sliceBlock, new IntWrapper(0), min_sliceBlock.length,
-                                                new_min, recoffset);
-                                        offset = first_endindex;
-                                        while (offset != outBlock.size()) {
-                                            int slice_size = outBlock.get(offset);
-                                            int endindex = offset + 2 + slice_size;
-                                            int origin_size = outBlock.get(offset + 1);
-                                            int[] sliceBlock = Arrays.copyOfRange(outBlock2, offset + 2, endindex);
-                                            int[] recovered = new int[origin_size];
-                                            recoffset = new IntWrapper(0);
-                                            codec.uncompress(sliceBlock, new IntWrapper(0), sliceBlock.length,
-                                                    recovered, recoffset);
-                                            uncompressed[j] = new_min[k];
-                                            j++;
-                                            k++;
-                                            for (i = 0; i < origin_size; i++) {
-                                                uncompressed[j] = deZigzag(recovered[i]) + uncompressed[j - 1];
-                                                j++;
-                                            }
-                                            offset = endindex;
-                                        }
-                                        decodeTime += System.nanoTime() - s;
-
-
-                                        final_ratio += 1.0 * outBlock.size() / origin.length;
-                                        final_compressed_size += outBlock.size() * 4;
-                                    }
-                                }
-
-                                String[] record = {
-                                        f.toString(),
-                                        "1",
-                                        encoding0 + "+" + encoding,
-                                        "NOCOMPRESSION",
-                                        String.valueOf(1.0 * encodeTime / fileRepeat),
-                                        String.valueOf(1.0 * decodeTime / fileRepeat),
-                                        "0",
-                                        "0",
-                                        String.valueOf(points),
-                                        String.valueOf(final_compressed_size / fileRepeat),
-                                        String.valueOf(final_ratio / fileRepeat)
-                                };
-                                writer.writeRecord(record);
-                                break;
-                            }
-                            case "RLE": {
-                                fileRepeat = 0;
-                                double final_ratio = 0;
-                                int final_compressed_size = 0;
-                                System.out.println(f);
-                                long encodeTime = 0;
-                                long decodeTime = 0;
-
-                                while (fileRepeat < 1) {
-                                    fileRepeat += 1;
-                                    InputStream inputStream = Files.newInputStream(f.toPath());
-                                    CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
-                                    ArrayList<String> data = new ArrayList<>();
-
-                                    for (int index : columnIndexes) {
-                                        if (index == 0) {
-                                            continue;
-                                        }
-                                        loader.readHeaders();
-                                        data.clear();
-                                        while (loader.readRecord()) {
-                                            String v = loader.getValues()[index];
-                                            data.add(v);
-                                        }
-                                        points = data.size();
-                                        inputStream.close();
-
-                                        int[] origin = new int[data.size()];
-                                        int i = 0;
-                                        for (String value : data) {
-                                            origin[i++] = Integer.parseInt(value);
-                                        }
-                                        // RLE+++
-                                        ArrayList<Integer> min = new ArrayList<>();
-                                        ArrayList<Integer> outBlock = new ArrayList<>();
-                                        long s = System.nanoTime();
-                                        int offset = 0;
-                                        while (offset < data.size()) {
-                                            int endindex = offset + blocksize;
-                                            if (endindex >= data.size()) {
-                                                endindex = data.size();
-                                            }
-                                            int[] slice = Arrays.copyOfRange(origin, offset, endindex);
-                                            ArrayList<Integer> repeat_list = new ArrayList<>();
-                                            ArrayList<Integer> new_slice_list = getAbsDeltaTsBlockRLE(slice, min, repeat_list);
-                                            int[] tmp = new int[new_slice_list.size()];
-                                            i = 0;
-                                            for (int value : new_slice_list) {
-                                                tmp[i++] = value;
-                                            }
-                                            int[] repeat = new int[repeat_list.size()];
-                                            i = 0;
-                                            for (int value : repeat_list) {
-                                                repeat[i++] = value;
-                                            }
-                                            compressed = new int[tmp.length + 1024];
-                                            inputoffset = new IntWrapper(0);
-                                            outputoffset = new IntWrapper(0);
-                                            codec.compress(tmp, inputoffset, tmp.length, compressed, outputoffset);
-                                            compressed = Arrays.copyOf(compressed, outputoffset.intValue());
-                                            outBlock.add(compressed.length);
-                                            outBlock.add(tmp.length);
-                                            for (i = 0; i < compressed.length; i++) {
-                                                outBlock.add(compressed[i]);
-                                            }
-                                            compressed = new int[repeat.length + 1024];
-                                            inputoffset = new IntWrapper(0);
-                                            outputoffset = new IntWrapper(0);
-                                            codec.compress(repeat, inputoffset, repeat.length, compressed, outputoffset);
-                                            compressed = Arrays.copyOf(compressed, outputoffset.intValue());
-                                            outBlock.add(compressed.length);
-                                            outBlock.add(repeat.length);
-                                            for (i = 0; i < compressed.length; i++) {
-                                                outBlock.add(compressed[i]);
-                                            }
-                                            offset = endindex;
-                                        }
-                                        int[] minList = new int[min.size()];
-                                        i = 0;
-                                        for (int value : min) {
-                                            minList[i] = value;
-                                            i++;
-                                        }
-                                        compressed = new int[minList.length + 1024];
-                                        inputoffset = new IntWrapper(0);
-                                        outputoffset = new IntWrapper(0);
-                                        codec.compress(minList, inputoffset, minList.length, compressed, outputoffset);
-                                        compressed = Arrays.copyOf(compressed, outputoffset.intValue());
-                                        for (i = compressed.length - 1; i >= 0; i--) {
-                                            outBlock.add(0, compressed[i]);
-                                        }
-                                        outBlock.add(0, minList.length);
-                                        outBlock.add(0, compressed.length);
-
-                                        int[] outBlock2 = new int[outBlock.size()];
-                                        i = 0;
-                                        for (int value : outBlock) {
-                                            outBlock2[i] = value;
-                                            i++;
-                                        }
-                                        encodeTime += System.nanoTime() - s;
-                                        s = System.nanoTime();
-                                        offset = 0;
-                                        int[] uncompressed = new int[data.size()];
-                                        int j = 0;
-                                        int k = 0;
-                                        int first_slice_size = outBlock.get(offset);
-                                        int first_endindex = offset + 2 + first_slice_size;
-                                        int min_origin_size = outBlock.get(offset + 1);
-                                        int[] new_min = new int[min_origin_size];
-                                        int[] min_sliceBlock = Arrays.copyOfRange(outBlock2, offset + 2, first_endindex);
-                                        IntWrapper recoffset = new IntWrapper(0);
-                                        codec.uncompress(min_sliceBlock, new IntWrapper(0), min_sliceBlock.length,
-                                                new_min, recoffset);
-                                        offset = first_endindex;
-                                        while (offset != outBlock.size()) {
-                                            //RLE---
-                                            int slice_size = outBlock.get(offset);
-                                            int endindex = offset + 2 + slice_size;
-                                            int origin_size = outBlock.get(offset + 1);
-                                            int[] sliceBlock = Arrays.copyOfRange(outBlock2, offset + 2, endindex);
-                                            int[] recovered = new int[origin_size];
-                                            recoffset = new IntWrapper(0);
-                                            codec.uncompress(sliceBlock, new IntWrapper(0), sliceBlock.length,
-                                                    recovered, recoffset);
-                                            offset = endindex;
-                                            slice_size = outBlock.get(offset);
-                                            endindex = offset + 2 + slice_size;
-                                            int origin_size2 = outBlock.get(offset + 1);
-                                            int[] recovered2 = new int[origin_size2];
-                                            recoffset = new IntWrapper(0);
-                                            int[] sliceBlock2 = Arrays.copyOfRange(outBlock2, offset + 2, endindex);
-                                            codec.uncompress(sliceBlock2, new IntWrapper(0), sliceBlock2.length,
-                                                    recovered2, recoffset);
-
-                                            int index2 = 0;
-                                            int index1;
-                                            int fake_index = 0;
-                                            for (index1 = 0; index1 < origin_size; index1++) {
-                                                if (index2 < recovered2.length && fake_index == recovered2[index2]) {
-                                                    //repeat
-                                                    int times = recovered2[index2 + 1];
-                                                    for (i = 0; i < times; i++) {
-                                                        uncompressed[j] = recovered[index1] + new_min[k];
-                                                        j++;
-                                                    }
-                                                    fake_index += recovered2[index2 + 1];
-                                                    index2 += 2;
-                                                } else {
-                                                    uncompressed[j] = recovered[index1] + new_min[k];
-                                                    j++;
-                                                    fake_index++;
-                                                }
-                                            }
-                                            k++;
-                                            offset = endindex;
-                                        }
-                                        decodeTime += System.nanoTime() - s;
-
-
-                                        final_ratio += 1.0 * outBlock.size() / origin.length;
-                                        final_compressed_size += outBlock.size() * 4;
-                                    }
-                                }
-
-                                String[] record = {
-                                        f.toString(),
-                                        "1",
-                                        encoding0 + "+" + encoding,
-                                        "NOCOMPRESSION",
-                                        String.valueOf(1.0 * encodeTime / fileRepeat),
-                                        String.valueOf(1.0 * decodeTime / fileRepeat),
-                                        "0",
-                                        "0",
-                                        String.valueOf(points),
-                                        String.valueOf(final_compressed_size / fileRepeat),
-                                        String.valueOf(final_ratio / fileRepeat)
-                                };
-                                writer.writeRecord(record);
-                                break;
-                            }
-                            case "TS_2DIFF1": {
-                                fileRepeat = 0;
-                                double final_ratio = 0;
-                                int final_compressed_size = 0;
-                                System.out.println(f);
-                                long encodeTime = 0;
-                                long decodeTime = 0;
-
-                                while (fileRepeat < 1) {
-                                    fileRepeat += 1;
-                                    InputStream inputStream = Files.newInputStream(f.toPath());
-                                    CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
-                                    ArrayList<String> data = new ArrayList<>();
-
-                                    for (int index : columnIndexes) {
-                                        if (index == 0) {
-                                            continue;
-                                        }
-                                        loader.readHeaders();
-                                        data.clear();
-                                        while (loader.readRecord()) {
-                                            String v = loader.getValues()[index];
-                                            data.add(v);
-                                        }
-                                        points = data.size();
-                                        inputStream.close();
-
-                                        int[] origin = new int[data.size()];
-                                        int i = 0;
-                                        for (String value : data) {
-                                            origin[i++] = Integer.parseInt(value);
-                                        }
-                                        // TS_2DIFF
-                                        inputoffset = new IntWrapper(0);
-                                        outputoffset = new IntWrapper(0);
-                                        compressed = new int[origin.length + 1024];
-                                        codec.compress(origin, inputoffset, origin.length, compressed, outputoffset);
-                                        long s = System.nanoTime();
-                                        compressed = Arrays.copyOf(compressed, outputoffset.intValue());
-                                        encodeTime += System.nanoTime() - s;
-                                        s = System.nanoTime();
-                                        int[] uncompressed = new int[data.size()];
-                                        IntWrapper recoffset = new IntWrapper(0);
-                                        codec.uncompress(compressed, new IntWrapper(0), compressed.length,
-                                                uncompressed, recoffset);
-                                        decodeTime += System.nanoTime() - s;
-
-
-                                        final_ratio += 1.0 * compressed.length / origin.length;
-                                        final_compressed_size += compressed.length * 4;
-                                    }
-                                }
-
-                                String[] record = {
-                                        f.toString(),
-                                        "1",
-                                        encoding0 + "+" + encoding,
-                                        "NOCOMPRESSION",
-                                        String.valueOf(1.0 * encodeTime / fileRepeat),
-                                        String.valueOf(1.0 * decodeTime / fileRepeat),
-                                        "0",
-                                        "0",
-                                        String.valueOf(points),
-                                        String.valueOf(final_compressed_size / fileRepeat),
-                                        String.valueOf(final_ratio / fileRepeat)
-                                };
-                                writer.writeRecord(record);
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-            writer.close();
-        }
-    }
-}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSBImproveTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSBImproveTest.java
new file mode 100644
index 0000000..8909dab
--- /dev/null
+++ b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSBImproveTest.java
@@ -0,0 +1,2430 @@
+package org.apache.iotdb.tsfile.encoding;
+
+import com.csvreader.CsvReader;
+import com.csvreader.CsvWriter;
+import org.junit.Test;
+
+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.ArrayList;
+import java.util.Arrays;
+
+import static java.lang.Math.pow;
+
+public class RLEBOSBImproveTest {
+
+    public static int getBitWith(int num) {
+        if (num == 0) return 1;
+        else return 32 - Integer.numberOfLeadingZeros(num);
+    }
+    public static int getCount(long long1, int mask) {
+        return ((int) (long1 & mask));
+    }
+    public static int getUniqueValue(long long1, int left_shift) {
+        return ((int) ((long1) >> left_shift));
+    }
+
+
+    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 ;
+                }
+            }
+        }
+
+    }
+
+    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 int[]  getAbsDeltaTsBlock(
+            int[] ts_block,
+            int i,
+            int block_size,
+            int remaining,
+            int[] min_delta,
+            ArrayList<Integer> repeat_count) {
+        int[] ts_block_delta = new int[remaining];
+
+        int value_delta_min = Integer.MAX_VALUE;
+        int value_delta_max = Integer.MIN_VALUE;
+        int base = i*block_size;
+        int end = i*block_size+remaining;
+        for (int j = base; j < end; j++) {
+
+            int integer = ts_block[j];
+            if (integer < value_delta_min) value_delta_min = integer;
+            if (integer > value_delta_max) {
+                value_delta_max = integer;
+            }
+        }
+        int pre_delta = ts_block[i*block_size]-value_delta_min;
+        int pre_count = 1;
+
+        min_delta[0]=(value_delta_min);
+        int repeat_i = 0;
+        int ts_block_delta_i = 0;
+        for (int j = base+1; j < end; j++) {
+            int delta = ts_block[j]-value_delta_min;
+            if(delta == pre_delta){
+                pre_count ++;
+            } else {
+                if(pre_count>7){
+                    repeat_count.add(repeat_i);
+                    repeat_count.add(pre_count);
+                    ts_block_delta[ts_block_delta_i]=pre_delta;
+                    ts_block_delta_i ++;
+                } else{
+                    for (int k = 0; k < pre_count; k++){
+                        ts_block_delta[ts_block_delta_i] =pre_delta;
+                        ts_block_delta_i++;
+                    }
+                }
+                pre_count =1;
+                repeat_i = j - i*block_size;
+            }
+            pre_delta = delta;
+
+        }
+        for (int j = 0; j < pre_count; j++){
+            ts_block_delta[ts_block_delta_i] =pre_delta;
+            ts_block_delta_i++;
+        }
+        min_delta[1]=(ts_block_delta_i);
+        min_delta[2]=(value_delta_max-value_delta_min);
+        int[] new_ts_block_delta = new int[ts_block_delta_i];
+        System.arraycopy(ts_block_delta, 0, new_ts_block_delta, 0, ts_block_delta_i);
+
+        return new_ts_block_delta;
+    }
+
+
+
+    public static int encodeOutlier2Bytes(
+            ArrayList<Integer> ts_block_delta,
+            int bit_width,
+            int encode_pos,  byte[] encoded_result) {
+
+        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
+
+        int n_k = ts_block_delta.size();
+        int n_k_b = n_k / 8;
+        long cur_remaining = 0; // encoded int
+        int cur_number_bits = 0; // the bit width used of encoded int
+        for (int i = n_k_b * 8; i < n_k; i++) {
+            long cur_value = ts_block_delta.get(i);
+            int cur_bit_width = bit_width; // remaining bit width of current value
+
+            if (cur_number_bits + bit_width >= 32) {
+                cur_remaining <<= (32 - cur_number_bits);
+                cur_bit_width = bit_width - 32 + cur_number_bits;
+                cur_remaining += ((cur_value >> cur_bit_width));
+                long2intBytes(cur_remaining,encode_pos,encoded_result);
+                encode_pos += 4;
+
+                cur_remaining = 0;
+                cur_number_bits = 0;
+            }
+
+            cur_remaining <<= cur_bit_width;
+            cur_number_bits += cur_bit_width;
+            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width));
+        }
+        cur_remaining <<= (32 - cur_number_bits);
+        long2intBytes(cur_remaining,encode_pos,encoded_result);
+        encode_pos += 4;
+        return encode_pos;
+
+    }
+
+
+    public static ArrayList<Integer> decodeOutlier2Bytes(
+            byte[] encoded,
+            int decode_pos,
+            int bit_width,
+            int length,
+            ArrayList<Integer> encoded_pos_result
+    ) {
+
+        int n_k_b = length / 8;
+        int remaining = length - n_k_b * 8;
+        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
+        decode_pos += n_k_b * bit_width;
+
+        ArrayList<Long> int_remaining = new ArrayList<>();
+        int int_remaining_size = remaining * bit_width / 32 + 1;
+        for (int j = 0; j < int_remaining_size; j++) {
+
+            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
+            decode_pos += 4;
+        }
+
+        int cur_remaining_bits = 32; // remaining bit width of current value
+        long cur_number = int_remaining.get(0);
+        int cur_number_i = 1;
+        for (int i = n_k_b * 8; i < length; i++) {
+            if (bit_width < cur_remaining_bits) {
+                int tmp = (int) (cur_number >> (32 - bit_width));
+                result_list.add(tmp);
+                cur_number <<= bit_width;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits -= bit_width;
+            } else {
+                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
+                int remain_bits = bit_width - cur_remaining_bits;
+                tmp <<= remain_bits;
+
+                cur_number = int_remaining.get(cur_number_i);
+                cur_number_i++;
+                tmp += (cur_number >> (32 - remain_bits));
+                result_list.add(tmp);
+                cur_number <<= remain_bits;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits = 32 - remain_bits;
+            }
+        }
+        encoded_pos_result.add(decode_pos);
+        return result_list;
+    }
+
+    private static int BOSEncodeBits(int[] ts_block_delta,
+                                      int init_block_size,
+                                      int final_k_start_value,
+                                     int final_x_l_plus,
+                                      int final_k_end_value,
+                                     int final_x_u_minus,
+                                      int max_delta_value,
+                                      int[] min_delta,
+                                      ArrayList<Integer> repeat_count,
+                                      int encode_pos,
+                                      byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        int k1 = 0;
+        int k2 = 0;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if (cur_value < final_k_start_value) {
+                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+
+
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+                final_normal.add(cur_value - final_x_l_plus);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int size = repeat_count.size();
+        intByte2Bytes(size,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        if (size != 0)
+            encode_pos =encodeOutlier2Bytes(repeat_count, getBitWith(init_block_size-1),encode_pos,cur_byte);
+
+
+
+        int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(final_k_end_value,encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+        int left_bit_width = getBitWith(final_k_start_value);
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value );
+        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        if (final_alpha == 0) {
+
+            for (int i : bitmap_outlier) {
+
+                intByte2Bytes(i,encode_pos,cur_byte);
+                encode_pos += 1;
+            }
+        } else {
+            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+        }
+        encode_pos =encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+        if (k1 != 0)
+            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+        if (k2 != 0)
+            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+        return encode_pos;
+
+    }
+
+
+
+
+    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size,int remaining, int encode_pos , byte[] cur_byte) {
+
+        ArrayList<Integer> repeat_count = new ArrayList<>();
+        int init_block_size = block_size;
+
+        int[] min_delta = new int[3];
+        int[]  ts_block_delta = getAbsDeltaTsBlock(ts_block,block_i, init_block_size,remaining, min_delta, repeat_count);
+        block_size = min_delta[1];
+
+
+        int max_delta_value = min_delta[2];
+        int[] value_list = new int[block_size];
+        int unique_value_count = 0;
+        int[] value_count_list = new int[max_delta_value+1];
+        for(int value:ts_block_delta){
+            if(value_count_list[value]==0){
+                value_count_list[value] = 1;
+                value_list[unique_value_count] = value;
+                unique_value_count ++;
+            }else{
+                value_count_list[value] ++;
+            }
+        }
+
+        int left_shift = getBitWith(block_size);
+        int mask =  (1 << left_shift) - 1;
+        long[] sorted_value_list = new long[unique_value_count];
+        int count = 0;
+
+        for(int i=0;i<unique_value_count;i++){
+            int value = value_list[i];
+
+            sorted_value_list[i] = (((long) value) << left_shift) + value_count_list[value];
+        }
+        Arrays.sort(sorted_value_list);
+
+        for(int i=0;i<unique_value_count;i++){
+            count += getCount(sorted_value_list[i], mask);
+            sorted_value_list[i] = (((long)getUniqueValue(sorted_value_list[i], left_shift) ) << left_shift) + count;//new_value_list[i]
+        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2 ) * (block_size));
+
+        int cur_k1 = 0;
+
+        int x_l_plus_value = 0; // x_l_plus
+        int x_u_minus_value = max_delta_value; // x_u_plus
+
+        for (int end_value_i = 1; end_value_i < unique_value_count; end_value_i++) {
+
+            x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+            int x_u_plus_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+            int cur_bits = 0;
+            int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value); // cur_k1 = 0
+            if (cur_k2 != 0)
+                cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus_value);
+
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_x_u_minus = x_u_minus_value;
+                final_k_end_value = x_u_plus_value;
+            }
+        }
+
+        int k_start_value = -1; // x_l_minus
+
+        int gamma_max = getBitWith(max_delta_value);
+        int[] gamma_count_list = new int[gamma_max+1];
+        int[] x_u_minus_value_list = new int[gamma_max+1];
+        int[] x_u_plus_value_list = new int[gamma_max+1];
+        int end_i = unique_value_count - 1;
+        for(int gamma = 0; gamma <= gamma_max; gamma++) {
+            int x_u_plus_pow_beta = max_delta_value - (1<<gamma) + 1;
+            for (; end_i > 0; end_i--) {
+                x_u_minus_value = getUniqueValue(sorted_value_list[end_i - 1], left_shift);
+                int x_u_plus_value = getUniqueValue(sorted_value_list[end_i], left_shift);
+                if (x_u_minus_value < x_u_plus_pow_beta && x_u_plus_value >= x_u_plus_pow_beta){
+                    gamma_count_list[gamma] = getCount(sorted_value_list[end_i-1],mask);
+                    x_u_minus_value_list[gamma] = x_u_minus_value;
+                    x_u_plus_value_list[gamma] = x_u_plus_value;
+                } else if (x_u_minus_value < x_u_plus_pow_beta) {
+                    break;
+                }
+            }
+        }
+        for(int gamma = 1; gamma < gamma_max; gamma++) {
+            if(gamma_count_list[gamma]==0){
+                gamma_count_list[gamma] = gamma_count_list[gamma-1];
+                x_u_minus_value_list[gamma] = x_u_minus_value_list[gamma-1];
+                x_u_plus_value_list[gamma] = x_u_plus_value_list[gamma-1];
+            }
+        }
+
+        for (int start_value_i = 0; start_value_i < unique_value_count-1; start_value_i++) {
+            long k_start_valueL = sorted_value_list[start_value_i];
+            k_start_value =  getUniqueValue(k_start_valueL, left_shift) ;
+            x_l_plus_value =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+
+
+            cur_k1 = getCount(k_start_valueL,mask);
+
+            int k_end_value;
+            int cur_bits;
+            int cur_k2;
+            k_end_value = max_delta_value + 1;
+
+            cur_bits = 0;
+            cur_k2 = 0;
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            cur_bits += cur_k1 * getBitWith(k_start_value);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k1) * getBitWith(k_end_value- x_l_plus_value); //cur_k2 =0
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_k_start_value = k_start_value;
+                final_x_l_plus = x_l_plus_value;
+                final_k_end_value = k_end_value;
+                final_x_u_minus = max_delta_value;
+            }
+
+            int beta_max = getBitWith(max_delta_value - x_l_plus_value);
+            int end_value_i = start_value_i + 1;
+
+            int lower_outlier_cost = cur_k1 * getBitWith(k_start_value);
+
+            for(int gamma = 0; gamma < beta_max; gamma++){
+//                int x_u_plus_pow_beta = (int) (max_delta_value - pow(2,gamma)+1);
+                x_u_minus_value = x_u_minus_value_list[gamma];
+                k_end_value =  x_u_plus_value_list[gamma];
+                cur_bits = 0;
+                cur_k2 = block_size - gamma_count_list[gamma];
+
+                cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                cur_bits += lower_outlier_cost;
+                if (cur_k1 + cur_k2 != block_size)
+                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+                if (cur_k2 != 0)
+                    cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+
+
+                if (cur_bits < min_bits) {
+                    min_bits = cur_bits;
+                    final_k_start_value = k_start_value;
+                    final_x_l_plus = x_l_plus_value;
+                    final_k_end_value = k_end_value;
+                    final_x_u_minus = x_u_minus_value;
+                }
+
+            }
+//            end_value_i = unique_value_count - 1;
+//            for(int gamma = 1; gamma <= beta_max; gamma++){
+//                for (; end_value_i > start_value_i; end_value_i--) {
+//                    int x_u_plus_pow_beta = (int) (max_delta_value - pow(2,gamma)+1);
+//                    x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+//                    k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+//                    if(x_u_minus_value < x_u_plus_pow_beta && k_end_value >= x_u_plus_pow_beta){
+//                        cur_bits = 0;
+//                        cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+//
+//                        cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+//                        cur_bits += cur_k1 * getBitWith(k_start_value);
+//                        if (cur_k1 + cur_k2 != block_size)
+//                            cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+//                        if (cur_k2 != 0)
+//                            cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+//
+//
+//                        if (cur_bits < min_bits) {
+//                            min_bits = cur_bits;
+//                            final_k_start_value = k_start_value;
+//                            final_x_l_plus = x_l_plus_value;
+//                            final_k_end_value = k_end_value;
+//                            final_x_u_minus = x_u_minus_value;
+//                        }
+//                    } else if (x_u_minus_value <= x_u_plus_pow_beta && k_end_value <= x_u_plus_pow_beta) {
+//                        break;
+//                    }
+//                }
+//            }
+
+
+        }
+        for(int beta = 1; beta <= gamma_max; beta++){
+            int pow_beta = 1<<beta;
+            int start_value_i = 0;
+            int end_value_i = start_value_i+1;
+
+            for (; start_value_i < unique_value_count-1; start_value_i++) {
+                long x_l_minusL = sorted_value_list[start_value_i];
+                int x_l_minus =  getUniqueValue(x_l_minusL, left_shift) ;
+                int x_l_plus =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+                int x_u_plus_pow_beta = pow_beta+x_l_plus;
+                if(x_u_plus_pow_beta > max_delta_value) break;
+
+
+
+                cur_k1 = getCount(x_l_minusL,mask);
+                int lower_outlier_cost = cur_k1 * getBitWith(x_l_minus);
+
+                while ( end_value_i < unique_value_count) {
+//                    if(beta==3 && end_value_i==22)
+//                    {
+//                        System.out.println(x_l_minus);
+//                        System.out.println(x_l_plus);
+//                    }
+
+                    int x_u_minus = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+                    int x_u_plus = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+                    if(x_u_minus < x_u_plus_pow_beta && x_u_plus >= x_u_plus_pow_beta){
+                        int cur_bits = 0;
+                        int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+
+                        cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                        cur_bits += lower_outlier_cost;
+                        if (cur_k1 + cur_k2 != block_size)
+                            cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus - x_l_plus);
+                        if (cur_k2 != 0)
+                            cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus);
+
+
+                        if (cur_bits < min_bits) {
+                            min_bits = cur_bits;
+                            final_k_start_value = x_l_minus;
+                            final_x_l_plus = x_l_plus;
+                            final_k_end_value = x_u_plus;
+                            final_x_u_minus = x_u_minus;
+                        }
+                        break;
+                    }
+//                    else if (x_u_minus >= x_u_plus_pow_beta && x_u_plus >= x_u_plus_pow_beta) {
+//                        break;
+//                    }
+
+                    end_value_i++;
+                }
+            }
+
+        }
+
+        encode_pos = BOSEncodeBits(ts_block_delta,init_block_size,  final_k_start_value,final_x_l_plus, final_k_end_value,final_x_u_minus,
+                max_delta_value, min_delta,repeat_count, encode_pos , cur_byte);
+
+        return encode_pos;
+    }
+
+    public static int BOSEncoder(
+            int[] data, int block_size, byte[] encoded_result) {
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+            encode_pos =  BOSBlockEncoder(data, i, block_size, block_size,encode_pos,encoded_result);
+//            System.out.println(encode_pos);
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        } else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+
+
+            encode_pos = BOSBlockEncoder(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+//            int[] ts_block = new int[length_all-start];
+//            if (length_all - start >= 0) System.arraycopy(data, start, ts_block, 0, length_all - start);
+//
+//
+//            encode_pos = BOSBlockEncoder(ts_block, encode_pos,encoded_result);
+
+        }
+
+
+        return encode_pos;
+    }
+
+    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list,int init_block_size, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int count_size = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        ArrayList<Integer> repeat_count = new ArrayList<>();
+        if (count_size != 0) {
+            ArrayList<Integer> repeat_count_result = new ArrayList<>();
+            repeat_count = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(init_block_size-1), count_size, repeat_count_result);
+            decode_pos = repeat_count_result.get(0);
+
+        }
+
+        int cur_block_size = block_size;
+        for (int i = 1; i < count_size; i += 2) {
+            cur_block_size -= (repeat_count.get(i) - 1);
+        }
+
+        int final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        int left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+        int right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+
+        if (final_alpha == 0) { // 0
+            int bitmap_bytes = (int) Math.ceil((double) (cur_block_size + k1 + k2) / (double) 8);
+//            System.out.println("bitmap_bytes:" + bitmap_bytes);
+            for (int i = 0; i < bitmap_bytes; i++) {
+                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                decode_pos += 1;
+            }
+            int bitmap_outlier_i = 0;
+            int remaining_bits = 8;
+            int tmp = bitmap_outlier.get(bitmap_outlier_i);
+            bitmap_outlier_i++;
+            int i = 0;
+            while (i < cur_block_size) {
+                if (remaining_bits > 1) {
+                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                    remaining_bits -= 1;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                    if (remaining_bits == 0) {
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                    }
+                } else if (remaining_bits == 1) {
+                    int bit_i = tmp & 0x1;
+                    remaining_bits = 8;
+                    if (bitmap_outlier_i >= bitmap_bytes) break;
+                    tmp = bitmap_outlier.get(bitmap_outlier_i);
+                    bitmap_outlier_i++;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                }
+                i++;
+            }
+        } else {
+
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(cur_block_size-1), k1, decode_pos_result_left);
+            decode_pos = (decode_pos_result_left.get(0));
+
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(cur_block_size-1), k2, decode_pos_result_right);
+            decode_pos = (decode_pos_result_right.get(0));
+
+        }
+
+
+        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, cur_block_size - k1 - k2, decode_pos_normal);
+
+        decode_pos = decode_pos_normal.get(0);
+        if (k1 != 0) {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+
+            decode_pos = decode_pos_result_left.get(0);
+        }
+        if (k2 != 0) {
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+            decode_pos = decode_pos_result_right.get(0);
+        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+        int pre_v;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+        int cur_i = 0;
+        int repeat_i = 0;
+        for (int i = 0; i < cur_block_size; i++) {
+
+            int current_delta;
+            if (left_outlier_i >= k1) {
+                if (right_outlier_i >= k2) {
+                    current_delta = final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
+                    current_delta = final_right_outlier.get(right_outlier_i) + final_k_end_value;
+                    right_outlier_i++;
+                } else {
+                    current_delta = final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                }
+            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
+                current_delta = final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+            } else {
+
+                if (right_outlier_i >= k2) {
+                    current_delta = final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
+                    current_delta = final_right_outlier.get(right_outlier_i) + final_k_end_value;
+                    right_outlier_i++;
+                } else {
+                    current_delta = final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                }
+            }
+            pre_v = current_delta + min_delta;
+            if (repeat_i < count_size) {
+                if (cur_i == repeat_count.get(repeat_i)) {
+                    cur_i += (repeat_count.get(repeat_i+1));
+
+                    for (int j = 0; j < repeat_count.get(repeat_i + 1); j++) {
+                        value_list[value_pos_arr[0]] = pre_v;
+                        value_pos_arr[0]++;
+                    }
+                    repeat_i += 2;
+                }else {
+                    cur_i++;
+                    value_list[value_pos_arr[0]] = pre_v;
+                    value_pos_arr[0]++;
+                }
+            } else {
+                cur_i++;
+                value_list[value_pos_arr[0]] = pre_v;
+                value_pos_arr[0]++;
+            }
+        }
+        return decode_pos;
+    }
+
+    public static void BOSDecoder(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        int[] value_pos_arr = new int[1];
+
+        for (int k = 0; k < block_num; k++) {
+            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list,block_size, block_size,value_pos_arr);
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            BOSBlockDecoder(encoded, decode_pos, value_list,block_size, remain_length, value_pos_arr);
+        }
+    }
+
+    public static int EncodeBits(int num,
+                                 int bit_width,
+                                 int encode_pos,
+                                 byte[] cur_byte,
+                                 int[] bit_index_list){
+        // 找到要插入的位的索引
+        int bit_index = bit_index_list[0] ;//cur_byte[encode_pos + 1];
+
+        // 计算数值的起始位位置
+        int remaining_bits = bit_width;
+
+        while (remaining_bits > 0) {
+            // 计算在当前字节中可以使用的位数
+            int available_bits = bit_index;
+            int bits_to_write = Math.min(available_bits, remaining_bits);
+
+            // 更新 bit_index
+            bit_index = available_bits - bits_to_write;
+
+            // 计算要写入的位的掩码和数值
+            int mask = (1 << bits_to_write) - 1;
+            int bits = (num >> (remaining_bits - bits_to_write)) & mask;
+
+            // 写入到当前位置
+            cur_byte[encode_pos] &= (byte) ~(mask << bit_index); // 清除对应位置的位
+            cur_byte[encode_pos] |= (byte) (bits << bit_index);
+
+            // 更新位宽和数值
+            remaining_bits -= bits_to_write;
+            if (bit_index == 0) {
+                bit_index = 8;
+                encode_pos++;
+            }
+        }
+        bit_index_list[0] = bit_index;
+//        cur_byte[encode_pos + 1] = (byte) bit_index;
+        return encode_pos;
+    }
+    private static int BOSEncodeBitsImprove(int[] ts_block_delta,
+                                            int init_block_size,
+                                            int final_k_start_value,
+                                            int final_x_l_plus,
+                                            int final_k_end_value,
+                                            int final_x_u_minus,
+                                            int max_delta_value,
+                                            int[] min_delta,
+                                            ArrayList<Integer> repeat_count,
+                                            int encode_pos,
+                                            byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+
+        int k1 = 0;
+        int k2 = 0;
+
+
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+//                encode_pos = EncodeBits(cur_value,left_bit_width,encode_pos,cur_byte);
+//                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+//                encode_pos = EncodeBits(cur_value- final_k_end_value,right_bit_width,encode_pos,cur_byte);
+//                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+//                final_normal.add(cur_value - final_x_l_plus);
+//                encode_pos = EncodeBits(cur_value- final_x_l_plus,right_bit_width,encode_pos,cur_byte);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int size = repeat_count.size();
+        intByte2Bytes(size,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        int[] bit_index_list = new int[1];
+        bit_index_list[0] = 8;
+        if (size != 0){
+            int bit_width_init = getBitWith(init_block_size-1);
+            for(int repeat_count_v:repeat_count){
+                encode_pos = EncodeBits(repeat_count_v, bit_width_init, encode_pos, cur_byte, bit_index_list);
+            }
+            if(bit_index_list[0] != 8){
+                bit_index_list[0] = 8;
+                encode_pos ++;
+            }
+        }
+//            encode_pos =encodeOutlier2Bytes(repeat_count, getBitWith(init_block_size-1),encode_pos,cur_byte);
+
+//        int2Bytes(min_delta[1],encode_pos,cur_byte);
+//        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+
+
+        if(final_k_start_value<0 && final_k_end_value > max_delta_value){
+//            int bit_width_final= getBitWith(final_x_u_minus - final_x_l_plus);
+//            cur_byte[encode_pos+1] = 8;
+            bit_index_list[0] = 8;
+            for (int cur_value : ts_block_delta) {
+                encode_pos = EncodeBits(cur_value, bit_width_final, encode_pos, cur_byte, bit_index_list);
+//                final_normal.add(cur_value);
+            }
+            if(bit_index_list[0] != 8){
+                encode_pos ++;
+            }
+//            cur_byte[encode_pos+1] = 0;
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+            return encode_pos;
+        }
+
+
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+        int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(final_k_end_value,encode_pos,cur_byte);
+        encode_pos += 4;
+
+//        bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//        encode_pos += 1;
+        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        if (final_alpha == 0) { // 0
+
+            for (int i : bitmap_outlier) {
+
+                intByte2Bytes(i,encode_pos,cur_byte);
+                encode_pos += 1;
+            }
+        } else {
+            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+        }
+//        cur_byte[encode_pos+1] = 8;
+//        bit_index_list[0] = 8;
+        for (int cur_value : ts_block_delta) {
+            if (cur_value <= final_k_start_value) {
+                encode_pos = EncodeBits(cur_value, left_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else if (cur_value >= final_k_end_value) {
+                encode_pos = EncodeBits(cur_value - final_k_end_value, right_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else {
+                encode_pos = EncodeBits(cur_value - final_x_l_plus, bit_width_final, encode_pos, cur_byte,bit_index_list);
+            }
+        }
+        if(bit_index_list[0] != 8){
+            encode_pos ++;
+        }
+
+//        cur_byte[encode_pos+1] = 0;
+
+//        if(k1==0 && k2==0){
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//
+//
+//        }
+//        else{
+//            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+//            encode_pos += 4;
+//            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+//            encode_pos += 4;
+//
+//            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            if (final_alpha == 0) { // 0
+//
+//                for (int i : bitmap_outlier) {
+//
+//                    intByte2Bytes(i,encode_pos,cur_byte);
+//                    encode_pos += 1;
+//                }
+//            } else {
+//                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//            }
+//        }
+
+
+//        if(k1+k2!=block_size)
+//        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//        if (k1 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+//        if (k2 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+//        System.out.println(encode_pos);
+        return encode_pos;
+
+    }
+    private static int BOSBlockEncoderImprove(int[] ts_block, int block_i, int block_size,int remaining, int encode_pos , byte[] cur_byte) {
+
+        ArrayList<Integer> repeat_count = new ArrayList<>();
+        int init_block_size = block_size;
+
+        int[] min_delta = new int[3];
+        int[]  ts_block_delta = getAbsDeltaTsBlock(ts_block,block_i, init_block_size,remaining, min_delta, repeat_count);
+        block_size = min_delta[1];
+
+
+        int max_delta_value = min_delta[2];
+        int[] value_list = new int[block_size];
+        int unique_value_count = 0;
+        int[] value_count_list = new int[max_delta_value+1];
+        for(int value:ts_block_delta){
+            if(value_count_list[value]==0){
+                value_count_list[value] = 1;
+                value_list[unique_value_count] = value;
+                unique_value_count ++;
+            }else{
+                value_count_list[value] ++;
+            }
+        }
+
+        int left_shift = getBitWith(block_size);
+        int mask =  (1 << left_shift) - 1;
+        long[] sorted_value_list = new long[unique_value_count];
+        int count = 0;
+
+        for(int i=0;i<unique_value_count;i++){
+            int value = value_list[i];
+
+            sorted_value_list[i] = (((long) value) << left_shift) + value_count_list[value];
+        }
+        Arrays.sort(sorted_value_list);
+
+        for(int i=0;i<unique_value_count;i++){
+            count += getCount(sorted_value_list[i], mask);
+            sorted_value_list[i] = (((long)getUniqueValue(sorted_value_list[i], left_shift) ) << left_shift) + count;//new_value_list[i]
+        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2 ) * (block_size));
+
+        int cur_k1 = 0;
+
+        int x_l_plus_value = 0; // x_l_plus
+        int x_u_minus_value = max_delta_value; // x_u_plus
+
+        for (int end_value_i = 1; end_value_i < unique_value_count; end_value_i++) {
+
+            x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+            int x_u_plus_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+            int cur_bits = 0;
+            int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value); // cur_k1 = 0
+            if (cur_k2 != 0)
+                cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus_value);
+
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_x_u_minus = x_u_minus_value;
+                final_k_end_value = x_u_plus_value;
+            }
+        }
+
+        int k_start_value = -1; // x_l_minus
+
+        int gamma_max = getBitWith(max_delta_value);
+        int[] gamma_count_list = new int[gamma_max+1];
+        int[] x_u_minus_value_list = new int[gamma_max+1];
+        int[] x_u_plus_value_list = new int[gamma_max+1];
+        int end_i = unique_value_count - 1;
+        for(int gamma = 0; gamma <= gamma_max; gamma++) {
+            int x_u_plus_pow_beta = max_delta_value - (1<<gamma) + 1;
+            for (; end_i > 0; end_i--) {
+                x_u_minus_value = getUniqueValue(sorted_value_list[end_i - 1], left_shift);
+                int x_u_plus_value = getUniqueValue(sorted_value_list[end_i], left_shift);
+                if (x_u_minus_value < x_u_plus_pow_beta && x_u_plus_value >= x_u_plus_pow_beta){
+                    gamma_count_list[gamma] = getCount(sorted_value_list[end_i-1],mask);
+                    x_u_minus_value_list[gamma] = x_u_minus_value;
+                    x_u_plus_value_list[gamma] = x_u_plus_value;
+                } else if (x_u_minus_value < x_u_plus_pow_beta) {
+                    break;
+                }
+            }
+        }
+        for(int gamma = 1; gamma < gamma_max; gamma++) {
+            if(gamma_count_list[gamma]==0){
+                gamma_count_list[gamma] = gamma_count_list[gamma-1];
+                x_u_minus_value_list[gamma] = x_u_minus_value_list[gamma-1];
+                x_u_plus_value_list[gamma] = x_u_plus_value_list[gamma-1];
+            }
+        }
+
+        for (int start_value_i = 0; start_value_i < unique_value_count-1; start_value_i++) {
+            long k_start_valueL = sorted_value_list[start_value_i];
+            k_start_value =  getUniqueValue(k_start_valueL, left_shift) ;
+            x_l_plus_value =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+
+
+            cur_k1 = getCount(k_start_valueL,mask);
+
+            int k_end_value;
+            int cur_bits;
+            int cur_k2;
+            k_end_value = max_delta_value + 1;
+
+            cur_bits = 0;
+            cur_k2 = 0;
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            cur_bits += cur_k1 * getBitWith(k_start_value);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k1) * getBitWith(k_end_value- x_l_plus_value); //cur_k2 =0
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_k_start_value = k_start_value;
+                final_x_l_plus = x_l_plus_value;
+                final_k_end_value = k_end_value;
+                final_x_u_minus = max_delta_value;
+            }
+
+            int beta_max = getBitWith(max_delta_value - x_l_plus_value);
+            int end_value_i = start_value_i + 1;
+
+            int lower_outlier_cost = cur_k1 * getBitWith(k_start_value);
+
+            for(int gamma = 0; gamma < beta_max; gamma++){
+//                int x_u_plus_pow_beta = (int) (max_delta_value - pow(2,gamma)+1);
+                x_u_minus_value = x_u_minus_value_list[gamma];
+                k_end_value =  x_u_plus_value_list[gamma];
+                cur_bits = 0;
+                cur_k2 = block_size - gamma_count_list[gamma];
+
+                cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                cur_bits += lower_outlier_cost;
+                if (cur_k1 + cur_k2 != block_size)
+                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+                if (cur_k2 != 0)
+                    cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+
+
+                if (cur_bits < min_bits) {
+                    min_bits = cur_bits;
+                    final_k_start_value = k_start_value;
+                    final_x_l_plus = x_l_plus_value;
+                    final_k_end_value = k_end_value;
+                    final_x_u_minus = x_u_minus_value;
+                }
+
+            }
+//            end_value_i = unique_value_count - 1;
+//            for(int gamma = 1; gamma <= beta_max; gamma++){
+//                for (; end_value_i > start_value_i; end_value_i--) {
+//                    int x_u_plus_pow_beta = (int) (max_delta_value - pow(2,gamma)+1);
+//                    x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+//                    k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+//                    if(x_u_minus_value < x_u_plus_pow_beta && k_end_value >= x_u_plus_pow_beta){
+//                        cur_bits = 0;
+//                        cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+//
+//                        cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+//                        cur_bits += cur_k1 * getBitWith(k_start_value);
+//                        if (cur_k1 + cur_k2 != block_size)
+//                            cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+//                        if (cur_k2 != 0)
+//                            cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+//
+//
+//                        if (cur_bits < min_bits) {
+//                            min_bits = cur_bits;
+//                            final_k_start_value = k_start_value;
+//                            final_x_l_plus = x_l_plus_value;
+//                            final_k_end_value = k_end_value;
+//                            final_x_u_minus = x_u_minus_value;
+//                        }
+//                    } else if (x_u_minus_value <= x_u_plus_pow_beta && k_end_value <= x_u_plus_pow_beta) {
+//                        break;
+//                    }
+//                }
+//            }
+
+
+        }
+        for(int beta = 0; beta <= gamma_max; beta++){
+            int pow_beta = 1<<beta;
+            int start_value_i = 0;
+            int end_value_i = start_value_i+1;
+
+            for (; start_value_i < unique_value_count-1; start_value_i++) {
+                long x_l_minusL = sorted_value_list[start_value_i];
+                int x_l_minus =  getUniqueValue(x_l_minusL, left_shift) ;
+                int x_l_plus =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+                int x_u_plus_pow_beta = pow_beta+x_l_plus;
+                if(x_u_plus_pow_beta > max_delta_value) break;
+
+
+
+                cur_k1 = getCount(x_l_minusL,mask);
+                int lower_outlier_cost = cur_k1 * getBitWith(x_l_minus);
+
+                while ( end_value_i < unique_value_count) {
+//                    if(beta==3 && end_value_i==22)
+//                    {
+//                        System.out.println(x_l_minus);
+//                        System.out.println(x_l_plus);
+//                    }
+
+                    int x_u_minus = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+                    int x_u_plus = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+                    if(x_u_minus < x_u_plus_pow_beta && x_u_plus >= x_u_plus_pow_beta){
+                        int cur_bits = 0;
+                        int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+
+                        cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                        cur_bits += lower_outlier_cost;
+                        if (cur_k1 + cur_k2 != block_size)
+                            cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus - x_l_plus);
+                        if (cur_k2 != 0)
+                            cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus);
+
+
+                        if (cur_bits < min_bits) {
+                            min_bits = cur_bits;
+                            final_k_start_value = x_l_minus;
+                            final_x_l_plus = x_l_plus;
+                            final_k_end_value = x_u_plus;
+                            final_x_u_minus = x_u_minus;
+                        }
+                        break;
+                    }
+//                    else if (x_u_minus >= x_u_plus_pow_beta && x_u_plus >= x_u_plus_pow_beta) {
+//                        break;
+//                    }
+
+                    end_value_i++;
+                }
+            }
+
+        }
+
+        encode_pos = BOSEncodeBitsImprove(ts_block_delta,init_block_size,  final_k_start_value,final_x_l_plus, final_k_end_value,final_x_u_minus,
+                max_delta_value, min_delta,repeat_count, encode_pos , cur_byte);
+
+        return encode_pos;
+    }
+
+    public static int BOSEncoderImprove(
+            int[] data, int block_size, byte[] encoded_result) {
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+
+
+            encode_pos =  BOSBlockEncoderImprove(data, i, block_size, block_size,encode_pos,encoded_result);
+//            System.out.println(encode_pos);
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        } else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+
+            encode_pos = BOSBlockEncoderImprove(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+//            int[] ts_block = new int[length_all-start];
+//            if (length_all - start >= 0) System.arraycopy(data, start, ts_block, 0, length_all - start);
+//
+//
+//            encode_pos = BOSBlockEncoder(ts_block, encode_pos,encoded_result);
+
+        }
+
+
+        return encode_pos;
+    }
+
+
+
+    public static int DecodeBits(byte[] cur_byte, int bit_width, int[] decode_pos_list) {
+        int decode_pos = decode_pos_list[0];
+        int bit_index = decode_pos_list[1];  //cur_byte[decode_pos + 1];
+        int remaining_bits = bit_width;
+        int num = 0;
+
+        while (remaining_bits > 0) {
+            int available_bits = bit_index;
+            int bits_to_read = Math.min(available_bits, remaining_bits);
+
+            // 计算要读取的位的掩码
+            int mask = (1 << bits_to_read) - 1;
+            int bits = (cur_byte[decode_pos] >> (available_bits - bits_to_read)) & mask;
+
+            // 将读取的位合并到结果中
+            num = (num << bits_to_read) | bits;
+
+            // 更新位宽和 bit_index
+            remaining_bits -= bits_to_read;
+            bit_index = available_bits - bits_to_read;
+
+            if (bit_index == 0) {
+                bit_index = 8;
+                decode_pos++;
+            }
+        }
+        decode_pos_list[0] = decode_pos;
+        decode_pos_list[1] = bit_index;
+
+        return num;
+    }
+
+    public static int BOSBlockDecoderImprove(byte[] encoded, int decode_pos, int[] value_list,int init_block_size, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+//        int value0 = bytes2Integer(encoded, decode_pos, 4);
+//        decode_pos += 4;
+//        value_list[value_pos_arr[0]] =value0;
+//        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int count_size = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        int[] decode_list = new int[2];
+        decode_list[0]= decode_pos;
+        decode_list[1]= 8;
+
+        int valuePos = value_pos_arr[0];
+
+//        ArrayList<Integer> repeat_count = new ArrayList<>();
+        ArrayList<Integer> repeat_count = new ArrayList<>();
+        if (count_size != 0) {
+            int bit_width_init =  getBitWith(init_block_size-1);
+            for(int i = 0;i<count_size;i++){
+                int repeat_count_v = DecodeBits(encoded, bit_width_init,  decode_list);
+                repeat_count.add(repeat_count_v);
+            }
+
+            if(decode_list[1] != 8){
+                decode_list[1] = 8;
+                decode_list[0] ++;
+            }
+//            repeat_count = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(init_block_size-1), count_size, repeat_count_result);
+            decode_pos = decode_list[0];
+//            decode_list[1]= 8;
+        }
+
+        int cur_block_size = block_size;
+        for (int i = 1; i < count_size; i += 2) {
+            cur_block_size -= (repeat_count.get(i) - 1);
+        }
+
+        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+
+
+        int pre_v;
+        int cur_i = 0;
+        int repeat_i = 0;
+        if(k1==0 && k2==0){
+//            int pre_v = value0;
+            decode_list[0] = decode_pos;
+            decode_list[1]= 8;
+            for (int i = 0; i < cur_block_size; i++) {
+                pre_v = min_delta + DecodeBits(encoded, bit_width_final,  decode_list);
+//                value_list[value_pos_arr[0]++] = pre_v;
+                if (repeat_i < count_size && cur_i == repeat_count.get(repeat_i)) {
+                    cur_i += (repeat_count.get(repeat_i+1));
+
+                    for (int j = 0; j < repeat_count.get(repeat_i + 1); j++) {
+                        value_list[value_pos_arr[0]++] = pre_v;
+                    }
+                    repeat_i += 2;
+                } else {
+                    cur_i++;
+                    value_list[value_pos_arr[0]++] = pre_v;
+                }
+            }
+            if(decode_list[1] != 8){
+                decode_list[1] = 8;
+                decode_list[0] ++;
+            }
+
+//            value_pos_arr[0] = valuePos;
+            return decode_list[0];
+        }
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+//        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+//        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+//        bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+//        decode_pos += 1;
+
+        left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+        right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        if (final_alpha == 0) {
+            int bitmap_bytes = (int) Math.ceil((double) (cur_block_size + k1 + k2) / (double) 8);
+            for (int i = 0; i < bitmap_bytes; i++) {
+                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                decode_pos += 1;
+            }
+            int bitmap_outlier_i = 0;
+            int remaining_bits = 8;
+            int tmp = bitmap_outlier.get(bitmap_outlier_i);
+            bitmap_outlier_i++;
+            int i = 0;
+            while (i < cur_block_size ) {
+                if (remaining_bits > 1) {
+                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                    remaining_bits -= 1;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                    if (remaining_bits == 0) {
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                    }
+                } else if (remaining_bits == 1) {
+                    int bit_i = tmp & 0x1;
+                    remaining_bits = 8;
+                    if (bitmap_outlier_i >= bitmap_bytes) break;
+                    tmp = bitmap_outlier.get(bitmap_outlier_i);
+                    bitmap_outlier_i++;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                }
+                i++;
+            }
+        } else {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(cur_block_size-1), k1, decode_pos_result_left);
+            decode_pos = (decode_pos_result_left.get(0));
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(cur_block_size-1), k2, decode_pos_result_right);
+            decode_pos = (decode_pos_result_right.get(0));
+        }
+
+
+
+
+
+//        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+//        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+//
+//        decode_pos = decode_pos_normal.get(0);
+//        if (k1 != 0) {
+//            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+//            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+//            decode_pos = decode_pos_result_left.get(0);
+//        }
+//        if (k2 != 0) {
+//            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+//            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+//            decode_pos = decode_pos_result_right.get(0);
+//        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+//        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+// Precompute constants
+        int normalOffset = min_delta + final_k_start_value;
+        int rightOutlierOffset = min_delta + final_k_end_value;
+
+// Initialize indices and pre-fetch next outlier positions
+        int leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+        int rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+        decode_list[0]= decode_pos;
+//        decode_list[1]= 8;
+        // Use a local variable for the position
+        for (int i = 0; i < cur_block_size; i++) {
+//            int currentDelta;
+            if (i == leftOutlierNextIndex) {
+                // Process left outlier
+                pre_v = min_delta + DecodeBits(encoded, left_bit_width,  decode_list); // final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+                leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+            } else if (i == rightOutlierNextIndex) {
+                // Process right outlier
+                pre_v = rightOutlierOffset + DecodeBits(encoded, right_bit_width,  decode_list);// final_right_outlier.get(right_outlier_i);
+                right_outlier_i++;
+                rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+            } else {
+                // Process normal value
+                pre_v = normalOffset + DecodeBits(encoded, bit_width_final,  decode_list);
+                normal_i++;
+            }
+            if (repeat_i < count_size && cur_i == repeat_count.get(repeat_i)) {
+                cur_i += (repeat_count.get(repeat_i+1));
+
+                for (int j = 0; j < repeat_count.get(repeat_i + 1); j++) {
+                    value_list[value_pos_arr[0]++] = pre_v;
+                }
+                repeat_i += 2;
+            } else {
+                cur_i++;
+                value_list[value_pos_arr[0]++] = pre_v;
+            }
+            // Update the cumulative value and store it
+//            pre_v += deZigzag(currentDelta);
+//            value_list[valuePos++] = pre_v;
+        }
+//        value_pos_arr[0] = valuePos;
+        if(decode_list[1]!=8){
+            return decode_list[0]+1;
+        }else {
+            return decode_list[0];
+        }
+//        decode_pos = decode_list[0];
+// Update the position in the array
+
+
+//        return decode_pos;
+    }
+    public static void BOSDecoderImprove(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        int[] value_pos_arr = new int[1];
+
+        for (int k = 0; k < block_num; k++) {
+//            System.out.println(k);
+            decode_pos = BOSBlockDecoderImprove(encoded, decode_pos, value_list, block_size, block_size, value_pos_arr);
+//            System.out.println(decode_pos);
+        }
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            BOSBlockDecoderImprove(encoded, decode_pos, value_list,block_size, remain_length, value_pos_arr);
+        }
+    }
+
+    public static void main(@org.jetbrains.annotations.NotNull String[] args) throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/rle_bos_b";
+
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        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(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 8; file_i < 9; file_i++) {
+
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoder(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "RLE+BOS-B",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+            }
+            writer.close();
+
+
+        }
+    }
+
+    @Test
+    public void BOSOUOExpTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+//        String output_parent_dir = parent_dir + "icde0802/compression_ratio/exp_b";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R2O3_lower_outlier_compare/compression_ratio/bos";
+        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<>();
+
+        dataset_name.add("Synthetic_Exp_100");
+        dataset_name.add("Synthetic_Exp_1000");
+        dataset_name.add("Synthetic_Exp_10000");
+        dataset_name.add("Synthetic_Exp_100000");
+        dataset_name.add("Synthetic_Exp_1000000");
+        dataset_name.add("Synthetic_Normal_100");
+        dataset_name.add("Synthetic_Normal_1000");
+        dataset_name.add("Synthetic_Normal_10000");
+        dataset_name.add("Synthetic_Normal_100000");
+        dataset_name.add("Synthetic_Normal_1000000");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        output_path_list.add(output_parent_dir + "/Exp_100.csv"); // 0
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/Exp_1000.csv");// 1
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Exp_10000.csv");// 2
+        output_path_list.add(output_parent_dir + "/Exp_100000.csv");// 2
+        output_path_list.add(output_parent_dir + "/Exp_1000000.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Normal_100.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Normal_1000.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/Normal_10000.csv");//5
+        output_path_list.add(output_parent_dir + "/Normal_100000.csv");//5
+        output_path_list.add(output_parent_dir + "/Normal_1000000.csv");//5
+//        dataset_block_size.add(2048);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 8; file_i < 9; file_i++) {
+
+        for (int file_i = input_path_list.size()-1; file_i >=0 ; file_i--) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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);
+                if(f.toString().contains(".DS")) continue;
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoder(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "RLE+BOS-B",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+            }
+            writer.close();
+
+
+        }
+    }
+    @Test
+    public void BOSImproveDecodeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R1O4_decode_time/compression_ratio/rle_bos_b";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 4; file_i < 5; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[1];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "RLE+BOS-B",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void BOSImproveEncodeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/rle_bos_b_improve";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 4; file_i < 5; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[1];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "RLE+BOS-B",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
+}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSHTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSHTest.java
deleted file mode 100644
index cbd88b1..0000000
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSHTest.java
+++ /dev/null
@@ -1,1559 +0,0 @@
-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.ArrayList;
-
-import static java.lang.Math.*;
-
-public class RLEBOSHTest {
-
-    public static int getBitWith(int num) {
-        if (num == 0) return 1;
-        else return 32 - Integer.numberOfLeadingZeros(num);
-    }
-
-    public static int getCount(long long1, int mask) {
-        return ((int) (long1 & mask));
-    }
-
-    public static int getUniqueValue(long long1, int left_shift) {
-        return ((int) ((long1) >> left_shift));
-    }
-
-
-    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;
-                }
-            }
-        }
-
-    }
-
-    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 int[] getAbsDeltaTsBlock(
-            int[] ts_block,
-            ArrayList<Integer> min_delta,
-            ArrayList<Integer> repeat_count) {
-        int[] ts_block_delta = new int[ts_block.length];
-
-
-        int value_delta_min = Integer.MAX_VALUE;
-        for (Integer integer : ts_block) {
-            if (integer < value_delta_min) value_delta_min = integer;
-        }
-        int repeat_i = 0;
-        int pre_delta = ts_block[0] - value_delta_min;
-        int pre_count = 1;
-        min_delta.add(value_delta_min);
-        int block_size = ts_block.length;
-
-        int ts_block_delta_i = 0;
-        for (int i = 1; i < block_size; i++) {
-            int delta = ts_block[i] - value_delta_min;
-            if (delta == pre_delta) {
-                pre_count++;
-            } else {
-                if (pre_count > 7) {
-                    repeat_count.add(repeat_i);
-                    repeat_count.add(pre_count);
-                    ts_block_delta[ts_block_delta_i] = pre_delta;
-                    ts_block_delta_i++;
-                } else {
-                    for (int j = 0; j < pre_count; j++) {
-                        ts_block_delta[ts_block_delta_i] = pre_delta;
-                        ts_block_delta_i++;
-                    }
-
-                }
-                pre_count = 1;
-                repeat_i = i;
-            }
-            pre_delta = delta;
-        }
-        for (int j = 0; j < pre_count; j++) {
-            ts_block_delta[ts_block_delta_i] = pre_delta;
-            ts_block_delta_i++;
-        }
-        min_delta.add(ts_block_delta_i);
-        int[] new_ts_block_delta = new int[ts_block_delta_i];
-        System.arraycopy(ts_block_delta, 0, new_ts_block_delta, 0, ts_block_delta_i);
-
-        return new_ts_block_delta;
-    }
-
-    public static int[] getAbsDeltaTsBlock(
-            int[] ts_block,
-            int i,
-            int block_size,
-            int remaining,
-            int[] min_delta,
-            ArrayList<Integer> repeat_count) {
-        int[] ts_block_delta = new int[remaining];
-
-        int value_delta_min = Integer.MAX_VALUE;
-        int value_delta_max = Integer.MIN_VALUE;
-        int base = i * block_size;
-        int end = i * block_size + remaining;
-        for (int j = base; j < end; j++) {
-
-            int integer = ts_block[j];
-            if (integer < value_delta_min) value_delta_min = integer;
-            if (integer > value_delta_max) {
-                value_delta_max = integer;
-            }
-        }
-        int pre_delta = ts_block[i * block_size] - value_delta_min;
-        int pre_count = 1;
-
-        min_delta[0] = (value_delta_min);
-        int repeat_i = 0;
-        int ts_block_delta_i = 0;
-        for (int j = base + 1; j < end; j++) {
-            int delta = ts_block[j] - value_delta_min;
-            if (delta == pre_delta) {
-                pre_count++;
-            } else {
-                if (pre_count > 7) {
-                    repeat_count.add(repeat_i);
-                    repeat_count.add(pre_count);
-                    ts_block_delta[ts_block_delta_i] = pre_delta;
-                    ts_block_delta_i++;
-                } else {
-                    for (int k = 0; k < pre_count; k++) {
-                        ts_block_delta[ts_block_delta_i] = pre_delta;
-                        ts_block_delta_i++;
-                    }
-                }
-                pre_count = 1;
-                repeat_i = j - i * block_size;
-            }
-            pre_delta = delta;
-
-        }
-        for (int j = 0; j < pre_count; j++) {
-            ts_block_delta[ts_block_delta_i] = pre_delta;
-            ts_block_delta_i++;
-        }
-        min_delta[1] = (ts_block_delta_i);
-        min_delta[2] = (value_delta_max - value_delta_min);
-        int[] new_ts_block_delta = new int[ts_block_delta_i];
-        System.arraycopy(ts_block_delta, 0, new_ts_block_delta, 0, ts_block_delta_i);
-
-        return new_ts_block_delta;
-    }
-
-
-    public static int encodeOutlier2Bytes(
-            ArrayList<Integer> ts_block_delta,
-            int bit_width,
-            int encode_pos, byte[] encoded_result) {
-
-        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
-
-        int n_k = ts_block_delta.size();
-        int n_k_b = n_k / 8;
-        long cur_remaining = 0; // encoded int
-        int cur_number_bits = 0; // the bit width used of encoded int
-        for (int i = n_k_b * 8; i < n_k; i++) {
-            long cur_value = ts_block_delta.get(i);
-            int cur_bit_width = bit_width; // remaining bit width of current value
-
-            if (cur_number_bits + bit_width >= 32) {
-                cur_remaining <<= (32 - cur_number_bits);
-                cur_bit_width = bit_width - 32 + cur_number_bits;
-                cur_remaining += ((cur_value >> cur_bit_width));
-                long2intBytes(cur_remaining, encode_pos, encoded_result);
-                encode_pos += 4;
-
-                cur_remaining = 0;
-                cur_number_bits = 0;
-            }
-
-            cur_remaining <<= cur_bit_width;
-            cur_number_bits += cur_bit_width;
-            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width));
-        }
-        cur_remaining <<= (32 - cur_number_bits);
-        long2intBytes(cur_remaining, encode_pos, encoded_result);
-        encode_pos += 4;
-        return encode_pos;
-
-    }
-
-
-    public static ArrayList<Integer> decodeOutlier2Bytes(
-            byte[] encoded,
-            int decode_pos,
-            int bit_width,
-            int length,
-            ArrayList<Integer> encoded_pos_result
-    ) {
-
-        int n_k_b = length / 8;
-        int remaining = length - n_k_b * 8;
-        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
-        decode_pos += n_k_b * bit_width;
-
-        ArrayList<Long> int_remaining = new ArrayList<>();
-        int int_remaining_size = remaining * bit_width / 32 + 1;
-        for (int j = 0; j < int_remaining_size; j++) {
-
-            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
-            decode_pos += 4;
-        }
-
-        int cur_remaining_bits = 32; // remaining bit width of current value
-        long cur_number = int_remaining.get(0);
-        int cur_number_i = 1;
-        for (int i = n_k_b * 8; i < length; i++) {
-            if (bit_width < cur_remaining_bits) {
-                int tmp = (int) (cur_number >> (32 - bit_width));
-                result_list.add(tmp);
-                cur_number <<= bit_width;
-                cur_number &= 0xFFFFFFFFL;
-                cur_remaining_bits -= bit_width;
-            } else {
-                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
-                int remain_bits = bit_width - cur_remaining_bits;
-                tmp <<= remain_bits;
-
-                cur_number = int_remaining.get(cur_number_i);
-                cur_number_i++;
-                tmp += (cur_number >> (32 - remain_bits));
-                result_list.add(tmp);
-                cur_number <<= remain_bits;
-                cur_number &= 0xFFFFFFFFL;
-                cur_remaining_bits = 32 - remain_bits;
-            }
-        }
-        encoded_pos_result.add(decode_pos);
-        return result_list;
-    }
-
-    private static int BOSEncodeBits(int[] ts_block_delta,
-                                     int init_block_size,
-                                     int final_k_start_value,
-                                     int final_k_end_value,
-                                     int max_delta_value,
-                                     int[] min_delta,
-                                     ArrayList<Integer> repeat_count,
-                                     int encode_pos,
-                                     byte[] cur_byte) {
-        int block_size = ts_block_delta.length;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal = new ArrayList<>();
-        int k1 = 0;
-        int k2 = 0;
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-        int index_bitmap_outlier = 0;
-        int cur_index_bitmap_outlier_bits = 0;
-        for (int i = 0; i < block_size; i++) {
-            int cur_value = ts_block_delta[i];
-            if (cur_value < final_k_start_value) {
-                final_left_outlier.add(cur_value);
-                final_left_outlier_index.add(i);
-                if (cur_index_bitmap_outlier_bits % 8 != 7) {
-                    index_bitmap_outlier <<= 2;
-                    index_bitmap_outlier += 3;
-                    cur_index_bitmap_outlier_bits += 2;
-                } else {
-                    index_bitmap_outlier <<= 1;
-                    index_bitmap_outlier += 1;
-                    bitmap_outlier.add(index_bitmap_outlier);
-                    index_bitmap_outlier = 1;
-                    cur_index_bitmap_outlier_bits = 1;
-                }
-
-
-                k1++;
-
-
-            } else if (cur_value > final_k_end_value) {
-                final_right_outlier.add(cur_value - final_k_end_value);
-                final_right_outlier_index.add(i);
-                if (cur_index_bitmap_outlier_bits % 8 != 7) {
-                    index_bitmap_outlier <<= 2;
-                    index_bitmap_outlier += 2;
-                    cur_index_bitmap_outlier_bits += 2;
-                } else {
-                    index_bitmap_outlier <<= 1;
-                    index_bitmap_outlier += 1;
-                    bitmap_outlier.add(index_bitmap_outlier);
-                    index_bitmap_outlier = 0;
-                    cur_index_bitmap_outlier_bits = 1;
-                }
-                k2++;
-
-            } else {
-                final_normal.add(cur_value - final_k_start_value - 1);
-                index_bitmap_outlier <<= 1;
-                cur_index_bitmap_outlier_bits += 1;
-            }
-            if (cur_index_bitmap_outlier_bits % 8 == 0) {
-                bitmap_outlier.add(index_bitmap_outlier);
-                index_bitmap_outlier = 0;
-            }
-        }
-        if (cur_index_bitmap_outlier_bits % 8 != 0) {
-
-            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
-
-            index_bitmap_outlier &= 0xFF;
-            bitmap_outlier.add(index_bitmap_outlier);
-        }
-        int final_alpha = ((k1 + k2) * getBitWith(block_size - 1)) <= (block_size + k1 + k2) ? 1 : 0;
-
-        int k_byte = (k1 << 1);
-        k_byte += final_alpha;
-        k_byte += (k2 << 16);
-
-        int2Bytes(k_byte, encode_pos, cur_byte);
-        encode_pos += 4;
-
-        int2Bytes(min_delta[0], encode_pos, cur_byte);
-        encode_pos += 4;
-        int size = repeat_count.size();
-        intByte2Bytes(size, encode_pos, cur_byte);
-        encode_pos += 1;
-
-        if (size != 0)
-            encode_pos = encodeOutlier2Bytes(repeat_count, getBitWith(init_block_size - 1), encode_pos, cur_byte);
-
-
-        int2Bytes(final_k_start_value, encode_pos, cur_byte);
-        encode_pos += 4;
-        int bit_width_final = getBitWith(final_k_end_value - final_k_start_value - 2);
-        intByte2Bytes(bit_width_final, encode_pos, cur_byte);
-        encode_pos += 1;
-        int left_bit_width = getBitWith(final_k_start_value);
-        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);
-        intByte2Bytes(left_bit_width, encode_pos, cur_byte);
-        encode_pos += 1;
-        intByte2Bytes(right_bit_width, encode_pos, cur_byte);
-        encode_pos += 1;
-        if (final_alpha == 0) {
-
-            for (int i : bitmap_outlier) {
-
-                intByte2Bytes(i, encode_pos, cur_byte);
-                encode_pos += 1;
-            }
-        } else {
-            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size - 1), encode_pos, cur_byte);
-            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size - 1), encode_pos, cur_byte);
-        }
-        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final, encode_pos, cur_byte);
-        if (k1 != 0)
-            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width, encode_pos, cur_byte);
-        if (k2 != 0)
-            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width, encode_pos, cur_byte);
-        return encode_pos;
-
-    }
-
-
-    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size, int remaining, int encode_pos, byte[] cur_byte) {
-
-        ArrayList<Integer> repeat_count = new ArrayList<>();
-        int init_block_size = block_size;
-
-        int[] min_delta = new int[3];
-        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, init_block_size, remaining, min_delta, repeat_count);
-        block_size = min_delta[1];
-        int max_delta_value = min_delta[2];
-
-
-
-
-        int boundary_index = (int) ((double) block_size / (double) (getBitWith(block_size-1)-1));
-
-        int max_bit_width = getBitWith(max_delta_value) + 1;
-        int[] lambda_list = {getBitWith(block_size-1),1};
-        int lambda_0 = lambda_list[0];
-
-        int count_x_min = 0;
-        int count_x_max = 0;
-        GroupL[] groupL = new GroupL[max_bit_width];
-        GroupU[] groupU = new GroupU[max_bit_width];
-        for (int i = 0; i < max_bit_width; i++) {
-            int[] numbers = new int[block_size];
-            int count = 0;
-            groupL[i] = new GroupL(numbers, count, i);
-            int[] numbersU = new int[block_size];
-            groupU[i] = new GroupU(numbersU, count, i);
-        }
-        for (int value : ts_block_delta) {
-            int alpha_i = getBitWith(value);
-            if (value == 0) {
-                count_x_min++;
-            } else {
-                groupL[alpha_i].addNumber(value); // (x_min+2^{alpha_i-1},x_min+2^{alpha_i})
-            }
-            int gamma_i = getBitWith(max_delta_value - value);
-            if (value == max_delta_value) {
-                count_x_max++;
-            } else {
-                groupU[gamma_i].addNumber(value);// (x_max-2^{gamma_i},x_max-2^{gamma_i-1})
-            }
-        }
-        int[] alpha_list = new int[max_bit_width];
-        int num_of_alpha_list = 0;
-        int[] gamma_list = new int[max_bit_width];
-        int num_of_gamma_list = 0;
-        for (int i = 1; i < max_bit_width; i++) {
-            if(groupL[i].count!=0){
-                groupL[i].setCount_array();
-                alpha_list[num_of_alpha_list] = i;
-                num_of_alpha_list ++;
-            }
-            if(groupU[i].count!=0){
-                groupU[i].setCount_array(max_delta_value);
-                gamma_list[num_of_gamma_list] = i;
-                num_of_gamma_list ++;
-                groupU[i].setinvert();
-            }
-        }
-
-
-        int final_k_start_value = -1;//getUniqueValue(sorted_value_list[0], left_shift);
-        int final_k_end_value = max_delta_value + 1;
-
-        int min_bits = 0;
-        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2) * (block_size));
-
-        int alpha_size = getBitWith(max(max_delta_value-1,0));
-
-        if( num_of_alpha_list ==0 && num_of_gamma_list==0){
-            encode_pos = BOSEncodeBits(ts_block_delta, init_block_size, final_k_start_value, final_k_end_value, max_delta_value,
-                    min_delta, repeat_count, encode_pos, cur_byte);
-            return  encode_pos;
-        }
-
-
-        // -------------x_min-------------------
-        // lower: x_min
-        // upper: x_max
-        int k1 = count_x_min;
-        int k1_start = 0;
-        int k2 = count_x_max;
-        int k2_end = max_delta_value;
-        int cur_bits = Math.min((k1 + k2) * getBitWith(block_size - 1), block_size + k1 + k2);
-        cur_bits += k1;
-        cur_bits += k2;
-        cur_bits += (block_size - k1 - k2) * getBitWith(k2_end - k1_start - 2);
-        if (cur_bits < min_bits) {
-            min_bits = cur_bits;
-            final_k_start_value = k1_start;
-            final_k_end_value = k2_end;
-        }
-
-        // lower: x_min
-        // upper:  x_max - 1, x_max - 2, x_max - 4  ...
-        //(x_max - 2^{gamma}, x_max - 2^{gamma-1} ]
-
-        for (int gamma_i = 0; gamma_i < num_of_gamma_list-1; gamma_i++) {
-
-            int gamma = gamma_list[gamma_i];
-
-            int gap_gamma = (int) pow(2, gamma - 1);
-            k2_end = max_delta_value - gap_gamma; // x_max - 2^{gamma-1}  gamma : 1 to alpha_size-1
-
-            GroupU cur_group_gamma = groupU[gamma];
-
-            long[] gamma_sorted = cur_group_gamma.sorted_value_list;
-            int gamma_unique_number = cur_group_gamma.unique_number;
-            int cur_gamma_count = cur_group_gamma.count;
-
-            for(int unique_i=0;unique_i<gamma_unique_number;unique_i++){
-                int unique_i_cur_k2 = k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-                int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);
-
-
-                cur_bits = 0;
-                cur_bits += k1;
-                cur_bits += Math.min((k1 + unique_i_cur_k2) * getBitWith(block_size - 1), block_size + k1 + unique_i_cur_k2);
-
-                if (k1 + unique_i_cur_k2 != block_size)
-                    cur_bits += (block_size - k1 - unique_i_cur_k2) *
-                            getBitWith(k2_end - x_u_i - 2);
-                cur_bits += unique_i_cur_k2 * gamma;//min_upper_outlier
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start;
-                    final_k_end_value = k2_end - x_u_i;
-                }
-            }
-            k2 += cur_gamma_count;
-
-        }
-
-        // lower: x_min
-        // k2_end = x_max - 2^{alpha_size-1}
-        // upper: (0,x_max - 2^{alpha_size-1}]
-
-        int gap_gamma = (int) pow(2,alpha_size-1);
-        k2_end = max_delta_value - gap_gamma;
-        GroupU cur_group_gamma = groupU[alpha_size];
-
-        long[] gamma_sorted = cur_group_gamma.sorted_value_list;
-        int gamma_unique_number = cur_group_gamma.unique_number;
-
-        for(int unique_i=0;unique_i<gamma_unique_number-1;unique_i++){
-            int  unique_i_cur_k2 = k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-            int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);
-
-
-            cur_bits = 0;
-            cur_bits += k1;
-            cur_bits += Math.min((k1 + unique_i_cur_k2) * getBitWith(block_size - 1), block_size + k1 + unique_i_cur_k2);
-
-            if (k1 + unique_i_cur_k2 != block_size)
-                cur_bits += (block_size - k1 - unique_i_cur_k2) *
-                        getBitWith(k2_end - x_u_i - 2);
-            cur_bits += unique_i_cur_k2 * alpha_size;
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k1_start;
-                final_k_end_value = k2_end - x_u_i;
-            }
-        }
-
-        // -------------x_min-------------------
-
-
-
-
-        // [x_min+2^{alpha-1},x_min+2^{alpha}) alpha = 1 to alphasize - 1
-        // -----------------[x_min+2^{alpha-1},x_min+2^{alpha})-------------------
-        // alpha_size = getBitWith(max_delta_value);
-
-        for (int alpha_i = 0; alpha_i < num_of_alpha_list-1; alpha_i++) {
-
-            int alpha = alpha_list[alpha_i];
-            int gap_alpha = (int) pow(2,alpha-1);
-            k1_start = gap_alpha;
-            GroupL cur_group_alpha = groupL[alpha];
-
-
-            // lower: [x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-            // upper: x_max
-
-            int alpha_value_count = cur_group_alpha.count;
-            long[] alpha_sorted = cur_group_alpha.sorted_value_list;
-            int alpha_unique_number = cur_group_alpha.unique_number;
-
-            // k1; count[x_min, x_min+2^{alpha-1}]
-            for (int unique_j=0;unique_j<alpha_unique_number;unique_j++) {
-
-                int unique_i_cur_k1 = k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);//alpha_unique_count_array[unique_j];// gamma_box_count_list[gamma];
-                int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);//alpha_unique_number_array[unique_j];
-                k2 = count_x_max;
-                k2_end = max_delta_value;
-                cur_bits = Math.min((unique_i_cur_k1 + k2) * getBitWith(block_size - 1), block_size + unique_i_cur_k1 + k2);
-                cur_bits += unique_i_cur_k1 * alpha;
-                cur_bits += k2;
-                if (unique_i_cur_k1 + k2 != block_size)
-                    cur_bits += (block_size - unique_i_cur_k1 - k2) * getBitWith(k2_end - k1_start - x_l_i - 2);
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start + x_l_i;
-                    final_k_end_value = k2_end;
-                }
-            }
-
-
-            int pow_2_alpha = (int) pow(2, alpha);
-            // lower: [x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-            // upper: (x_max - 2^{gamma}, x_max - 2^{gamma-1}]:  k2_end - gap_gamma, k2_end
-
-
-            int cur_k1 = k1; //count[x_min, x_min+2^{alpha-1}]
-
-            // lower: (x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-            // upper:  (x_max - 2^{gamma}, x_max - 2^{gamma-1}]:  k2_end - gap_gamma, k2_end
-            // gamma size : x_min+2^{alpha} <= x_max - 2^{gamma} => 2^{gamma} <= x_max - 2^{alpha}
-            int gamma_size = (int) (log(max_delta_value - (int) pow(2, alpha)) / log(2));
-
-            int max_pow_2_lambda = (int) pow(2, lambda_0);
-            int max_lambda = lambda_0;
-            int cur_k2 = k2; // count(x_max)
-            int gamma_i = 0;
-            for (; gamma_i < num_of_gamma_list; gamma_i++) {
-                int gamma = gamma_list[gamma_i];
-                if(gamma > gamma_size){
-                    break;
-                }
-
-
-                // k1: count[x_min,x_min+2^{alpha-1}]
-
-                gap_gamma = (int) pow(2, gamma - 1);
-                k2_end = max_delta_value - gap_gamma;
-                cur_group_gamma = groupU[gamma]; // (x_max - 2^{gamma}, x_max - 2^{gamma-1})
-                int gamma_value_count = cur_group_gamma.count;
-                gamma_sorted = cur_group_gamma.sorted_value_list;
-                gamma_unique_number = cur_group_gamma.unique_number;
-
-
-                int pow_2_gamma = gap_gamma*2;
-
-                // prop 5.7
-
-                int cur_k1_start = k1_start + gap_alpha - 1;
-                int cur_k2_end = k2_end - gap_gamma + 1;
-                int cur_k2_start_of_lambda = cur_k2 + gamma_value_count;// count[x_max - 2^{gamma}+1, x_max]
-                int cur_k1_start_of_lambda = k1 + alpha_value_count; // count[x_min, 2^{alpha}-1]
-
-                cur_bits = 0;
-                cur_bits +=  Math.min((cur_k1_start_of_lambda + cur_k2_start_of_lambda) * lambda_0, block_size + cur_k1_start_of_lambda + cur_k2_start_of_lambda); // (lambda * (cur_cur_k1 + cur_k2_start_of_lambda) + zeta);
-                cur_bits += (cur_k1_start_of_lambda * alpha);
-                cur_bits += (cur_k2_start_of_lambda * gamma);
-                cur_bits += ((block_size - cur_k1_start_of_lambda - cur_k2_start_of_lambda) * getBitWith(cur_k2_end - cur_k1_start - 2));
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = cur_k1_start;
-                    final_k_end_value = cur_k2_end;
-                }
-
-                // prop 5.4
-                int prop_5_4_k1 = cur_k1 + alpha_value_count; //count[x_min, x_min+2^{alpha}-1]
-
-                cur_bits = 0;
-                cur_bits += Math.min((prop_5_4_k1 + cur_k2) * lambda_0, block_size + prop_5_4_k1 + cur_k2); //(lambda * (prop_5_4_k1 + prop_5_4_k2) + zeta);
-                cur_bits += (prop_5_4_k1 * alpha);
-                cur_bits += (cur_k2 * gamma);
-                cur_bits += ((block_size - prop_5_4_k1 - cur_k2) * getBitWith(k2_end - k1_start - gap_alpha  - 1));
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start + gap_alpha - 1;
-                    final_k_end_value = k2_end;
-                }
-
-                // prop 5.5
-                int prop_5_5_k2 = cur_k2 + gamma_value_count; // count[x_max - 2^{gamma}+1,x_max}
-
-                cur_bits = 0;
-                cur_bits += Math.min((cur_k1 + prop_5_5_k2) * lambda_0, block_size + cur_k1 + prop_5_5_k2);// (lambda * (prop_5_5_k1 + prop_5_5_k2) + zeta);
-                cur_bits += (cur_k1 * alpha);
-                cur_bits += (prop_5_5_k2 * gamma);
-                cur_bits += ((block_size - cur_k1 - prop_5_5_k2) * getBitWith(k2_end - gap_gamma - k1_start - 1));
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start;
-                    final_k_end_value = k2_end - gap_gamma + 1;
-                }
-
-                // prop 5.6
-
-                cur_bits = 0;
-                cur_bits += Math.min((cur_k1 + cur_k2) * lambda_0, block_size + cur_k1 + cur_k2);//(lambda * (prop_5_6_k1 + prop_5_6_k2) + zeta);
-                cur_bits += (cur_k1 * alpha);
-                cur_bits += (cur_k2 * gamma);
-                cur_bits += ((block_size - cur_k1 - cur_k2) * getBitWith(k2_end - k1_start - 2));
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start;
-                    final_k_end_value = k2_end;
-                }
-
-
-
-                if ((max_pow_2_lambda + 1) * pow_2_alpha + pow_2_gamma <= max_delta_value
-                        && pow_2_alpha + (max_pow_2_lambda + 1) * pow_2_gamma <= max_delta_value) {
-
-
-                }
-                else {
-
-                    // lower: (x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-                    // upper:  (x_max - 2^{gamma}, x_max - 2^{gamma-1}):  k2_end - gap_gamma, k2_end
-                    // beta: getBitWidth(x_max - 2^{gamma} -(x_min+2^{alpha})) to getBitWidth(x_max - 2^{gamma-1}-(x_min+2^{alpha-1}) )
-                    int min_beta = getBitWith(max_delta_value-pow_2_gamma-pow_2_alpha);
-                    int max_beta = getBitWith(k2_end-k1_start);
-
-
-
-                    for(int beta = min_beta;beta <= max_beta;beta++) {
-                        int pow_2_beta = (int) pow(2, beta);
-                        if (beta >= alpha + max_lambda && beta <= gamma + 1 ){
-                            if(pow_2_beta + pow_2_alpha + gap_gamma >= max_delta_value){
-
-                            }else {
-                                int cur_cur_k1;
-                                for (int unique_j = 0; unique_j < alpha_unique_number; unique_j++) {
-                                    cur_cur_k1 = cur_k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);//alpha_unique_count_array[unique_j];// gamma_box_count_list[gamma];
-                                    int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);//alpha_unique_number_array[unique_j];
-
-                                    int cur_cur_k2 ; // count[x_max - 2^{gamma-1}, x_max]
-
-                                    int x_u_i_start =  Math.min(Math.max(0, k2_end - ( pow_2_beta + k1_start + x_l_i + 2)),gap_gamma-1);
-                                    int x_u_i_end = Math.max(0,Math.min(k2_end -( pow_2_beta/2 + k1_start + x_l_i + 2),gap_gamma));
-                                    int unique_s = cur_group_gamma.invert[x_u_i_start];
-                                    int unique_e = cur_group_gamma.invert[x_u_i_end];
-
-
-
-                                    for (int unique_i = unique_s; unique_i < unique_e; unique_i++) {
-                                        int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);//<=x_u_i_end
-
-                                        cur_cur_k2 = cur_k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-
-                                        cur_bits = 0;
-                                        cur_bits += Math.min((cur_cur_k1 + cur_cur_k2) * lambda_0, block_size + cur_cur_k1 + cur_cur_k2);
-                                        // (lambda * (cur_k1_start_of_lambda + cur_cur_k2) + zeta); // Math.min((cur_k1 + cur_cur_k2) * getBitWith(block_size - 1), block_size + cur_k1 + cur_k2);
-                                        cur_bits += cur_cur_k1 * alpha;
-                                        if (cur_cur_k1 + cur_cur_k2 != block_size)
-                                            cur_bits += (block_size - cur_cur_k1 - cur_cur_k2) *
-                                                    getBitWith(k2_end - x_u_i - k1_start - x_l_i - 2);
-                                        cur_bits += cur_cur_k2 * gamma;
-                                        if (cur_bits < min_bits) {
-                                            min_bits = cur_bits;
-                                            final_k_start_value = k1_start + x_l_i;
-                                            final_k_end_value = k2_end - x_u_i;
-                                        }
-
-                                    }
-                                }
-                            }
-                        }else if (beta <= alpha + 1 && beta >= gamma + max_lambda) {
-                            if(pow_2_beta + gap_alpha + pow_2_gamma >= max_delta_value){
-
-                            }else {
-                                int cur_cur_k1;
-                                for (int unique_j = 0; unique_j < alpha_unique_number; unique_j++) {
-                                    cur_cur_k1 = cur_k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);//alpha_unique_count_array[unique_j];// gamma_box_count_list[gamma];
-                                    int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);//alpha_unique_number_array[unique_j];
-
-                                    int cur_cur_k2 ; // count[x_max - 2^{gamma-1}, x_max]
-
-                                    int x_u_i_start =  Math.min(Math.max(0, k2_end - ( pow_2_beta + k1_start + x_l_i + 2)),gap_gamma-1);
-                                    int x_u_i_end = Math.max(0,Math.min(k2_end -( pow_2_beta/2 + k1_start + x_l_i + 2),gap_gamma));
-                                    int unique_s = cur_group_gamma.invert[x_u_i_start];
-                                    int unique_e = cur_group_gamma.invert[x_u_i_end];
-
-
-
-                                    for (int unique_i = unique_s; unique_i < unique_e; unique_i++) {
-                                        int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);//<=x_u_i_end
-                                        cur_cur_k2 = cur_k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-
-                                        cur_bits = 0;
-                                        cur_bits += Math.min((cur_cur_k1 + cur_cur_k2) * lambda_0, block_size + cur_cur_k1 + cur_cur_k2);
-                                        // (lambda * (cur_k1_start_of_lambda + cur_cur_k2) + zeta); // Math.min((cur_k1 + cur_cur_k2) * getBitWith(block_size - 1), block_size + cur_k1 + cur_k2);
-                                        cur_bits += cur_cur_k1 * alpha;
-                                        if (cur_cur_k1 + cur_cur_k2 != block_size)
-                                            cur_bits += (block_size - cur_cur_k1 - cur_cur_k2) *
-                                                    getBitWith(k2_end - x_u_i - k1_start - x_l_i - 2);
-                                        cur_bits += cur_cur_k2 * gamma;
-                                        if (cur_bits < min_bits) {
-                                            min_bits = cur_bits;
-                                            final_k_start_value = k1_start + x_l_i;
-                                            final_k_end_value = k2_end - x_u_i;
-                                        }
-
-                                    }
-                                }
-                            }
-                        } else if (beta <= alpha + 1 && beta <= gamma + 1) {
-                            if(pow_2_beta + gap_alpha + gap_gamma > max_delta_value){
-
-                            }else {
-                                int cur_cur_k1;
-                                for (int unique_j = 0; unique_j < alpha_unique_number; unique_j++) {
-                                    cur_cur_k1 = cur_k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);//alpha_unique_count_array[unique_j];// gamma_box_count_list[gamma];
-                                    int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);//alpha_unique_number_array[unique_j];
-                                    int cur_cur_k2 ; // count[x_max - 2^{gamma-1}, x_max]
-
-                                    int x_u_i_start =  Math.min(Math.max(0, k2_end - ( pow_2_beta + k1_start + x_l_i + 2)),gap_gamma-1);
-                                    int x_u_i_end = Math.max(0,Math.min(k2_end -( pow_2_beta/2 + k1_start + x_l_i + 2),gap_gamma));
-                                    int unique_s = cur_group_gamma.invert[x_u_i_start];
-                                    int unique_e = cur_group_gamma.invert[x_u_i_end];
-
-
-
-                                    for (int unique_i = unique_s; unique_i < unique_e; unique_i++) {
-                                        int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);//<=x_u_i_end
-                                        cur_cur_k2 = cur_k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-
-                                        cur_bits = 0;
-                                        cur_bits += Math.min((cur_cur_k1 + cur_cur_k2) * lambda_0, block_size + cur_cur_k1 + cur_cur_k2);
-                                        // (lambda * (cur_k1_start_of_lambda + cur_cur_k2) + zeta); // Math.min((cur_k1 + cur_cur_k2) * getBitWith(block_size - 1), block_size + cur_k1 + cur_k2);
-                                        cur_bits += cur_cur_k1 * alpha;
-                                        if (cur_cur_k1 + cur_cur_k2 != block_size)
-                                            cur_bits += (block_size - cur_cur_k1 - cur_cur_k2) *
-                                                    getBitWith(k2_end - x_u_i - k1_start - x_l_i - 2);
-                                        cur_bits += cur_cur_k2 * gamma;
-                                        if (cur_bits < min_bits) {
-                                            min_bits = cur_bits;
-                                            final_k_start_value = k1_start + x_l_i;
-                                            final_k_end_value = k2_end - x_u_i;
-                                        }
-
-                                    }
-                                }
-                            }
-                        }else{
-                            int cur_cur_k1;
-                            for (int unique_j = 0; unique_j < alpha_unique_number; unique_j++) {
-                                cur_cur_k1 = cur_k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);//alpha_unique_count_array[unique_j];// gamma_box_count_list[gamma];
-                                int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);//alpha_unique_number_array[unique_j];
-
-                                int cur_cur_k2 ; // count[x_max - 2^{gamma-1}, x_max]
-
-                                int x_u_i_start =  Math.min(Math.max(0, k2_end - ( pow_2_beta + k1_start + x_l_i + 2)),gap_gamma-1);
-                                int x_u_i_end = Math.max(0,Math.min(k2_end -( pow_2_beta/2 + k1_start + x_l_i + 2),gap_gamma));
-                                int unique_s = cur_group_gamma.invert[x_u_i_start];
-                                int unique_e = cur_group_gamma.invert[x_u_i_end];
-
-
-
-                                for (int unique_i = unique_s; unique_i < unique_e; unique_i++) {
-                                    int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);//<=x_u_i_end
-                                    cur_cur_k2 = cur_k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-
-                                    cur_bits = 0;
-                                    cur_bits += Math.min((cur_cur_k1 + cur_cur_k2) * lambda_0, block_size + cur_cur_k1 + cur_cur_k2);
-                                    // (lambda * (cur_k1_start_of_lambda + cur_cur_k2) + zeta); // Math.min((cur_k1 + cur_cur_k2) * getBitWith(block_size - 1), block_size + cur_k1 + cur_k2);
-                                    cur_bits += cur_cur_k1 * alpha;
-                                    if (cur_cur_k1 + cur_cur_k2 != block_size)
-                                        cur_bits += (block_size - cur_cur_k1 - cur_cur_k2) *
-                                                getBitWith(k2_end - x_u_i - k1_start - x_l_i - 2);
-                                    cur_bits += cur_cur_k2 * gamma;
-                                    if (cur_bits < min_bits) {
-                                        min_bits = cur_bits;
-                                        final_k_start_value = k1_start + x_l_i;
-                                        final_k_end_value = k2_end - x_u_i;
-                                    }
-
-                                }
-                            }
-                        }
-
-                    }
-
-                }
-
-                cur_k2 = cur_k2 + gamma_value_count; // += count(x_max - 2^{gamma}, x_max - 2^{gamma-1})
-
-                if(cur_k1+cur_k2>boundary_index){
-                    max_pow_2_lambda = (int) pow(2, 1);
-                    max_lambda = 1;
-                }
-
-            }
-
-
-            k2 = cur_k2;
-
-            // gamma:  gamma_size+1 to ....
-            // gamma size : x_min+2^{alpha} <= x_max - 2^{gamma} => 2^{gamma} <= x_max - 2^{alpha}
-            //k2_end = x_max - 2^{gamma-1} ; gamma : 1 to gamma_size
-            // lower: [x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-            // upper:  (x_max - 2^{gamma}, x_max - 2^{gamma-1}]
-
-
-            for (; gamma_i < num_of_gamma_list; gamma_i++) {
-                int gamma = gamma_list[gamma_i];
-                gap_gamma = (int) pow(2, gamma-1);
-                cur_group_gamma = groupU[gamma];
-                k2_end = max_delta_value - gap_gamma;
-
-                if(k2_end <= k1_start){
-                    break;
-                }
-                int gamma_value_count = cur_group_gamma.count;
-
-                gamma_unique_number = cur_group_gamma.unique_number;
-                gamma_sorted = cur_group_gamma.sorted_value_list;
-
-                for (int unique_j=0;unique_j<alpha_unique_number;unique_j++) {
-                    int unique_j_cur_k1 = cur_k1+ cur_group_alpha.getCount(alpha_sorted[unique_j]);// gamma_box_count_list[gamma];
-                    int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);
-                    int x_u_i_end = Math.max(0,Math.min(k2_end - k1_start - x_l_i,gap_gamma));
-                    int unique_e = cur_group_gamma.invert[x_u_i_end];
-                    for (int unique_i = 0; unique_i < unique_e; unique_i++) {
-                        int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);
-                        int unique_i_cur_k2 = cur_k2+ cur_group_gamma.getCount(gamma_sorted[unique_i]);
-                        cur_bits = 0;
-                        cur_bits += Math.min((unique_j_cur_k1 + unique_i_cur_k2) * getBitWith(block_size - 1), block_size + unique_j_cur_k1 + unique_i_cur_k2);
-                        cur_bits += unique_j_cur_k1*alpha;
-                        if (unique_j_cur_k1 + unique_i_cur_k2 != block_size)
-                            cur_bits += (block_size - unique_j_cur_k1 - unique_i_cur_k2) *
-                                    getBitWith(k2_end - x_u_i-k1_start-x_l_i - 2);
-                        cur_bits += unique_i_cur_k2 * gamma;
-                        if (cur_bits < min_bits) {
-                            min_bits = cur_bits;
-                            final_k_start_value = k1_start + x_l_i;
-                            final_k_end_value = k2_end - x_u_i;
-                        }
-                    }
-
-                }
-                cur_k2 += gamma_value_count;
-            }
-
-            k1 += alpha_value_count;
-        }
-        // -------------------[x_min+2^{alpha-1},x_min+2^{alpha})-----------------
-
-
-        //  [x_min+2^{alpha_size-1},x_max)
-        // ----------------[x_min+2^{alpha_size-1},x_max)--------------------
-
-        // x_min+2^{alpha_size-1} < x_max && x_min+2^{alpha_size} >= x_max
-        // alpha_size - 1  < log(xmax) && alpha_size >= log(xmax)
-        // alpha_size = \lceil log(x_max-1+1) \rceil
-
-        alpha_size = alpha_list[num_of_alpha_list-1];
-        int gap_alpha = (int) pow(2,alpha_size-1);
-        k1_start = gap_alpha;
-        GroupL cur_group_alpha = groupL[alpha_size];
-        int alpha_value_count = cur_group_alpha.count;
-
-
-        // lower: [x_min+2^{alpha_size-1},x_max)
-        // ----------------- [x_min+2^{alpha_size-1},x_max)----------------------
-        long[] alpha_sorted = cur_group_alpha.sorted_value_list;
-        int alpha_unique_number = cur_group_alpha.unique_number;
-
-        int x_l_i_end = max_delta_value - k1_start; // [1, x_max - x_min+2^{alpha_size-1})
-        for (int unique_j=0;unique_j<alpha_unique_number;unique_j++) {
-
-            int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);
-            if (x_l_i >= x_l_i_end) {
-                break;
-            }
-            int unique_j_cur_k1 = k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);// gamma_box_count_list[gamma];
-
-            // lower: [x_min+2^{alpha_size-1},x_max) : k1_start, k1_start + gap_alpha
-            // upper: x_max
-            k2 = count_x_max;
-            k2_end = max_delta_value;
-
-            cur_bits = 0;
-            cur_bits += Math.min((unique_j_cur_k1 + k2) * getBitWith(block_size - 1), block_size + unique_j_cur_k1 + k2);
-            cur_bits += unique_j_cur_k1 * alpha_size;
-            cur_bits += k2;
-            if (unique_j_cur_k1 + k2 != block_size)
-                cur_bits += (block_size - unique_j_cur_k1 - k2) * getBitWith(k2_end - k1_start - x_l_i - 2);
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k1_start + x_l_i;
-                final_k_end_value = k2_end;
-            }
-        }
-        // lower: (x_min+2^{alpha_size-1},x_max)
-        // upper: (x_max - 2^{gamma}, x_max)
-        // gamma:  gamma_size+1 to ....
-        // lower: (x_min+2^{alpha_size-1},x_max) : k1_start, k1_start + gap_alpha
-        // upper:  (x_max - 2^{gamma}, x_max - 2^{gamma-1}] : k2_end - gap_gamma, k2_end
-
-        int max_pow_2_lambda = (int) pow(2, lambda_0);
-        int max_lambda = lambda_0;
-        for (int gamma_i = 0; gamma_i < num_of_gamma_list; gamma_i++) {
-            int gamma =  gamma_list[gamma_i];
-            gap_gamma = (int) pow(2, gamma-1);
-            k2_end = max_delta_value - gap_gamma; // x_max - 2^{gamma} ;
-
-            if(k2_end<=k1_start){
-                break;
-            }
-            cur_group_gamma = groupU[gamma];
-
-            int gamma_value_count = cur_group_gamma.count;
-            gamma_sorted = cur_group_gamma.sorted_value_list;
-            gamma_unique_number = cur_group_gamma.unique_number;
-
-            int pow_2_gamma = gap_gamma*2;
-
-
-            for (int unique_j=0;unique_j<alpha_unique_number;unique_j++) {
-                int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);
-                int x_u_i_end = k2_end - k1_start - x_l_i; // x_u_i>= k2_end - k1_start - x_l_i; break ;
-
-                if(x_u_i_end <= 0 || x_l_i >= x_l_i_end){
-                    break;
-                }
-
-                int unique_j_cur_k1 = k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);// gamma_box_count_list[gamma];
-                x_u_i_end = Math.min(x_u_i_end,gap_gamma - 1);
-                int unique_e = cur_group_gamma.invert[x_u_i_end];
-
-
-                for(int unique_i=0;unique_i<unique_e;unique_i++){
-
-                    int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);
-                    int unique_i_cur_k2 = k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-                    cur_bits = 0;
-                    cur_bits += Math.min((unique_j_cur_k1 + unique_i_cur_k2) * getBitWith(block_size - 1), block_size + unique_j_cur_k1 + unique_i_cur_k2);
-                    cur_bits += unique_j_cur_k1*alpha_size;
-                    if (unique_j_cur_k1 + unique_i_cur_k2 != block_size)
-                        cur_bits += (block_size - unique_j_cur_k1 - unique_i_cur_k2) *
-                                getBitWith(k2_end - x_u_i-k1_start-x_l_i - 2);
-                    cur_bits += unique_i_cur_k2 * gamma;
-                    if (cur_bits < min_bits) {
-                        min_bits = cur_bits;
-                        final_k_start_value = k1_start + x_l_i;
-                        final_k_end_value = k2_end - x_u_i;
-                    }
-                }
-            }
-
-
-
-
-            k2 += gamma_value_count;
-
-
-
-        }
-        // ------------------ [x_min+2^{alpha_size-1},x_max)--------------------
-
-
-
-        encode_pos = BOSEncodeBits(ts_block_delta, init_block_size, final_k_start_value, final_k_end_value, max_delta_value,
-                min_delta, repeat_count, encode_pos, cur_byte);
-
-        return encode_pos;
-    }
-
-    public static int BOSEncoder(
-            int[] data, int block_size, byte[] encoded_result) {
-
-        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;
-
-        for (int i = 0; i < block_num; i++) {
-            encode_pos = BOSBlockEncoder(data, i, block_size, block_size, encode_pos, encoded_result);
-        }
-
-        int remaining_length = length_all - block_num * block_size;
-        if (remaining_length <= 3) {
-            for (int i = remaining_length; i > 0; i--) {
-                int2Bytes(data[data.length - i], encode_pos, encoded_result);
-                encode_pos += 4;
-            }
-
-        } else {
-
-            int start = block_num * block_size;
-            int remaining = length_all - start;
-
-
-            encode_pos = BOSBlockEncoder(data, block_num, block_size, remaining, encode_pos, encoded_result);
-
-        }
-
-
-        return encode_pos;
-    }
-
-    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list, int init_block_size, int block_size, int[] value_pos_arr) {
-
-        int k_byte = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-        int k1_byte = (int) (k_byte % pow(2, 16));
-        int k1 = k1_byte / 2;
-        int final_alpha = k1_byte % 2;
-
-        int k2 = (int) (k_byte / pow(2, 16));
-
-
-        int min_delta = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int count_size = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        ArrayList<Integer> repeat_count = new ArrayList<>();
-        if (count_size != 0) {
-            ArrayList<Integer> repeat_count_result = new ArrayList<>();
-            repeat_count = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(init_block_size - 1), count_size, repeat_count_result);
-            decode_pos = repeat_count_result.get(0);
-
-        }
-
-        int cur_block_size = block_size;
-        for (int i = 1; i < count_size; i += 2) {
-            cur_block_size -= (repeat_count.get(i) - 1);
-        }
-
-        int final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        int left_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-        int right_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal;
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-
-        if (final_alpha == 0) { // 0
-            int bitmap_bytes = (int) Math.ceil((double) (cur_block_size + k1 + k2) / (double) 8);
-            for (int i = 0; i < bitmap_bytes; i++) {
-                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
-                decode_pos += 1;
-            }
-            int bitmap_outlier_i = 0;
-            int remaining_bits = 8;
-            int tmp = bitmap_outlier.get(bitmap_outlier_i);
-            bitmap_outlier_i++;
-            int i = 0;
-            while (i < cur_block_size) {
-                if (remaining_bits > 1) {
-                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
-                    remaining_bits -= 1;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                    if (remaining_bits == 0) {
-                        remaining_bits = 8;
-                        if (bitmap_outlier_i >= bitmap_bytes) break;
-                        tmp = bitmap_outlier.get(bitmap_outlier_i);
-                        bitmap_outlier_i++;
-                    }
-                } else if (remaining_bits == 1) {
-                    int bit_i = tmp & 0x1;
-                    remaining_bits = 8;
-                    if (bitmap_outlier_i >= bitmap_bytes) break;
-                    tmp = bitmap_outlier.get(bitmap_outlier_i);
-                    bitmap_outlier_i++;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                }
-                i++;
-            }
-        } else {
-
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(cur_block_size - 1), k1, decode_pos_result_left);
-            decode_pos = (decode_pos_result_left.get(0));
-
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(cur_block_size - 1), k2, decode_pos_result_right);
-            decode_pos = (decode_pos_result_right.get(0));
-
-        }
-
-
-        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
-        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, cur_block_size - k1 - k2, decode_pos_normal);
-
-        decode_pos = decode_pos_normal.get(0);
-        if (k1 != 0) {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
-
-            decode_pos = decode_pos_result_left.get(0);
-        }
-        if (k2 != 0) {
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
-            decode_pos = decode_pos_result_right.get(0);
-        }
-        int left_outlier_i = 0;
-        int right_outlier_i = 0;
-        int normal_i = 0;
-        int pre_v;
-        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
-
-        int cur_i = 0;
-        int repeat_i = 0;
-        for (int i = 0; i < cur_block_size; i++) {
-
-            int current_delta;
-            if (left_outlier_i >= k1) {
-                if (right_outlier_i >= k2) {
-                    current_delta = final_normal.get(normal_i) + final_k_start_value + 1;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta = final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta = final_normal.get(normal_i) + final_k_start_value + 1;
-                    normal_i++;
-                }
-            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
-                current_delta = final_left_outlier.get(left_outlier_i);
-                left_outlier_i++;
-            } else {
-
-                if (right_outlier_i >= k2) {
-                    current_delta = final_normal.get(normal_i) + final_k_start_value + 1;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta = final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta = final_normal.get(normal_i) + final_k_start_value + 1;
-                    normal_i++;
-                }
-            }
-            pre_v = current_delta + min_delta;
-            if (repeat_i < count_size) {
-                if (cur_i == repeat_count.get(repeat_i)) {
-                    cur_i += (repeat_count.get(repeat_i + 1));
-
-                    for (int j = 0; j < repeat_count.get(repeat_i + 1); j++) {
-                        value_list[value_pos_arr[0]] = pre_v;
-                        value_pos_arr[0]++;
-                    }
-                    repeat_i += 2;
-                } else {
-                    cur_i++;
-                    value_list[value_pos_arr[0]] = pre_v;
-                    value_pos_arr[0]++;
-                }
-            } else {
-                cur_i++;
-                value_list[value_pos_arr[0]] = pre_v;
-                value_pos_arr[0]++;
-            }
-        }
-        return decode_pos;
-    }
-
-    public static void BOSDecoder(byte[] encoded) {
-
-        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[] value_list = new int[length_all + block_size];
-        int[] value_pos_arr = new int[1];
-
-        for (int k = 0; k < block_num; k++) {
-            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list, block_size, block_size, value_pos_arr);
-        }
-
-        if (remain_length <= 3) {
-            for (int i = 0; i < remain_length; i++) {
-                int value_end = bytes2Integer(encoded, decode_pos, 4);
-                decode_pos += 4;
-                value_list[value_pos_arr[0]] = value_end;
-                value_pos_arr[0]++;
-            }
-        } else {
-            BOSBlockDecoder(encoded, decode_pos, value_list, block_size, remain_length, value_pos_arr);
-        }
-    }
-
-    public static void main(@org.jetbrains.annotations.NotNull String[] args) throws IOException {
-        String parent_dir = "/Users/xiaojinzhao/Desktop/encoding-outlier/";// your data path
-        String output_parent_dir = parent_dir + "vldb/compression_ratio/rle_pruning";
-        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<>();
-        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");
-
-        for (String value : dataset_name) {
-            input_path_list.add(input_parent_dir + value);
-            dataset_block_size.add(1024);
-        }
-
-        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(2048);
-        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
-//        dataset_block_size.add(2048);
-        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(1024);
-        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
-//        dataset_block_size.add(1024);
-        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
-//        dataset_block_size.add(1024);
-
-        int repeatTime2 = 100;
-        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
-
-            String inputPath = input_path_list.get(file_i);
-            System.out.println(inputPath);
-            String Output = output_path_list.get(file_i);
-
-            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<Integer> data1 = new ArrayList<>();
-                ArrayList<Integer> data2 = new ArrayList<>();
-
-
-                loader.readHeaders();
-                while (loader.readRecord()) {
-                    data1.add(Integer.valueOf(loader.getValues()[0]));
-                    data2.add(Integer.valueOf(loader.getValues()[1]));
-                }
-
-                inputStream.close();
-                int[] data2_arr = new int[data1.size()];
-                for (int i = 0; i < data2.size(); i++) {
-                    data2_arr[i] = data2.get(i);
-                }
-                byte[] encoded_result = new byte[data2_arr.length * 4];
-                long encodeTime = 0;
-                long decodeTime = 0;
-                double ratio = 0;
-                double compressed_size = 0;
-
-
-                int length = 0;
-
-                long s = System.nanoTime();
-                for (int repeat = 0; repeat < repeatTime2; repeat++) {
-                    length = BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
-                }
-
-                long e = System.nanoTime();
-                encodeTime += ((e - s) / repeatTime2);
-                compressed_size += length;
-                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
-                ratio += ratioTmp;
-                s = System.nanoTime();
-                for (int repeat = 0; repeat < repeatTime2; repeat++)
-                    BOSDecoder(encoded_result);
-                e = System.nanoTime();
-                decodeTime += ((e - s) / repeatTime2);
-
-
-                String[] record = {
-                        f.toString(),
-                        "RLE+BOS-P",
-                        String.valueOf(encodeTime),
-                        String.valueOf(decodeTime),
-                        String.valueOf(data1.size()),
-                        String.valueOf(compressed_size),
-                        String.valueOf(ratio)
-                };
-                writer.writeRecord(record);
-                System.out.println(ratio);
-
-            }
-            writer.close();
-
-
-        }
-    }
-
-}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSLTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSLTest.java
deleted file mode 100644
index 536e82d..0000000
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSLTest.java
+++ /dev/null
@@ -1,1214 +0,0 @@
-package org.apache.iotdb.tsfile.encoding;
-
-import com.csvreader.CsvReader;
-import com.csvreader.CsvWriter;
-import org.jetbrains.annotations.NotNull;
-
-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.ArrayList;
-
-import static java.lang.Math.pow;
-
-public class RLEBOSLTest {
-
-    public static int getBitWith(int num) {
-        if (num == 0) return 1;
-        else return 32 - Integer.numberOfLeadingZeros(num);
-    }
-    public static int getCount(long long1, int mask) {
-        return ((int) (long1 & mask));
-    }
-    public static int getUniqueValue(long long1, int left_shift) {
-        return ((int) ((long1) >> left_shift));
-    }
-
-
-    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 ;
-                }
-            }
-        }
-
-    }
-
-    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 int[] getAbsDeltaTsBlock(
-            int[] ts_block,
-            ArrayList<Integer> min_delta,
-            ArrayList<Integer> repeat_count) {
-        int[] ts_block_delta = new int[ts_block.length];
-
-
-        int value_delta_min = Integer.MAX_VALUE;
-        for (Integer integer : ts_block) {
-            if (integer < value_delta_min) value_delta_min = integer;
-        }
-        int repeat_i = 0;
-        int pre_delta = ts_block[0] - value_delta_min;
-        int pre_count = 1;
-        min_delta.add(value_delta_min);
-        int block_size =ts_block.length;
-
-        int ts_block_delta_i = 0;
-        for (int i = 1; i < block_size; i++) {
-            int delta = ts_block[i] - value_delta_min;
-            if (delta == pre_delta) {
-                pre_count++;
-            } else {
-                if (pre_count > 7) {
-                    repeat_count.add(repeat_i);
-                    repeat_count.add(pre_count);
-                    ts_block_delta[ts_block_delta_i]=pre_delta;
-                    ts_block_delta_i ++;
-                } else {
-                    for (int j = 0; j < pre_count; j++){
-                        ts_block_delta[ts_block_delta_i] =pre_delta;
-                        ts_block_delta_i++;
-                    }
-
-                }
-                pre_count = 1;
-                repeat_i = i;
-            }
-            pre_delta = delta;
-        }
-        for (int j = 0; j < pre_count; j++){
-            ts_block_delta[ts_block_delta_i] =pre_delta;
-            ts_block_delta_i++;
-        }
-        min_delta.add(ts_block_delta_i);
-        int[] new_ts_block_delta = new int[ts_block_delta_i];
-        System.arraycopy(ts_block_delta, 0, new_ts_block_delta, 0, ts_block_delta_i);
-
-        return new_ts_block_delta;
-    }
-
-    public static int[]  getAbsDeltaTsBlock(
-            int[] ts_block,
-            int i,
-            int block_size,
-            int remaining,
-            int[] min_delta,
-            ArrayList<Integer> repeat_count) {
-        int[] ts_block_delta = new int[ts_block.length];
-
-        int value_delta_min = Integer.MAX_VALUE;
-        int value_delta_max = Integer.MIN_VALUE;
-        int base = i*block_size;
-        int end = i*block_size+remaining;
-        for (int j = base; j < end; j++) {
-
-            int integer = ts_block[j];
-            if (integer < value_delta_min) value_delta_min = integer;
-            if (integer > value_delta_max) {
-                value_delta_max = integer;
-            }
-        }
-        int pre_delta = ts_block[i*block_size]-value_delta_min;
-        int pre_count = 1;
-
-        min_delta[0]=(value_delta_min);
-        int repeat_i = 0;
-        int ts_block_delta_i = 0;
-        for (int j = base+1; j < end; j++) {
-            int delta = ts_block[j]-value_delta_min;
-            if(delta == pre_delta){
-                pre_count ++;
-            } else {
-                if(pre_count>7){
-                    repeat_count.add(repeat_i);
-                    repeat_count.add(pre_count);
-                    ts_block_delta[ts_block_delta_i]=pre_delta;
-                    ts_block_delta_i ++;
-                } else{
-                    for (int k = 0; k < pre_count; k++){
-                        ts_block_delta[ts_block_delta_i] =pre_delta;
-                        ts_block_delta_i++;
-                    }
-                }
-                pre_count =1;
-                repeat_i = j - i*block_size;
-            }
-            pre_delta = delta;
-
-        }
-        for (int j = 0; j < pre_count; j++){
-            ts_block_delta[ts_block_delta_i] =pre_delta;
-            ts_block_delta_i++;
-        }
-        min_delta[1]=(ts_block_delta_i);
-        min_delta[2]=(value_delta_max-value_delta_min);
-        int[] new_ts_block_delta = new int[ts_block_delta_i];
-        System.arraycopy(ts_block_delta, 0, new_ts_block_delta, 0, ts_block_delta_i);
-
-        return new_ts_block_delta;
-    }
-
-
-
-    public static int encodeOutlier2Bytes(
-            ArrayList<Integer> ts_block_delta,
-            int bit_width,
-            int encode_pos,  byte[] encoded_result) {
-
-        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
-
-        int n_k = ts_block_delta.size();
-        int n_k_b = n_k / 8;
-        long cur_remaining = 0; // encoded int
-        int cur_number_bits = 0; // the bit width used of encoded int
-        for (int i = n_k_b * 8; i < n_k; i++) {
-            long cur_value = ts_block_delta.get(i);
-            int cur_bit_width = bit_width; // remaining bit width of current value
-
-            if (cur_number_bits + bit_width >= 32) {
-                cur_remaining <<= (32 - cur_number_bits);
-                cur_bit_width = bit_width - 32 + cur_number_bits;
-                cur_remaining += ((cur_value >> cur_bit_width));
-                long2intBytes(cur_remaining,encode_pos,encoded_result);
-                encode_pos += 4;
-
-                cur_remaining = 0;
-                cur_number_bits = 0;
-            }
-
-            cur_remaining <<= cur_bit_width;
-            cur_number_bits += cur_bit_width;
-            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width));
-        }
-        cur_remaining <<= (32 - cur_number_bits);
-        long2intBytes(cur_remaining,encode_pos,encoded_result);
-        encode_pos += 4;
-        return encode_pos;
-
-    }
-
-
-    public static ArrayList<Integer> decodeOutlier2Bytes(
-            byte[] encoded,
-            int decode_pos,
-            int bit_width,
-            int length,
-            ArrayList<Integer> encoded_pos_result
-    ) {
-
-        int n_k_b = length / 8;
-        int remaining = length - n_k_b * 8;
-        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
-        decode_pos += n_k_b * bit_width;
-
-        ArrayList<Long> int_remaining = new ArrayList<>();
-        int int_remaining_size = remaining * bit_width / 32 + 1;
-        for (int j = 0; j < int_remaining_size; j++) {
-
-            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
-            decode_pos += 4;
-        }
-
-        int cur_remaining_bits = 32; // remaining bit width of current value
-        long cur_number = int_remaining.get(0);
-        int cur_number_i = 1;
-        for (int i = n_k_b * 8; i < length; i++) {
-            if (bit_width < cur_remaining_bits) {
-                int tmp = (int) (cur_number >> (32 - bit_width));
-                result_list.add(tmp);
-                cur_number <<= bit_width;
-                cur_number &= 0xFFFFFFFFL;
-                cur_remaining_bits -= bit_width;
-            } else {
-                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
-                int remain_bits = bit_width - cur_remaining_bits;
-                tmp <<= remain_bits;
-
-                cur_number = int_remaining.get(cur_number_i);
-                cur_number_i++;
-                tmp += (cur_number >> (32 - remain_bits));
-                result_list.add(tmp);
-                cur_number <<= remain_bits;
-                cur_number &= 0xFFFFFFFFL;
-                cur_remaining_bits = 32 - remain_bits;
-            }
-        }
-        encoded_pos_result.add(decode_pos);
-        return result_list;
-    }
-
-    private static int BOSEncodeBits(int[] ts_block_delta,
-                                      int init_block_size,
-                                      int final_k_start_value,
-                                      int final_k_end_value,
-                                      int max_delta_value,
-                                      int[] min_delta,
-                                      ArrayList<Integer> repeat_count,
-                                      int encode_pos,
-                                      byte[] cur_byte) {
-        int block_size = ts_block_delta.length;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal = new ArrayList<>();
-        int k1 = 0;
-        int k2 = 0;
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-        int index_bitmap_outlier = 0;
-        int cur_index_bitmap_outlier_bits = 0;
-        for (int i = 0; i < block_size; i++) {
-            int cur_value = ts_block_delta[i];
-            if (cur_value < final_k_start_value) {
-                final_left_outlier.add(cur_value);
-                final_left_outlier_index.add(i);
-                if (cur_index_bitmap_outlier_bits % 8 != 7) {
-                    index_bitmap_outlier <<= 2;
-                    index_bitmap_outlier += 3;
-                    cur_index_bitmap_outlier_bits += 2;
-                } else {
-                    index_bitmap_outlier <<= 1;
-                    index_bitmap_outlier += 1;
-                    bitmap_outlier.add(index_bitmap_outlier);
-                    index_bitmap_outlier = 1;
-                    cur_index_bitmap_outlier_bits = 1;
-                }
-
-
-                k1++;
-
-
-            } else if (cur_value > final_k_end_value) {
-                final_right_outlier.add(cur_value - final_k_end_value);
-                final_right_outlier_index.add(i);
-                if (cur_index_bitmap_outlier_bits % 8 != 7) {
-                    index_bitmap_outlier <<= 2;
-                    index_bitmap_outlier += 2;
-                    cur_index_bitmap_outlier_bits += 2;
-                } else {
-                    index_bitmap_outlier <<= 1;
-                    index_bitmap_outlier += 1;
-                    bitmap_outlier.add(index_bitmap_outlier);
-                    index_bitmap_outlier = 0;
-                    cur_index_bitmap_outlier_bits = 1;
-                }
-                k2++;
-
-            } else {
-                final_normal.add(cur_value - final_k_start_value-1);
-                index_bitmap_outlier <<= 1;
-                cur_index_bitmap_outlier_bits += 1;
-            }
-            if (cur_index_bitmap_outlier_bits % 8 == 0) {
-                bitmap_outlier.add(index_bitmap_outlier);
-                index_bitmap_outlier = 0;
-            }
-        }
-        if (cur_index_bitmap_outlier_bits % 8 != 0) {
-
-            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
-
-            index_bitmap_outlier &= 0xFF;
-            bitmap_outlier.add(index_bitmap_outlier);
-        }
-        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
-
-        int k_byte = (k1 << 1);
-        k_byte += final_alpha;
-        k_byte += (k2 << 16);
-
-        int2Bytes(k_byte,encode_pos,cur_byte);
-        encode_pos += 4;
-
-        int2Bytes(min_delta[0],encode_pos,cur_byte);
-        encode_pos += 4;
-        int size = repeat_count.size();
-        intByte2Bytes(size,encode_pos,cur_byte);
-        encode_pos += 1;
-
-        if (size != 0)
-            encode_pos =encodeOutlier2Bytes(repeat_count, getBitWith(init_block_size-1),encode_pos,cur_byte);
-
-
-
-        int2Bytes(final_k_start_value,encode_pos,cur_byte);
-        encode_pos += 4;
-        int bit_width_final = getBitWith(final_k_end_value - final_k_start_value-2);
-        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
-        encode_pos += 1;
-        int left_bit_width = getBitWith(final_k_start_value);
-        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);
-        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        if (final_alpha == 0) {
-
-            for (int i : bitmap_outlier) {
-
-                intByte2Bytes(i,encode_pos,cur_byte);
-                encode_pos += 1;
-            }
-        } else {
-            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
-            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
-        }
-        encode_pos =encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
-        if (k1 != 0)
-            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
-        if (k2 != 0)
-            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
-        return encode_pos;
-
-    }
-
-
-
-    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size,int remaining, int encode_pos , byte[] cur_byte) {
-
-        ArrayList<Integer> repeat_count = new ArrayList<>();
-        int init_block_size = block_size;
-
-        int[] min_delta = new int[3];
-        int[]  ts_block_delta = getAbsDeltaTsBlock(ts_block,block_i, init_block_size,remaining, min_delta, repeat_count);
-        block_size = min_delta[1];
-
-
-        // RLE need to substitute
-        int max_delta_value = min_delta[2];
-        int max_bit = getBitWith(max_delta_value);
-        int[] alpha_count_list = new int[max_bit+1];//count(xmin) count(xmin + 1) count(xmin + 2)... count(xmin + 8) ... count(xmin + 2^(i - 1))
-        int[] alpha_box_count_list = new int[max_bit+1];// count(xmin, xmin + 1), count(xmin +1, xmin + 2)... count (xmin + 2^(i - 1), xmin + 2^i)
-        int[] gamma_count_list = new int[max_bit+1];//count(xmax) count(xmax - 1)... count(xmax - 2^(i - 1))
-        int[] gamma_box_count_list = new int[max_bit+1]; // count (xmax - 2^i, xmin - 2^(i-1))
-        for(int value:ts_block_delta){
-            if (value == 0){
-                alpha_count_list[0]++;
-            }
-            else if (value == pow(2,getBitWith(value)-1)){
-                alpha_count_list[getBitWith(value)]++;
-            }else {
-                alpha_box_count_list[getBitWith(value)]++;
-            }
-            if (value == max_delta_value){
-                gamma_count_list[0]++;
-            }
-            else if (max_delta_value - value == pow(2,getBitWith(max_delta_value-value)-1)){
-                gamma_count_list[getBitWith(max_delta_value-value)]++;
-            }else {
-                gamma_box_count_list[getBitWith(max_delta_value-value)]++;
-            }
-        }
-
-        int final_k_start_value = -1;
-        int final_k_end_value = max_delta_value+1;
-
-        int min_bits = 0;
-        min_bits += (getBitWith(final_k_end_value - final_k_start_value -2) * (block_size));
-
-        int cur_k1_close = alpha_count_list[0]; // lower: x_min
-        int k_start_value_close = 0;
-
-        int cur_bits = 0;
-        int alpha_2_pow = 1;
-        int gamma_size = (int) (Math.log(max_delta_value - alpha_2_pow - 1)/Math.log(2));
-        int cur_k2_close = gamma_count_list[0];
-        cur_k2_close += gamma_count_list[1];
-        cur_k2_close += gamma_box_count_list[0];
-        for (int gamma = 1;  gamma<=gamma_size;gamma++){
-            int k_end_value_close = max_delta_value - (int) pow(2,gamma);
-
-            cur_k2_close += gamma_count_list[gamma+1];
-            cur_k2_close += gamma_box_count_list[gamma];
-            cur_bits = cur_k1_close;
-            cur_bits += Math.min((cur_k1_close + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_close);
-            if (cur_k1_close + cur_k2_close != block_size)
-                cur_bits += (block_size - cur_k1_close - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_close - 2);
-            if (cur_k2_close != 0)
-                cur_bits += cur_k2_close * (gamma + 1);
-
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_close;
-                final_k_end_value = k_end_value_close;
-            }
-
-            int cur_k2_open = cur_k2_close - gamma_count_list[gamma+1];
-            int k_end_value_open = k_end_value_close + 1;
-
-            //C4 k1 close k2 open
-            cur_bits = cur_k1_close;
-            cur_bits += Math.min((cur_k1_close + cur_k2_open) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_open);
-
-            if (cur_k1_close + cur_k2_open != block_size)
-                cur_bits += (block_size - cur_k1_close - cur_k2_open) * getBitWith(k_end_value_open - k_start_value_close - 2);
-            if (cur_k2_open != 0)
-                cur_bits += cur_k2_open * gamma;
-
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_close;
-                final_k_end_value = k_end_value_open;
-            }
-        }
-
-        // lower: x_min +1
-        //  -------------------------------
-        cur_k1_close += alpha_count_list[1]; // lower outliers: x_min +1
-        cur_k1_close += alpha_box_count_list[0];
-        k_start_value_close = 1;
-        cur_k2_close = gamma_count_list[0];
-        cur_k2_close += gamma_count_list[1];
-        cur_k2_close += gamma_box_count_list[0];
-        for (int gamma = 1;  gamma<=gamma_size;gamma++){
-            int k_end_value_close = max_delta_value - (int) pow(2,gamma);
-
-            cur_k2_close += gamma_count_list[gamma+1];
-            cur_k2_close += gamma_box_count_list[gamma];
-            cur_bits = cur_k1_close;
-            cur_bits += Math.min((cur_k1_close + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_close);
-            if (cur_k1_close + cur_k2_close != block_size)
-                cur_bits += (block_size - cur_k1_close - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_close - 2);
-            if (cur_k2_close != 0)
-                cur_bits += cur_k2_close * (gamma + 1);
-
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_close;
-                final_k_end_value = k_end_value_close;
-            }
-
-            int cur_k2_open = cur_k2_close - gamma_count_list[gamma+1];
-            int k_end_value_open = k_end_value_close + 1;
-
-            //C4 k1 close k2 open
-            cur_bits = cur_k1_close;
-            cur_bits += Math.min((cur_k1_close + cur_k2_open) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_open);
-
-            if (cur_k1_close + cur_k2_open != block_size)
-                cur_bits += (block_size - cur_k1_close - cur_k2_open) * getBitWith(k_end_value_open - k_start_value_close - 2);
-            if (cur_k2_open != 0)
-                cur_bits += cur_k2_open * gamma;
-
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_close;
-                final_k_end_value = k_end_value_open;
-            }
-        }
-        // lower: x_min + 2 ^alpha
-        //  -------------------------------
-
-        for (int alpha = 1; alpha  <= max_bit-1; alpha++) {
-            //C1 k1 close k2 close
-            k_start_value_close = (int) pow(2,alpha);//close
-            int pow_2_alpha_i = alpha_count_list[alpha+1];
-            int pow_2_alpha_i_1_to_2_alpha_i = alpha_box_count_list[alpha];
-
-
-            cur_k1_close += pow_2_alpha_i;
-            cur_k1_close += pow_2_alpha_i_1_to_2_alpha_i;
-
-            int k_end_value_close;
-
-            alpha_2_pow = (int)pow(2,alpha);
-            gamma_size = (int) (Math.log(max_delta_value - alpha_2_pow - 1)/Math.log(2));
-
-            // upper outliers: x_max
-            cur_k2_close = gamma_count_list[0];
-            k_end_value_close = max_delta_value;
-
-            cur_bits=cur_k2_close;
-            cur_bits += Math.min((cur_k1_close + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_close);
-            if (cur_k1_close != 0)
-                cur_bits += cur_k1_close * (alpha + 1);
-            if (cur_k1_close + cur_k2_close != block_size)
-                cur_bits += (block_size - cur_k1_close - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_close - 2);
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_close;
-                final_k_end_value = k_end_value_close;
-            }
-
-            int cur_k1_open = cur_k1_close - alpha_count_list[alpha+1];
-            int k_start_value_open = k_start_value_close - 1;
-            cur_bits=cur_k2_close;
-            cur_bits += Math.min((cur_k1_open + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_open + cur_k2_close);
-            if (cur_k1_open != 0)
-                cur_bits += cur_k1_open * (alpha);
-            if (cur_k1_open + cur_k2_close != block_size)
-                cur_bits += (block_size - cur_k1_open - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_open - 2);
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_open;
-                final_k_end_value = k_end_value_close;
-            }
-            // upper outliers:  x_max -1
-            cur_k2_close += gamma_count_list[1];
-            cur_k2_close += gamma_box_count_list[0];
-            k_end_value_close = max_delta_value-1;
-            cur_bits=cur_k2_close;
-            cur_bits += Math.min((cur_k1_close + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_close);
-            if (cur_k1_close != 0)
-                cur_bits += cur_k1_close * (alpha + 1);
-            if (cur_k1_close + cur_k2_close != block_size)
-                cur_bits += (block_size - cur_k1_close - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_close - 2);
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_close;
-                final_k_end_value = k_end_value_close;
-            }
-
-            cur_k1_open = cur_k1_close - alpha_count_list[alpha+1];
-            k_start_value_open = k_start_value_close - 1;
-            cur_bits=cur_k2_close;
-            cur_bits += Math.min((cur_k1_open + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_open + cur_k2_close);
-            if (cur_k1_open != 0)
-                cur_bits += cur_k1_open * (alpha);
-            if (cur_k1_open + cur_k2_close != block_size)
-                cur_bits += (block_size - cur_k1_open - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_open - 2);
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_open;
-                final_k_end_value = k_end_value_close;
-            }
-            // upper outliers:  x_max -2^gamma
-            for (int gamma = 1;  gamma<=gamma_size;gamma++){
-                int flag = 0;
-                k_end_value_close = max_delta_value - (int) pow(2,gamma);
-                cur_bits = 0;
-                int pow_2_gamma_i = gamma_count_list[gamma+1];
-                int pow_2_gamma_i_1_to_2_gamma_i = gamma_box_count_list[gamma];
-
-                cur_k2_close += pow_2_gamma_i;
-                cur_k2_close += pow_2_gamma_i_1_to_2_gamma_i;
-
-                cur_bits += Math.min((cur_k1_close + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_close);
-                if (cur_k1_close != 0)
-                    cur_bits += cur_k1_close * (alpha + 1);
-                if (cur_k1_close + cur_k2_close != block_size)
-                    cur_bits += (block_size - cur_k1_close - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_close - 2);
-                if (cur_k2_close != 0)
-                    cur_bits += cur_k2_close * (gamma + 1);
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    flag = 1;
-                }
-
-                //C2 k1open k2open
-                cur_bits = 0;
-                cur_k1_open = cur_k1_close - alpha_count_list[alpha+1];
-                int cur_k2_open = cur_k2_close - gamma_count_list[gamma+1];
-                k_start_value_open = k_start_value_close - 1;
-                int k_end_value_open = k_end_value_close + 1;
-                cur_bits += Math.min((cur_k1_open + cur_k2_open) * getBitWith(block_size-1), block_size + cur_k1_open + cur_k2_open);
-                if (cur_k1_open != 0)
-                    cur_bits += cur_k1_open * alpha;
-                if (cur_k1_open + cur_k2_open != block_size)
-                    cur_bits += (block_size - cur_k1_open - cur_k2_open) * getBitWith(k_end_value_open - k_start_value_open - 2);
-                if (cur_k2_open != 0)
-                    cur_bits += cur_k2_open * gamma;
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    flag = 2;
-                }
-
-                //C3 k1 open k2 close
-                cur_bits = 0;
-                cur_bits += Math.min((cur_k1_open + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_open + cur_k2_close);
-                if (cur_k1_open != 0)
-                    cur_bits += cur_k1_open * alpha;
-                if (cur_k1_open + cur_k2_close != block_size)
-                    cur_bits += (block_size - cur_k1_open - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_open - 2);
-                if (cur_k2_close != 0)
-                    cur_bits += cur_k2_close * (gamma + 1);
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    flag = 3;
-                }
-
-                //C4 k1 close k2 open
-                cur_bits = 0;
-                cur_bits += Math.min((cur_k1_close + cur_k2_open) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_open);
-                if (cur_k1_close != 0)
-                    cur_bits += cur_k1_close * (alpha + 1);
-                if (cur_k1_close + cur_k2_open != block_size)
-                    cur_bits += (block_size - cur_k1_close - cur_k2_open) * getBitWith(k_end_value_open - k_start_value_close - 2);
-                if (cur_k2_open != 0)
-                    cur_bits += cur_k2_open * gamma;
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    flag = 4;
-                }
-                if(flag == 1){
-                    final_k_start_value = k_start_value_close;
-                    final_k_end_value = k_end_value_close;
-                } else if (flag == 2) {
-                    final_k_start_value = k_start_value_open;
-                    final_k_end_value = k_end_value_open;
-                } else if (flag == 3) {
-                    final_k_start_value = k_start_value_open;
-                    final_k_end_value = k_end_value_close;
-                } else if (flag == 4) {
-                    final_k_start_value = k_start_value_close;
-                    final_k_end_value = k_end_value_open;
-                }
-
-            }
-        }
-
-
-
-        encode_pos = BOSEncodeBits(ts_block_delta,init_block_size,  final_k_start_value, final_k_end_value, max_delta_value,
-                min_delta,repeat_count, encode_pos , cur_byte);
-
-
-        return encode_pos;
-    }
-
-    public static int BOSEncoder(
-            int[] data, int block_size, byte[] encoded_result) {
-
-        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;
-
-        for (int i = 0; i < block_num; i++) {
-            encode_pos =  BOSBlockEncoder(data, i, block_size, block_size,encode_pos,encoded_result);
-//            System.out.println(encode_pos);
-        }
-
-        int remaining_length = length_all - block_num * block_size;
-        if (remaining_length <= 3) {
-            for (int i = remaining_length; i > 0; i--) {
-                int2Bytes(data[data.length - i], encode_pos, encoded_result);
-                encode_pos += 4;
-            }
-
-        } else {
-
-            int start = block_num * block_size;
-            int remaining = length_all-start;
-
-
-            encode_pos = BOSBlockEncoder(data, block_num, block_size,remaining, encode_pos,encoded_result);
-
-//            int[] ts_block = new int[length_all-start];
-//            if (length_all - start >= 0) System.arraycopy(data, start, ts_block, 0, length_all - start);
-//
-//
-//            encode_pos = BOSBlockEncoder(ts_block, encode_pos,encoded_result);
-
-        }
-
-
-        return encode_pos;
-    }
-
-    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list,int init_block_size, int block_size, int[] value_pos_arr) {
-
-        int k_byte = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-        int k1_byte = (int) (k_byte % pow(2, 16));
-        int k1 = k1_byte / 2;
-        int final_alpha = k1_byte % 2;
-
-        int k2 = (int) (k_byte / pow(2, 16));
-
-
-        int min_delta = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int count_size = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        ArrayList<Integer> repeat_count = new ArrayList<>();
-        if (count_size != 0) {
-            ArrayList<Integer> repeat_count_result = new ArrayList<>();
-            repeat_count = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(init_block_size-1), count_size, repeat_count_result);
-            decode_pos = repeat_count_result.get(0);
-
-        }
-
-        int cur_block_size = block_size;
-        for (int i = 1; i < count_size; i += 2) {
-            cur_block_size -= (repeat_count.get(i) - 1);
-        }
-
-        int final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        int left_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-        int right_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal;
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-
-        if (final_alpha == 0) { // 0
-            int bitmap_bytes = (int) Math.ceil((double) (cur_block_size + k1 + k2) / (double) 8);
-//            System.out.println("bitmap_bytes:" + bitmap_bytes);
-            for (int i = 0; i < bitmap_bytes; i++) {
-                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
-                decode_pos += 1;
-            }
-            int bitmap_outlier_i = 0;
-            int remaining_bits = 8;
-            int tmp = bitmap_outlier.get(bitmap_outlier_i);
-            bitmap_outlier_i++;
-            int i = 0;
-            while (i < cur_block_size) {
-                if (remaining_bits > 1) {
-                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
-                    remaining_bits -= 1;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                    if (remaining_bits == 0) {
-                        remaining_bits = 8;
-                        if (bitmap_outlier_i >= bitmap_bytes) break;
-                        tmp = bitmap_outlier.get(bitmap_outlier_i);
-                        bitmap_outlier_i++;
-                    }
-                } else if (remaining_bits == 1) {
-                    int bit_i = tmp & 0x1;
-                    remaining_bits = 8;
-                    if (bitmap_outlier_i >= bitmap_bytes) break;
-                    tmp = bitmap_outlier.get(bitmap_outlier_i);
-                    bitmap_outlier_i++;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                }
-                i++;
-            }
-        } else {
-
-                ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-                final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(cur_block_size-1), k1, decode_pos_result_left);
-                decode_pos = (decode_pos_result_left.get(0));
-
-                ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-                final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(cur_block_size-1), k2, decode_pos_result_right);
-                decode_pos = (decode_pos_result_right.get(0));
-
-        }
-
-
-        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
-        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, cur_block_size - k1 - k2, decode_pos_normal);
-
-        decode_pos = decode_pos_normal.get(0);
-        if (k1 != 0) {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
-
-            decode_pos = decode_pos_result_left.get(0);
-        }
-        if (k2 != 0) {
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
-            decode_pos = decode_pos_result_right.get(0);
-        }
-        int left_outlier_i = 0;
-        int right_outlier_i = 0;
-        int normal_i = 0;
-        int pre_v;
-        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
-
-        int cur_i = 0;
-        int repeat_i = 0;
-        for (int i = 0; i < cur_block_size; i++) {
-
-            int current_delta;
-            if (left_outlier_i >= k1) {
-                if (right_outlier_i >= k2) {
-                    current_delta = final_normal.get(normal_i) + final_k_start_value+1;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta = final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta = final_normal.get(normal_i) + final_k_start_value+1;
-                    normal_i++;
-                }
-            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
-                current_delta = final_left_outlier.get(left_outlier_i);
-                left_outlier_i++;
-            } else {
-
-                if (right_outlier_i >= k2) {
-                    current_delta = final_normal.get(normal_i) + final_k_start_value+1;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta = final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta = final_normal.get(normal_i) + final_k_start_value+1;
-                    normal_i++;
-                }
-            }
-            pre_v = current_delta + min_delta;
-            if (repeat_i < count_size) {
-                if (cur_i == repeat_count.get(repeat_i)) {
-                    cur_i += (repeat_count.get(repeat_i+1));
-
-                    for (int j = 0; j < repeat_count.get(repeat_i + 1); j++) {
-                        value_list[value_pos_arr[0]] = pre_v;
-                        value_pos_arr[0]++;
-                    }
-                    repeat_i += 2;
-                }else {
-                    cur_i++;
-                    value_list[value_pos_arr[0]] = pre_v;
-                    value_pos_arr[0]++;
-                }
-            } else {
-                cur_i++;
-                value_list[value_pos_arr[0]] = pre_v;
-                value_pos_arr[0]++;
-            }
-        }
-        return decode_pos;
-    }
-
-    public static void BOSDecoder(byte[] encoded) {
-
-        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;
-//        block_size--;
-
-        int block_num = length_all / block_size;
-        int remain_length = length_all - block_num * block_size;
-
-        int[] value_list = new int[length_all+block_size];
-        int[] value_pos_arr = new int[1];
-
-        for (int k = 0; k < block_num; k++) {
-            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list,block_size, block_size,value_pos_arr);
-        }
-
-        if (remain_length <= 3) {
-            for (int i = 0; i < remain_length; i++) {
-                int value_end = bytes2Integer(encoded, decode_pos, 4);
-                decode_pos += 4;
-                value_list[value_pos_arr[0]] = value_end;
-                value_pos_arr[0]++;
-            }
-        } else {
-            BOSBlockDecoder(encoded, decode_pos, value_list,block_size, remain_length, value_pos_arr);
-        }
-    }
-
-    public static void main(@NotNull String[] args) throws IOException {
-//        String parent_dir = "/Users/xiaojinzhao/Desktop/encoding-outlier/";// your data path
-        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
-        String output_parent_dir = parent_dir + "vldb/compression_ratio/rle_bws";
-        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<>();
-        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");
-
-        for (String value : dataset_name) {
-            input_path_list.add(input_parent_dir + value);
-            dataset_block_size.add(1024);
-        }
-
-        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(2048);
-        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
-//        dataset_block_size.add(2048);
-        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(1024);
-        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
-//        dataset_block_size.add(1024);
-        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
-//        dataset_block_size.add(1024);
-
-//        for (int file_i = 8; file_i < 9; file_i++) {
-        int repeatTime2 = 100;
-        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
-
-            String inputPath = input_path_list.get(file_i);
-            System.out.println(inputPath);
-            String Output = output_path_list.get(file_i);
-
-            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<Integer> data1 = new ArrayList<>();
-                ArrayList<Integer> data2 = new ArrayList<>();
-
-
-
-                loader.readHeaders();
-                while (loader.readRecord()) {
-                    data1.add(Integer.valueOf(loader.getValues()[0]));
-                    data2.add(Integer.valueOf(loader.getValues()[1]));
-                }
-
-                inputStream.close();
-                int[] data2_arr = new int[data1.size()];
-                for(int i = 0;i<data2.size();i++){
-                    data2_arr[i] = data2.get(i);
-                }
-                byte[] encoded_result = new byte[data2_arr.length*4];
-                long encodeTime = 0;
-                long decodeTime = 0;
-                double ratio = 0;
-                double compressed_size = 0;
-
-
-                int length = 0;
-
-                long s = System.nanoTime();
-                for (int repeat = 0; repeat < repeatTime2; repeat++) {
-                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
-                }
-
-                long e = System.nanoTime();
-                encodeTime += ((e - s) / repeatTime2);
-                compressed_size += length;
-                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
-                ratio += ratioTmp;
-                s = System.nanoTime();
-                for (int repeat = 0; repeat < repeatTime2; repeat++)
-                    BOSDecoder(encoded_result);
-                e = System.nanoTime();
-                decodeTime += ((e - s) / repeatTime2);
-
-
-                String[] record = {
-                        f.toString(),
-                        "RLE+BWS",
-                        String.valueOf(encodeTime),
-                        String.valueOf(decodeTime),
-                        String.valueOf(data1.size()),
-                        String.valueOf(compressed_size),
-                        String.valueOf(ratio)
-                };
-                writer.writeRecord(record);
-                System.out.println(ratio);
-
-            }
-            writer.close();
-
-
-        }
-    }
-
-}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSMTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSMTest.java
new file mode 100644
index 0000000..8367368
--- /dev/null
+++ b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSMTest.java
@@ -0,0 +1,2417 @@
+package org.apache.iotdb.tsfile.encoding;
+
+import com.csvreader.CsvReader;
+import com.csvreader.CsvWriter;
+import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
+import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
+import org.apache.iotdb.tsfile.compress.ICompressor;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.junit.Test;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.ArrayList;
+
+import static java.lang.Math.*;
+import static org.apache.iotdb.tsfile.constant.TestConstant.random;
+
+public class RLEBOSMTest {
+
+    public static int findMedianImprove(int[] arr) {
+        if (arr == null || arr.length == 0) {
+            throw new IllegalArgumentException("数组不能为空");
+        }
+        int n = arr.length;
+        return quickSelect2(arr, 0, n - 1, n / 2);
+    }
+
+    private static int quickSelect2(int[] arr, int left, int right, int k){
+        int pivotV=arr[left+random.nextInt(right-left+1)],tmpV;
+        int posEqual=left,posSmaller=left; // a[left,posEqual): = pivotV; a[posEqual,posSmaller): < pivotV
+        for(int i=left;i<=right;i++){
+            if(arr[i]==pivotV){
+                tmpV=arr[i];
+                arr[i]=arr[posSmaller];
+                arr[posSmaller]=arr[posEqual];
+                arr[posEqual]=tmpV;
+                posEqual++;
+                posSmaller++;
+            }else
+            if(arr[i]<pivotV){
+                tmpV=arr[posSmaller];
+                arr[posSmaller]=arr[i];
+                arr[i]=tmpV;
+                posSmaller++;
+            }
+        }
+        if(k+(posEqual-left)<=posSmaller-1)return quickSelect2(arr,posEqual,posSmaller-1,k+(posEqual-left));
+        else if(k<=posSmaller-1)return pivotV;
+        else return quickSelect2(arr,posSmaller,right,k);
+    }
+    public static int findMedian(int[] arr) {
+        if (arr == null || arr.length == 0) {
+            throw new IllegalArgumentException("数组不能为空");
+        }
+        int n = arr.length;
+        return quickSelect(arr, 0, n - 1, n / 2);
+    }
+
+    private static int quickSelect(int[] arr, int left, int right, int k) {
+        if (left == right) {
+            return arr[left];
+        }
+
+        int pivotIndex = partition(arr, left, right);
+        if (k == pivotIndex) {
+            return arr[k];
+        } else if (k < pivotIndex) {
+            return quickSelect(arr, left, pivotIndex - 1, k);
+        } else {
+            return quickSelect(arr, pivotIndex + 1, right, k);
+        }
+    }
+
+    private static int partition(int[] arr, int left, int right) {
+        int pivot = arr[right];
+        int i = left;
+        for (int j = left; j < right; j++) {
+            if (arr[j] <= pivot) {
+                swap(arr, i, j);
+                i++;
+            }
+        }
+        swap(arr, i, right);
+        return i;
+    }
+
+    private static void swap(int[] arr, int i, int j) {
+        int temp = arr[i];
+        arr[i] = arr[j];
+        arr[j] = temp;
+    }
+
+    public static int getBitWith(int num) {
+        if (num == 0) return 1;
+        else return 32 - Integer.numberOfLeadingZeros(num);
+    }
+    public static int getCount(long long1, int mask) {
+        return ((int) (long1 & mask));
+    }
+    public static int getUniqueValue(long long1, int left_shift) {
+        return ((int) ((long1) >> left_shift));
+    }
+
+
+    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 ;
+                }
+            }
+        }
+
+    }
+
+    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 int[]  getAbsDeltaTsBlock(
+            int[] ts_block,
+            int i,
+            int block_size,
+            int remaining,
+            int[] min_delta,
+            ArrayList<Integer> repeat_count) {
+        int[] ts_block_delta = new int[remaining];
+
+        int value_delta_min = Integer.MAX_VALUE;
+        int value_delta_max = Integer.MIN_VALUE;
+        int base = i*block_size;
+        int end = i*block_size+remaining;
+        for (int j = base; j < end; j++) {
+
+            int integer = ts_block[j];
+            if (integer < value_delta_min) value_delta_min = integer;
+            if (integer > value_delta_max) {
+                value_delta_max = integer;
+            }
+        }
+        int pre_delta = ts_block[i*block_size]-value_delta_min;
+        int pre_count = 1;
+
+        min_delta[0]=(value_delta_min);
+        int repeat_i = 0;
+        int ts_block_delta_i = 0;
+        for (int j = base+1; j < end; j++) {
+            int delta = ts_block[j]-value_delta_min;
+            if(delta == pre_delta){
+                pre_count ++;
+            } else {
+                if(pre_count>7){
+                    repeat_count.add(repeat_i);
+                    repeat_count.add(pre_count);
+                    ts_block_delta[ts_block_delta_i]=pre_delta;
+                    ts_block_delta_i ++;
+                } else{
+                    for (int k = 0; k < pre_count; k++){
+                        ts_block_delta[ts_block_delta_i] =pre_delta;
+                        ts_block_delta_i++;
+                    }
+                }
+                pre_count =1;
+                repeat_i = j - i*block_size;
+            }
+            pre_delta = delta;
+
+        }
+        for (int j = 0; j < pre_count; j++){
+            ts_block_delta[ts_block_delta_i] =pre_delta;
+            ts_block_delta_i++;
+        }
+        min_delta[1]=(ts_block_delta_i);
+        min_delta[2]=(value_delta_max-value_delta_min);
+        int[] new_ts_block_delta = new int[ts_block_delta_i];
+        System.arraycopy(ts_block_delta, 0, new_ts_block_delta, 0, ts_block_delta_i);
+
+        return new_ts_block_delta;
+    }
+
+
+
+    public static int encodeOutlier2Bytes(
+            ArrayList<Integer> ts_block_delta,
+            int bit_width,
+            int encode_pos,  byte[] encoded_result) {
+
+        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
+
+        int n_k = ts_block_delta.size();
+        int n_k_b = n_k / 8;
+        long cur_remaining = 0; // encoded int
+        int cur_number_bits = 0; // the bit width used of encoded int
+        for (int i = n_k_b * 8; i < n_k; i++) {
+            long cur_value = ts_block_delta.get(i);
+            int cur_bit_width = bit_width; // remaining bit width of current value
+
+            if (cur_number_bits + bit_width >= 32) {
+                cur_remaining <<= (32 - cur_number_bits);
+                cur_bit_width = bit_width - 32 + cur_number_bits;
+                cur_remaining += ((cur_value >> cur_bit_width));
+                long2intBytes(cur_remaining,encode_pos,encoded_result);
+                encode_pos += 4;
+
+                cur_remaining = 0;
+                cur_number_bits = 0;
+            }
+
+            cur_remaining <<= cur_bit_width;
+            cur_number_bits += cur_bit_width;
+            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width));
+        }
+        cur_remaining <<= (32 - cur_number_bits);
+        long2intBytes(cur_remaining,encode_pos,encoded_result);
+        encode_pos += 4;
+        return encode_pos;
+
+    }
+
+
+    public static ArrayList<Integer> decodeOutlier2Bytes(
+            byte[] encoded,
+            int decode_pos,
+            int bit_width,
+            int length,
+            ArrayList<Integer> encoded_pos_result
+    ) {
+
+        int n_k_b = length / 8;
+        int remaining = length - n_k_b * 8;
+        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
+        decode_pos += n_k_b * bit_width;
+
+        ArrayList<Long> int_remaining = new ArrayList<>();
+        int int_remaining_size = remaining * bit_width / 32 + 1;
+        for (int j = 0; j < int_remaining_size; j++) {
+
+            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
+            decode_pos += 4;
+        }
+
+        int cur_remaining_bits = 32; // remaining bit width of current value
+        long cur_number = int_remaining.get(0);
+        int cur_number_i = 1;
+        for (int i = n_k_b * 8; i < length; i++) {
+            if (bit_width < cur_remaining_bits) {
+                int tmp = (int) (cur_number >> (32 - bit_width));
+                result_list.add(tmp);
+                cur_number <<= bit_width;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits -= bit_width;
+            } else {
+                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
+                int remain_bits = bit_width - cur_remaining_bits;
+                tmp <<= remain_bits;
+
+                cur_number = int_remaining.get(cur_number_i);
+                cur_number_i++;
+                tmp += (cur_number >> (32 - remain_bits));
+                result_list.add(tmp);
+                cur_number <<= remain_bits;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits = 32 - remain_bits;
+            }
+        }
+        encoded_pos_result.add(decode_pos);
+        return result_list;
+    }
+
+    private static void addToArchiveCompression(SevenZOutputFile out, File file, String dir) {
+        String name = dir + File.separator + file.getName();
+        if(dir.equals(".")) {
+            name = file.getName();
+        }
+        if (file.isFile()){
+            SevenZArchiveEntry entry = null;
+            FileInputStream in = null;
+            try {
+                entry = out.createArchiveEntry(file, name);
+                out.putArchiveEntry(entry);
+                in = new FileInputStream(file);
+                byte[] b = new byte[1024];
+                int count = 0;
+                while ((count = in.read(b)) > 0) {
+                    out.write(b, 0, count);
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    out.closeArchiveEntry();
+                    in.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+
+            }
+        } else if (file.isDirectory()) {
+            File[] children = file.listFiles();
+            if (children != null){
+                for (File child : children){
+                    addToArchiveCompression(out, child, name);
+                }
+            }
+        } else {
+            System.out.println(file.getName() + " is not supported");
+        }
+    }
+
+    private static int BOSEncodeBits(int[] ts_block_delta,
+                                      int init_block_size,
+                                      int final_k_start_value,
+                                     int final_x_l_plus,
+                                      int final_k_end_value,
+                                     int final_x_u_minus,
+                                      int max_delta_value,
+                                      int[] min_delta,
+                                      ArrayList<Integer> repeat_count,
+                                      int encode_pos,
+                                      byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        int k1 = 0;
+        int k2 = 0;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if (cur_value < final_k_start_value) {
+                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+
+
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+                final_normal.add(cur_value - final_x_l_plus);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int size = repeat_count.size();
+        intByte2Bytes(size,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        if (size != 0)
+            encode_pos =encodeOutlier2Bytes(repeat_count, getBitWith(init_block_size-1),encode_pos,cur_byte);
+
+
+        int bit_width_final = 0;
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+
+        if(k1==0 && k2==0){
+            bit_width_final = getBitWith(max_delta_value);
+            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+            encode_pos += 1;
+
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//            return encode_pos;
+        }
+        else{
+            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+            encode_pos += 4;
+            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+            encode_pos += 4;
+
+            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+            encode_pos += 1;
+            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+            encode_pos += 1;
+            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+            encode_pos += 1;
+            if (final_alpha == 0) { // 0
+
+                for (int i : bitmap_outlier) {
+
+                    intByte2Bytes(i,encode_pos,cur_byte);
+                    encode_pos += 1;
+                }
+            } else {
+                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            }
+        }
+
+        encode_pos =encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+        if (k1 != 0)
+            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+        if (k2 != 0)
+            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+        return encode_pos;
+
+    }
+
+
+
+
+    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size,int remaining, int encode_pos , byte[] cur_byte) {
+
+        ArrayList<Integer> repeat_count = new ArrayList<>();
+        int init_block_size = block_size;
+
+        int[] min_delta = new int[3];
+        int[]  ts_block_delta = getAbsDeltaTsBlock(ts_block,block_i, init_block_size,remaining, min_delta, repeat_count);
+        block_size = min_delta[1];
+        int max_delta_value = min_delta[2];
+
+        int max_bit_width = getBitWith(max_delta_value) + 1;
+
+
+        int[] findMedianArray = new int[block_size];
+        System.arraycopy(ts_block_delta, 0, findMedianArray, 0, block_size);
+
+        int median = findMedian(findMedianArray);
+
+        //        int xl=  median;
+        //        int xu = median;
+        // xl = 2 median - xu
+        // xl = xu - 2 ^ beta
+        int left_number = 0;
+        int right_number = 0;
+
+        int length_outlier = block_size;
+//        for(int value:findMedianArray){
+//            if(value<=median) left_number++;
+//            if (value >= median)  right_number ++;
+//        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2) * (block_size));
+
+
+        int[] count_left = new int[max_bit_width];
+        int[] count_right = new int[max_bit_width];
+        int count_0 = 0;
+
+
+        for(int i=0;i<length_outlier;i++){
+            int cur_value = ts_block_delta[i];
+            if(cur_value > median){
+                int beta = getBitWith(cur_value - median) ;
+                count_right[beta] ++;
+            } else if (cur_value < median) {
+                int beta = getBitWith(median - cur_value) ;
+                count_left[beta] ++;
+            }else{
+                count_0 ++;
+            }
+
+
+        }
+
+        for(int beta = max_bit_width - 1; beta > 0 ; beta --){
+            left_number += count_left[beta];
+            right_number += count_right[beta];
+            int pow_beta = (int) pow(2,beta-1);
+            int xu = min(max_delta_value+1, median + pow_beta) ;
+            int xl = max(median - pow_beta,-1);
+            int cur_bits = Math.min((left_number + right_number) * getBitWith(block_size - 1), block_size + left_number + right_number);
+            cur_bits += left_number * getBitWith(xl);
+            cur_bits += right_number * getBitWith(max_delta_value - xu);
+            cur_bits += (block_size - left_number - right_number) * getBitWith(xu - xl - 2);
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+
+                final_k_start_value = xl;
+                final_x_l_plus = xl + 1;
+                final_k_end_value = xu;
+                final_x_u_minus = xu -1;
+            }
+
+        }
+
+        encode_pos = BOSEncodeBits(ts_block_delta,init_block_size,  final_k_start_value,final_x_l_plus, final_k_end_value,final_x_u_minus,
+                max_delta_value, min_delta,repeat_count, encode_pos , cur_byte);
+
+        return encode_pos;
+    }
+
+    public static int BOSEncoder(
+            int[] data, int block_size, byte[] encoded_result) {
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+
+            encode_pos =  BOSBlockEncoder(data, i, block_size, block_size,encode_pos,encoded_result);
+//            System.out.println(encode_pos);
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        } else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+
+
+            encode_pos = BOSBlockEncoder(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+//            int[] ts_block = new int[length_all-start];
+//            if (length_all - start >= 0) System.arraycopy(data, start, ts_block, 0, length_all - start);
+//
+//
+//            encode_pos = BOSBlockEncoder(ts_block, encode_pos,encoded_result);
+
+        }
+
+
+        return encode_pos;
+    }
+
+    public static int EncodeBits(int num,
+                                 int bit_width,
+                                 int encode_pos,
+                                 byte[] cur_byte,
+                                 int[] bit_index_list){
+        // 找到要插入的位的索引
+        int bit_index = bit_index_list[0] ;//cur_byte[encode_pos + 1];
+
+        // 计算数值的起始位位置
+        int remaining_bits = bit_width;
+
+        while (remaining_bits > 0) {
+            // 计算在当前字节中可以使用的位数
+            int available_bits = bit_index;
+            int bits_to_write = Math.min(available_bits, remaining_bits);
+
+            // 更新 bit_index
+            bit_index = available_bits - bits_to_write;
+
+            // 计算要写入的位的掩码和数值
+            int mask = (1 << bits_to_write) - 1;
+            int bits = (num >> (remaining_bits - bits_to_write)) & mask;
+
+            // 写入到当前位置
+            cur_byte[encode_pos] &= (byte) ~(mask << bit_index); // 清除对应位置的位
+            cur_byte[encode_pos] |= (byte) (bits << bit_index);
+
+            // 更新位宽和数值
+            remaining_bits -= bits_to_write;
+            if (bit_index == 0) {
+                bit_index = 8;
+                encode_pos++;
+            }
+        }
+        bit_index_list[0] = bit_index;
+//        cur_byte[encode_pos + 1] = (byte) bit_index;
+        return encode_pos;
+    }
+    private static int BOSEncodeBitsImprove(int[] ts_block_delta,
+                                            int init_block_size,
+                                            int final_k_start_value,
+                                            int final_x_l_plus,
+                                            int final_k_end_value,
+                                            int final_x_u_minus,
+                                            int max_delta_value,
+                                            int[] min_delta,
+                                            ArrayList<Integer> repeat_count,
+                                            int encode_pos,
+                                            byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+
+        int k1 = 0;
+        int k2 = 0;
+
+
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+//                encode_pos = EncodeBits(cur_value,left_bit_width,encode_pos,cur_byte);
+//                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+//                encode_pos = EncodeBits(cur_value- final_k_end_value,right_bit_width,encode_pos,cur_byte);
+//                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+//                final_normal.add(cur_value - final_x_l_plus);
+//                encode_pos = EncodeBits(cur_value- final_x_l_plus,right_bit_width,encode_pos,cur_byte);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int size = repeat_count.size();
+        intByte2Bytes(size,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        int[] bit_index_list = new int[1];
+        bit_index_list[0] = 8;
+        if (size != 0){
+            int bit_width_init = getBitWith(init_block_size-1);
+            for(int repeat_count_v:repeat_count){
+                encode_pos = EncodeBits(repeat_count_v, bit_width_init, encode_pos, cur_byte, bit_index_list);
+            }
+            if(bit_index_list[0] != 8){
+                bit_index_list[0] = 8;
+                encode_pos ++;
+            }
+        }
+//            encode_pos =encodeOutlier2Bytes(repeat_count, getBitWith(init_block_size-1),encode_pos,cur_byte);
+
+//        int2Bytes(min_delta[1],encode_pos,cur_byte);
+//        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+
+
+        if(final_k_start_value<0 && final_k_end_value > max_delta_value){
+//            int bit_width_final= getBitWith(final_x_u_minus - final_x_l_plus);
+//            cur_byte[encode_pos+1] = 8;
+            bit_index_list[0] = 8;
+            for (int cur_value : ts_block_delta) {
+                encode_pos = EncodeBits(cur_value, bit_width_final, encode_pos, cur_byte, bit_index_list);
+//                final_normal.add(cur_value);
+            }
+            if(bit_index_list[0] != 8){
+                encode_pos ++;
+            }
+//            cur_byte[encode_pos+1] = 0;
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+            return encode_pos;
+        }
+
+
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+        int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(final_k_end_value,encode_pos,cur_byte);
+        encode_pos += 4;
+
+//        bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//        encode_pos += 1;
+        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        if (final_alpha == 0) { // 0
+
+            for (int i : bitmap_outlier) {
+
+                intByte2Bytes(i,encode_pos,cur_byte);
+                encode_pos += 1;
+            }
+        } else {
+            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+        }
+//        cur_byte[encode_pos+1] = 8;
+//        bit_index_list[0] = 8;
+        for (int cur_value : ts_block_delta) {
+            if (cur_value <= final_k_start_value) {
+                encode_pos = EncodeBits(cur_value, left_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else if (cur_value >= final_k_end_value) {
+                encode_pos = EncodeBits(cur_value - final_k_end_value, right_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else {
+                encode_pos = EncodeBits(cur_value - final_x_l_plus, bit_width_final, encode_pos, cur_byte,bit_index_list);
+            }
+        }
+        if(bit_index_list[0] != 8){
+            encode_pos ++;
+        }
+
+//        cur_byte[encode_pos+1] = 0;
+
+//        if(k1==0 && k2==0){
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//
+//
+//        }
+//        else{
+//            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+//            encode_pos += 4;
+//            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+//            encode_pos += 4;
+//
+//            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            if (final_alpha == 0) { // 0
+//
+//                for (int i : bitmap_outlier) {
+//
+//                    intByte2Bytes(i,encode_pos,cur_byte);
+//                    encode_pos += 1;
+//                }
+//            } else {
+//                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//            }
+//        }
+
+
+//        if(k1+k2!=block_size)
+//        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//        if (k1 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+//        if (k2 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+//        System.out.println(encode_pos);
+        return encode_pos;
+
+    }
+    private static int BOSBlockEncoderImprove(int[] ts_block, int block_i, int block_size,int remaining, int encode_pos , byte[] cur_byte) {
+
+        ArrayList<Integer> repeat_count = new ArrayList<>();
+        int init_block_size = block_size;
+
+        int[] min_delta = new int[3];
+        int[]  ts_block_delta = getAbsDeltaTsBlock(ts_block,block_i, init_block_size,remaining, min_delta, repeat_count);
+        block_size = min_delta[1];
+        int max_delta_value = min_delta[2];
+
+        int max_bit_width = getBitWith(max_delta_value) + 1;
+
+
+        int[] findMedianArray = new int[block_size];
+        System.arraycopy(ts_block_delta, 0, findMedianArray, 0, block_size);
+
+        int median = findMedianImprove(findMedianArray);
+
+        //        int xl=  median;
+        //        int xu = median;
+        // xl = 2 median - xu
+        // xl = xu - 2 ^ beta
+        int left_number = 0;
+        int right_number = 0;
+
+        int length_outlier = block_size;
+//        for(int value:findMedianArray){
+//            if(value<=median) left_number++;
+//            if (value >= median)  right_number ++;
+//        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2) * (block_size));
+
+
+        int[] count_left = new int[max_bit_width];
+        int[] count_right = new int[max_bit_width];
+        int count_0 = 0;
+
+
+        for(int i=0;i<length_outlier;i++){
+            int cur_value = ts_block_delta[i];
+            if(cur_value > median){
+                int beta = getBitWith(cur_value - median) ;
+                count_right[beta] ++;
+            } else if (cur_value < median) {
+                int beta = getBitWith(median - cur_value) ;
+                count_left[beta] ++;
+            }else{
+                count_0 ++;
+            }
+
+
+        }
+
+        for(int beta = max_bit_width - 1; beta > 0 ; beta --){
+            left_number += count_left[beta];
+            right_number += count_right[beta];
+            int pow_beta = 1 << (beta-1);
+            int xu = min(max_delta_value+1, median + pow_beta) ;
+            int xl = max(median - pow_beta,-1);
+            int cur_bits = Math.min((left_number + right_number) * getBitWith(block_size - 1), block_size + left_number + right_number);
+            cur_bits += left_number * getBitWith(xl);
+            cur_bits += right_number * getBitWith(max_delta_value - xu);
+            cur_bits += (block_size - left_number - right_number) * getBitWith(xu - xl - 2);
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+
+                final_k_start_value = xl;
+                final_x_l_plus = xl + 1;
+                final_k_end_value = xu;
+                final_x_u_minus = xu -1;
+            }
+
+        }
+
+        encode_pos = BOSEncodeBitsImprove(ts_block_delta,init_block_size,  final_k_start_value,final_x_l_plus, final_k_end_value,final_x_u_minus,
+                max_delta_value, min_delta,repeat_count, encode_pos , cur_byte);
+
+        return encode_pos;
+    }
+
+    public static int BOSEncoderImprove(
+            int[] data, int block_size, byte[] encoded_result) {
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+
+
+            encode_pos =  BOSBlockEncoderImprove(data, i, block_size, block_size,encode_pos,encoded_result);
+//            System.out.println(encode_pos);
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        } else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+
+            encode_pos = BOSBlockEncoderImprove(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+//            int[] ts_block = new int[length_all-start];
+//            if (length_all - start >= 0) System.arraycopy(data, start, ts_block, 0, length_all - start);
+//
+//
+//            encode_pos = BOSBlockEncoder(ts_block, encode_pos,encoded_result);
+
+        }
+
+
+        return encode_pos;
+    }
+
+
+    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list,int init_block_size, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int count_size = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        ArrayList<Integer> repeat_count = new ArrayList<>();
+        if (count_size != 0) {
+            ArrayList<Integer> repeat_count_result = new ArrayList<>();
+            repeat_count = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(init_block_size-1), count_size, repeat_count_result);
+            decode_pos = repeat_count_result.get(0);
+
+        }
+
+        int cur_block_size = block_size;
+        for (int i = 1; i < count_size; i += 2) {
+            cur_block_size -= (repeat_count.get(i) - 1);
+        }
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        if(k1!=0 || k2 != 0){
+            final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+            decode_pos += 4;
+
+            final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+            decode_pos += 4;
+
+            bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+
+            left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+            right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+
+            if (final_alpha == 0) {
+                int bitmap_bytes = (int) Math.ceil((double) (cur_block_size + k1 + k2) / (double) 8);
+                for (int i = 0; i < bitmap_bytes; i++) {
+                    bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                    decode_pos += 1;
+                }
+                int bitmap_outlier_i = 0;
+                int remaining_bits = 8;
+                int tmp = bitmap_outlier.get(bitmap_outlier_i);
+                bitmap_outlier_i++;
+                int i = 0;
+                while (i < block_size ) {
+                    if (remaining_bits > 1) {
+                        int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_i == 1) {
+                            int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                            remaining_bits -= 1;
+                            if (bit_left_right == 1) {
+                                final_left_outlier_index.add(i);
+                            } else {
+                                final_right_outlier_index.add(i);
+                            }
+                        }
+                        if (remaining_bits == 0) {
+                            remaining_bits = 8;
+                            if (bitmap_outlier_i >= bitmap_bytes) break;
+                            tmp = bitmap_outlier.get(bitmap_outlier_i);
+                            bitmap_outlier_i++;
+                        }
+                    } else if (remaining_bits == 1) {
+                        int bit_i = tmp & 0x1;
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                        if (bit_i == 1) {
+                            int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                            remaining_bits -= 1;
+                            if (bit_left_right == 1) {
+                                final_left_outlier_index.add(i);
+                            } else {
+                                final_right_outlier_index.add(i);
+                            }
+                        }
+                    }
+                    i++;
+                }
+            } else {
+                ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+                final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
+                decode_pos = (decode_pos_result_left.get(0));
+                ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+                final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
+                decode_pos = (decode_pos_result_right.get(0));
+            }
+        }else {
+            bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+
+            decode_pos += 1;
+        }
+
+
+//        System.out.println(bit_width_final);
+//        System.out.println("cur_block_size" + cur_block_size);
+//        System.out.println(k1);
+//        System.out.println("k2"+k2);
+        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, cur_block_size - k1 - k2, decode_pos_normal);
+
+        decode_pos = decode_pos_normal.get(0);
+        if (k1 != 0) {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+
+            decode_pos = decode_pos_result_left.get(0);
+        }
+        if (k2 != 0) {
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+            decode_pos = decode_pos_result_right.get(0);
+        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+        int pre_v;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+        int cur_i = 0;
+        int repeat_i = 0;
+        for (int i = 0; i < cur_block_size; i++) {
+
+            int current_delta;
+            if (left_outlier_i >= k1) {
+                if (right_outlier_i >= k2) {
+                    current_delta = final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
+                    current_delta = final_right_outlier.get(right_outlier_i) + final_k_end_value;
+                    right_outlier_i++;
+                } else {
+                    current_delta = final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                }
+            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
+                current_delta = final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+            } else {
+
+                if (right_outlier_i >= k2) {
+                    current_delta = final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
+                    current_delta = final_right_outlier.get(right_outlier_i) + final_k_end_value;
+                    right_outlier_i++;
+                } else {
+                    current_delta = final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                }
+            }
+            pre_v = current_delta + min_delta;
+            if (repeat_i < count_size) {
+                if (cur_i == repeat_count.get(repeat_i)) {
+                    cur_i += (repeat_count.get(repeat_i+1));
+
+                    for (int j = 0; j < repeat_count.get(repeat_i + 1); j++) {
+                        value_list[value_pos_arr[0]] = pre_v;
+                        value_pos_arr[0]++;
+                    }
+                    repeat_i += 2;
+                }else {
+                    cur_i++;
+                    value_list[value_pos_arr[0]] = pre_v;
+                    value_pos_arr[0]++;
+                }
+            } else {
+                cur_i++;
+                value_list[value_pos_arr[0]] = pre_v;
+                value_pos_arr[0]++;
+            }
+        }
+        return decode_pos;
+    }
+
+    public static void BOSDecoder(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        int[] value_pos_arr = new int[1];
+
+        for (int k = 0; k < block_num; k++) {
+//            System.out.println(k);
+            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list,block_size, block_size,value_pos_arr);
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            BOSBlockDecoder(encoded, decode_pos, value_list,block_size, remain_length, value_pos_arr);
+        }
+    }
+
+    public static int DecodeBits(byte[] cur_byte, int bit_width, int[] decode_pos_list) {
+        int decode_pos = decode_pos_list[0];
+        int bit_index = decode_pos_list[1];  //cur_byte[decode_pos + 1];
+        int remaining_bits = bit_width;
+        int num = 0;
+
+        while (remaining_bits > 0) {
+            int available_bits = bit_index;
+            int bits_to_read = Math.min(available_bits, remaining_bits);
+
+            // 计算要读取的位的掩码
+            int mask = (1 << bits_to_read) - 1;
+            int bits = (cur_byte[decode_pos] >> (available_bits - bits_to_read)) & mask;
+
+            // 将读取的位合并到结果中
+            num = (num << bits_to_read) | bits;
+
+            // 更新位宽和 bit_index
+            remaining_bits -= bits_to_read;
+            bit_index = available_bits - bits_to_read;
+
+            if (bit_index == 0) {
+                bit_index = 8;
+                decode_pos++;
+            }
+        }
+        decode_pos_list[0] = decode_pos;
+        decode_pos_list[1] = bit_index;
+
+        return num;
+    }
+    public static int BOSBlockDecoderImprove(byte[] encoded, int decode_pos, int[] value_list,int init_block_size, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+//        int value0 = bytes2Integer(encoded, decode_pos, 4);
+//        decode_pos += 4;
+//        value_list[value_pos_arr[0]] =value0;
+//        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int count_size = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        int[] decode_list = new int[2];
+        decode_list[0]= decode_pos;
+        decode_list[1]= 8;
+
+        int valuePos = value_pos_arr[0];
+
+//        ArrayList<Integer> repeat_count = new ArrayList<>();
+        ArrayList<Integer> repeat_count = new ArrayList<>();
+        if (count_size != 0) {
+            int bit_width_init =  getBitWith(init_block_size-1);
+            for(int i = 0;i<count_size;i++){
+                int repeat_count_v = DecodeBits(encoded, bit_width_init,  decode_list);
+                repeat_count.add(repeat_count_v);
+            }
+
+            if(decode_list[1] != 8){
+                decode_list[1] = 8;
+                decode_list[0] ++;
+            }
+//            repeat_count = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(init_block_size-1), count_size, repeat_count_result);
+            decode_pos = decode_list[0];
+//            decode_list[1]= 8;
+        }
+
+        int cur_block_size = block_size;
+        for (int i = 1; i < count_size; i += 2) {
+            cur_block_size -= (repeat_count.get(i) - 1);
+        }
+
+        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+
+
+        int pre_v;
+        int cur_i = 0;
+        int repeat_i = 0;
+        if(k1==0 && k2==0){
+//            int pre_v = value0;
+            decode_list[0] = decode_pos;
+            decode_list[1]= 8;
+            for (int i = 0; i < cur_block_size; i++) {
+                pre_v = min_delta + DecodeBits(encoded, bit_width_final,  decode_list);
+//                value_list[value_pos_arr[0]++] = pre_v;
+                if (repeat_i < count_size && cur_i == repeat_count.get(repeat_i)) {
+                    cur_i += (repeat_count.get(repeat_i+1));
+
+                    for (int j = 0; j < repeat_count.get(repeat_i + 1); j++) {
+                        value_list[value_pos_arr[0]++] = pre_v;
+                    }
+                    repeat_i += 2;
+                } else {
+                    cur_i++;
+                    value_list[value_pos_arr[0]++] = pre_v;
+                }
+            }
+            if(decode_list[1] != 8){
+                decode_list[1] = 8;
+                decode_list[0] ++;
+            }
+
+//            value_pos_arr[0] = valuePos;
+            return decode_list[0];
+        }
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+//        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+//        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+//        bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+//        decode_pos += 1;
+
+        left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+        right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        if (final_alpha == 0) {
+            int bitmap_bytes = (int) Math.ceil((double) (cur_block_size + k1 + k2) / (double) 8);
+            for (int i = 0; i < bitmap_bytes; i++) {
+                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                decode_pos += 1;
+            }
+            int bitmap_outlier_i = 0;
+            int remaining_bits = 8;
+            int tmp = bitmap_outlier.get(bitmap_outlier_i);
+            bitmap_outlier_i++;
+            int i = 0;
+            while (i < cur_block_size ) {
+                if (remaining_bits > 1) {
+                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                    remaining_bits -= 1;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                    if (remaining_bits == 0) {
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                    }
+                } else if (remaining_bits == 1) {
+                    int bit_i = tmp & 0x1;
+                    remaining_bits = 8;
+                    if (bitmap_outlier_i >= bitmap_bytes) break;
+                    tmp = bitmap_outlier.get(bitmap_outlier_i);
+                    bitmap_outlier_i++;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                }
+                i++;
+            }
+        } else {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(cur_block_size-1), k1, decode_pos_result_left);
+            decode_pos = (decode_pos_result_left.get(0));
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(cur_block_size-1), k2, decode_pos_result_right);
+            decode_pos = (decode_pos_result_right.get(0));
+        }
+
+
+
+
+
+//        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+//        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+//
+//        decode_pos = decode_pos_normal.get(0);
+//        if (k1 != 0) {
+//            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+//            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+//            decode_pos = decode_pos_result_left.get(0);
+//        }
+//        if (k2 != 0) {
+//            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+//            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+//            decode_pos = decode_pos_result_right.get(0);
+//        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+//        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+// Precompute constants
+        int normalOffset = min_delta + final_k_start_value;
+        int rightOutlierOffset = min_delta + final_k_end_value;
+
+// Initialize indices and pre-fetch next outlier positions
+        int leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+        int rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+        decode_list[0]= decode_pos;
+//        decode_list[1]= 8;
+        // Use a local variable for the position
+        for (int i = 0; i < cur_block_size; i++) {
+//            int currentDelta;
+            if (i == leftOutlierNextIndex) {
+                // Process left outlier
+                pre_v = min_delta + DecodeBits(encoded, left_bit_width,  decode_list); // final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+                leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+            } else if (i == rightOutlierNextIndex) {
+                // Process right outlier
+                pre_v = rightOutlierOffset + DecodeBits(encoded, right_bit_width,  decode_list);// final_right_outlier.get(right_outlier_i);
+                right_outlier_i++;
+                rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+            } else {
+                // Process normal value
+                pre_v = normalOffset + DecodeBits(encoded, bit_width_final,  decode_list);
+                normal_i++;
+            }
+            if (repeat_i < count_size && cur_i == repeat_count.get(repeat_i)) {
+                cur_i += (repeat_count.get(repeat_i+1));
+
+                for (int j = 0; j < repeat_count.get(repeat_i + 1); j++) {
+                    value_list[value_pos_arr[0]++] = pre_v;
+                }
+                repeat_i += 2;
+            } else {
+                cur_i++;
+                value_list[value_pos_arr[0]++] = pre_v;
+            }
+            // Update the cumulative value and store it
+//            pre_v += deZigzag(currentDelta);
+//            value_list[valuePos++] = pre_v;
+        }
+//        value_pos_arr[0] = valuePos;
+        if(decode_list[1]!=8){
+            return decode_list[0]+1;
+        }else {
+            return decode_list[0];
+        }
+//        decode_pos = decode_list[0];
+// Update the position in the array
+
+
+//        return decode_pos;
+    }
+    public static void BOSDecoderImprove(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        int[] value_pos_arr = new int[1];
+
+        for (int k = 0; k < block_num; k++) {
+//            System.out.println(k);
+            decode_pos = BOSBlockDecoderImprove(encoded, decode_pos, value_list, block_size, block_size, value_pos_arr);
+//            System.out.println(decode_pos);
+        }
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            BOSBlockDecoderImprove(encoded, decode_pos, value_list,block_size, remain_length, value_pos_arr);
+        }
+    }
+
+
+    public static void main(@org.jetbrains.annotations.NotNull String[] args) throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/rle_bos_m";
+
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        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(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 0; file_i < 1; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoder(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "RLE+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void ExpTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+//        String output_parent_dir = parent_dir + "icde0802/compression_ratio/exp_m";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R2O3_lower_outlier_compare/compression_ratio/bos";
+        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<>();
+        dataset_name.add("Synthetic_Exp_100");
+        dataset_name.add("Synthetic_Exp_1000");
+        dataset_name.add("Synthetic_Exp_10000");
+        dataset_name.add("Synthetic_Exp_100000");
+        dataset_name.add("Synthetic_Exp_1000000");
+        dataset_name.add("Synthetic_Normal_100");
+        dataset_name.add("Synthetic_Normal_1000");
+        dataset_name.add("Synthetic_Normal_10000");
+        dataset_name.add("Synthetic_Normal_100000");
+        dataset_name.add("Synthetic_Normal_1000000");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        output_path_list.add(output_parent_dir + "/Exp_100.csv"); // 0
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/Exp_1000.csv");// 1
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Exp_10000.csv");// 2
+        output_path_list.add(output_parent_dir + "/Exp_100000.csv");// 2
+        output_path_list.add(output_parent_dir + "/Exp_1000000.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Normal_100.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Normal_1000.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/Normal_10000.csv");//5
+        output_path_list.add(output_parent_dir + "/Normal_100000.csv");//5
+        output_path_list.add(output_parent_dir + "/Normal_1000000.csv");//5
+//        dataset_block_size.add(2048);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 8; file_i < 9; file_i++) {
+
+        for (int file_i = input_path_list.size()-1; file_i >=0 ; file_i--) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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);
+                if(f.toString().contains(".DS")) continue;
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoder(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "RLE+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void compressTest() throws IOException {
+//        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R3O2_compare_compression/compression_ratio/rle_m_c";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        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(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 1;
+//        for (int file_i = 8; file_i < 9; file_i++) {
+        CompressionType[] compressList = {
+                CompressionType.LZ4,
+                CompressionType.LZMA2,
+        };
+
+        for (int file_i = input_path_list.size()-1; file_i >=0 ; file_i--) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            File file = new File(inputPath);
+            File[] tempList = file.listFiles();
+
+            CsvWriter writer = new CsvWriter(Output, ',', StandardCharsets.UTF_8);
+
+            String[] head = {
+                    "Input Direction",
+                    "Encoding Algorithm",
+                    "Compress 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<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+                inputStream.close();
+
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+
+                for (CompressionType comp : compressList) {
+                    double ratio = 0;
+                    double compressed_size = 0;
+                    ICompressor compressor = ICompressor.getCompressor(comp);
+                    byte[] compressed = compressor.compress(encoded_result);
+
+                    // test compression ratio and compressed size
+                    compressed_size += compressed.length;
+                    double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                    ratio += ratioTmp;
+                    s = System.nanoTime();
+                    for (int repeat = 0; repeat < repeatTime2; repeat++)
+                        BOSDecoder(encoded_result);
+                    e = System.nanoTime();
+                    decodeTime += ((e - s) / repeatTime2);
+
+
+                    String[] record = {
+                            f.toString(),
+                            "RLE+BOS-M",
+                            comp.toString(),
+                            String.valueOf(encodeTime),
+                            String.valueOf(decodeTime),
+                            String.valueOf(data1.size()),
+                            String.valueOf(compressed_size),
+                            String.valueOf(ratio)
+                    };
+                    writer.writeRecord(record);
+                    System.out.println(ratio);
+                }
+                double ratio = 0;
+                double compressed_size = 0;
+                File outfile = new File(parent_dir + "icde0802/example.bin");
+
+                // 使用FileOutputStream将byte数组写入文件
+                try (FileOutputStream fos = new FileOutputStream(outfile)) {
+                    fos.write(encoded_result);
+                } catch (IOException e2) {
+                    // 处理可能的I/O异常
+                    e2.printStackTrace();
+                }
+
+                File input = new File(parent_dir + "icde0802/example.bin");
+                File output = new File(parent_dir + "icde0802/example.7z");
+                SevenZOutputFile out = new SevenZOutputFile(output);
+
+                addToArchiveCompression(out, input, ".");
+                out.closeArchiveEntry();
+
+                long compressed = output.length();
+
+
+                // test compression ratio and compressed size
+                compressed_size += compressed;
+                double ratioTmp =
+                        (double) compressed / (double) (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+
+
+                String[] record = {
+                        f.toString(),
+                        "RLE+BOS-M",
+                        "7ZIP",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void BOSImproveDecodeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R1O4_decode_time/compression_ratio/rle_bos_m";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 4; file_i < 5; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[1];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "RLE+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void BOSImproveEncodeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/rle_bos_m_improve";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 4; file_i < 5; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[1];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "RLE+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
+}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSVTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSVTest.java
index 3cf9de6..223701c 100644
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSVTest.java
+++ b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/RLEBOSVTest.java
@@ -2,6 +2,7 @@
 
 import com.csvreader.CsvReader;
 import com.csvreader.CsvWriter;
+import org.junit.Test;
 
 import java.io.File;
 import java.io.IOException;
@@ -11,7 +12,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 
-import static java.lang.Math.pow;
+import static java.lang.Math.*;
 
 public class RLEBOSVTest {
 
@@ -323,7 +324,9 @@
     private static int BOSEncodeBits(int[] ts_block_delta,
                                       int init_block_size,
                                       int final_k_start_value,
+                                     int final_x_l_plus,
                                       int final_k_end_value,
+                                     int final_x_u_minus,
                                       int max_delta_value,
                                       int[] min_delta,
                                       ArrayList<Integer> repeat_count,
@@ -362,7 +365,7 @@
                 k1++;
 
 
-            } else if (cur_value > final_k_end_value) {
+            } else if (cur_value >= final_k_end_value) {
                 final_right_outlier.add(cur_value - final_k_end_value);
                 final_right_outlier_index.add(i);
                 if (cur_index_bitmap_outlier_bits % 8 != 7) {
@@ -379,7 +382,7 @@
                 k2++;
 
             } else {
-                final_normal.add(cur_value - final_k_start_value-1);
+                final_normal.add(cur_value - final_x_l_plus);
                 index_bitmap_outlier <<= 1;
                 cur_index_bitmap_outlier_bits += 1;
             }
@@ -415,13 +418,16 @@
 
 
 
-        int2Bytes(final_k_start_value,encode_pos,cur_byte);
+        int2Bytes(final_x_l_plus,encode_pos,cur_byte);
         encode_pos += 4;
-        int bit_width_final = getBitWith(final_k_end_value - final_k_start_value-2);
+        int2Bytes(final_k_end_value,encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
         intByte2Bytes(bit_width_final,encode_pos,cur_byte);
         encode_pos += 1;
         int left_bit_width = getBitWith(final_k_start_value);
-        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);
+        int right_bit_width = getBitWith(max_delta_value -final_k_end_value );
         intByte2Bytes(left_bit_width,encode_pos,cur_byte);
         encode_pos += 1;
         intByte2Bytes(right_bit_width,encode_pos,cur_byte);
@@ -491,36 +497,81 @@
         }
 
 
-        int final_k_start_value = -1;
-        int final_k_end_value = max_delta_value+1;
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
 
         int min_bits = 0;
-        min_bits += (getBitWith(final_k_end_value - final_k_start_value ) * (block_size));
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2 ) * (block_size));
+
+        int cur_k1 = 0;
+
+        int x_l_plus_value = 0; // x_l_plus
+        int x_u_minus_value = max_delta_value; // x_u_plus
+
+        for (int end_value_i = 1; end_value_i < unique_value_count; end_value_i++) {
+
+            x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+            int x_u_plus_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+            int cur_bits = 0;
+            int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value); // cur_k1 = 0
+            if (cur_k2 != 0)
+                cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus_value);
 
 
-        int start_value_size =  unique_value_count;
-        for (int start_value_i = 0; start_value_i < start_value_size; start_value_i++) {
-            int k_start_value =  getUniqueValue(sorted_value_list[start_value_i], left_shift) ;
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_x_u_minus = x_u_minus_value;
+                final_k_end_value = x_u_plus_value;
+            }
+        }
 
-            int cur_k1 = getCount(sorted_value_list[start_value_i],mask);
+        int k_start_value = -1; // x_l_minus
+
+        for (int start_value_i = 0; start_value_i < unique_value_count-1; start_value_i++) {
+            long k_start_valueL = sorted_value_list[start_value_i];
+            k_start_value =  getUniqueValue(k_start_valueL, left_shift) ;
+            x_l_plus_value =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+
+
+            cur_k1 = getCount(k_start_valueL,mask);
 
             int k_end_value;
             int cur_bits;
             int cur_k2;
+            k_end_value = max_delta_value + 1;
 
+            cur_bits = 0;
+            cur_k2 = 0;
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            cur_bits += cur_k1 * getBitWith(k_start_value);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k1) * getBitWith(k_end_value- x_l_plus_value); //cur_k2 =0
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_k_start_value = k_start_value;
+                final_x_l_plus = x_l_plus_value;
+                final_k_end_value = k_end_value;
+                final_x_u_minus = max_delta_value;
+            }
 
             for (int end_value_i = start_value_i + 1; end_value_i < unique_value_count; end_value_i++) {
 
+                x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
                 k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
 
                 cur_bits = 0;
                 cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
 
                 cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
-                if (cur_k1 != 0)
-                    cur_bits += cur_k1 * getBitWith(k_start_value);
+                cur_bits += cur_k1 * getBitWith(k_start_value);
                 if (cur_k1 + cur_k2 != block_size)
-                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(k_end_value - k_start_value-2);
+                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
                 if (cur_k2 != 0)
                     cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
 
@@ -528,14 +579,17 @@
                 if (cur_bits < min_bits) {
                     min_bits = cur_bits;
                     final_k_start_value = k_start_value;
+                    final_x_l_plus = x_l_plus_value;
                     final_k_end_value = k_end_value;
+                    final_x_u_minus = x_u_minus_value;
                 }
 
             }
         }
 
-        encode_pos = BOSEncodeBits(ts_block_delta,init_block_size,  final_k_start_value, final_k_end_value, max_delta_value,
-                min_delta,repeat_count, encode_pos , cur_byte);
+
+        encode_pos = BOSEncodeBits(ts_block_delta,init_block_size,  final_k_start_value,final_x_l_plus, final_k_end_value,final_x_u_minus,
+                max_delta_value, min_delta,repeat_count, encode_pos , cur_byte);
 
         return encode_pos;
     }
@@ -585,6 +639,452 @@
         return encode_pos;
     }
 
+    public static int EncodeBits(int num,
+                                 int bit_width,
+                                 int encode_pos,
+                                 byte[] cur_byte,
+                                 int[] bit_index_list){
+        // 找到要插入的位的索引
+        int bit_index = bit_index_list[0] ;//cur_byte[encode_pos + 1];
+
+        // 计算数值的起始位位置
+        int remaining_bits = bit_width;
+
+        while (remaining_bits > 0) {
+            // 计算在当前字节中可以使用的位数
+            int available_bits = bit_index;
+            int bits_to_write = Math.min(available_bits, remaining_bits);
+
+            // 更新 bit_index
+            bit_index = available_bits - bits_to_write;
+
+            // 计算要写入的位的掩码和数值
+            int mask = (1 << bits_to_write) - 1;
+            int bits = (num >> (remaining_bits - bits_to_write)) & mask;
+
+            // 写入到当前位置
+            cur_byte[encode_pos] &= (byte) ~(mask << bit_index); // 清除对应位置的位
+            cur_byte[encode_pos] |= (byte) (bits << bit_index);
+
+            // 更新位宽和数值
+            remaining_bits -= bits_to_write;
+            if (bit_index == 0) {
+                bit_index = 8;
+                encode_pos++;
+            }
+        }
+        bit_index_list[0] = bit_index;
+//        cur_byte[encode_pos + 1] = (byte) bit_index;
+        return encode_pos;
+    }
+    private static int BOSEncodeBitsImprove(int[] ts_block_delta,
+                                            int init_block_size,
+                                            int final_k_start_value,
+                                            int final_x_l_plus,
+                                            int final_k_end_value,
+                                            int final_x_u_minus,
+                                            int max_delta_value,
+                                            int[] min_delta,
+                                            ArrayList<Integer> repeat_count,
+                                            int encode_pos,
+                                            byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+
+        int k1 = 0;
+        int k2 = 0;
+
+
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+//                encode_pos = EncodeBits(cur_value,left_bit_width,encode_pos,cur_byte);
+//                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+//                encode_pos = EncodeBits(cur_value- final_k_end_value,right_bit_width,encode_pos,cur_byte);
+//                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+//                final_normal.add(cur_value - final_x_l_plus);
+//                encode_pos = EncodeBits(cur_value- final_x_l_plus,right_bit_width,encode_pos,cur_byte);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int size = repeat_count.size();
+        intByte2Bytes(size,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        int[] bit_index_list = new int[1];
+        bit_index_list[0] = 8;
+        if (size != 0){
+            int bit_width_init = getBitWith(init_block_size-1);
+            for(int repeat_count_v:repeat_count){
+                encode_pos = EncodeBits(repeat_count_v, bit_width_init, encode_pos, cur_byte, bit_index_list);
+            }
+            if(bit_index_list[0] != 8){
+                bit_index_list[0] = 8;
+                encode_pos ++;
+            }
+        }
+//            encode_pos =encodeOutlier2Bytes(repeat_count, getBitWith(init_block_size-1),encode_pos,cur_byte);
+
+//        int2Bytes(min_delta[1],encode_pos,cur_byte);
+//        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+
+
+        if(final_k_start_value<0 && final_k_end_value > max_delta_value){
+//            int bit_width_final= getBitWith(final_x_u_minus - final_x_l_plus);
+//            cur_byte[encode_pos+1] = 8;
+            bit_index_list[0] = 8;
+            for (int cur_value : ts_block_delta) {
+                encode_pos = EncodeBits(cur_value, bit_width_final, encode_pos, cur_byte, bit_index_list);
+//                final_normal.add(cur_value);
+            }
+            if(bit_index_list[0] != 8){
+                encode_pos ++;
+            }
+//            cur_byte[encode_pos+1] = 0;
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+            return encode_pos;
+        }
+
+
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+        int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(final_k_end_value,encode_pos,cur_byte);
+        encode_pos += 4;
+
+//        bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//        encode_pos += 1;
+        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        if (final_alpha == 0) { // 0
+
+            for (int i : bitmap_outlier) {
+
+                intByte2Bytes(i,encode_pos,cur_byte);
+                encode_pos += 1;
+            }
+        } else {
+            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+        }
+//        cur_byte[encode_pos+1] = 8;
+//        bit_index_list[0] = 8;
+        for (int cur_value : ts_block_delta) {
+            if (cur_value <= final_k_start_value) {
+                encode_pos = EncodeBits(cur_value, left_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else if (cur_value >= final_k_end_value) {
+                encode_pos = EncodeBits(cur_value - final_k_end_value, right_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else {
+                encode_pos = EncodeBits(cur_value - final_x_l_plus, bit_width_final, encode_pos, cur_byte,bit_index_list);
+            }
+        }
+        if(bit_index_list[0] != 8){
+            encode_pos ++;
+        }
+
+//        cur_byte[encode_pos+1] = 0;
+
+//        if(k1==0 && k2==0){
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//
+//
+//        }
+//        else{
+//            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+//            encode_pos += 4;
+//            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+//            encode_pos += 4;
+//
+//            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            if (final_alpha == 0) { // 0
+//
+//                for (int i : bitmap_outlier) {
+//
+//                    intByte2Bytes(i,encode_pos,cur_byte);
+//                    encode_pos += 1;
+//                }
+//            } else {
+//                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//            }
+//        }
+
+
+//        if(k1+k2!=block_size)
+//        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//        if (k1 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+//        if (k2 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+//        System.out.println(encode_pos);
+        return encode_pos;
+
+    }
+    private static int BOSBlockEncoderImprove(int[] ts_block, int block_i, int block_size,int remaining, int encode_pos , byte[] cur_byte) {
+
+        ArrayList<Integer> repeat_count = new ArrayList<>();
+        int init_block_size = block_size;
+
+        int[] min_delta = new int[3];
+        int[]  ts_block_delta = getAbsDeltaTsBlock(ts_block,block_i, init_block_size,remaining, min_delta, repeat_count);
+        block_size = min_delta[1];
+
+
+        int max_delta_value = min_delta[2];
+        int[] value_list = new int[block_size];
+        int unique_value_count = 0;
+        int[] value_count_list = new int[max_delta_value+1];
+        for(int value:ts_block_delta){
+            if(value_count_list[value]==0){
+                value_count_list[value] = 1;
+                value_list[unique_value_count] = value;
+                unique_value_count ++;
+            }else{
+                value_count_list[value] ++;
+            }
+        }
+
+        int left_shift = getBitWith(block_size);
+        int mask =  (1 << left_shift) - 1;
+        long[] sorted_value_list = new long[unique_value_count];
+        int count = 0;
+
+        for(int i=0;i<unique_value_count;i++){
+            int value = value_list[i];
+
+            sorted_value_list[i] = (((long) value) << left_shift) + value_count_list[value];
+        }
+        Arrays.sort(sorted_value_list);
+
+        for(int i=0;i<unique_value_count;i++){
+            count += getCount(sorted_value_list[i], mask);
+            sorted_value_list[i] = (((long)getUniqueValue(sorted_value_list[i], left_shift) ) << left_shift) + count;//new_value_list[i]
+        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2 ) * (block_size));
+
+        int cur_k1 = 0;
+
+        int x_l_plus_value = 0; // x_l_plus
+        int x_u_minus_value = max_delta_value; // x_u_plus
+
+        for (int end_value_i = 1; end_value_i < unique_value_count; end_value_i++) {
+
+            x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+            int x_u_plus_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+            int cur_bits = 0;
+            int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value); // cur_k1 = 0
+            if (cur_k2 != 0)
+                cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus_value);
+
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_x_u_minus = x_u_minus_value;
+                final_k_end_value = x_u_plus_value;
+            }
+        }
+
+        int k_start_value = -1; // x_l_minus
+
+        for (int start_value_i = 0; start_value_i < unique_value_count-1; start_value_i++) {
+            long k_start_valueL = sorted_value_list[start_value_i];
+            k_start_value =  getUniqueValue(k_start_valueL, left_shift) ;
+            x_l_plus_value =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+
+
+            cur_k1 = getCount(k_start_valueL,mask);
+
+            int k_end_value;
+            int cur_bits;
+            int cur_k2;
+            k_end_value = max_delta_value + 1;
+
+            cur_bits = 0;
+            cur_k2 = 0;
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            cur_bits += cur_k1 * getBitWith(k_start_value);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k1) * getBitWith(k_end_value- x_l_plus_value); //cur_k2 =0
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_k_start_value = k_start_value;
+                final_x_l_plus = x_l_plus_value;
+                final_k_end_value = k_end_value;
+                final_x_u_minus = max_delta_value;
+            }
+
+            for (int end_value_i = start_value_i + 1; end_value_i < unique_value_count; end_value_i++) {
+
+                x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+                k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+
+                cur_bits = 0;
+                cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+
+                cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                cur_bits += cur_k1 * getBitWith(k_start_value);
+                if (cur_k1 + cur_k2 != block_size)
+                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+                if (cur_k2 != 0)
+                    cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+
+
+                if (cur_bits < min_bits) {
+                    min_bits = cur_bits;
+                    final_k_start_value = k_start_value;
+                    final_x_l_plus = x_l_plus_value;
+                    final_k_end_value = k_end_value;
+                    final_x_u_minus = x_u_minus_value;
+                }
+
+            }
+        }
+
+
+        encode_pos = BOSEncodeBitsImprove(ts_block_delta,init_block_size,  final_k_start_value,final_x_l_plus, final_k_end_value,final_x_u_minus,
+                max_delta_value, min_delta,repeat_count, encode_pos , cur_byte);
+
+        return encode_pos;
+    }
+
+    public static int BOSEncoderImprove(
+            int[] data, int block_size, byte[] encoded_result) {
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+
+
+            encode_pos =  BOSBlockEncoderImprove(data, i, block_size, block_size,encode_pos,encoded_result);
+//            System.out.println(encode_pos);
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        } else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+
+            encode_pos = BOSBlockEncoderImprove(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+//            int[] ts_block = new int[length_all-start];
+//            if (length_all - start >= 0) System.arraycopy(data, start, ts_block, 0, length_all - start);
+//
+//
+//            encode_pos = BOSBlockEncoder(ts_block, encode_pos,encoded_result);
+
+        }
+
+
+        return encode_pos;
+    }
+
     public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list,int init_block_size, int block_size, int[] value_pos_arr) {
 
         int k_byte = bytes2Integer(encoded, decode_pos, 4);
@@ -618,6 +1118,9 @@
         int final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
         decode_pos += 4;
 
+        int final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
         int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
         decode_pos += 1;
 
@@ -714,7 +1217,7 @@
         int right_outlier_i = 0;
         int normal_i = 0;
         int pre_v;
-        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
 
         int cur_i = 0;
         int repeat_i = 0;
@@ -803,10 +1306,321 @@
         }
     }
 
+    public static int DecodeBits(byte[] cur_byte, int bit_width, int[] decode_pos_list) {
+        int decode_pos = decode_pos_list[0];
+        int bit_index = decode_pos_list[1];  //cur_byte[decode_pos + 1];
+        int remaining_bits = bit_width;
+        int num = 0;
+
+        while (remaining_bits > 0) {
+            int available_bits = bit_index;
+            int bits_to_read = Math.min(available_bits, remaining_bits);
+
+            // 计算要读取的位的掩码
+            int mask = (1 << bits_to_read) - 1;
+            int bits = (cur_byte[decode_pos] >> (available_bits - bits_to_read)) & mask;
+
+            // 将读取的位合并到结果中
+            num = (num << bits_to_read) | bits;
+
+            // 更新位宽和 bit_index
+            remaining_bits -= bits_to_read;
+            bit_index = available_bits - bits_to_read;
+
+            if (bit_index == 0) {
+                bit_index = 8;
+                decode_pos++;
+            }
+        }
+        decode_pos_list[0] = decode_pos;
+        decode_pos_list[1] = bit_index;
+
+        return num;
+    }
+
+    public static int BOSBlockDecoderImprove(byte[] encoded, int decode_pos, int[] value_list,int init_block_size, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+//        int value0 = bytes2Integer(encoded, decode_pos, 4);
+//        decode_pos += 4;
+//        value_list[value_pos_arr[0]] =value0;
+//        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int count_size = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        int[] decode_list = new int[2];
+        decode_list[0]= decode_pos;
+        decode_list[1]= 8;
+
+        int valuePos = value_pos_arr[0];
+
+//        ArrayList<Integer> repeat_count = new ArrayList<>();
+        ArrayList<Integer> repeat_count = new ArrayList<>();
+        if (count_size != 0) {
+            int bit_width_init =  getBitWith(init_block_size-1);
+            for(int i = 0;i<count_size;i++){
+                int repeat_count_v = DecodeBits(encoded, bit_width_init,  decode_list);
+                repeat_count.add(repeat_count_v);
+            }
+
+            if(decode_list[1] != 8){
+                decode_list[1] = 8;
+                decode_list[0] ++;
+            }
+//            repeat_count = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(init_block_size-1), count_size, repeat_count_result);
+            decode_pos = decode_list[0];
+//            decode_list[1]= 8;
+        }
+
+        int cur_block_size = block_size;
+        for (int i = 1; i < count_size; i += 2) {
+            cur_block_size -= (repeat_count.get(i) - 1);
+        }
+
+        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+
+
+        int pre_v;
+        int cur_i = 0;
+        int repeat_i = 0;
+        if(k1==0 && k2==0){
+//            int pre_v = value0;
+            decode_list[0] = decode_pos;
+            decode_list[1]= 8;
+            for (int i = 0; i < cur_block_size; i++) {
+                pre_v = min_delta + DecodeBits(encoded, bit_width_final,  decode_list);
+//                value_list[value_pos_arr[0]++] = pre_v;
+                if (repeat_i < count_size && cur_i == repeat_count.get(repeat_i)) {
+                    cur_i += (repeat_count.get(repeat_i+1));
+
+                    for (int j = 0; j < repeat_count.get(repeat_i + 1); j++) {
+                        value_list[value_pos_arr[0]++] = pre_v;
+                    }
+                    repeat_i += 2;
+                } else {
+                    cur_i++;
+                    value_list[value_pos_arr[0]++] = pre_v;
+                }
+            }
+            if(decode_list[1] != 8){
+                decode_list[1] = 8;
+                decode_list[0] ++;
+            }
+
+//            value_pos_arr[0] = valuePos;
+            return decode_list[0];
+        }
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+//        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+//        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+//        bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+//        decode_pos += 1;
+
+        left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+        right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        if (final_alpha == 0) {
+            int bitmap_bytes = (int) Math.ceil((double) (cur_block_size + k1 + k2) / (double) 8);
+            for (int i = 0; i < bitmap_bytes; i++) {
+                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                decode_pos += 1;
+            }
+            int bitmap_outlier_i = 0;
+            int remaining_bits = 8;
+            int tmp = bitmap_outlier.get(bitmap_outlier_i);
+            bitmap_outlier_i++;
+            int i = 0;
+            while (i < cur_block_size ) {
+                if (remaining_bits > 1) {
+                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                    remaining_bits -= 1;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                    if (remaining_bits == 0) {
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                    }
+                } else if (remaining_bits == 1) {
+                    int bit_i = tmp & 0x1;
+                    remaining_bits = 8;
+                    if (bitmap_outlier_i >= bitmap_bytes) break;
+                    tmp = bitmap_outlier.get(bitmap_outlier_i);
+                    bitmap_outlier_i++;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                }
+                i++;
+            }
+        } else {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(cur_block_size-1), k1, decode_pos_result_left);
+            decode_pos = (decode_pos_result_left.get(0));
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(cur_block_size-1), k2, decode_pos_result_right);
+            decode_pos = (decode_pos_result_right.get(0));
+        }
+
+
+
+
+
+//        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+//        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+//
+//        decode_pos = decode_pos_normal.get(0);
+//        if (k1 != 0) {
+//            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+//            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+//            decode_pos = decode_pos_result_left.get(0);
+//        }
+//        if (k2 != 0) {
+//            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+//            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+//            decode_pos = decode_pos_result_right.get(0);
+//        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+//        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+// Precompute constants
+        int normalOffset = min_delta + final_k_start_value;
+        int rightOutlierOffset = min_delta + final_k_end_value;
+
+// Initialize indices and pre-fetch next outlier positions
+        int leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+        int rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+        decode_list[0]= decode_pos;
+//        decode_list[1]= 8;
+        // Use a local variable for the position
+        for (int i = 0; i < cur_block_size; i++) {
+//            int currentDelta;
+            if (i == leftOutlierNextIndex) {
+                // Process left outlier
+                pre_v = min_delta + DecodeBits(encoded, left_bit_width,  decode_list); // final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+                leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+            } else if (i == rightOutlierNextIndex) {
+                // Process right outlier
+                pre_v = rightOutlierOffset + DecodeBits(encoded, right_bit_width,  decode_list);// final_right_outlier.get(right_outlier_i);
+                right_outlier_i++;
+                rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+            } else {
+                // Process normal value
+                pre_v = normalOffset + DecodeBits(encoded, bit_width_final,  decode_list);
+                normal_i++;
+            }
+            if (repeat_i < count_size && cur_i == repeat_count.get(repeat_i)) {
+                cur_i += (repeat_count.get(repeat_i+1));
+
+                for (int j = 0; j < repeat_count.get(repeat_i + 1); j++) {
+                    value_list[value_pos_arr[0]++] = pre_v;
+                }
+                repeat_i += 2;
+            } else {
+                cur_i++;
+                value_list[value_pos_arr[0]++] = pre_v;
+            }
+            // Update the cumulative value and store it
+//            pre_v += deZigzag(currentDelta);
+//            value_list[valuePos++] = pre_v;
+        }
+//        value_pos_arr[0] = valuePos;
+        if(decode_list[1]!=8){
+            return decode_list[0]+1;
+        }else {
+            return decode_list[0];
+        }
+//        decode_pos = decode_list[0];
+// Update the position in the array
+
+
+//        return decode_pos;
+    }
+    public static void BOSDecoderImprove(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        int[] value_pos_arr = new int[1];
+
+        for (int k = 0; k < block_num; k++) {
+//            System.out.println(k);
+            decode_pos = BOSBlockDecoderImprove(encoded, decode_pos, value_list, block_size, block_size, value_pos_arr);
+//            System.out.println(decode_pos);
+        }
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            BOSBlockDecoderImprove(encoded, decode_pos, value_list,block_size, remain_length, value_pos_arr);
+        }
+    }
+
     public static void main(@org.jetbrains.annotations.NotNull String[] args) throws IOException {
-//        String parent_dir = "/Users/xiaojinzhao/Desktop/encoding-outlier/";// your data path
-        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
-        String output_parent_dir = parent_dir + "vldb/compression_ratio/rle_bos";
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/rle_bos";
         String input_parent_dir = parent_dir + "trans_data/";
         ArrayList<String> input_path_list = new ArrayList<>();
         ArrayList<String> output_path_list = new ArrayList<>();
@@ -931,7 +1745,7 @@
 
                 String[] record = {
                         f.toString(),
-                        "RLE+BOS-O",
+                        "RLE+BOS-V",
                         String.valueOf(encodeTime),
                         String.valueOf(decodeTime),
                         String.valueOf(data1.size()),
@@ -947,4 +1761,285 @@
         }
     }
 
+    @Test
+    public void ExpTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/exp_v";
+        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<>();
+
+        dataset_name.add("Synthetic_Exp_100");
+        dataset_name.add("Synthetic_Exp_1000");
+        dataset_name.add("Synthetic_Exp_10000");
+        dataset_name.add("Synthetic_Exp_100000");
+        dataset_name.add("Synthetic_Exp_1000000");
+        dataset_name.add("Synthetic_Normal_100");
+        dataset_name.add("Synthetic_Normal_1000");
+        dataset_name.add("Synthetic_Normal_10000");
+        dataset_name.add("Synthetic_Normal_100000");
+        dataset_name.add("Synthetic_Normal_1000000");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        output_path_list.add(output_parent_dir + "/Exp_100.csv"); // 0
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/Exp_1000.csv");// 1
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Exp_10000.csv");// 2
+        output_path_list.add(output_parent_dir + "/Exp_100000.csv");// 2
+        output_path_list.add(output_parent_dir + "/Exp_1000000.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Normal_100.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Normal_1000.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/Normal_10000.csv");//5
+        output_path_list.add(output_parent_dir + "/Normal_100000.csv");//5
+        output_path_list.add(output_parent_dir + "/Normal_1000000.csv");//5
+//        dataset_block_size.add(2048);
+
+        int repeatTime2 = 1000;
+//        for (int file_i = 8; file_i < 9; file_i++) {
+
+        for (int file_i = input_path_list.size()-1; file_i >=0 ; file_i--) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoder(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "RLE+BOS-V",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+            }
+            writer.close();
+
+
+        }
+    }
+
+    @Test
+    public void BOSImproveTimeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R1O4_decode_time/compression_ratio/rle_bos_v";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 4; file_i < 5; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[1];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "RLE+BOS-V",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
 }
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSBTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSBTest.java
new file mode 100644
index 0000000..2090235
--- /dev/null
+++ b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSBTest.java
@@ -0,0 +1,2150 @@
+package org.apache.iotdb.tsfile.encoding;
+
+import com.csvreader.CsvReader;
+import com.csvreader.CsvWriter;
+import org.junit.Test;
+
+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.ArrayList;
+import java.util.Arrays;
+
+import static java.lang.Math.pow;
+
+public class SPRINTZBOSBTest {
+
+    public static int getBitWith(int num) {
+        if (num == 0) return 1;
+        else return 32 - Integer.numberOfLeadingZeros(num);
+    }
+    public static int getCount(long long1, int mask) {
+        return ((int) (long1 & mask));
+    }
+    public static int getUniqueValue(long long1, int left_shift) {
+        return ((int) ((long1) >> left_shift));
+    }
+
+    public static int zigzag(int num) {
+        if (num < 0) return ((-num)<<1)-1;
+        else return num<<1;
+    }
+
+    public static int deZigzag(int num) {
+        if (num % 2 == 0) return num>>1;
+        else return -((num+1)>>1);
+    }
+
+    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 ;
+                }
+            }
+        }
+
+    }
+
+    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 int[] getAbsDeltaTsBlock(
+            int[] ts_block,
+            int i,
+            int block_size,
+            int remaining,
+            int[] min_delta) {
+        int[] ts_block_delta = new int[remaining-1];
+
+        int base = i*block_size+1;
+        int end = i*block_size+remaining;
+        min_delta[0]=ts_block[base-1];
+        int value_delta_min = Integer.MAX_VALUE;
+        int value_delta_max = Integer.MIN_VALUE;
+        for (int j = base; j < end; j++) {
+            int epsilon_v = ts_block[j] - ts_block[j - 1];
+            epsilon_v = zigzag(epsilon_v);
+            if (epsilon_v < value_delta_min) {
+                value_delta_min = epsilon_v;
+            }
+            if (epsilon_v > value_delta_max) {
+                value_delta_max = epsilon_v;
+            }
+            ts_block_delta[j-base] =epsilon_v;
+
+        }
+        for (int j = 0; j < remaining-1; j++) {
+            ts_block_delta[j] =ts_block_delta[j]-value_delta_min;
+
+        }
+        min_delta[1] = (value_delta_min);
+        min_delta[2] = (value_delta_max-value_delta_min);
+
+
+        return ts_block_delta;
+    }
+
+    public static int encodeOutlier2Bytes(
+            ArrayList<Integer> ts_block_delta,
+            int bit_width,
+            int encode_pos,  byte[] encoded_result)     {
+
+        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
+
+        int n_k = ts_block_delta.size();
+        int n_k_b = n_k / 8;
+        long cur_remaining = 0; // encoded int
+        int cur_number_bits = 0; // the bit width used of encoded int
+        for (int i = n_k_b * 8; i < n_k; i++) {
+            long cur_value = ts_block_delta.get(i);
+            int cur_bit_width = bit_width; // remaining bit width of current value
+
+            if (cur_number_bits + bit_width >= 32) {
+                cur_remaining <<= (32 - cur_number_bits);
+                cur_bit_width = bit_width - 32 + cur_number_bits;
+                cur_remaining += ((cur_value >> cur_bit_width));
+                long2intBytes(cur_remaining,encode_pos,encoded_result);
+                encode_pos += 4;
+                cur_remaining = 0;
+                cur_number_bits = 0;
+            }
+
+            cur_remaining <<= cur_bit_width;
+            cur_number_bits += cur_bit_width;
+            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width));
+        }
+        cur_remaining <<= (32 - cur_number_bits);
+        long2intBytes(cur_remaining,encode_pos,encoded_result);
+        encode_pos += 4;
+        return encode_pos;
+
+
+    }
+
+
+    public static ArrayList<Integer> decodeOutlier2Bytes(
+            byte[] encoded,
+            int decode_pos,
+            int bit_width,
+            int length,
+            ArrayList<Integer> encoded_pos_result
+    ) {
+
+        int n_k_b = length / 8;
+        int remaining = length - n_k_b * 8;
+        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
+        decode_pos += n_k_b * bit_width;
+
+        ArrayList<Long> int_remaining = new ArrayList<>();
+        int int_remaining_size = remaining * bit_width / 32 + 1;
+        for (int j = 0; j < int_remaining_size; j++) {
+            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
+            decode_pos += 4;
+        }
+
+        int cur_remaining_bits = 32; // remaining bit width of current value
+        long cur_number = int_remaining.get(0);
+        int cur_number_i = 1;
+        for (int i = n_k_b * 8; i < length; i++) {
+            if (bit_width < cur_remaining_bits) {
+                int tmp = (int) (cur_number >> (32 - bit_width));
+                result_list.add(tmp);
+                cur_number <<= bit_width;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits -= bit_width;
+            } else {
+                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
+                int remain_bits = bit_width - cur_remaining_bits;
+                tmp <<= remain_bits;
+
+                cur_number = int_remaining.get(cur_number_i);
+                cur_number_i++;
+                tmp += (cur_number >> (32 - remain_bits));
+                result_list.add(tmp);
+                cur_number <<= remain_bits;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits = 32 - remain_bits;
+            }
+        }
+        encoded_pos_result.add(decode_pos);
+        return result_list;
+    }
+
+    private static int BOSEncodeBits(int[] ts_block_delta,
+                                     int final_k_start_value,
+                                     int final_x_l_plus,
+                                     int final_k_end_value,
+                                     int final_x_u_minus,
+                                     int max_delta_value,
+                                     int[] min_delta,
+                                     int encode_pos,
+                                     byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        int k1 = 0;
+        int k2 = 0;
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+                final_normal.add(cur_value - final_k_start_value-1);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte); // x0
+        encode_pos += 4;
+        int2Bytes(min_delta[1],encode_pos,cur_byte); // x_min
+        encode_pos += 4;
+        int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(final_k_end_value,encode_pos,cur_byte);
+        encode_pos += 4;
+//        int2Bytes(final_k_start_value,encode_pos,cur_byte);
+//        encode_pos += 4;
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        if (final_alpha == 0) { // 0
+
+            for (int i : bitmap_outlier) {
+
+                intByte2Bytes(i,encode_pos,cur_byte);
+                encode_pos += 1;
+            }
+        } else {
+            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+        }
+        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+        if (k1 != 0)
+            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+        if (k2 != 0)
+            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+        return encode_pos;
+
+    }
+
+
+    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size, int remaining ,int encode_pos , byte[] cur_byte) {
+
+        int[] min_delta = new int[3];
+        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
+
+
+        block_size = remaining-1;
+        int max_delta_value = min_delta[2];
+
+        int[] value_list = new int[block_size];
+        int unique_value_count = 0;
+        int[] value_count_list = new int[max_delta_value+1];
+        for(int value:ts_block_delta){
+            if(value_count_list[value]==0){
+                value_count_list[value] = 1;
+                value_list[unique_value_count] = value;
+                unique_value_count ++;
+            }else{
+                value_count_list[value] ++;
+            }
+        }
+
+        int left_shift = getBitWith(block_size);
+        int mask =  (1 << left_shift) - 1;
+        long[] sorted_value_list = new long[unique_value_count];
+        int count = 0;
+
+        for(int i=0;i<unique_value_count;i++){
+            int value = value_list[i];
+            sorted_value_list[i] = (((long) value) << left_shift) + value_count_list[value];
+        }
+        Arrays.sort(sorted_value_list);
+
+        for(int i=0;i<unique_value_count;i++){
+            count += getCount(sorted_value_list[i], mask);
+            sorted_value_list[i] = (((long)getUniqueValue(sorted_value_list[i], left_shift) ) << left_shift) + count;//new_value_list[i]
+        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2 ) * (block_size));
+
+        int cur_k1 = 0;
+
+        int x_l_plus_value = 0; // x_l_plus
+        int x_u_minus_value = max_delta_value; // x_u_plus
+
+        for (int end_value_i = 1; end_value_i < unique_value_count; end_value_i++) {
+
+            x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+            int x_u_plus_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+            int cur_bits = 0;
+            int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value); // cur_k1 = 0
+            if (cur_k2 != 0)
+                cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus_value);
+
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_x_u_minus = x_u_minus_value;
+                final_k_end_value = x_u_plus_value;
+            }
+        }
+
+        int k_start_value = -1; // x_l_minus
+
+        int gamma_max = getBitWith(max_delta_value);
+        int[] gamma_count_list = new int[gamma_max+1];
+        int[] x_u_minus_value_list = new int[gamma_max+1];
+        int[] x_u_plus_value_list = new int[gamma_max+1];
+        int end_i = unique_value_count - 1;
+        for(int gamma = 0; gamma <= gamma_max; gamma++) {
+            int x_u_plus_pow_beta = (int) (max_delta_value - pow(2, gamma) + 1);
+            for (; end_i > 0; end_i--) {
+                x_u_minus_value = getUniqueValue(sorted_value_list[end_i - 1], left_shift);
+                int x_u_plus_value = getUniqueValue(sorted_value_list[end_i], left_shift);
+                if (x_u_minus_value < x_u_plus_pow_beta && x_u_plus_value >= x_u_plus_pow_beta){
+                    gamma_count_list[gamma] = getCount(sorted_value_list[end_i-1],mask);
+                    x_u_minus_value_list[gamma] = x_u_minus_value;
+                    x_u_plus_value_list[gamma] = x_u_plus_value;
+                } else if (x_u_minus_value < x_u_plus_pow_beta) {
+                    break;
+                }
+            }
+        }
+        for(int gamma = 1; gamma < gamma_max; gamma++) {
+            if(gamma_count_list[gamma]==0){
+                gamma_count_list[gamma] = gamma_count_list[gamma-1];
+                x_u_minus_value_list[gamma] = x_u_minus_value_list[gamma-1];
+                x_u_plus_value_list[gamma] = x_u_plus_value_list[gamma-1];
+            }
+        }
+
+        for (int start_value_i = 0; start_value_i < unique_value_count-1; start_value_i++) {
+            long k_start_valueL = sorted_value_list[start_value_i];
+            k_start_value =  getUniqueValue(k_start_valueL, left_shift) ;
+            x_l_plus_value =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+
+
+            cur_k1 = getCount(k_start_valueL,mask);
+
+            int k_end_value;
+            int cur_bits;
+            int cur_k2;
+            k_end_value = max_delta_value + 1;
+
+            cur_bits = 0;
+            cur_k2 = 0;
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            cur_bits += cur_k1 * getBitWith(k_start_value);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k1) * getBitWith(k_end_value- x_l_plus_value); //cur_k2 =0
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_k_start_value = k_start_value;
+                final_x_l_plus = x_l_plus_value;
+                final_k_end_value = k_end_value;
+                final_x_u_minus = max_delta_value;
+            }
+
+            int beta_max = getBitWith(max_delta_value - x_l_plus_value);
+            int end_value_i = start_value_i + 1;
+            int lower_outlier_cost = cur_k1 * getBitWith(k_start_value);
+            for(int beta = 1; beta < beta_max; beta++){
+                int x_u_plus_pow_beta = (int) (x_l_plus_value + pow(2,beta));
+
+                for (; end_value_i < unique_value_count; end_value_i++) {
+                    long k_end_valueL = sorted_value_list[end_value_i-1];
+
+                    x_u_minus_value = getUniqueValue(k_end_valueL, left_shift);
+                    k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+                    if(x_u_minus_value < x_u_plus_pow_beta && k_end_value >= x_u_plus_pow_beta){
+                        cur_bits = 0;
+                        cur_k2 = block_size - getCount(k_end_valueL,mask);
+
+                        cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                        cur_bits += lower_outlier_cost;
+                        if (cur_k1 + cur_k2 != block_size)
+                            cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+                        if (cur_k2 != 0)
+                            cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+
+
+                        if (cur_bits < min_bits) {
+                            min_bits = cur_bits;
+                            final_k_start_value = k_start_value;
+                            final_x_l_plus = x_l_plus_value;
+                            final_k_end_value = k_end_value;
+                            final_x_u_minus = x_u_minus_value;
+                        }
+                    } else if (x_u_minus_value >= x_u_plus_pow_beta && k_end_value >= x_u_plus_pow_beta) {
+                        break;
+                    }
+                }
+            }
+
+            for(int gamma = 0; gamma < beta_max; gamma++){
+//                int x_u_plus_pow_beta = (int) (max_delta_value - pow(2,gamma)+1);
+                x_u_minus_value = x_u_minus_value_list[gamma];
+                k_end_value =  x_u_plus_value_list[gamma];
+                cur_bits = 0;
+                cur_k2 = block_size - gamma_count_list[gamma];
+
+                cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                cur_bits += lower_outlier_cost;
+                if (cur_k1 + cur_k2 != block_size)
+                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+                if (cur_k2 != 0)
+                    cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+
+
+                if (cur_bits < min_bits) {
+                    min_bits = cur_bits;
+                    final_k_start_value = k_start_value;
+                    final_x_l_plus = x_l_plus_value;
+                    final_k_end_value = k_end_value;
+                    final_x_u_minus = x_u_minus_value;
+                }
+
+            }
+
+//            end_value_i = unique_value_count - 1;
+//            for(int gamma = 1; gamma <= beta_max; gamma++){
+//                for (; end_value_i > start_value_i; end_value_i--) {
+//                    int x_u_plus_pow_beta = (int) (max_delta_value - pow(2,gamma)+1);
+//                    x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+//                    k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+//                    if(x_u_minus_value < x_u_plus_pow_beta && k_end_value >= x_u_plus_pow_beta){
+//                        cur_bits = 0;
+//                        cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+//
+//                        cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+//                        cur_bits += cur_k1 * getBitWith(k_start_value);
+//                        if (cur_k1 + cur_k2 != block_size)
+//                            cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+//                        if (cur_k2 != 0)
+//                            cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+//
+//
+//                        if (cur_bits < min_bits) {
+//                            min_bits = cur_bits;
+//                            final_k_start_value = k_start_value;
+//                            final_x_l_plus = x_l_plus_value;
+//                            final_k_end_value = k_end_value;
+//                            final_x_u_minus = x_u_minus_value;
+//                        }
+//                    } else if (x_u_minus_value <= x_u_plus_pow_beta && k_end_value <= x_u_plus_pow_beta) {
+//                        break;
+//                    }
+//                }
+//            }
+
+
+        }
+
+        encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_x_l_plus, final_k_end_value, final_x_u_minus,
+                max_delta_value, min_delta, encode_pos , cur_byte);
+
+        return encode_pos;
+    }
+
+    public static int BOSEncoder(
+            int[] data, int block_size, byte[] encoded_result) {
+        block_size++;
+
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+
+            encode_pos =  BOSBlockEncoder(data, i, block_size,block_size, encode_pos,encoded_result);
+
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        } else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+
+
+            encode_pos = BOSBlockEncoder(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+
+//            int[] ts_block = new int[length_all-start];
+//            if (length_all - start >= 0) System.arraycopy(data, start, ts_block, 0, length_all - start);
+//
+//            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;
+//            }
+//
+//
+//            encode_pos = BOSBlockEncoder(ts_block, supple_length, encode_pos,encoded_result);
+        }
+
+
+        return encode_pos;
+    }
+    public static int EncodeBits(int num,
+                                 int bit_width,
+                                 int encode_pos,
+                                 byte[] cur_byte,
+                                 int[] bit_index_list){
+        // 找到要插入的位的索引
+        int bit_index = bit_index_list[0] ;//cur_byte[encode_pos + 1];
+
+        // 计算数值的起始位位置
+        int remaining_bits = bit_width;
+
+        while (remaining_bits > 0) {
+            // 计算在当前字节中可以使用的位数
+            int available_bits = bit_index;
+            int bits_to_write = Math.min(available_bits, remaining_bits);
+
+            // 更新 bit_index
+            bit_index = available_bits - bits_to_write;
+
+            // 计算要写入的位的掩码和数值
+            int mask = (1 << bits_to_write) - 1;
+            int bits = (num >> (remaining_bits - bits_to_write)) & mask;
+
+            // 写入到当前位置
+            cur_byte[encode_pos] &= (byte) ~(mask << bit_index); // 清除对应位置的位
+            cur_byte[encode_pos] |= (byte) (bits << bit_index);
+
+            // 更新位宽和数值
+            remaining_bits -= bits_to_write;
+            if (bit_index == 0) {
+                bit_index = 8;
+                encode_pos++;
+            }
+        }
+        bit_index_list[0] = bit_index;
+//        cur_byte[encode_pos + 1] = (byte) bit_index;
+        return encode_pos;
+    }
+    private static int BOSEncodeBitsImprove(int[] ts_block_delta,
+                                            int final_k_start_value,
+                                            int final_x_l_plus,
+                                            int final_k_end_value,
+                                            int final_x_u_minus,
+                                            int max_delta_value,
+                                            int[] min_delta,
+                                            int encode_pos,
+                                            byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        int k1 = 0;
+        int k2 = 0;
+
+
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+//                encode_pos = EncodeBits(cur_value,left_bit_width,encode_pos,cur_byte);
+//                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+//                encode_pos = EncodeBits(cur_value- final_k_end_value,right_bit_width,encode_pos,cur_byte);
+//                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+//                final_normal.add(cur_value - final_x_l_plus);
+//                encode_pos = EncodeBits(cur_value- final_x_l_plus,right_bit_width,encode_pos,cur_byte);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+        int[] bit_index_list = new int[1];
+        bit_index_list[0] = 8;
+
+        if(final_k_start_value<0 && final_k_end_value > max_delta_value){
+//            int bit_width_final= getBitWith(final_x_u_minus - final_x_l_plus);
+//            cur_byte[encode_pos+1] = 8;
+            for (int cur_value : ts_block_delta) {
+                encode_pos = EncodeBits(cur_value, bit_width_final, encode_pos, cur_byte, bit_index_list);
+//                final_normal.add(cur_value);
+            }
+            if(bit_index_list[0] != 8){
+                encode_pos ++;
+            }
+//            cur_byte[encode_pos+1] = 0;
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+            return encode_pos;
+        }
+
+
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+        int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(final_k_end_value,encode_pos,cur_byte);
+        encode_pos += 4;
+
+//        bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//        encode_pos += 1;
+        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        if (final_alpha == 0) { // 0
+
+            for (int i : bitmap_outlier) {
+
+                intByte2Bytes(i,encode_pos,cur_byte);
+                encode_pos += 1;
+            }
+        } else {
+            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+        }
+//        cur_byte[encode_pos+1] = 8;
+//        bit_index_list[0] = 8;
+        for (int cur_value : ts_block_delta) {
+            if (cur_value <= final_k_start_value) {
+                encode_pos = EncodeBits(cur_value, left_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else if (cur_value >= final_k_end_value) {
+                encode_pos = EncodeBits(cur_value - final_k_end_value, right_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else {
+                encode_pos = EncodeBits(cur_value - final_x_l_plus, bit_width_final, encode_pos, cur_byte,bit_index_list);
+            }
+        }
+        if(bit_index_list[0] != 8){
+            encode_pos ++;
+        }
+
+//        cur_byte[encode_pos+1] = 0;
+
+//        if(k1==0 && k2==0){
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//
+//
+//        }
+//        else{
+//            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+//            encode_pos += 4;
+//            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+//            encode_pos += 4;
+//
+//            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            if (final_alpha == 0) { // 0
+//
+//                for (int i : bitmap_outlier) {
+//
+//                    intByte2Bytes(i,encode_pos,cur_byte);
+//                    encode_pos += 1;
+//                }
+//            } else {
+//                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//            }
+//        }
+
+
+//        if(k1+k2!=block_size)
+//        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//        if (k1 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+//        if (k2 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+        return encode_pos;
+
+    }
+    private static int BOSBlockEncoderImprove(int[] ts_block, int block_i, int block_size, int remaining ,int encode_pos , byte[] cur_byte) {
+
+        int[] min_delta = new int[3];
+        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
+
+
+        block_size = remaining-1;
+        int max_delta_value = min_delta[2];
+
+        int[] value_list = new int[block_size];
+        int unique_value_count = 0;
+        int[] value_count_list = new int[max_delta_value+1];
+        for(int value:ts_block_delta){
+            if(value_count_list[value]==0){
+                value_count_list[value] = 1;
+                value_list[unique_value_count] = value;
+                unique_value_count ++;
+            }else{
+                value_count_list[value] ++;
+            }
+        }
+
+        int left_shift = getBitWith(block_size);
+        int mask =  (1 << left_shift) - 1;
+        long[] sorted_value_list = new long[unique_value_count];
+        int count = 0;
+
+        for(int i=0;i<unique_value_count;i++){
+            int value = value_list[i];
+            sorted_value_list[i] = (((long) value) << left_shift) + value_count_list[value];
+        }
+        Arrays.sort(sorted_value_list);
+
+        for(int i=0;i<unique_value_count;i++){
+            count += getCount(sorted_value_list[i], mask);
+            sorted_value_list[i] = (((long)getUniqueValue(sorted_value_list[i], left_shift) ) << left_shift) + count;//new_value_list[i]
+        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2 ) * (block_size));
+
+        int cur_k1 = 0;
+
+        int x_l_plus_value = 0; // x_l_plus
+        int x_u_minus_value = max_delta_value; // x_u_plus
+
+        for (int end_value_i = 1; end_value_i < unique_value_count; end_value_i++) {
+
+            x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+            int x_u_plus_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+            int cur_bits = 0;
+            int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value); // cur_k1 = 0
+            if (cur_k2 != 0)
+                cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus_value);
+
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_x_u_minus = x_u_minus_value;
+                final_k_end_value = x_u_plus_value;
+            }
+        }
+
+        int k_start_value = -1; // x_l_minus
+
+        int gamma_max = getBitWith(max_delta_value);
+        int[] gamma_count_list = new int[gamma_max+1];
+        int[] x_u_minus_value_list = new int[gamma_max+1];
+        int[] x_u_plus_value_list = new int[gamma_max+1];
+        int end_i = unique_value_count - 1;
+        for(int gamma = 0; gamma <= gamma_max; gamma++) {
+            int x_u_plus_pow_beta = max_delta_value - (1<< gamma) + 1;
+            for (; end_i > 0; end_i--) {
+                x_u_minus_value = getUniqueValue(sorted_value_list[end_i - 1], left_shift);
+                int x_u_plus_value = getUniqueValue(sorted_value_list[end_i], left_shift);
+                if (x_u_minus_value < x_u_plus_pow_beta && x_u_plus_value >= x_u_plus_pow_beta){
+                    gamma_count_list[gamma] = getCount(sorted_value_list[end_i-1],mask);
+                    x_u_minus_value_list[gamma] = x_u_minus_value;
+                    x_u_plus_value_list[gamma] = x_u_plus_value;
+                } else if (x_u_minus_value < x_u_plus_pow_beta) {
+                    break;
+                }
+            }
+        }
+        for(int gamma = 1; gamma < gamma_max; gamma++) {
+            if(gamma_count_list[gamma]==0){
+                gamma_count_list[gamma] = gamma_count_list[gamma-1];
+                x_u_minus_value_list[gamma] = x_u_minus_value_list[gamma-1];
+                x_u_plus_value_list[gamma] = x_u_plus_value_list[gamma-1];
+            }
+        }
+
+        for (int start_value_i = 0; start_value_i < unique_value_count-1; start_value_i++) {
+            long k_start_valueL = sorted_value_list[start_value_i];
+            k_start_value =  getUniqueValue(k_start_valueL, left_shift) ;
+            x_l_plus_value =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+
+
+            cur_k1 = getCount(k_start_valueL,mask);
+
+            int k_end_value;
+            int cur_bits;
+            int cur_k2;
+            k_end_value = max_delta_value + 1;
+
+            cur_bits = 0;
+            cur_k2 = 0;
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            cur_bits += cur_k1 * getBitWith(k_start_value);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k1) * getBitWith(k_end_value- x_l_plus_value); //cur_k2 =0
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_k_start_value = k_start_value;
+                final_x_l_plus = x_l_plus_value;
+                final_k_end_value = k_end_value;
+                final_x_u_minus = max_delta_value;
+            }
+
+            int beta_max = getBitWith(max_delta_value - x_l_plus_value);
+
+            int lower_outlier_cost = cur_k1 * getBitWith(k_start_value);
+
+
+
+            for(int gamma = 0; gamma < beta_max; gamma++){
+//                int x_u_plus_pow_beta = (int) (max_delta_value - pow(2,gamma)+1);
+                x_u_minus_value = x_u_minus_value_list[gamma];
+                k_end_value =  x_u_plus_value_list[gamma];
+                cur_bits = 0;
+                cur_k2 = block_size - gamma_count_list[gamma];
+
+                cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                cur_bits += lower_outlier_cost;
+                if (cur_k1 + cur_k2 != block_size)
+                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+                if (cur_k2 != 0)
+                    cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+
+
+                if (cur_bits < min_bits) {
+                    min_bits = cur_bits;
+                    final_k_start_value = k_start_value;
+                    final_x_l_plus = x_l_plus_value;
+                    final_k_end_value = k_end_value;
+                    final_x_u_minus = x_u_minus_value;
+                }
+
+            }
+//            end_value_i = unique_value_count - 1;
+//            for(int gamma = 0; gamma <= beta_max; gamma++){
+//                for (; end_value_i > start_value_i; end_value_i--) {
+//                    int x_u_plus_pow_beta = (int) (max_delta_value - pow(2,gamma)+1);
+//                    x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+//                    k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+//                    if(x_u_minus_value < x_u_plus_pow_beta && k_end_value >= x_u_plus_pow_beta){
+//                        cur_bits = 0;
+//                        cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+//
+//                        cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+//                        cur_bits += cur_k1 * getBitWith(k_start_value);
+//                        if (cur_k1 + cur_k2 != block_size)
+//                            cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+//                        if (cur_k2 != 0)
+//                            cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+//
+//
+//                        if (cur_bits < min_bits) {
+//                            min_bits = cur_bits;
+//                            final_k_start_value = k_start_value;
+//                            final_x_l_plus = x_l_plus_value;
+//                            final_k_end_value = k_end_value;
+//                            final_x_u_minus = x_u_minus_value;
+//                        }
+//                    } else if (x_u_minus_value < x_u_plus_pow_beta && k_end_value < x_u_plus_pow_beta) {
+//                        break;
+//                    }
+//                }
+//            }
+//
+
+        }
+
+        for(int beta = 0; beta < gamma_max; beta++){
+
+            int pow_beta = 1<<beta;
+            int start_value_i = 0;
+            int end_value_i = start_value_i+1;
+
+            for (; start_value_i < unique_value_count-1; start_value_i++) {
+                long x_l_minusL = sorted_value_list[start_value_i];
+                int x_l_minus =  getUniqueValue(x_l_minusL, left_shift) ;
+                int x_l_plus =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+                int x_u_plus_pow_beta = pow_beta+x_l_plus;
+                if(x_u_plus_pow_beta > max_delta_value) break;
+
+
+
+                cur_k1 = getCount(x_l_minusL,mask);
+                int lower_outlier_cost = cur_k1 * getBitWith(x_l_minus);
+
+                while ( end_value_i < unique_value_count) {
+//                    if(beta==3 && end_value_i==22)
+//                    {
+//                        System.out.println(x_l_minus);
+//                        System.out.println(x_l_plus);
+//                    }
+
+                    int x_u_minus = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+                    int x_u_plus = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+                    if(x_u_minus < x_u_plus_pow_beta && x_u_plus >= x_u_plus_pow_beta){
+                        int cur_bits = 0;
+                        int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+
+                        cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                        cur_bits += lower_outlier_cost;
+                        if (cur_k1 + cur_k2 != block_size)
+                            cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus - x_l_plus);
+                        if (cur_k2 != 0)
+                            cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus);
+
+
+                        if (cur_bits < min_bits) {
+                            min_bits = cur_bits;
+                            final_k_start_value = x_l_minus;
+                            final_x_l_plus = x_l_plus;
+                            final_k_end_value = x_u_plus;
+                            final_x_u_minus = x_u_minus;
+                        }
+                        break;
+                    }
+//                    else if (x_u_minus >= x_u_plus_pow_beta && x_u_plus >= x_u_plus_pow_beta) {
+//                        break;
+//                    }
+
+                    end_value_i++;
+                }
+            }
+
+        }
+
+        encode_pos = BOSEncodeBitsImprove(ts_block_delta,  final_k_start_value, final_x_l_plus, final_k_end_value, final_x_u_minus,
+                max_delta_value, min_delta, encode_pos , cur_byte);
+
+        return encode_pos;
+    }
+
+    public static int BOSEncoderImprove(
+            int[] data, int block_size, byte[] encoded_result) {
+        block_size++;
+
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+
+            encode_pos =  BOSBlockEncoderImprove(data, i, block_size,block_size, encode_pos,encoded_result);
+
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        } else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+
+
+            encode_pos = BOSBlockEncoderImprove(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+
+//            int[] ts_block = new int[length_all-start];
+//            if (length_all - start >= 0) System.arraycopy(data, start, ts_block, 0, length_all - start);
+//
+//            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;
+//            }
+//
+//
+//            encode_pos = BOSBlockEncoder(ts_block, supple_length, encode_pos,encoded_result);
+        }
+
+
+        return encode_pos;
+    }
+
+
+    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+        int value0 = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        value_list[value_pos_arr[0]] =value0;
+        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        int left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+        int right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+
+        if (final_alpha == 0) {
+            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
+
+            for (int i = 0; i < bitmap_bytes; i++) {
+                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                decode_pos += 1;
+            }
+            int bitmap_outlier_i = 0;
+            int remaining_bits = 8;
+            int tmp = bitmap_outlier.get(bitmap_outlier_i);
+            bitmap_outlier_i++;
+            int i = 0;
+            while (i < block_size) {
+                if (remaining_bits > 1) {
+                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                    remaining_bits -= 1;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                    if (remaining_bits == 0) {
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                    }
+                } else if (remaining_bits == 1) {
+                    int bit_i = tmp & 0x1;
+                    remaining_bits = 8;
+                    if (bitmap_outlier_i >= bitmap_bytes) break;
+                    tmp = bitmap_outlier.get(bitmap_outlier_i);
+                    bitmap_outlier_i++;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                }
+                i++;
+            }
+        } else {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
+            decode_pos = (decode_pos_result_left.get(0));
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
+            decode_pos = (decode_pos_result_right.get(0));
+        }
+
+
+        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+
+        decode_pos = decode_pos_normal.get(0);
+        if (k1 != 0) {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+            decode_pos = decode_pos_result_left.get(0);
+        }
+        if (k2 != 0) {
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+            decode_pos = decode_pos_result_right.get(0);
+        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+
+        for (int i = 0; i < block_size; i++) {
+            int current_delta;
+            if (left_outlier_i >= k1) {
+                if (right_outlier_i >= k2) {
+                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
+                    current_delta =  final_right_outlier.get(right_outlier_i) + final_k_end_value;
+                    right_outlier_i++;
+                } else {
+                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                }
+            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
+                current_delta =  final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+            } else {
+
+                if (right_outlier_i >= k2) {
+                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
+                    current_delta =  final_right_outlier.get(right_outlier_i) + final_k_end_value;
+                    right_outlier_i++;
+                } else {
+                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                }
+            }
+
+            pre_v = deZigzag(current_delta) + min_delta + pre_v;
+            value_list[value_pos_arr[0]] =pre_v;
+            value_pos_arr[0] ++;
+        }
+        return decode_pos;
+    }
+
+    public static void BOSDecoder(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        block_size --;
+
+        int[] value_pos_arr = new int[1];
+        for (int k = 0; k < block_num; k++) {
+            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list, block_size,value_pos_arr);
+
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            remain_length --;
+            BOSBlockDecoder(encoded, decode_pos, value_list, remain_length, value_pos_arr);
+        }
+    }
+
+    public static int DecodeBits(byte[] cur_byte, int bit_width, int[] decode_pos_list) {
+        int decode_pos = decode_pos_list[0];
+        int bit_index = decode_pos_list[1];  //cur_byte[decode_pos + 1];
+        int remaining_bits = bit_width;
+        int num = 0;
+
+        while (remaining_bits > 0) {
+            int available_bits = bit_index;
+            int bits_to_read = Math.min(available_bits, remaining_bits);
+
+            // 计算要读取的位的掩码
+            int mask = (1 << bits_to_read) - 1;
+            int bits = (cur_byte[decode_pos] >> (available_bits - bits_to_read)) & mask;
+
+            // 将读取的位合并到结果中
+            num = (num << bits_to_read) | bits;
+
+            // 更新位宽和 bit_index
+            remaining_bits -= bits_to_read;
+            bit_index = available_bits - bits_to_read;
+
+            if (bit_index == 0) {
+                bit_index = 8;
+                decode_pos++;
+            }
+        }
+        decode_pos_list[0] = decode_pos;
+        decode_pos_list[1] = bit_index;
+
+        return num;
+    }
+    public static int BOSBlockDecoderImprove(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+        int value0 = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        value_list[value_pos_arr[0]] =value0;
+        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        int[] decode_list = new int[2];
+        decode_list[0]= decode_pos;
+        decode_list[1]= 8;
+
+        int valuePos = value_pos_arr[0];
+
+        if(k1==0 && k2==0){
+            int pre_v = value0;
+            for (int i = 0; i < block_size; i++) {
+                int cur_delta = min_delta + DecodeBits(encoded, bit_width_final,  decode_list);
+                pre_v += deZigzag(cur_delta);
+                value_list[valuePos++] = pre_v;
+            }
+            value_pos_arr[0] = valuePos;
+            return decode_list[0];
+        }
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+//        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+//        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+//        bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+//        decode_pos += 1;
+
+        left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+        right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        if (final_alpha == 0) {
+            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
+            for (int i = 0; i < bitmap_bytes; i++) {
+                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                decode_pos += 1;
+            }
+            int bitmap_outlier_i = 0;
+            int remaining_bits = 8;
+            int tmp = bitmap_outlier.get(bitmap_outlier_i);
+            bitmap_outlier_i++;
+            int i = 0;
+            while (i < block_size ) {
+                if (remaining_bits > 1) {
+                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                    remaining_bits -= 1;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                    if (remaining_bits == 0) {
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                    }
+                } else if (remaining_bits == 1) {
+                    int bit_i = tmp & 0x1;
+                    remaining_bits = 8;
+                    if (bitmap_outlier_i >= bitmap_bytes) break;
+                    tmp = bitmap_outlier.get(bitmap_outlier_i);
+                    bitmap_outlier_i++;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                }
+                i++;
+            }
+        } else {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
+            decode_pos = (decode_pos_result_left.get(0));
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
+            decode_pos = (decode_pos_result_right.get(0));
+        }
+
+
+
+
+
+//        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+//        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+//
+//        decode_pos = decode_pos_normal.get(0);
+//        if (k1 != 0) {
+//            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+//            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+//            decode_pos = decode_pos_result_left.get(0);
+//        }
+//        if (k2 != 0) {
+//            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+//            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+//            decode_pos = decode_pos_result_right.get(0);
+//        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+// Precompute constants
+        int normalOffset = min_delta + final_k_start_value;
+        int rightOutlierOffset = min_delta + final_k_end_value;
+
+// Initialize indices and pre-fetch next outlier positions
+        int leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+        int rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+        decode_list[0]= decode_pos;
+//        decode_list[1]= 8;
+        // Use a local variable for the position
+        for (int i = 0; i < block_size; i++) {
+            int currentDelta;
+            if (i == leftOutlierNextIndex) {
+                // Process left outlier
+                currentDelta = min_delta + DecodeBits(encoded, left_bit_width,  decode_list); // final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+                leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+            } else if (i == rightOutlierNextIndex) {
+                // Process right outlier
+                currentDelta = rightOutlierOffset + DecodeBits(encoded, right_bit_width,  decode_list);// final_right_outlier.get(right_outlier_i);
+                right_outlier_i++;
+                rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+            } else {
+                // Process normal value
+                currentDelta = normalOffset + DecodeBits(encoded, bit_width_final,  decode_list);
+                normal_i++;
+            }
+
+            // Update the cumulative value and store it
+            pre_v += deZigzag(currentDelta);
+            value_list[valuePos++] = pre_v;
+        }
+        value_pos_arr[0] = valuePos;
+        if(decode_list[1]!=8){
+            return decode_list[0]+1;
+        }else {
+            return decode_list[0];
+        }
+//        decode_pos = decode_list[0];
+// Update the position in the array
+
+
+//        return decode_pos;
+    }
+    public static void BOSDecoderImprove(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        block_size --;
+
+        int[] value_pos_arr = new int[1];
+        for (int k = 0; k < block_num; k++) {
+            decode_pos = BOSBlockDecoderImprove(encoded, decode_pos, value_list, block_size,value_pos_arr);
+
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            remain_length --;
+            BOSBlockDecoderImprove(encoded, decode_pos, value_list, remain_length, value_pos_arr);
+        }
+    }
+
+    public static void main(@org.jetbrains.annotations.NotNull String[] args) throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/sprintz_bos_b";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        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(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+//        for (int file_i = 8; file_i < 9; file_i++) {
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+
+
+            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) {
+//                f = tempList[1];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+                loader.readHeaders();
+
+                while (loader.readRecord()) {
+
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+
+                }
+
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+                int repeatTime2 = 500;
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoder(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+                    String[] record = {
+                            f.toString(),
+                            "SPRINTZ+BOS-B",
+                            String.valueOf(encodeTime),
+                            String.valueOf(decodeTime),
+                            String.valueOf(data1.size()),
+                            String.valueOf(compressed_size),
+                            String.valueOf(ratio)
+                    };
+                    writer.writeRecord(record);
+                    System.out.println(ratio);
+
+
+            }
+            writer.close();
+
+        }
+    }
+
+    @Test
+    public void BOSImproveDecodeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R1O4_decode_time/compression_ratio/sprintz_bos_b";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[2];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "SPRINTZ+BOS-B",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void BOSImproveEncodeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/sprintz_bos_b_improve";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[2];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "SPRINTZ+BOS-B",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
+}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSHTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSHTest.java
deleted file mode 100644
index f14d94e..0000000
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSHTest.java
+++ /dev/null
@@ -1,1464 +0,0 @@
-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.ArrayList;
-
-import static java.lang.Math.*;
-
-public class SPRINTZBOSHTest {
-
-    public static int getBitWith(int num) {
-        if (num == 0) return 1;
-        else return 32 - Integer.numberOfLeadingZeros(num);
-    }
-    public static int getCount(long long1, int mask) {
-        return ((int) (long1 & mask));
-    }
-    public static int getUniqueValue(long long1, int left_shift) {
-        return ((int) ((long1) >> left_shift));
-    }
-
-    public static int zigzag(int num) {
-        if (num < 0) return ((-num)<<1)-1;
-        else return num<<1;
-    }
-
-    public static int deZigzag(int num) {
-        if (num % 2 == 0) return num>>1;
-        else return -((num+1)>>1);
-    }
-
-    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 ;
-                }
-            }
-        }
-
-    }
-
-    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 int[] getAbsDeltaTsBlock(
-            int[] ts_block,
-            ArrayList<Integer> min_delta,
-            int supple_length) {
-
-        int[] ts_block_delta = new int[ts_block.length+supple_length-1];
-        int block_size = ts_block.length-1;
-
-        for (int i = 0; i < block_size; i++) {
-
-            int epsilon_v = ts_block[i+1] - ts_block[i];
-            epsilon_v = zigzag(epsilon_v);
-            ts_block_delta[i] = epsilon_v;
-        }
-        for(int i = block_size;i<block_size+supple_length;i++){
-            ts_block_delta[i] = 0;
-        }
-        min_delta.add(ts_block[0]);
-        return ts_block_delta;
-    }
-    public static int[] getAbsDeltaTsBlock(
-            int[] ts_block,
-            int i,
-            int block_size,
-            int remaining,
-            int[] min_delta) {
-        int[] ts_block_delta = new int[remaining-1];
-
-        int base = i*block_size+1;
-        int end = i*block_size+remaining;
-        min_delta[0]=ts_block[base-1];
-        int value_delta_min = Integer.MAX_VALUE;
-        int value_delta_max = Integer.MIN_VALUE;
-        for (int j = base; j < end; j++) {
-            int epsilon_v = ts_block[j] - ts_block[j - 1];
-            epsilon_v = zigzag(epsilon_v);
-            if (epsilon_v < value_delta_min) {
-                value_delta_min = epsilon_v;
-            }
-            if (epsilon_v > value_delta_max) {
-                value_delta_max = epsilon_v;
-            }
-            ts_block_delta[j-base] =epsilon_v;
-
-        }
-        for (int j = 0; j < remaining-1; j++) {
-            ts_block_delta[j] =ts_block_delta[j]-value_delta_min;
-
-        }
-        min_delta[1] = (value_delta_min);
-        min_delta[2] = (value_delta_max-value_delta_min);
-
-
-        return ts_block_delta;
-    }
-
-    public static int encodeOutlier2Bytes(
-            ArrayList<Integer> ts_block_delta,
-            int bit_width,
-            int encode_pos,  byte[] encoded_result)     {
-
-        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
-
-        int n_k = ts_block_delta.size();
-        int n_k_b = n_k / 8;
-        long cur_remaining = 0; // encoded int
-        int cur_number_bits = 0; // the bit width used of encoded int
-        for (int i = n_k_b * 8; i < n_k; i++) {
-            long cur_value = ts_block_delta.get(i);
-            int cur_bit_width = bit_width; // remaining bit width of current value
-
-            if (cur_number_bits + bit_width >= 32) {
-                cur_remaining <<= (32 - cur_number_bits);
-                cur_bit_width = bit_width - 32 + cur_number_bits;
-                cur_remaining += ((cur_value >> cur_bit_width));
-                long2intBytes(cur_remaining,encode_pos,encoded_result);
-                encode_pos += 4;
-                cur_remaining = 0;
-                cur_number_bits = 0;
-            }
-
-            cur_remaining <<= cur_bit_width;
-            cur_number_bits += cur_bit_width;
-            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width));
-        }
-        cur_remaining <<= (32 - cur_number_bits);
-        long2intBytes(cur_remaining,encode_pos,encoded_result);
-        encode_pos += 4;
-        return encode_pos;
-
-
-    }
-
-
-    public static ArrayList<Integer> decodeOutlier2Bytes(
-            byte[] encoded,
-            int decode_pos,
-            int bit_width,
-            int length,
-            ArrayList<Integer> encoded_pos_result
-    ) {
-
-        int n_k_b = length / 8;
-        int remaining = length - n_k_b * 8;
-        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
-        decode_pos += n_k_b * bit_width;
-
-        ArrayList<Long> int_remaining = new ArrayList<>();
-        int int_remaining_size = remaining * bit_width / 32 + 1;
-        for (int j = 0; j < int_remaining_size; j++) {
-            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
-            decode_pos += 4;
-        }
-
-        int cur_remaining_bits = 32; // remaining bit width of current value
-        long cur_number = int_remaining.get(0);
-        int cur_number_i = 1;
-        for (int i = n_k_b * 8; i < length; i++) {
-            if (bit_width < cur_remaining_bits) {
-                int tmp = (int) (cur_number >> (32 - bit_width));
-                result_list.add(tmp);
-                cur_number <<= bit_width;
-                cur_number &= 0xFFFFFFFFL;
-                cur_remaining_bits -= bit_width;
-            } else {
-                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
-                int remain_bits = bit_width - cur_remaining_bits;
-                tmp <<= remain_bits;
-
-                cur_number = int_remaining.get(cur_number_i);
-                cur_number_i++;
-                tmp += (cur_number >> (32 - remain_bits));
-                result_list.add(tmp);
-                cur_number <<= remain_bits;
-                cur_number &= 0xFFFFFFFFL;
-                cur_remaining_bits = 32 - remain_bits;
-            }
-        }
-        encoded_pos_result.add(decode_pos);
-        return result_list;
-    }
-
-    private static int BOSEncodeBits(int[] ts_block_delta,
-                                     int final_k_start_value,
-                                     int final_k_end_value,
-                                     int max_delta_value,
-                                     int[] min_delta,
-                                     int encode_pos,
-                                     byte[] cur_byte) {
-        int block_size = ts_block_delta.length;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal = new ArrayList<>();
-        int k1 = 0;
-        int k2 = 0;
-
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-        int index_bitmap_outlier = 0;
-        int cur_index_bitmap_outlier_bits = 0;
-        for (int i = 0; i < block_size; i++) {
-            int cur_value = ts_block_delta[i];
-            if ( cur_value<= final_k_start_value) {
-                final_left_outlier.add(cur_value);
-                final_left_outlier_index.add(i);
-                if (cur_index_bitmap_outlier_bits % 8 != 7) {
-                    index_bitmap_outlier <<= 2;
-                    index_bitmap_outlier += 3;
-                    cur_index_bitmap_outlier_bits += 2;
-                } else {
-                    index_bitmap_outlier <<= 1;
-                    index_bitmap_outlier += 1;
-                    bitmap_outlier.add(index_bitmap_outlier);
-                    index_bitmap_outlier = 1;
-                    cur_index_bitmap_outlier_bits = 1;
-                }
-                k1++;
-
-
-            } else if (cur_value >= final_k_end_value) {
-                final_right_outlier.add(cur_value - final_k_end_value);
-                final_right_outlier_index.add(i);
-                if (cur_index_bitmap_outlier_bits % 8 != 7) {
-                    index_bitmap_outlier <<= 2;
-                    index_bitmap_outlier += 2;
-                    cur_index_bitmap_outlier_bits += 2;
-                } else {
-                    index_bitmap_outlier <<= 1;
-                    index_bitmap_outlier += 1;
-                    bitmap_outlier.add(index_bitmap_outlier);
-                    index_bitmap_outlier = 0;
-                    cur_index_bitmap_outlier_bits = 1;
-                }
-                k2++;
-
-            } else {
-                final_normal.add(cur_value - final_k_start_value-1);
-                index_bitmap_outlier <<= 1;
-                cur_index_bitmap_outlier_bits += 1;
-            }
-            if (cur_index_bitmap_outlier_bits % 8 == 0) {
-                bitmap_outlier.add(index_bitmap_outlier);
-                index_bitmap_outlier = 0;
-            }
-        }
-        if (cur_index_bitmap_outlier_bits % 8 != 0) {
-
-            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
-            index_bitmap_outlier &= 0xFF;
-            bitmap_outlier.add(index_bitmap_outlier);
-        }
-
-        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
-
-
-        int k_byte = (k1 << 1);
-        k_byte += final_alpha;
-        k_byte += (k2 << 16);
-
-
-        int2Bytes(k_byte,encode_pos,cur_byte);
-        encode_pos += 4;
-
-        int2Bytes(min_delta[0],encode_pos,cur_byte); // x0
-        encode_pos += 4;
-        int2Bytes(min_delta[1],encode_pos,cur_byte); // x_min
-        encode_pos += 4;
-        int2Bytes(final_k_start_value,encode_pos,cur_byte);
-        encode_pos += 4;
-        int bit_width_final = getBitWith(final_k_end_value - final_k_start_value-2);
-        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
-        encode_pos += 1;
-        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
-        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
-        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        if (final_alpha == 0) { // 0
-
-            for (int i : bitmap_outlier) {
-
-                intByte2Bytes(i,encode_pos,cur_byte);
-                encode_pos += 1;
-            }
-        } else {
-            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
-            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
-        }
-        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
-        if (k1 != 0)
-            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
-        if (k2 != 0)
-            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
-        return encode_pos;
-
-    }
-
-    // sprintz need to substitute ---- start
-    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size, int remaining, int encode_pos, byte[] cur_byte) {
-
-        int[] min_delta = new int[3];
-        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
-
-        block_size = remaining - 1;
-        int max_delta_value = min_delta[2];
-
-        int boundary_index = (int) ((double) block_size / (double) (getBitWith(block_size-1)-1));
-
-        int max_bit_width = getBitWith(max_delta_value) + 1;
-        int[] lambda_list = {getBitWith(block_size-1),1};
-        int lambda_0 = lambda_list[0];
-
-        int count_x_min = 0;
-        int count_x_max = 0;
-        GroupL[] groupL = new GroupL[max_bit_width];
-        GroupU[] groupU = new GroupU[max_bit_width];
-        for (int i = 0; i < max_bit_width; i++) {
-            int[] numbers = new int[block_size];
-            int count = 0;
-            groupL[i] = new GroupL(numbers, count, i);
-            int[] numbersU = new int[block_size];
-            groupU[i] = new GroupU(numbersU, count, i);
-        }
-        for (int value : ts_block_delta) {
-            int alpha_i = getBitWith(value);
-            if (value == 0) {
-                count_x_min++;
-            } else {
-                groupL[alpha_i].addNumber(value); // (x_min+2^{alpha_i-1},x_min+2^{alpha_i})
-            }
-            int gamma_i = getBitWith(max_delta_value - value);
-            if (value == max_delta_value) {
-                count_x_max++;
-            } else {
-                groupU[gamma_i].addNumber(value);// (x_max-2^{gamma_i},x_max-2^{gamma_i-1})
-            }
-        }
-        int[] alpha_list = new int[max_bit_width];
-        int num_of_alpha_list = 0;
-        int[] gamma_list = new int[max_bit_width];
-        int num_of_gamma_list = 0;
-        for (int i = 1; i < max_bit_width; i++) {
-            if(groupL[i].count!=0){
-                groupL[i].setCount_array();
-                alpha_list[num_of_alpha_list] = i;
-                num_of_alpha_list ++;
-            }
-            if(groupU[i].count!=0){
-                groupU[i].setCount_array(max_delta_value);
-                gamma_list[num_of_gamma_list] = i;
-                num_of_gamma_list ++;
-                groupU[i].setinvert();
-            }
-        }
-
-
-        int final_k_start_value = -1;//getUniqueValue(sorted_value_list[0], left_shift);
-        int final_k_end_value = max_delta_value + 1;
-
-        int min_bits = 0;
-        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2) * (block_size));
-
-        int alpha_size = getBitWith(max(max_delta_value-1,0));
-
-        if( num_of_alpha_list ==0 && num_of_gamma_list==0){
-            encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_k_end_value, max_delta_value,
-                    min_delta, encode_pos , cur_byte);
-            return  encode_pos;
-        }
-
-
-        // -------------x_min-------------------
-        // lower: x_min
-        // upper: x_max
-        int k1 =    count_x_min;
-        int k1_start = 0;
-        int k2 = count_x_max;
-        int k2_end = max_delta_value;
-        int cur_bits = Math.min((k1 + k2) * getBitWith(block_size - 1), block_size + k1 + k2);
-        cur_bits += k1;
-        cur_bits += k2;
-        cur_bits += (block_size - k1 - k2) * getBitWith(k2_end - k1_start - 2);
-        if (cur_bits < min_bits) {
-            min_bits = cur_bits;
-            final_k_start_value = k1_start;
-            final_k_end_value = k2_end;
-        }
-
-        // lower: x_min
-        // upper:  x_max - 1, x_max - 2, x_max - 4  ...
-        //(x_max - 2^{gamma}, x_max - 2^{gamma-1} ]
-
-        for (int gamma_i = 0; gamma_i < num_of_gamma_list-1; gamma_i++) {
-
-            int gamma = gamma_list[gamma_i];
-
-            int gap_gamma = (int) pow(2, gamma - 1);
-            k2_end = max_delta_value - gap_gamma; // x_max - 2^{gamma-1}  gamma : 1 to alpha_size-1
-
-            GroupU cur_group_gamma = groupU[gamma];
-
-            long[] gamma_sorted = cur_group_gamma.sorted_value_list;
-            int gamma_unique_number = cur_group_gamma.unique_number;
-            int cur_gamma_count = cur_group_gamma.count;
-
-            for(int unique_i=0;unique_i<gamma_unique_number;unique_i++){
-                int unique_i_cur_k2 = k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-                int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);
-
-
-                cur_bits = 0;
-                cur_bits += k1;
-                cur_bits += Math.min((k1 + unique_i_cur_k2) * getBitWith(block_size - 1), block_size + k1 + unique_i_cur_k2);
-
-                if (k1 + unique_i_cur_k2 != block_size)
-                    cur_bits += (block_size - k1 - unique_i_cur_k2) *
-                            getBitWith(k2_end - x_u_i - 2);
-                cur_bits += unique_i_cur_k2 * gamma;//min_upper_outlier
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start;
-                    final_k_end_value = k2_end - x_u_i;
-                }
-            }
-            k2 += cur_gamma_count;
-
-        }
-
-        // lower: x_min
-        // k2_end = x_max - 2^{alpha_size-1}
-        // upper: (0,x_max - 2^{alpha_size-1}]
-
-        int gap_gamma = (int) pow(2,alpha_size-1);
-        k2_end = max_delta_value - gap_gamma;
-        GroupU cur_group_gamma = groupU[alpha_size];
-
-        long[] gamma_sorted = cur_group_gamma.sorted_value_list;
-        int gamma_unique_number = cur_group_gamma.unique_number;
-
-        for(int unique_i=0;unique_i<gamma_unique_number-1;unique_i++){
-            int  unique_i_cur_k2 = k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-            int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);
-
-
-            cur_bits = 0;
-            cur_bits += k1;
-            cur_bits += Math.min((k1 + unique_i_cur_k2) * getBitWith(block_size - 1), block_size + k1 + unique_i_cur_k2);
-
-            if (k1 + unique_i_cur_k2 != block_size)
-                cur_bits += (block_size - k1 - unique_i_cur_k2) *
-                        getBitWith(k2_end - x_u_i - 2);
-            cur_bits += unique_i_cur_k2 * alpha_size;
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k1_start;
-                final_k_end_value = k2_end - x_u_i;
-            }
-        }
-
-        // -------------x_min-------------------
-
-
-
-
-        // [x_min+2^{alpha-1},x_min+2^{alpha}) alpha = 1 to alphasize - 1
-        // -----------------[x_min+2^{alpha-1},x_min+2^{alpha})-------------------
-        // alpha_size = getBitWith(max_delta_value);
-
-        for (int alpha_i = 0; alpha_i < num_of_alpha_list-1; alpha_i++) {
-
-            int alpha = alpha_list[alpha_i];
-            int gap_alpha = (int) pow(2,alpha-1);
-            k1_start = gap_alpha;
-            GroupL cur_group_alpha = groupL[alpha];
-
-
-            // lower: [x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-            // upper: x_max
-
-            int alpha_value_count = cur_group_alpha.count;
-            long[] alpha_sorted = cur_group_alpha.sorted_value_list;
-            int alpha_unique_number = cur_group_alpha.unique_number;
-
-            // k1; count[x_min, x_min+2^{alpha-1}]
-            for (int unique_j=0;unique_j<alpha_unique_number;unique_j++) {
-
-                int unique_i_cur_k1 = k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);//alpha_unique_count_array[unique_j];// gamma_box_count_list[gamma];
-                int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);//alpha_unique_number_array[unique_j];
-                k2 = count_x_max;
-                k2_end = max_delta_value;
-                cur_bits = Math.min((unique_i_cur_k1 + k2) * getBitWith(block_size - 1), block_size + unique_i_cur_k1 + k2);
-                cur_bits += unique_i_cur_k1 * alpha;
-                cur_bits += k2;
-                if (unique_i_cur_k1 + k2 != block_size)
-                    cur_bits += (block_size - unique_i_cur_k1 - k2) * getBitWith(k2_end - k1_start - x_l_i - 2);
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start + x_l_i;
-                    final_k_end_value = k2_end;
-                }
-            }
-
-
-            int pow_2_alpha = (int) pow(2, alpha);
-            // lower: [x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-            // upper: (x_max - 2^{gamma}, x_max - 2^{gamma-1}]:  k2_end - gap_gamma, k2_end
-
-
-            int cur_k1 = k1; //count[x_min, x_min+2^{alpha-1}]
-
-            // lower: (x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-            // upper:  (x_max - 2^{gamma}, x_max - 2^{gamma-1}]:  k2_end - gap_gamma, k2_end
-            // gamma size : x_min+2^{alpha} <= x_max - 2^{gamma} => 2^{gamma} <= x_max - 2^{alpha}
-            int gamma_size = (int) (log(max_delta_value - (int) pow(2, alpha)) / log(2));
-
-            int max_pow_2_lambda = (int) pow(2, lambda_0);
-            int max_lambda = lambda_0;
-            int cur_k2 = k2; // count(x_max)
-            int gamma_i = 0;
-            for (; gamma_i < num_of_gamma_list; gamma_i++) {
-                int gamma = gamma_list[gamma_i];
-                if(gamma > gamma_size){
-                    break;
-                }
-
-
-                // k1: count[x_min,x_min+2^{alpha-1}]
-
-                gap_gamma = (int) pow(2, gamma - 1);
-                k2_end = max_delta_value - gap_gamma;
-                cur_group_gamma = groupU[gamma]; // (x_max - 2^{gamma}, x_max - 2^{gamma-1})
-                int gamma_value_count = cur_group_gamma.count;
-                gamma_sorted = cur_group_gamma.sorted_value_list;
-                gamma_unique_number = cur_group_gamma.unique_number;
-
-
-                int pow_2_gamma = gap_gamma*2;
-
-                // prop 5.7
-
-                int cur_k1_start = k1_start + gap_alpha - 1;
-                int cur_k2_end = k2_end - gap_gamma + 1;
-                int cur_k2_start_of_lambda = cur_k2 + gamma_value_count;// count[x_max - 2^{gamma}+1, x_max]
-                int cur_k1_start_of_lambda = k1 + alpha_value_count; // count[x_min, 2^{alpha}-1]
-
-                cur_bits = 0;
-                cur_bits +=  Math.min((cur_k1_start_of_lambda + cur_k2_start_of_lambda) * lambda_0, block_size + cur_k1_start_of_lambda + cur_k2_start_of_lambda); // (lambda * (cur_cur_k1 + cur_k2_start_of_lambda) + zeta);
-                cur_bits += (cur_k1_start_of_lambda * alpha);
-                cur_bits += (cur_k2_start_of_lambda * gamma);
-                cur_bits += ((block_size - cur_k1_start_of_lambda - cur_k2_start_of_lambda) * getBitWith(cur_k2_end - cur_k1_start - 2));
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = cur_k1_start;
-                    final_k_end_value = cur_k2_end;
-                }
-
-                // prop 5.4
-                int prop_5_4_k1 = cur_k1 + alpha_value_count; //count[x_min, x_min+2^{alpha}-1]
-
-                cur_bits = 0;
-                cur_bits += Math.min((prop_5_4_k1 + cur_k2) * lambda_0, block_size + prop_5_4_k1 + cur_k2); //(lambda * (prop_5_4_k1 + prop_5_4_k2) + zeta);
-                cur_bits += (prop_5_4_k1 * alpha);
-                cur_bits += (cur_k2 * gamma);
-                cur_bits += ((block_size - prop_5_4_k1 - cur_k2) * getBitWith(k2_end - k1_start - gap_alpha  - 1));
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start + gap_alpha - 1;
-                    final_k_end_value = k2_end;
-                }
-
-                // prop 5.5
-                int prop_5_5_k2 = cur_k2 + gamma_value_count; // count[x_max - 2^{gamma}+1,x_max}
-
-                cur_bits = 0;
-                cur_bits += Math.min((cur_k1 + prop_5_5_k2) * lambda_0, block_size + cur_k1 + prop_5_5_k2);// (lambda * (prop_5_5_k1 + prop_5_5_k2) + zeta);
-                cur_bits += (cur_k1 * alpha);
-                cur_bits += (prop_5_5_k2 * gamma);
-                cur_bits += ((block_size - cur_k1 - prop_5_5_k2) * getBitWith(k2_end - gap_gamma - k1_start - 1));
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start;
-                    final_k_end_value = k2_end - gap_gamma + 1;
-                }
-
-                // prop 5.6
-
-                cur_bits = 0;
-                cur_bits += Math.min((cur_k1 + cur_k2) * lambda_0, block_size + cur_k1 + cur_k2);//(lambda * (prop_5_6_k1 + prop_5_6_k2) + zeta);
-                cur_bits += (cur_k1 * alpha);
-                cur_bits += (cur_k2 * gamma);
-                cur_bits += ((block_size - cur_k1 - cur_k2) * getBitWith(k2_end - k1_start - 2));
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start;
-                    final_k_end_value = k2_end;
-                }
-
-
-
-                if ((max_pow_2_lambda + 1) * pow_2_alpha + pow_2_gamma <= max_delta_value
-                        && pow_2_alpha + (max_pow_2_lambda + 1) * pow_2_gamma <= max_delta_value) {
-
-
-                }
-                else {
-
-                    // lower: (x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-                    // upper:  (x_max - 2^{gamma}, x_max - 2^{gamma-1}):  k2_end - gap_gamma, k2_end
-                    // beta: getBitWidth(x_max - 2^{gamma} -(x_min+2^{alpha})) to getBitWidth(x_max - 2^{gamma-1}-(x_min+2^{alpha-1}) )
-                    int min_beta = getBitWith(max_delta_value-pow_2_gamma-pow_2_alpha);
-                    int max_beta = getBitWith(k2_end-k1_start);
-
-
-
-                    for(int beta = min_beta;beta <= max_beta;beta++) {
-                        int pow_2_beta = (int) pow(2, beta);
-                        if (beta >= alpha + max_lambda && beta <= gamma + 1 ){
-                            if(pow_2_beta + pow_2_alpha + gap_gamma >= max_delta_value){
-
-                            }else {
-                                int cur_cur_k1;
-                                for (int unique_j = 0; unique_j < alpha_unique_number; unique_j++) {
-                                    cur_cur_k1 = cur_k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);//alpha_unique_count_array[unique_j];// gamma_box_count_list[gamma];
-                                    int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);//alpha_unique_number_array[unique_j];
-
-                                    int cur_cur_k2 ; // count[x_max - 2^{gamma-1}, x_max]
-
-                                    int x_u_i_start =  Math.min(Math.max(0, k2_end - ( pow_2_beta + k1_start + x_l_i + 2)),gap_gamma-1);
-                                    int x_u_i_end = Math.max(0,Math.min(k2_end -( pow_2_beta/2 + k1_start + x_l_i + 2),gap_gamma));
-                                    int unique_s = cur_group_gamma.invert[x_u_i_start];
-                                    int unique_e = cur_group_gamma.invert[x_u_i_end];
-
-
-
-                                    for (int unique_i = unique_s; unique_i < unique_e; unique_i++) {
-                                        int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);//<=x_u_i_end
-                                        cur_cur_k2 = cur_k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-
-                                        cur_bits = 0;
-                                        cur_bits += Math.min((cur_cur_k1 + cur_cur_k2) * lambda_0, block_size + cur_cur_k1 + cur_cur_k2);
-                                        // (lambda * (cur_k1_start_of_lambda + cur_cur_k2) + zeta); // Math.min((cur_k1 + cur_cur_k2) * getBitWith(block_size - 1), block_size + cur_k1 + cur_k2);
-                                        cur_bits += cur_cur_k1 * alpha;
-                                        if (cur_cur_k1 + cur_cur_k2 != block_size)
-                                            cur_bits += (block_size - cur_cur_k1 - cur_cur_k2) *
-                                                    getBitWith(k2_end - x_u_i - k1_start - x_l_i - 2);
-                                        cur_bits += cur_cur_k2 * gamma;
-                                        if (cur_bits < min_bits) {
-                                            min_bits = cur_bits;
-                                            final_k_start_value = k1_start + x_l_i;
-                                            final_k_end_value = k2_end - x_u_i;
-                                        }
-
-                                    }
-                                }
-                            }
-                        }else if (beta <= alpha + 1 && beta >= gamma + max_lambda) {
-                            if(pow_2_beta + gap_alpha + pow_2_gamma >= max_delta_value){
-
-                            }else {
-                                int cur_cur_k1;
-                                for (int unique_j = 0; unique_j < alpha_unique_number; unique_j++) {
-                                    cur_cur_k1 = cur_k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);//alpha_unique_count_array[unique_j];// gamma_box_count_list[gamma];
-                                    int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);//alpha_unique_number_array[unique_j];
-
-                                    int cur_cur_k2 ; // count[x_max - 2^{gamma-1}, x_max]
-
-                                    int x_u_i_start =  Math.min(Math.max(0, k2_end - ( pow_2_beta + k1_start + x_l_i + 2)),gap_gamma-1);
-                                    int x_u_i_end = Math.max(0,Math.min(k2_end -( pow_2_beta/2 + k1_start + x_l_i + 2),gap_gamma));
-                                    int unique_s = cur_group_gamma.invert[x_u_i_start];
-                                    int unique_e = cur_group_gamma.invert[x_u_i_end];
-
-
-
-                                    for (int unique_i = unique_s; unique_i < unique_e; unique_i++) {
-                                        int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);//<=x_u_i_end
-                                        cur_cur_k2 = cur_k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-
-                                        cur_bits = 0;
-                                        cur_bits += Math.min((cur_cur_k1 + cur_cur_k2) * lambda_0, block_size + cur_cur_k1 + cur_cur_k2);
-                                        // (lambda * (cur_k1_start_of_lambda + cur_cur_k2) + zeta); // Math.min((cur_k1 + cur_cur_k2) * getBitWith(block_size - 1), block_size + cur_k1 + cur_k2);
-                                        cur_bits += cur_cur_k1 * alpha;
-                                        if (cur_cur_k1 + cur_cur_k2 != block_size)
-                                            cur_bits += (block_size - cur_cur_k1 - cur_cur_k2) *
-                                                    getBitWith(k2_end - x_u_i - k1_start - x_l_i - 2);
-                                        cur_bits += cur_cur_k2 * gamma;
-                                        if (cur_bits < min_bits) {
-                                            min_bits = cur_bits;
-                                            final_k_start_value = k1_start + x_l_i;
-                                            final_k_end_value = k2_end - x_u_i;
-                                        }
-
-                                    }
-                                }
-                            }
-                        } else if (beta <= alpha + 1 && beta <= gamma + 1) {
-                            if(pow_2_beta + gap_alpha + gap_gamma > max_delta_value){
-
-                            }else {
-                                int cur_cur_k1;
-                                for (int unique_j = 0; unique_j < alpha_unique_number; unique_j++) {
-                                    cur_cur_k1 = cur_k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);//alpha_unique_count_array[unique_j];// gamma_box_count_list[gamma];
-                                    int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);//alpha_unique_number_array[unique_j];
-                                    int cur_cur_k2 ; // count[x_max - 2^{gamma-1}, x_max]
-
-                                    int x_u_i_start =  Math.min(Math.max(0, k2_end - ( pow_2_beta + k1_start + x_l_i + 2)),gap_gamma-1);
-                                    int x_u_i_end = Math.max(0,Math.min(k2_end -( pow_2_beta/2 + k1_start + x_l_i + 2),gap_gamma));
-                                    int unique_s = cur_group_gamma.invert[x_u_i_start];
-                                    int unique_e = cur_group_gamma.invert[x_u_i_end];
-
-
-
-                                    for (int unique_i = unique_s; unique_i < unique_e; unique_i++) {
-                                        int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);//<=x_u_i_end
-                                        cur_cur_k2 = cur_k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-
-                                        cur_bits = 0;
-                                        cur_bits += Math.min((cur_cur_k1 + cur_cur_k2) * lambda_0, block_size + cur_cur_k1 + cur_cur_k2);
-                                        // (lambda * (cur_k1_start_of_lambda + cur_cur_k2) + zeta); // Math.min((cur_k1 + cur_cur_k2) * getBitWith(block_size - 1), block_size + cur_k1 + cur_k2);
-                                        cur_bits += cur_cur_k1 * alpha;
-                                        if (cur_cur_k1 + cur_cur_k2 != block_size)
-                                            cur_bits += (block_size - cur_cur_k1 - cur_cur_k2) *
-                                                    getBitWith(k2_end - x_u_i - k1_start - x_l_i - 2);
-                                        cur_bits += cur_cur_k2 * gamma;
-                                        if (cur_bits < min_bits) {
-                                            min_bits = cur_bits;
-                                            final_k_start_value = k1_start + x_l_i;
-                                            final_k_end_value = k2_end - x_u_i;
-                                        }
-
-                                    }
-                                }
-                            }
-                        }else{
-                            int cur_cur_k1;
-                            for (int unique_j = 0; unique_j < alpha_unique_number; unique_j++) {
-                                cur_cur_k1 = cur_k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);//alpha_unique_count_array[unique_j];// gamma_box_count_list[gamma];
-                                int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);//alpha_unique_number_array[unique_j];
-
-                                int cur_cur_k2 ; // count[x_max - 2^{gamma-1}, x_max]
-
-                                int x_u_i_start =  Math.min(Math.max(0, k2_end - ( pow_2_beta + k1_start + x_l_i + 2)),gap_gamma-1);
-                                int x_u_i_end = Math.max(0,Math.min(k2_end -( pow_2_beta/2 + k1_start + x_l_i + 2),gap_gamma));
-                                int unique_s = cur_group_gamma.invert[x_u_i_start];
-                                int unique_e = cur_group_gamma.invert[x_u_i_end];
-
-
-
-                                for (int unique_i = unique_s; unique_i < unique_e; unique_i++) {
-                                    int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);//<=x_u_i_end
-                                    cur_cur_k2 = cur_k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-
-                                    cur_bits = 0;
-                                    cur_bits += Math.min((cur_cur_k1 + cur_cur_k2) * lambda_0, block_size + cur_cur_k1 + cur_cur_k2);
-                                    // (lambda * (cur_k1_start_of_lambda + cur_cur_k2) + zeta); // Math.min((cur_k1 + cur_cur_k2) * getBitWith(block_size - 1), block_size + cur_k1 + cur_k2);
-                                    cur_bits += cur_cur_k1 * alpha;
-                                    if (cur_cur_k1 + cur_cur_k2 != block_size)
-                                        cur_bits += (block_size - cur_cur_k1 - cur_cur_k2) *
-                                                getBitWith(k2_end - x_u_i - k1_start - x_l_i - 2);
-                                    cur_bits += cur_cur_k2 * gamma;
-                                    if (cur_bits < min_bits) {
-                                        min_bits = cur_bits;
-                                        final_k_start_value = k1_start + x_l_i;
-                                        final_k_end_value = k2_end - x_u_i;
-                                    }
-
-                                }
-                            }
-                        }
-
-                    }
-
-                }
-
-                cur_k2 = cur_k2 + gamma_value_count; // += count(x_max - 2^{gamma}, x_max - 2^{gamma-1})
-
-                if(cur_k1+cur_k2>boundary_index){
-                    max_pow_2_lambda = (int) pow(2, 1);
-                    max_lambda = 1;
-                }
-
-            }
-
-
-            k2 = cur_k2;
-
-            // gamma:  gamma_size+1 to ....
-            // gamma size : x_min+2^{alpha} <= x_max - 2^{gamma} => 2^{gamma} <= x_max - 2^{alpha}
-            //k2_end = x_max - 2^{gamma-1} ; gamma : 1 to gamma_size
-            // lower: [x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-            // upper:  (x_max - 2^{gamma}, x_max - 2^{gamma-1}]
-
-
-            for (; gamma_i < num_of_gamma_list; gamma_i++) {
-                int gamma = gamma_list[gamma_i];
-                gap_gamma = (int) pow(2, gamma-1);
-                cur_group_gamma = groupU[gamma];
-                k2_end = max_delta_value - gap_gamma;
-
-                if(k2_end <= k1_start){
-                    break;
-                }
-                int gamma_value_count = cur_group_gamma.count;
-
-                gamma_unique_number = cur_group_gamma.unique_number;
-                gamma_sorted = cur_group_gamma.sorted_value_list;
-
-                for (int unique_j=0;unique_j<alpha_unique_number;unique_j++) {
-                    int unique_j_cur_k1 = cur_k1+ cur_group_alpha.getCount(alpha_sorted[unique_j]);// gamma_box_count_list[gamma];
-                    int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);
-                    int x_u_i_end = Math.max(0,Math.min(k2_end - k1_start - x_l_i,gap_gamma));
-                    int unique_e = cur_group_gamma.invert[x_u_i_end];
-                    for (int unique_i = 0; unique_i < unique_e; unique_i++) {
-                        int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);
-                        int unique_i_cur_k2 = cur_k2+ cur_group_gamma.getCount(gamma_sorted[unique_i]);
-                        cur_bits = 0;
-                        cur_bits += Math.min((unique_j_cur_k1 + unique_i_cur_k2) * getBitWith(block_size - 1), block_size + unique_j_cur_k1 + unique_i_cur_k2);
-                        cur_bits += unique_j_cur_k1*alpha;
-                        if (unique_j_cur_k1 + unique_i_cur_k2 != block_size)
-                            cur_bits += (block_size - unique_j_cur_k1 - unique_i_cur_k2) *
-                                    getBitWith(k2_end - x_u_i-k1_start-x_l_i - 2);
-                        cur_bits += unique_i_cur_k2 * gamma;
-                        if (cur_bits < min_bits) {
-                            min_bits = cur_bits;
-                            final_k_start_value = k1_start + x_l_i;
-                            final_k_end_value = k2_end - x_u_i;
-                        }
-                    }
-
-                }
-                cur_k2 += gamma_value_count;
-            }
-
-            k1 += alpha_value_count;
-        }
-        // -------------------[x_min+2^{alpha-1},x_min+2^{alpha})-----------------
-
-
-        //  [x_min+2^{alpha_size-1},x_max)
-        // ----------------[x_min+2^{alpha_size-1},x_max)--------------------
-
-        // x_min+2^{alpha_size-1} < x_max && x_min+2^{alpha_size} >= x_max
-        // alpha_size - 1  < log(xmax) && alpha_size >= log(xmax)
-        // alpha_size = \lceil log(x_max-1+1) \rceil
-
-        alpha_size = alpha_list[num_of_alpha_list-1];
-        int gap_alpha = (int) pow(2,alpha_size-1);
-        k1_start = gap_alpha;
-        GroupL cur_group_alpha = groupL[alpha_size];
-        int alpha_value_count = cur_group_alpha.count;
-
-
-        // lower: [x_min+2^{alpha_size-1},x_max)
-        // ----------------- [x_min+2^{alpha_size-1},x_max)----------------------
-        long[] alpha_sorted = cur_group_alpha.sorted_value_list;
-        int alpha_unique_number = cur_group_alpha.unique_number;
-
-        int x_l_i_end = max_delta_value - k1_start; // [1, x_max - x_min+2^{alpha_size-1})
-        for (int unique_j=0;unique_j<alpha_unique_number;unique_j++) {
-
-            int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);
-            if (x_l_i >= x_l_i_end) {
-                break;
-            }
-            int unique_j_cur_k1 = k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);// gamma_box_count_list[gamma];
-
-            // lower: [x_min+2^{alpha_size-1},x_max) : k1_start, k1_start + gap_alpha
-            // upper: x_max
-            k2 = count_x_max;
-            k2_end = max_delta_value;
-
-            cur_bits = 0;
-            cur_bits += Math.min((unique_j_cur_k1 + k2) * getBitWith(block_size - 1), block_size + unique_j_cur_k1 + k2);
-            cur_bits += unique_j_cur_k1 * alpha_size;
-            cur_bits += k2;
-            if (unique_j_cur_k1 + k2 != block_size)
-                cur_bits += (block_size - unique_j_cur_k1 - k2) * getBitWith(k2_end - k1_start - x_l_i - 2);
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k1_start + x_l_i;
-                final_k_end_value = k2_end;
-            }
-        }
-        // lower: (x_min+2^{alpha_size-1},x_max)
-        // upper: (x_max - 2^{gamma}, x_max)
-        // gamma:  gamma_size+1 to ....
-        // lower: (x_min+2^{alpha_size-1},x_max) : k1_start, k1_start + gap_alpha
-        // upper:  (x_max - 2^{gamma}, x_max - 2^{gamma-1}] : k2_end - gap_gamma, k2_end
-
-        int max_pow_2_lambda = (int) pow(2, lambda_0);
-        int max_lambda = lambda_0;
-        for (int gamma_i = 0; gamma_i < num_of_gamma_list; gamma_i++) {
-            int gamma =  gamma_list[gamma_i];
-            gap_gamma = (int) pow(2, gamma-1);
-            k2_end = max_delta_value - gap_gamma; // x_max - 2^{gamma} ;
-
-            if(k2_end<=k1_start){
-                break;
-            }
-            cur_group_gamma = groupU[gamma];
-
-            int gamma_value_count = cur_group_gamma.count;
-            gamma_sorted = cur_group_gamma.sorted_value_list;
-            gamma_unique_number = cur_group_gamma.unique_number;
-
-            int pow_2_gamma = gap_gamma*2;
-            for (int unique_j=0;unique_j<alpha_unique_number;unique_j++) {
-                int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);
-                int x_u_i_end = k2_end - k1_start - x_l_i; // x_u_i>= k2_end - k1_start - x_l_i; break ;
-
-                if(x_u_i_end <= 0 || x_l_i >= x_l_i_end){
-                    break;
-                }
-                int unique_j_cur_k1 = k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);// gamma_box_count_list[gamma];
-                x_u_i_end = Math.min(x_u_i_end,gap_gamma - 1);
-                int unique_e = cur_group_gamma.invert[x_u_i_end];
-
-
-                for(int unique_i=0;unique_i<unique_e;unique_i++){
-
-                    int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);
-                    int unique_i_cur_k2 = k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-                    cur_bits = 0;
-                    cur_bits += Math.min((unique_j_cur_k1 + unique_i_cur_k2) * getBitWith(block_size - 1), block_size + unique_j_cur_k1 + unique_i_cur_k2);
-                    cur_bits += unique_j_cur_k1*alpha_size;
-                    if (unique_j_cur_k1 + unique_i_cur_k2 != block_size)
-                        cur_bits += (block_size - unique_j_cur_k1 - unique_i_cur_k2) *
-                                getBitWith(k2_end - x_u_i-k1_start-x_l_i - 2);
-                    cur_bits += unique_i_cur_k2 * gamma;
-                    if (cur_bits < min_bits) {
-                        min_bits = cur_bits;
-                        final_k_start_value = k1_start + x_l_i;
-                        final_k_end_value = k2_end - x_u_i;
-                    }
-                }
-            }
-
-
-            k2 += gamma_value_count;
-
-
-
-        }
-        // ------------------ [x_min+2^{alpha_size-1},x_max)--------------------
-
-        encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_k_end_value, max_delta_value,
-                min_delta, encode_pos , cur_byte);
-
-        return encode_pos;
-    }
-
-    public static int BOSEncoder(
-            int[] data, int block_size, byte[] encoded_result) {
-        block_size++;
-
-
-        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;
-
-        for (int i = 0; i < block_num; i++) {
-
-            encode_pos =  BOSBlockEncoder(data, i, block_size,block_size, encode_pos,encoded_result);
-        }
-
-        int remaining_length = length_all - block_num * block_size;
-        if (remaining_length <= 3) {
-            for (int i = remaining_length; i > 0; i--) {
-                int2Bytes(data[data.length - i], encode_pos, encoded_result);
-                encode_pos += 4;
-            }
-
-        } else {
-
-            int start = block_num * block_size;
-            int remaining = length_all-start;
-
-
-            encode_pos = BOSBlockEncoder(data, block_num, block_size,remaining, encode_pos,encoded_result);
-
-
-        }
-
-
-        return encode_pos;
-    }
-
-
-    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
-        int k_byte = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-        int k1_byte = (int) (k_byte % pow(2, 16));
-        int k1 = k1_byte / 2;
-        int final_alpha = k1_byte % 2;
-
-        int k2 = (int) (k_byte / pow(2, 16));
-
-        int value0 = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-        value_list[value_pos_arr[0]] =value0;
-        value_pos_arr[0] ++;
-
-        int min_delta = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        int left_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-        int right_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal;
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-
-        if (final_alpha == 0) {
-            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
-
-            for (int i = 0; i < bitmap_bytes; i++) {
-                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
-                decode_pos += 1;
-            }
-            int bitmap_outlier_i = 0;
-            int remaining_bits = 8;
-            int tmp = bitmap_outlier.get(bitmap_outlier_i);
-            bitmap_outlier_i++;
-            int i = 0;
-            while (i < block_size) {
-                if (remaining_bits > 1) {
-                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
-                    remaining_bits -= 1;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                    if (remaining_bits == 0) {
-                        remaining_bits = 8;
-                        if (bitmap_outlier_i >= bitmap_bytes) break;
-                        tmp = bitmap_outlier.get(bitmap_outlier_i);
-                        bitmap_outlier_i++;
-                    }
-                } else if (remaining_bits == 1) {
-                    int bit_i = tmp & 0x1;
-                    remaining_bits = 8;
-                    if (bitmap_outlier_i >= bitmap_bytes) break;
-                    tmp = bitmap_outlier.get(bitmap_outlier_i);
-                    bitmap_outlier_i++;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                }
-                i++;
-            }
-        } else {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
-            decode_pos = (decode_pos_result_left.get(0));
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
-            decode_pos = (decode_pos_result_right.get(0));
-        }
-
-
-        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
-        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
-
-        decode_pos = decode_pos_normal.get(0);
-        if (k1 != 0) {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
-            decode_pos = decode_pos_result_left.get(0);
-        }
-        if (k2 != 0) {
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
-            decode_pos = decode_pos_result_right.get(0);
-        }
-        int left_outlier_i = 0;
-        int right_outlier_i = 0;
-        int normal_i = 0;
-        int pre_v = value0;
-        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
-
-
-        for (int i = 0; i < block_size; i++) {
-            int current_delta;
-            if (left_outlier_i >= k1) {
-                if (right_outlier_i >= k2) {
-                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta =  final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
-                    normal_i++;
-                }
-            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
-                current_delta =  final_left_outlier.get(left_outlier_i);
-                left_outlier_i++;
-            } else {
-
-                if (right_outlier_i >= k2) {
-                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta =  final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
-                    normal_i++;
-                }
-            }
-
-            pre_v = deZigzag(current_delta) + min_delta + pre_v;
-            value_list[value_pos_arr[0]] =pre_v;
-            value_pos_arr[0] ++;
-        }
-        return decode_pos;
-    }
-
-    public static void BOSDecoder(byte[] encoded) {
-
-        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[] value_list = new int[length_all+block_size];
-        block_size --;
-
-        int[] value_pos_arr = new int[1];
-        for (int k = 0; k < block_num; k++) {
-            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list, block_size,value_pos_arr);
-
-        }
-
-        if (remain_length <= 3) {
-            for (int i = 0; i < remain_length; i++) {
-                int value_end = bytes2Integer(encoded, decode_pos, 4);
-                decode_pos += 4;
-                value_list[value_pos_arr[0]] = value_end;
-                value_pos_arr[0]++;
-            }
-        } else {
-            remain_length --;
-            BOSBlockDecoder(encoded, decode_pos, value_list, remain_length, value_pos_arr);
-        }
-    }
-
-    public static void main(@org.jetbrains.annotations.NotNull String[] args) throws IOException {
-        String parent_dir = "/Users/xiaojinzhao/Desktop/encoding-outlier/";// your data path
-        String output_parent_dir = parent_dir + "vldb/compression_ratio/sprintz_pruning";
-        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<>();
-        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");
-
-        for (String value : dataset_name) {
-            input_path_list.add(input_parent_dir + value);
-            dataset_block_size.add(1024);
-        }
-
-        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(2048);
-        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
-//        dataset_block_size.add(1024);
-        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
-//        dataset_block_size.add(1024);
-        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
-//        dataset_block_size.add(1024);
-
-        int repeatTime2 = 100;
-        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
-
-            String inputPath = input_path_list.get(file_i);
-            System.out.println(inputPath);
-            String Output = output_path_list.get(file_i);
-
-
-
-            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) {
-//                f = tempList[1];
-                System.out.println(f);
-                InputStream inputStream = Files.newInputStream(f.toPath());
-
-                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
-                ArrayList<Integer> data1 = new ArrayList<>();
-                ArrayList<Integer> data2 = new ArrayList<>();
-
-                loader.readHeaders();
-
-                while (loader.readRecord()) {
-
-                    data1.add(Integer.valueOf(loader.getValues()[0]));
-                    data2.add(Integer.valueOf(loader.getValues()[1]));
-
-                }
-
-                inputStream.close();
-                int[] data2_arr = new int[data1.size()];
-                for(int i = 0;i<data2.size();i++){
-                    data2_arr[i] = data2.get(i);
-                }
-                byte[] encoded_result = new byte[data2_arr.length*4];
-                long encodeTime = 0;
-                long decodeTime = 0;
-                double ratio = 0;
-                double compressed_size = 0;
-
-
-                int length = 0;
-
-                long s = System.nanoTime();
-                for (int repeat = 0; repeat < repeatTime2; repeat++) {
-                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
-                }
-
-                long e = System.nanoTime();
-                encodeTime += ((e - s) / repeatTime2);
-                compressed_size += length;
-                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
-                ratio += ratioTmp;
-                s = System.nanoTime();
-                for (int repeat = 0; repeat < repeatTime2; repeat++)
-                    BOSDecoder(encoded_result);
-                e = System.nanoTime();
-                decodeTime += ((e - s) / repeatTime2);
-
-                    String[] record = {
-                            f.toString(),
-                            "SPRINTZ+BOS-P",
-                            String.valueOf(encodeTime),
-                            String.valueOf(decodeTime),
-                            String.valueOf(data1.size()),
-                            String.valueOf(compressed_size),
-                            String.valueOf(ratio)
-                    };
-                    writer.writeRecord(record);
-                    System.out.println(ratio);
-            }
-            writer.close();
-
-        }
-    }
-
-}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSMTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSMTest.java
new file mode 100644
index 0000000..7e053c1
--- /dev/null
+++ b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSMTest.java
@@ -0,0 +1,2301 @@
+package org.apache.iotdb.tsfile.encoding;
+
+import com.csvreader.CsvReader;
+import com.csvreader.CsvWriter;
+import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
+import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
+import org.apache.iotdb.tsfile.compress.ICompressor;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.junit.Test;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.ArrayList;
+
+import static java.lang.Math.*;
+import static org.apache.iotdb.tsfile.constant.TestConstant.random;
+
+public class SPRINTZBOSMTest {
+
+    public static int getBitWith(int num) {
+        if (num == 0) return 1;
+        else return 32 - Integer.numberOfLeadingZeros(num);
+    }
+    public static int getCount(long long1, int mask) {
+        return ((int) (long1 & mask));
+    }
+    public static int getUniqueValue(long long1, int left_shift) {
+        return ((int) ((long1) >> left_shift));
+    }
+
+    public static int findMedianImprove(int[] arr) {
+        if (arr == null || arr.length == 0) {
+            throw new IllegalArgumentException("数组不能为空");
+        }
+        int n = arr.length;
+        return quickSelect2(arr, 0, n - 1, n / 2);
+    }
+
+    private static int quickSelect2(int[] arr, int left, int right, int k){
+        int pivotV=arr[left+random.nextInt(right-left+1)],tmpV;
+        int posEqual=left,posSmaller=left; // a[left,posEqual): = pivotV; a[posEqual,posSmaller): < pivotV
+        for(int i=left;i<=right;i++){
+            if(arr[i]==pivotV){
+                tmpV=arr[i];
+                arr[i]=arr[posSmaller];
+                arr[posSmaller]=arr[posEqual];
+                arr[posEqual]=tmpV;
+                posEqual++;
+                posSmaller++;
+            }else
+            if(arr[i]<pivotV){
+                tmpV=arr[posSmaller];
+                arr[posSmaller]=arr[i];
+                arr[i]=tmpV;
+                posSmaller++;
+            }
+        }
+        if(k+(posEqual-left)<=posSmaller-1)return quickSelect2(arr,posEqual,posSmaller-1,k+(posEqual-left));
+        else if(k<=posSmaller-1)return pivotV;
+        else return quickSelect2(arr,posSmaller,right,k);
+    }
+    public static int findMedian(int[] arr) {
+        if (arr == null || arr.length == 0) {
+            throw new IllegalArgumentException("数组不能为空");
+        }
+        int n = arr.length;
+        return quickSelect(arr, 0, n - 1, n / 2);
+    }
+
+    private static int quickSelect(int[] arr, int left, int right, int k) {
+        if (left == right) {
+            return arr[left];
+        }
+
+        int pivotIndex = partition(arr, left, right);
+        if (k == pivotIndex) {
+            return arr[k];
+        } else if (k < pivotIndex) {
+            return quickSelect(arr, left, pivotIndex - 1, k);
+        } else {
+            return quickSelect(arr, pivotIndex + 1, right, k);
+        }
+    }
+
+    private static int partition(int[] arr, int left, int right) {
+        int pivot = arr[right];
+        int i = left;
+        for (int j = left; j < right; j++) {
+            if (arr[j] <= pivot) {
+                swap(arr, i, j);
+                i++;
+            }
+        }
+        swap(arr, i, right);
+        return i;
+    }
+
+    private static void swap(int[] arr, int i, int j) {
+        int temp = arr[i];
+        arr[i] = arr[j];
+        arr[j] = temp;
+    }
+    public static int zigzag(int num) {
+        if (num < 0) return ((-num)<<1)-1;
+        else return num<<1;
+    }
+
+    public static int deZigzag(int num) {
+        if (num % 2 == 0) return num>>1;
+        else return -((num+1)>>1);
+    }
+
+    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 ;
+                }
+            }
+        }
+
+    }
+
+    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 int[] getAbsDeltaTsBlock(
+            int[] ts_block,
+            int i,
+            int block_size,
+            int remaining,
+            int[] min_delta) {
+        int[] ts_block_delta = new int[remaining-1];
+
+        int base = i*block_size+1;
+        int end = i*block_size+remaining;
+        min_delta[0]=ts_block[base-1];
+        int value_delta_min = Integer.MAX_VALUE;
+        int value_delta_max = Integer.MIN_VALUE;
+        for (int j = base; j < end; j++) {
+            int epsilon_v = ts_block[j] - ts_block[j - 1];
+            epsilon_v = zigzag(epsilon_v);
+            if (epsilon_v < value_delta_min) {
+                value_delta_min = epsilon_v;
+            }
+            if (epsilon_v > value_delta_max) {
+                value_delta_max = epsilon_v;
+            }
+            ts_block_delta[j-base] =epsilon_v;
+
+        }
+        for (int j = 0; j < remaining-1; j++) {
+            ts_block_delta[j] =ts_block_delta[j]-value_delta_min;
+
+        }
+        min_delta[1] = (value_delta_min);
+        min_delta[2] = (value_delta_max-value_delta_min);
+
+
+        return ts_block_delta;
+    }
+
+    public static int encodeOutlier2Bytes(
+            ArrayList<Integer> ts_block_delta,
+            int bit_width,
+            int encode_pos,  byte[] encoded_result)     {
+
+        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
+
+        int n_k = ts_block_delta.size();
+        int n_k_b = n_k / 8;
+        long cur_remaining = 0; // encoded int
+        int cur_number_bits = 0; // the bit width used of encoded int
+        for (int i = n_k_b * 8; i < n_k; i++) {
+            long cur_value = ts_block_delta.get(i);
+            int cur_bit_width = bit_width; // remaining bit width of current value
+
+            if (cur_number_bits + bit_width >= 32) {
+                cur_remaining <<= (32 - cur_number_bits);
+                cur_bit_width = bit_width - 32 + cur_number_bits;
+                cur_remaining += ((cur_value >> cur_bit_width));
+                long2intBytes(cur_remaining,encode_pos,encoded_result);
+                encode_pos += 4;
+                cur_remaining = 0;
+                cur_number_bits = 0;
+            }
+
+            cur_remaining <<= cur_bit_width;
+            cur_number_bits += cur_bit_width;
+            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width));
+        }
+        cur_remaining <<= (32 - cur_number_bits);
+        long2intBytes(cur_remaining,encode_pos,encoded_result);
+        encode_pos += 4;
+        return encode_pos;
+
+
+    }
+
+
+    public static ArrayList<Integer> decodeOutlier2Bytes(
+            byte[] encoded,
+            int decode_pos,
+            int bit_width,
+            int length,
+            ArrayList<Integer> encoded_pos_result
+    ) {
+
+        int n_k_b = length / 8;
+        int remaining = length - n_k_b * 8;
+        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
+        decode_pos += n_k_b * bit_width;
+
+        ArrayList<Long> int_remaining = new ArrayList<>();
+        int int_remaining_size = remaining * bit_width / 32 + 1;
+        for (int j = 0; j < int_remaining_size; j++) {
+            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
+            decode_pos += 4;
+        }
+
+        int cur_remaining_bits = 32; // remaining bit width of current value
+        long cur_number = int_remaining.get(0);
+        int cur_number_i = 1;
+        for (int i = n_k_b * 8; i < length; i++) {
+            if (bit_width < cur_remaining_bits) {
+                int tmp = (int) (cur_number >> (32 - bit_width));
+                result_list.add(tmp);
+                cur_number <<= bit_width;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits -= bit_width;
+            } else {
+                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
+                int remain_bits = bit_width - cur_remaining_bits;
+                tmp <<= remain_bits;
+
+                cur_number = int_remaining.get(cur_number_i);
+                cur_number_i++;
+                tmp += (cur_number >> (32 - remain_bits));
+                result_list.add(tmp);
+                cur_number <<= remain_bits;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits = 32 - remain_bits;
+            }
+        }
+        encoded_pos_result.add(decode_pos);
+        return result_list;
+    }
+
+    private static void addToArchiveCompression(SevenZOutputFile out, File file, String dir) {
+        String name = dir + File.separator + file.getName();
+        if(dir.equals(".")) {
+            name = file.getName();
+        }
+        if (file.isFile()){
+            SevenZArchiveEntry entry = null;
+            FileInputStream in = null;
+            try {
+                entry = out.createArchiveEntry(file, name);
+                out.putArchiveEntry(entry);
+                in = new FileInputStream(file);
+                byte[] b = new byte[1024];
+                int count = 0;
+                while ((count = in.read(b)) > 0) {
+                    out.write(b, 0, count);
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    out.closeArchiveEntry();
+                    in.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+
+            }
+        } else if (file.isDirectory()) {
+            File[] children = file.listFiles();
+            if (children != null){
+                for (File child : children){
+                    addToArchiveCompression(out, child, name);
+                }
+            }
+        } else {
+            System.out.println(file.getName() + " is not supported");
+        }
+    }
+    public static int EncodeBits(int num,
+                                 int bit_width,
+                                 int encode_pos,
+                                 byte[] cur_byte,
+                                 int[] bit_index_list){
+        // 找到要插入的位的索引
+        int bit_index = bit_index_list[0] ;//cur_byte[encode_pos + 1];
+
+        // 计算数值的起始位位置
+        int remaining_bits = bit_width;
+
+        while (remaining_bits > 0) {
+            // 计算在当前字节中可以使用的位数
+            int available_bits = bit_index;
+            int bits_to_write = Math.min(available_bits, remaining_bits);
+
+            // 更新 bit_index
+            bit_index = available_bits - bits_to_write;
+
+            // 计算要写入的位的掩码和数值
+            int mask = (1 << bits_to_write) - 1;
+            int bits = (num >> (remaining_bits - bits_to_write)) & mask;
+
+            // 写入到当前位置
+            cur_byte[encode_pos] &= (byte) ~(mask << bit_index); // 清除对应位置的位
+            cur_byte[encode_pos] |= (byte) (bits << bit_index);
+
+            // 更新位宽和数值
+            remaining_bits -= bits_to_write;
+            if (bit_index == 0) {
+                bit_index = 8;
+                encode_pos++;
+            }
+        }
+        bit_index_list[0] = bit_index;
+//        cur_byte[encode_pos + 1] = (byte) bit_index;
+        return encode_pos;
+    }
+    private static int BOSEncodeBitsImprove(int[] ts_block_delta,
+                                            int final_k_start_value,
+                                            int final_x_l_plus,
+                                            int final_k_end_value,
+                                            int final_x_u_minus,
+                                            int max_delta_value,
+                                            int[] min_delta,
+                                            int encode_pos,
+                                            byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        int k1 = 0;
+        int k2 = 0;
+
+
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+//                encode_pos = EncodeBits(cur_value,left_bit_width,encode_pos,cur_byte);
+//                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+//                encode_pos = EncodeBits(cur_value- final_k_end_value,right_bit_width,encode_pos,cur_byte);
+//                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+//                final_normal.add(cur_value - final_x_l_plus);
+//                encode_pos = EncodeBits(cur_value- final_x_l_plus,right_bit_width,encode_pos,cur_byte);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+        int[] bit_index_list = new int[1];
+        bit_index_list[0] = 8;
+
+        if(final_k_start_value<0 && final_k_end_value > max_delta_value){
+//            int bit_width_final= getBitWith(final_x_u_minus - final_x_l_plus);
+//            cur_byte[encode_pos+1] = 8;
+            for (int cur_value : ts_block_delta) {
+                encode_pos = EncodeBits(cur_value, bit_width_final, encode_pos, cur_byte, bit_index_list);
+//                final_normal.add(cur_value);
+            }
+            if(bit_index_list[0] != 8){
+                encode_pos ++;
+            }
+//            cur_byte[encode_pos+1] = 0;
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+            return encode_pos;
+        }
+
+
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+        int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(final_k_end_value,encode_pos,cur_byte);
+        encode_pos += 4;
+
+//        bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//        encode_pos += 1;
+        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        if (final_alpha == 0) { // 0
+
+            for (int i : bitmap_outlier) {
+
+                intByte2Bytes(i,encode_pos,cur_byte);
+                encode_pos += 1;
+            }
+        } else {
+            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+        }
+//        cur_byte[encode_pos+1] = 8;
+//        bit_index_list[0] = 8;
+        for (int cur_value : ts_block_delta) {
+            if (cur_value <= final_k_start_value) {
+                encode_pos = EncodeBits(cur_value, left_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else if (cur_value >= final_k_end_value) {
+                encode_pos = EncodeBits(cur_value - final_k_end_value, right_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else {
+                encode_pos = EncodeBits(cur_value - final_x_l_plus, bit_width_final, encode_pos, cur_byte,bit_index_list);
+            }
+        }
+        if(bit_index_list[0] != 8){
+            encode_pos ++;
+        }
+
+//        cur_byte[encode_pos+1] = 0;
+
+//        if(k1==0 && k2==0){
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//
+//
+//        }
+//        else{
+//            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+//            encode_pos += 4;
+//            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+//            encode_pos += 4;
+//
+//            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            if (final_alpha == 0) { // 0
+//
+//                for (int i : bitmap_outlier) {
+//
+//                    intByte2Bytes(i,encode_pos,cur_byte);
+//                    encode_pos += 1;
+//                }
+//            } else {
+//                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//            }
+//        }
+
+
+//        if(k1+k2!=block_size)
+//        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//        if (k1 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+//        if (k2 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+        return encode_pos;
+
+    }
+    private static int BOSBlockEncoderImprove(int[] ts_block, int block_i, int block_size, int remaining ,int encode_pos , byte[] cur_byte) {
+
+        int[] min_delta = new int[3];
+        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
+
+
+        block_size = remaining-1;
+        int max_delta_value = min_delta[2];
+
+        int max_bit_width = getBitWith(max_delta_value) + 1;
+
+
+        int[] findMedianArray = new int[block_size];
+        System.arraycopy(ts_block_delta, 0, findMedianArray, 0, block_size);
+
+        int median = findMedianImprove(findMedianArray);
+
+        //        int xl=  median;
+        //        int xu = median;
+        // xl = 2 median - xu
+        // xl = xu - 2 ^ beta
+        int left_number = 0;
+        int right_number = 0;
+
+        int length_outlier = block_size;
+//        for(int value:findMedianArray){
+//            if(value<=median) left_number++;
+//            if (value >= median)  right_number ++;
+//        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2) * (block_size));
+
+
+        int[] count_left = new int[max_bit_width];
+        int[] count_right = new int[max_bit_width];
+        int count_0 = 0;
+
+
+        for(int i=0;i<length_outlier;i++){
+            int cur_value = ts_block_delta[i];
+            if(cur_value > median){
+                int beta = getBitWith(cur_value - median) ;
+                count_right[beta] ++;
+            } else if (cur_value < median) {
+                int beta = getBitWith(median - cur_value) ;
+                count_left[beta] ++;
+            }else{
+                count_0 ++;
+            }
+
+
+        }
+
+
+        for(int beta = max_bit_width - 1; beta > 0 ; beta --){
+            left_number += count_left[beta];
+            right_number += count_right[beta];
+            int pow_beta = (int) pow(2,beta-1);
+            int xu = min(max_delta_value+1, median + pow_beta) ;
+            int xl = max(median - pow_beta,-1);
+            int cur_bits = Math.min((left_number + right_number) * getBitWith(block_size - 1), block_size + left_number + right_number);
+            cur_bits += left_number * getBitWith(xl);
+            cur_bits += right_number * getBitWith(max_delta_value - xu);
+            cur_bits += (block_size - left_number - right_number) * getBitWith(xu - xl - 2);
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+
+                final_k_start_value = xl;
+                final_x_l_plus = xl + 1;
+                final_k_end_value = xu;
+                final_x_u_minus = xu -1;
+            }
+
+        }
+
+        encode_pos = BOSEncodeBitsImprove(ts_block_delta,  final_k_start_value, final_x_l_plus, final_k_end_value, final_x_u_minus,
+                max_delta_value, min_delta, encode_pos , cur_byte);
+
+        return encode_pos;
+    }
+
+    public static int BOSEncoderImprove(
+            int[] data, int block_size, byte[] encoded_result) {
+        block_size++;
+
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+
+            encode_pos =  BOSBlockEncoderImprove(data, i, block_size,block_size, encode_pos,encoded_result);
+
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        } else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+
+
+            encode_pos = BOSBlockEncoderImprove(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+
+//            int[] ts_block = new int[length_all-start];
+//            if (length_all - start >= 0) System.arraycopy(data, start, ts_block, 0, length_all - start);
+//
+//            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;
+//            }
+//
+//
+//            encode_pos = BOSBlockEncoder(ts_block, supple_length, encode_pos,encoded_result);
+        }
+
+
+        return encode_pos;
+    }
+
+    private static int BOSEncodeBits(int[] ts_block_delta,
+                                     int final_k_start_value,
+                                     int final_x_l_plus,
+                                     int final_k_end_value,
+                                     int final_x_u_minus,
+                                     int max_delta_value,
+                                     int[] min_delta,
+                                     int encode_pos,
+                                     byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        int k1 = 0;
+        int k2 = 0;
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+                final_normal.add(cur_value - final_k_start_value-1);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+
+        if(k1==0 && k2==0){
+            bit_width_final = getBitWith(max_delta_value);
+            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+            encode_pos += 1;
+
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//            return encode_pos;
+        }
+        else{
+            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+            encode_pos += 4;
+            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+            encode_pos += 4;
+
+            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+            encode_pos += 1;
+            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+            encode_pos += 1;
+            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+            encode_pos += 1;
+            if (final_alpha == 0) { // 0
+
+                for (int i : bitmap_outlier) {
+
+                    intByte2Bytes(i,encode_pos,cur_byte);
+                    encode_pos += 1;
+                }
+            } else {
+                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            }
+        }
+
+        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+        if (k1 != 0)
+            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+        if (k2 != 0)
+            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+        return encode_pos;
+
+    }
+
+
+    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size, int remaining ,int encode_pos , byte[] cur_byte) {
+
+        int[] min_delta = new int[3];
+        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
+
+
+        block_size = remaining-1;
+        int max_delta_value = min_delta[2];
+
+        int max_bit_width = getBitWith(max_delta_value) + 1;
+
+
+        int[] findMedianArray = new int[block_size];
+        System.arraycopy(ts_block_delta, 0, findMedianArray, 0, block_size);
+
+        int median = findMedian(findMedianArray);
+
+        //        int xl=  median;
+        //        int xu = median;
+        // xl = 2 median - xu
+        // xl = xu - 2 ^ beta
+        int left_number = 0;
+        int right_number = 0;
+
+        int length_outlier = block_size;
+//        for(int value:findMedianArray){
+//            if(value<=median) left_number++;
+//            if (value >= median)  right_number ++;
+//        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2) * (block_size));
+
+
+        int[] count_left = new int[max_bit_width];
+        int[] count_right = new int[max_bit_width];
+        int count_0 = 0;
+
+
+        for(int i=0;i<length_outlier;i++){
+            int cur_value = ts_block_delta[i];
+            if(cur_value > median){
+                int beta = getBitWith(cur_value - median) ;
+                count_right[beta] ++;
+            } else if (cur_value < median) {
+                int beta = getBitWith(median - cur_value) ;
+                count_left[beta] ++;
+            }else{
+                count_0 ++;
+            }
+
+
+        }
+
+
+        for(int beta = max_bit_width - 1; beta > 0 ; beta --){
+            left_number += count_left[beta];
+            right_number += count_right[beta];
+            int pow_beta = (int) pow(2,beta-1);
+            int xu = min(max_delta_value+1, median + pow_beta) ;
+            int xl = max(median - pow_beta,-1);
+            int cur_bits = Math.min((left_number + right_number) * getBitWith(block_size - 1), block_size + left_number + right_number);
+            cur_bits += left_number * getBitWith(xl);
+            cur_bits += right_number * getBitWith(max_delta_value - xu);
+            cur_bits += (block_size - left_number - right_number) * getBitWith(xu - xl - 2);
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+
+                final_k_start_value = xl;
+                final_x_l_plus = xl + 1;
+                final_k_end_value = xu;
+                final_x_u_minus = xu -1;
+            }
+
+        }
+
+        encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_x_l_plus, final_k_end_value, final_x_u_minus,
+                max_delta_value, min_delta, encode_pos , cur_byte);
+
+        return encode_pos;
+    }
+
+
+    public static int BOSEncoder(
+            int[] data, int block_size, byte[] encoded_result) {
+        block_size++;
+
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+
+            encode_pos =  BOSBlockEncoder(data, i, block_size,block_size, encode_pos,encoded_result);
+
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        } else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+
+
+            encode_pos = BOSBlockEncoder(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+
+//            int[] ts_block = new int[length_all-start];
+//            if (length_all - start >= 0) System.arraycopy(data, start, ts_block, 0, length_all - start);
+//
+//            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;
+//            }
+//
+//
+//            encode_pos = BOSBlockEncoder(ts_block, supple_length, encode_pos,encoded_result);
+        }
+
+
+        return encode_pos;
+    }
+
+
+    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+        int value0 = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        value_list[value_pos_arr[0]] =value0;
+        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        if(k1!=0 || k2 != 0){
+            final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+            decode_pos += 4;
+
+            final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+            decode_pos += 4;
+
+            bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+
+            left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+            right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+
+            if (final_alpha == 0) {
+                int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
+                for (int i = 0; i < bitmap_bytes; i++) {
+                    bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                    decode_pos += 1;
+                }
+                int bitmap_outlier_i = 0;
+                int remaining_bits = 8;
+                int tmp = bitmap_outlier.get(bitmap_outlier_i);
+                bitmap_outlier_i++;
+                int i = 0;
+                while (i < block_size ) {
+                    if (remaining_bits > 1) {
+                        int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_i == 1) {
+                            int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                            remaining_bits -= 1;
+                            if (bit_left_right == 1) {
+                                final_left_outlier_index.add(i);
+                            } else {
+                                final_right_outlier_index.add(i);
+                            }
+                        }
+                        if (remaining_bits == 0) {
+                            remaining_bits = 8;
+                            if (bitmap_outlier_i >= bitmap_bytes) break;
+                            tmp = bitmap_outlier.get(bitmap_outlier_i);
+                            bitmap_outlier_i++;
+                        }
+                    } else if (remaining_bits == 1) {
+                        int bit_i = tmp & 0x1;
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                        if (bit_i == 1) {
+                            int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                            remaining_bits -= 1;
+                            if (bit_left_right == 1) {
+                                final_left_outlier_index.add(i);
+                            } else {
+                                final_right_outlier_index.add(i);
+                            }
+                        }
+                    }
+                    i++;
+                }
+            } else {
+                ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+                final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
+                decode_pos = (decode_pos_result_left.get(0));
+                ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+                final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
+                decode_pos = (decode_pos_result_right.get(0));
+            }
+        }else {
+            bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+        }
+
+
+        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+
+        decode_pos = decode_pos_normal.get(0);
+        if (k1 != 0) {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+            decode_pos = decode_pos_result_left.get(0);
+        }
+        if (k2 != 0) {
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+            decode_pos = decode_pos_result_right.get(0);
+        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+
+        for (int i = 0; i < block_size; i++) {
+            int current_delta;
+            if (left_outlier_i >= k1) {
+                if (right_outlier_i >= k2) {
+                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
+                    current_delta =  final_right_outlier.get(right_outlier_i) + final_k_end_value;
+                    right_outlier_i++;
+                } else {
+                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                }
+            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
+                current_delta =  final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+            } else {
+
+                if (right_outlier_i >= k2) {
+                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
+                    current_delta =  final_right_outlier.get(right_outlier_i) + final_k_end_value;
+                    right_outlier_i++;
+                } else {
+                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
+                    normal_i++;
+                }
+            }
+
+            pre_v = deZigzag(current_delta) + min_delta + pre_v;
+            value_list[value_pos_arr[0]] =pre_v;
+            value_pos_arr[0] ++;
+        }
+        return decode_pos;
+    }
+
+    public static int DecodeBits(byte[] cur_byte, int bit_width, int[] decode_pos_list) {
+        int decode_pos = decode_pos_list[0];
+        int bit_index = decode_pos_list[1];  //cur_byte[decode_pos + 1];
+        int remaining_bits = bit_width;
+        int num = 0;
+
+        while (remaining_bits > 0) {
+            int available_bits = bit_index;
+            int bits_to_read = Math.min(available_bits, remaining_bits);
+
+            // 计算要读取的位的掩码
+            int mask = (1 << bits_to_read) - 1;
+            int bits = (cur_byte[decode_pos] >> (available_bits - bits_to_read)) & mask;
+
+            // 将读取的位合并到结果中
+            num = (num << bits_to_read) | bits;
+
+            // 更新位宽和 bit_index
+            remaining_bits -= bits_to_read;
+            bit_index = available_bits - bits_to_read;
+
+            if (bit_index == 0) {
+                bit_index = 8;
+                decode_pos++;
+            }
+        }
+        decode_pos_list[0] = decode_pos;
+        decode_pos_list[1] = bit_index;
+
+        return num;
+    }
+    public static int BOSBlockDecoderImprove(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+        int value0 = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        value_list[value_pos_arr[0]] =value0;
+        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        int[] decode_list = new int[2];
+        decode_list[0]= decode_pos;
+        decode_list[1]= 8;
+
+        int valuePos = value_pos_arr[0];
+
+        if(k1==0 && k2==0){
+            int pre_v = value0;
+            for (int i = 0; i < block_size; i++) {
+                int cur_delta = min_delta + DecodeBits(encoded, bit_width_final,  decode_list);
+                pre_v += deZigzag(cur_delta);
+                value_list[valuePos++] = pre_v;
+            }
+            value_pos_arr[0] = valuePos;
+            return decode_list[0];
+        }
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+//        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+//        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+//        bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+//        decode_pos += 1;
+
+        left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+        right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        if (final_alpha == 0) {
+            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
+            for (int i = 0; i < bitmap_bytes; i++) {
+                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                decode_pos += 1;
+            }
+            int bitmap_outlier_i = 0;
+            int remaining_bits = 8;
+            int tmp = bitmap_outlier.get(bitmap_outlier_i);
+            bitmap_outlier_i++;
+            int i = 0;
+            while (i < block_size ) {
+                if (remaining_bits > 1) {
+                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                    remaining_bits -= 1;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                    if (remaining_bits == 0) {
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                    }
+                } else if (remaining_bits == 1) {
+                    int bit_i = tmp & 0x1;
+                    remaining_bits = 8;
+                    if (bitmap_outlier_i >= bitmap_bytes) break;
+                    tmp = bitmap_outlier.get(bitmap_outlier_i);
+                    bitmap_outlier_i++;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                }
+                i++;
+            }
+        } else {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
+            decode_pos = (decode_pos_result_left.get(0));
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
+            decode_pos = (decode_pos_result_right.get(0));
+        }
+
+
+
+
+
+//        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+//        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+//
+//        decode_pos = decode_pos_normal.get(0);
+//        if (k1 != 0) {
+//            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+//            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+//            decode_pos = decode_pos_result_left.get(0);
+//        }
+//        if (k2 != 0) {
+//            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+//            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+//            decode_pos = decode_pos_result_right.get(0);
+//        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+// Precompute constants
+        int normalOffset = min_delta + final_k_start_value;
+        int rightOutlierOffset = min_delta + final_k_end_value;
+
+// Initialize indices and pre-fetch next outlier positions
+        int leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+        int rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+        decode_list[0]= decode_pos;
+//        decode_list[1]= 8;
+        // Use a local variable for the position
+        for (int i = 0; i < block_size; i++) {
+            int currentDelta;
+            if (i == leftOutlierNextIndex) {
+                // Process left outlier
+                currentDelta = min_delta + DecodeBits(encoded, left_bit_width,  decode_list); // final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+                leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+            } else if (i == rightOutlierNextIndex) {
+                // Process right outlier
+                currentDelta = rightOutlierOffset + DecodeBits(encoded, right_bit_width,  decode_list);// final_right_outlier.get(right_outlier_i);
+                right_outlier_i++;
+                rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+            } else {
+                // Process normal value
+                currentDelta = normalOffset + DecodeBits(encoded, bit_width_final,  decode_list);
+                normal_i++;
+            }
+
+            // Update the cumulative value and store it
+            pre_v += deZigzag(currentDelta);
+            value_list[valuePos++] = pre_v;
+        }
+        value_pos_arr[0] = valuePos;
+        if(decode_list[1]!=8){
+            return decode_list[0]+1;
+        }else {
+            return decode_list[0];
+        }
+//        decode_pos = decode_list[0];
+// Update the position in the array
+
+
+//        return decode_pos;
+    }
+    public static void BOSDecoderImprove(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        block_size --;
+
+        int[] value_pos_arr = new int[1];
+        for (int k = 0; k < block_num; k++) {
+            decode_pos = BOSBlockDecoderImprove(encoded, decode_pos, value_list, block_size,value_pos_arr);
+
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            remain_length --;
+            BOSBlockDecoderImprove(encoded, decode_pos, value_list, remain_length, value_pos_arr);
+        }
+    }
+
+    public static void BOSDecoder(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        block_size --;
+
+        int[] value_pos_arr = new int[1];
+        for (int k = 0; k < block_num; k++) {
+            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list, block_size,value_pos_arr);
+
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            remain_length --;
+            BOSBlockDecoder(encoded, decode_pos, value_list, remain_length, value_pos_arr);
+        }
+    }
+
+    public static void main(@org.jetbrains.annotations.NotNull String[] args) throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/sprintz_bos_m";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        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(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+//        for (int file_i = 8; file_i < 9; file_i++) {
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+
+
+            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) {
+//                f = tempList[1];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+                loader.readHeaders();
+
+                while (loader.readRecord()) {
+
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+
+                }
+
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+                int repeatTime2 = 100;
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoder(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+                    String[] record = {
+                            f.toString(),
+                            "SPRINTZ+BOS-M",
+                            String.valueOf(encodeTime),
+                            String.valueOf(decodeTime),
+                            String.valueOf(data1.size()),
+                            String.valueOf(compressed_size),
+                            String.valueOf(ratio)
+                    };
+                    writer.writeRecord(record);
+                    System.out.println(ratio);
+
+
+            }
+            writer.close();
+
+        }
+    }
+
+    @Test
+    public void compressTest() throws IOException {
+//        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R3O2_compare_compression/compression_ratio/sprintz_m_c";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        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(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 1;
+//        for (int file_i = 8; file_i < 9; file_i++) {
+        CompressionType[] compressList = {
+                CompressionType.LZ4,
+                CompressionType.LZMA2,
+        };
+
+        for (int file_i = input_path_list.size()-1; file_i >=0 ; file_i--) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            File file = new File(inputPath);
+            File[] tempList = file.listFiles();
+
+            CsvWriter writer = new CsvWriter(Output, ',', StandardCharsets.UTF_8);
+
+            String[] head = {
+                    "Input Direction",
+                    "Encoding Algorithm",
+                    "Compress 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<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+                inputStream.close();
+
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+
+                for (CompressionType comp : compressList) {
+                    double ratio = 0;
+                    double compressed_size = 0;
+                    ICompressor compressor = ICompressor.getCompressor(comp);
+                    byte[] compressed = compressor.compress(encoded_result);
+
+                    // test compression ratio and compressed size
+                    compressed_size += compressed.length;
+                    double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                    ratio += ratioTmp;
+                    s = System.nanoTime();
+                    for (int repeat = 0; repeat < repeatTime2; repeat++)
+                        BOSDecoder(encoded_result);
+                    e = System.nanoTime();
+                    decodeTime += ((e - s) / repeatTime2);
+
+
+                    String[] record = {
+                            f.toString(),
+                            "SPRINTZ+BOS-M",
+                            comp.toString(),
+                            String.valueOf(encodeTime),
+                            String.valueOf(decodeTime),
+                            String.valueOf(data1.size()),
+                            String.valueOf(compressed_size),
+                            String.valueOf(ratio)
+                    };
+                    writer.writeRecord(record);
+                    System.out.println(ratio);
+                }
+                double ratio = 0;
+                double compressed_size = 0;
+                File outfile = new File(parent_dir + "icde0802/example.bin");
+
+                // 使用FileOutputStream将byte数组写入文件
+                try (FileOutputStream fos = new FileOutputStream(outfile)) {
+                    fos.write(encoded_result);
+                } catch (IOException e2) {
+                    // 处理可能的I/O异常
+                    e2.printStackTrace();
+                }
+
+                File input = new File(parent_dir + "icde0802/example.bin");
+                File output = new File(parent_dir + "icde0802/example.7z");
+                SevenZOutputFile out = new SevenZOutputFile(output);
+
+                addToArchiveCompression(out, input, ".");
+                out.closeArchiveEntry();
+
+                long compressed = output.length();
+
+
+                // test compression ratio and compressed size
+                compressed_size += compressed;
+                double ratioTmp =
+                        (double) compressed / (double) (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+
+
+                String[] record = {
+                        f.toString(),
+                        "SPRINTZ+BOS-M",
+                        "7ZIP",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void ExpTest() throws IOException {//        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/sprintz_exp_test";
+        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<>();
+        dataset_name.add("Synthetic_Exp_100");
+        dataset_name.add("Synthetic_Exp_1000");
+        dataset_name.add("Synthetic_Exp_10000");
+        dataset_name.add("Synthetic_Exp_100000");
+        dataset_name.add("Synthetic_Exp_1000000");
+        dataset_name.add("Synthetic_Normal_100");
+        dataset_name.add("Synthetic_Normal_1000");
+        dataset_name.add("Synthetic_Normal_10000");
+        dataset_name.add("Synthetic_Normal_100000");
+        dataset_name.add("Synthetic_Normal_1000000");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        output_path_list.add(output_parent_dir + "/Exp_100.csv"); // 0
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/Exp_1000.csv");// 1
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Exp_10000.csv");// 2
+        output_path_list.add(output_parent_dir + "/Exp_100000.csv");// 2
+        output_path_list.add(output_parent_dir + "/Exp_1000000.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Normal_100.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Normal_1000.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/Normal_10000.csv");//5
+        output_path_list.add(output_parent_dir + "/Normal_100000.csv");//5
+        output_path_list.add(output_parent_dir + "/Normal_1000000.csv");//5
+//        dataset_block_size.add(2048);
+
+//        for (int file_i = 8; file_i < 9; file_i++) {
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+
+
+            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) {
+//                f = tempList[1];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+                loader.readHeaders();
+
+                while (loader.readRecord()) {
+
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+
+                }
+
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+                int repeatTime2 = 1;
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoder(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+                String[] record = {
+                        f.toString(),
+                        "SPRINTZ+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+
+
+            }
+            writer.close();
+
+        }
+    }
+
+    @Test
+    public void BOSImproveDecodeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R1O4_decode_time/compression_ratio/sprintz_bos_m";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[2];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "SPRINTZ+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void BOSImproveEncodeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/sprintz_bos_m_improve";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[2];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "SPRINTZ+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
+}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSVTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSVTest.java
index acf736e..da8590d 100644
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSVTest.java
+++ b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSVTest.java
@@ -2,6 +2,7 @@
 
 import com.csvreader.CsvReader;
 import com.csvreader.CsvWriter;
+import org.junit.Test;
 
 import java.io.File;
 import java.io.IOException;
@@ -11,7 +12,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 
-import static java.lang.Math.pow;
+import static java.lang.Math.*;
 
 public class SPRINTZBOSVTest {
 
@@ -180,6 +181,7 @@
 
     // -----------------------------------------------------------------
 
+
     public static int[] getAbsDeltaTsBlock(
             int[] ts_block,
             int i,
@@ -215,7 +217,6 @@
 
         return ts_block_delta;
     }
-
     public static int encodeOutlier2Bytes(
             ArrayList<Integer> ts_block_delta,
             int bit_width,
@@ -304,7 +305,9 @@
 
     private static int BOSEncodeBits(int[] ts_block_delta,
                                      int final_k_start_value,
+                                     int final_x_l_plus,
                                      int final_k_end_value,
+                                     int final_x_u_minus,
                                      int max_delta_value,
                                      int[] min_delta,
                                      int encode_pos,
@@ -385,32 +388,49 @@
         int2Bytes(k_byte,encode_pos,cur_byte);
         encode_pos += 4;
 
-        int2Bytes(min_delta[0],encode_pos,cur_byte); // x0
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
         encode_pos += 4;
-        int2Bytes(min_delta[1],encode_pos,cur_byte); // x_min
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
         encode_pos += 4;
-        int2Bytes(final_k_start_value,encode_pos,cur_byte);
-        encode_pos += 4;
-        int bit_width_final = getBitWith(final_k_end_value - final_k_start_value-2);
-        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
-        encode_pos += 1;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
         int left_bit_width = getBitWith(final_k_start_value);//final_left_max
         int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
-        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        if (final_alpha == 0) { // 0
 
-            for (int i : bitmap_outlier) {
+        if(k1==0 && k2==0){
+            bit_width_final = getBitWith(max_delta_value);
+            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+            encode_pos += 1;
 
-                intByte2Bytes(i,encode_pos,cur_byte);
-                encode_pos += 1;
-            }
-        } else {
-            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
-            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//            return encode_pos;
         }
+        else{
+            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+            encode_pos += 4;
+            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+            encode_pos += 4;
+
+            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+            encode_pos += 1;
+            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+            encode_pos += 1;
+            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+            encode_pos += 1;
+            if (final_alpha == 0) { // 0
+
+                for (int i : bitmap_outlier) {
+
+                    intByte2Bytes(i,encode_pos,cur_byte);
+                    encode_pos += 1;
+                }
+            } else {
+                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            }
+        }
+
         encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
         if (k1 != 0)
             encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
@@ -429,6 +449,7 @@
 
         block_size = remaining-1;
         int max_delta_value = min_delta[2];
+
         int[] value_list = new int[block_size];
         int unique_value_count = 0;
         int[] value_count_list = new int[max_delta_value+1];
@@ -459,34 +480,81 @@
         }
 
 
-        int final_k_start_value = -1;
-        int final_k_end_value = max_delta_value+1;
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
 
         int min_bits = 0;
-        min_bits += (getBitWith(final_k_end_value - final_k_start_value ) * (block_size));
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2 ) * (block_size));
+
+        int cur_k1 = 0;
+
+        int x_l_plus_value = 0; // x_l_plus
+        int x_u_minus_value = max_delta_value; // x_u_plus
+
+        for (int end_value_i = 1; end_value_i < unique_value_count; end_value_i++) {
+
+            x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+            int x_u_plus_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+            int cur_bits = 0;
+            int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value); // cur_k1 = 0
+            if (cur_k2 != 0)
+                cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus_value);
 
 
-        int start_value_size =  unique_value_count;
-        for (int start_value_i = 0; start_value_i < start_value_size; start_value_i++) {
-            int k_start_value =  getUniqueValue(sorted_value_list[start_value_i], left_shift) ;
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_x_u_minus = x_u_minus_value;
+                final_k_end_value = x_u_plus_value;
+            }
+        }
 
-            int cur_k1 = getCount(sorted_value_list[start_value_i],mask);
+        int k_start_value = -1; // x_l_minus
+
+        for (int start_value_i = 0; start_value_i < unique_value_count-1; start_value_i++) {
+            long k_start_valueL = sorted_value_list[start_value_i];
+            k_start_value =  getUniqueValue(k_start_valueL, left_shift) ;
+            x_l_plus_value =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+
+
+            cur_k1 = getCount(k_start_valueL,mask);
+
             int k_end_value;
             int cur_bits;
             int cur_k2;
+            k_end_value = max_delta_value + 1;
+
+            cur_bits = 0;
+            cur_k2 = 0;
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            cur_bits += cur_k1 * getBitWith(k_start_value);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k1) * getBitWith(k_end_value- x_l_plus_value); //cur_k2 =0
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_k_start_value = k_start_value;
+                final_x_l_plus = x_l_plus_value;
+                final_k_end_value = k_end_value;
+                final_x_u_minus = max_delta_value;
+            }
 
             for (int end_value_i = start_value_i + 1; end_value_i < unique_value_count; end_value_i++) {
 
+                x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
                 k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
 
                 cur_bits = 0;
                 cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
 
                 cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
-                if (cur_k1 != 0)
-                    cur_bits += cur_k1 * getBitWith(k_start_value);
+                cur_bits += cur_k1 * getBitWith(k_start_value);
                 if (cur_k1 + cur_k2 != block_size)
-                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(k_end_value - k_start_value-2);
+                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
                 if (cur_k2 != 0)
                     cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
 
@@ -494,14 +562,16 @@
                 if (cur_bits < min_bits) {
                     min_bits = cur_bits;
                     final_k_start_value = k_start_value;
+                    final_x_l_plus = x_l_plus_value;
                     final_k_end_value = k_end_value;
+                    final_x_u_minus = x_u_minus_value;
                 }
 
             }
         }
 
-        encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_k_end_value, max_delta_value,
-                min_delta, encode_pos , cur_byte);
+        encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_x_l_plus, final_k_end_value, final_x_u_minus,
+                max_delta_value, min_delta, encode_pos , cur_byte);
 
         return encode_pos;
     }
@@ -561,8 +631,438 @@
 
         return encode_pos;
     }
+    public static int EncodeBits(int num,
+                                 int bit_width,
+                                 int encode_pos,
+                                 byte[] cur_byte,
+                                 int[] bit_index_list){
+        // 找到要插入的位的索引
+        int bit_index = bit_index_list[0] ;//cur_byte[encode_pos + 1];
+
+        // 计算数值的起始位位置
+        int remaining_bits = bit_width;
+
+        while (remaining_bits > 0) {
+            // 计算在当前字节中可以使用的位数
+            int available_bits = bit_index;
+            int bits_to_write = Math.min(available_bits, remaining_bits);
+
+            // 更新 bit_index
+            bit_index = available_bits - bits_to_write;
+
+            // 计算要写入的位的掩码和数值
+            int mask = (1 << bits_to_write) - 1;
+            int bits = (num >> (remaining_bits - bits_to_write)) & mask;
+
+            // 写入到当前位置
+            cur_byte[encode_pos] &= (byte) ~(mask << bit_index); // 清除对应位置的位
+            cur_byte[encode_pos] |= (byte) (bits << bit_index);
+
+            // 更新位宽和数值
+            remaining_bits -= bits_to_write;
+            if (bit_index == 0) {
+                bit_index = 8;
+                encode_pos++;
+            }
+        }
+        bit_index_list[0] = bit_index;
+//        cur_byte[encode_pos + 1] = (byte) bit_index;
+        return encode_pos;
+    }
+    private static int BOSEncodeBitsImprove(int[] ts_block_delta,
+                                            int final_k_start_value,
+                                            int final_x_l_plus,
+                                            int final_k_end_value,
+                                            int final_x_u_minus,
+                                            int max_delta_value,
+                                            int[] min_delta,
+                                            int encode_pos,
+                                            byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        int k1 = 0;
+        int k2 = 0;
 
 
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+//                encode_pos = EncodeBits(cur_value,left_bit_width,encode_pos,cur_byte);
+//                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+//                encode_pos = EncodeBits(cur_value- final_k_end_value,right_bit_width,encode_pos,cur_byte);
+//                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+//                final_normal.add(cur_value - final_x_l_plus);
+//                encode_pos = EncodeBits(cur_value- final_x_l_plus,right_bit_width,encode_pos,cur_byte);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+        int[] bit_index_list = new int[1];
+        bit_index_list[0] = 8;
+
+        if(final_k_start_value<0 && final_k_end_value > max_delta_value){
+//            int bit_width_final= getBitWith(final_x_u_minus - final_x_l_plus);
+//            cur_byte[encode_pos+1] = 8;
+            for (int cur_value : ts_block_delta) {
+                encode_pos = EncodeBits(cur_value, bit_width_final, encode_pos, cur_byte, bit_index_list);
+//                final_normal.add(cur_value);
+            }
+            if(bit_index_list[0] != 8){
+                encode_pos ++;
+            }
+//            cur_byte[encode_pos+1] = 0;
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+            return encode_pos;
+        }
+
+
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+        int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(final_k_end_value,encode_pos,cur_byte);
+        encode_pos += 4;
+
+//        bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//        encode_pos += 1;
+        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        if (final_alpha == 0) { // 0
+
+            for (int i : bitmap_outlier) {
+
+                intByte2Bytes(i,encode_pos,cur_byte);
+                encode_pos += 1;
+            }
+        } else {
+            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+        }
+//        cur_byte[encode_pos+1] = 8;
+//        bit_index_list[0] = 8;
+        for (int cur_value : ts_block_delta) {
+            if (cur_value <= final_k_start_value) {
+                encode_pos = EncodeBits(cur_value, left_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else if (cur_value >= final_k_end_value) {
+                encode_pos = EncodeBits(cur_value - final_k_end_value, right_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else {
+                encode_pos = EncodeBits(cur_value - final_x_l_plus, bit_width_final, encode_pos, cur_byte,bit_index_list);
+            }
+        }
+        if(bit_index_list[0] != 8){
+            encode_pos ++;
+        }
+
+//        cur_byte[encode_pos+1] = 0;
+
+//        if(k1==0 && k2==0){
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//
+//
+//        }
+//        else{
+//            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+//            encode_pos += 4;
+//            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+//            encode_pos += 4;
+//
+//            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            if (final_alpha == 0) { // 0
+//
+//                for (int i : bitmap_outlier) {
+//
+//                    intByte2Bytes(i,encode_pos,cur_byte);
+//                    encode_pos += 1;
+//                }
+//            } else {
+//                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//            }
+//        }
+
+
+//        if(k1+k2!=block_size)
+//        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//        if (k1 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+//        if (k2 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+        return encode_pos;
+
+    }
+
+    private static int BOSBlockEncoderImprove(int[] ts_block, int block_i, int block_size, int remaining ,int encode_pos , byte[] cur_byte) {
+
+        int[] min_delta = new int[3];
+        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
+
+
+        block_size = remaining-1;
+        int max_delta_value = min_delta[2];
+
+        int[] value_list = new int[block_size];
+        int unique_value_count = 0;
+        int[] value_count_list = new int[max_delta_value+1];
+        for(int value:ts_block_delta){
+            if(value_count_list[value]==0){
+                value_count_list[value] = 1;
+                value_list[unique_value_count] = value;
+                unique_value_count ++;
+            }else{
+                value_count_list[value] ++;
+            }
+        }
+
+        int left_shift = getBitWith(block_size);
+        int mask =  (1 << left_shift) - 1;
+        long[] sorted_value_list = new long[unique_value_count];
+        int count = 0;
+
+        for(int i=0;i<unique_value_count;i++){
+            int value = value_list[i];
+            sorted_value_list[i] = (((long) value) << left_shift) + value_count_list[value];
+        }
+        Arrays.sort(sorted_value_list);
+
+        for(int i=0;i<unique_value_count;i++){
+            count += getCount(sorted_value_list[i], mask);
+            sorted_value_list[i] = (((long)getUniqueValue(sorted_value_list[i], left_shift) ) << left_shift) + count;//new_value_list[i]
+        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2 ) * (block_size));
+
+        int cur_k1 = 0;
+
+        int x_l_plus_value = 0; // x_l_plus
+        int x_u_minus_value = max_delta_value; // x_u_plus
+
+        for (int end_value_i = 1; end_value_i < unique_value_count; end_value_i++) {
+
+            x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+            int x_u_plus_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+            int cur_bits = 0;
+            int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value); // cur_k1 = 0
+            if (cur_k2 != 0)
+                cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus_value);
+
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_x_u_minus = x_u_minus_value;
+                final_k_end_value = x_u_plus_value;
+            }
+        }
+
+        int k_start_value = -1; // x_l_minus
+
+        for (int start_value_i = 0; start_value_i < unique_value_count-1; start_value_i++) {
+            long k_start_valueL = sorted_value_list[start_value_i];
+            k_start_value =  getUniqueValue(k_start_valueL, left_shift) ;
+            x_l_plus_value =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+
+
+            cur_k1 = getCount(k_start_valueL,mask);
+
+            int k_end_value;
+            int cur_bits;
+            int cur_k2;
+            k_end_value = max_delta_value + 1;
+
+            cur_bits = 0;
+            cur_k2 = 0;
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            cur_bits += cur_k1 * getBitWith(k_start_value);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k1) * getBitWith(k_end_value- x_l_plus_value); //cur_k2 =0
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_k_start_value = k_start_value;
+                final_x_l_plus = x_l_plus_value;
+                final_k_end_value = k_end_value;
+                final_x_u_minus = max_delta_value;
+            }
+
+            for (int end_value_i = start_value_i + 1; end_value_i < unique_value_count; end_value_i++) {
+
+                x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+                k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+
+                cur_bits = 0;
+                cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+
+                cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                cur_bits += cur_k1 * getBitWith(k_start_value);
+                if (cur_k1 + cur_k2 != block_size)
+                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+                if (cur_k2 != 0)
+                    cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+
+
+                if (cur_bits < min_bits) {
+                    min_bits = cur_bits;
+                    final_k_start_value = k_start_value;
+                    final_x_l_plus = x_l_plus_value;
+                    final_k_end_value = k_end_value;
+                    final_x_u_minus = x_u_minus_value;
+                }
+
+            }
+        }
+
+        encode_pos = BOSEncodeBitsImprove(ts_block_delta,  final_k_start_value, final_x_l_plus, final_k_end_value, final_x_u_minus,
+                max_delta_value, min_delta, encode_pos , cur_byte);
+
+        return encode_pos;
+    }
+
+    public static int BOSEncoderImprove(
+            int[] data, int block_size, byte[] encoded_result) {
+        block_size++;
+
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+
+            encode_pos =  BOSBlockEncoderImprove(data, i, block_size,block_size, encode_pos,encoded_result);
+
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        } else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+
+
+            encode_pos = BOSBlockEncoderImprove(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+
+//            int[] ts_block = new int[length_all-start];
+//            if (length_all - start >= 0) System.arraycopy(data, start, ts_block, 0, length_all - start);
+//
+//            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;
+//            }
+//
+//
+//            encode_pos = BOSBlockEncoder(ts_block, supple_length, encode_pos,encoded_result);
+        }
+
+
+        return encode_pos;
+    }
     public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
         int k_byte = bytes2Integer(encoded, decode_pos, 4);
         decode_pos += 4;
@@ -579,81 +1079,92 @@
 
         int min_delta = bytes2Integer(encoded, decode_pos, 4);
         decode_pos += 4;
-
-        int final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        int left_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-        int right_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
         ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
         ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
         ArrayList<Integer> final_left_outlier = new ArrayList<>();
         ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal;
+        ArrayList<Integer> final_normal= new ArrayList<>();;
         ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
 
-        if (final_alpha == 0) {
-            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
+        if(k1!=0 || k2 != 0){
+            final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+            decode_pos += 4;
 
-            for (int i = 0; i < bitmap_bytes; i++) {
-                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
-                decode_pos += 1;
-            }
-            int bitmap_outlier_i = 0;
-            int remaining_bits = 8;
-            int tmp = bitmap_outlier.get(bitmap_outlier_i);
-            bitmap_outlier_i++;
-            int i = 0;
-            while (i < block_size) {
-                if (remaining_bits > 1) {
-                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
-                    remaining_bits -= 1;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+            final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+            decode_pos += 4;
+
+            bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+
+            left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+            right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+
+            if (final_alpha == 0) {
+                int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
+                for (int i = 0; i < bitmap_bytes; i++) {
+                    bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                    decode_pos += 1;
+                }
+                int bitmap_outlier_i = 0;
+                int remaining_bits = 8;
+                int tmp = bitmap_outlier.get(bitmap_outlier_i);
+                bitmap_outlier_i++;
+                int i = 0;
+                while (i < block_size ) {
+                    if (remaining_bits > 1) {
+                        int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
                         remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
+                        if (bit_i == 1) {
+                            int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                            remaining_bits -= 1;
+                            if (bit_left_right == 1) {
+                                final_left_outlier_index.add(i);
+                            } else {
+                                final_right_outlier_index.add(i);
+                            }
                         }
-                    }
-                    if (remaining_bits == 0) {
+                        if (remaining_bits == 0) {
+                            remaining_bits = 8;
+                            if (bitmap_outlier_i >= bitmap_bytes) break;
+                            tmp = bitmap_outlier.get(bitmap_outlier_i);
+                            bitmap_outlier_i++;
+                        }
+                    } else if (remaining_bits == 1) {
+                        int bit_i = tmp & 0x1;
                         remaining_bits = 8;
                         if (bitmap_outlier_i >= bitmap_bytes) break;
                         tmp = bitmap_outlier.get(bitmap_outlier_i);
                         bitmap_outlier_i++;
-                    }
-                } else if (remaining_bits == 1) {
-                    int bit_i = tmp & 0x1;
-                    remaining_bits = 8;
-                    if (bitmap_outlier_i >= bitmap_bytes) break;
-                    tmp = bitmap_outlier.get(bitmap_outlier_i);
-                    bitmap_outlier_i++;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
+                        if (bit_i == 1) {
+                            int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                            remaining_bits -= 1;
+                            if (bit_left_right == 1) {
+                                final_left_outlier_index.add(i);
+                            } else {
+                                final_right_outlier_index.add(i);
+                            }
                         }
                     }
+                    i++;
                 }
-                i++;
+            } else {
+                ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+                final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
+                decode_pos = (decode_pos_result_left.get(0));
+                ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+                final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
+                decode_pos = (decode_pos_result_right.get(0));
             }
-        } else {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
-            decode_pos = (decode_pos_result_left.get(0));
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
-            decode_pos = (decode_pos_result_right.get(0));
+        }else {
+            bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
         }
 
 
@@ -675,7 +1186,7 @@
         int right_outlier_i = 0;
         int normal_i = 0;
         int pre_v = value0;
-        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
 
 
         for (int i = 0; i < block_size; i++) {
@@ -748,10 +1259,263 @@
         }
     }
 
+    public static int DecodeBits(byte[] cur_byte, int bit_width, int[] decode_pos_list) {
+        int decode_pos = decode_pos_list[0];
+        int bit_index = decode_pos_list[1];  //cur_byte[decode_pos + 1];
+        int remaining_bits = bit_width;
+        int num = 0;
+
+        while (remaining_bits > 0) {
+            int available_bits = bit_index;
+            int bits_to_read = Math.min(available_bits, remaining_bits);
+
+            // 计算要读取的位的掩码
+            int mask = (1 << bits_to_read) - 1;
+            int bits = (cur_byte[decode_pos] >> (available_bits - bits_to_read)) & mask;
+
+            // 将读取的位合并到结果中
+            num = (num << bits_to_read) | bits;
+
+            // 更新位宽和 bit_index
+            remaining_bits -= bits_to_read;
+            bit_index = available_bits - bits_to_read;
+
+            if (bit_index == 0) {
+                bit_index = 8;
+                decode_pos++;
+            }
+        }
+        decode_pos_list[0] = decode_pos;
+        decode_pos_list[1] = bit_index;
+
+        return num;
+    }
+    public static int BOSBlockDecoderImprove(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+        int value0 = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        value_list[value_pos_arr[0]] =value0;
+        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        int[] decode_list = new int[2];
+        decode_list[0]= decode_pos;
+        decode_list[1]= 8;
+
+        int valuePos = value_pos_arr[0];
+
+        if(k1==0 && k2==0){
+            int pre_v = value0;
+            for (int i = 0; i < block_size; i++) {
+                int cur_delta = min_delta + DecodeBits(encoded, bit_width_final,  decode_list);
+                pre_v += deZigzag(cur_delta);
+                value_list[valuePos++] = pre_v;
+            }
+            value_pos_arr[0] = valuePos;
+            return decode_list[0];
+        }
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+//        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+//        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+//        bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+//        decode_pos += 1;
+
+        left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+        right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        if (final_alpha == 0) {
+            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
+            for (int i = 0; i < bitmap_bytes; i++) {
+                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                decode_pos += 1;
+            }
+            int bitmap_outlier_i = 0;
+            int remaining_bits = 8;
+            int tmp = bitmap_outlier.get(bitmap_outlier_i);
+            bitmap_outlier_i++;
+            int i = 0;
+            while (i < block_size ) {
+                if (remaining_bits > 1) {
+                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                    remaining_bits -= 1;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                    if (remaining_bits == 0) {
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                    }
+                } else if (remaining_bits == 1) {
+                    int bit_i = tmp & 0x1;
+                    remaining_bits = 8;
+                    if (bitmap_outlier_i >= bitmap_bytes) break;
+                    tmp = bitmap_outlier.get(bitmap_outlier_i);
+                    bitmap_outlier_i++;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                }
+                i++;
+            }
+        } else {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
+            decode_pos = (decode_pos_result_left.get(0));
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
+            decode_pos = (decode_pos_result_right.get(0));
+        }
+
+
+
+
+
+//        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+//        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+//
+//        decode_pos = decode_pos_normal.get(0);
+//        if (k1 != 0) {
+//            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+//            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+//            decode_pos = decode_pos_result_left.get(0);
+//        }
+//        if (k2 != 0) {
+//            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+//            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+//            decode_pos = decode_pos_result_right.get(0);
+//        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+// Precompute constants
+        int normalOffset = min_delta + final_k_start_value;
+        int rightOutlierOffset = min_delta + final_k_end_value;
+
+// Initialize indices and pre-fetch next outlier positions
+        int leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+        int rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+        decode_list[0]= decode_pos;
+//        decode_list[1]= 8;
+        // Use a local variable for the position
+        for (int i = 0; i < block_size; i++) {
+            int currentDelta;
+            if (i == leftOutlierNextIndex) {
+                // Process left outlier
+                currentDelta = min_delta + DecodeBits(encoded, left_bit_width,  decode_list); // final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+                leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+            } else if (i == rightOutlierNextIndex) {
+                // Process right outlier
+                currentDelta = rightOutlierOffset + DecodeBits(encoded, right_bit_width,  decode_list);// final_right_outlier.get(right_outlier_i);
+                right_outlier_i++;
+                rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+            } else {
+                // Process normal value
+                currentDelta = normalOffset + DecodeBits(encoded, bit_width_final,  decode_list);
+                normal_i++;
+            }
+
+            // Update the cumulative value and store it
+            pre_v += deZigzag(currentDelta);
+            value_list[valuePos++] = pre_v;
+        }
+        value_pos_arr[0] = valuePos;
+        if(decode_list[1]!=8){
+            return decode_list[0]+1;
+        }else {
+            return decode_list[0];
+        }
+//        decode_pos = decode_list[0];
+// Update the position in the array
+
+
+//        return decode_pos;
+    }
+    public static void BOSDecoderImprove(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        block_size --;
+
+        int[] value_pos_arr = new int[1];
+        for (int k = 0; k < block_num; k++) {
+            decode_pos = BOSBlockDecoderImprove(encoded, decode_pos, value_list, block_size,value_pos_arr);
+
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            remain_length --;
+            BOSBlockDecoderImprove(encoded, decode_pos, value_list, remain_length, value_pos_arr);
+        }
+    }
+
     public static void main(@org.jetbrains.annotations.NotNull String[] args) throws IOException {
-//        String parent_dir = "/Users/xiaojinzhao/Desktop/encoding-outlier/";// your data path
-        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
-        String output_parent_dir = parent_dir + "vldb/compression_ratio/sprintz_bos";
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/sprintz_bos";
         String input_parent_dir = parent_dir + "trans_data/";
         ArrayList<String> input_path_list = new ArrayList<>();
         ArrayList<String> output_path_list = new ArrayList<>();
@@ -877,7 +1641,7 @@
 
                     String[] record = {
                             f.toString(),
-                            "SPRINTZ+BOS-O",
+                            "SPRINTZ+BOS-V",
                             String.valueOf(encodeTime),
                             String.valueOf(decodeTime),
                             String.valueOf(data1.size()),
@@ -894,4 +1658,150 @@
         }
     }
 
+
+    @Test
+    public void BOSImproveTimeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R1O4_decode_time/compression_ratio/sprintz_bos_v";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[2];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "SPRINTZ+BOS-V",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
 }
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSLTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBPTest.java
similarity index 64%
rename from iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSLTest.java
rename to iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBPTest.java
index 5937c72..ecd724a 100644
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBOSLTest.java
+++ b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/SPRINTZBPTest.java
@@ -2,6 +2,7 @@
 
 import com.csvreader.CsvReader;
 import com.csvreader.CsvWriter;
+import org.junit.Test;
 
 import java.io.File;
 import java.io.IOException;
@@ -12,7 +13,7 @@
 
 import static java.lang.Math.pow;
 
-public class SPRINTZBOSLTest {
+public class SPRINTZBPTest {
 
     public static int getBitWith(int num) {
         if (num == 0) return 1;
@@ -24,7 +25,47 @@
     public static int getUniqueValue(long long1, int left_shift) {
         return ((int) ((long1) >> left_shift));
     }
+    public static int findMedian(int[] arr) {
+        if (arr == null || arr.length == 0) {
+            throw new IllegalArgumentException("数组不能为空");
+        }
+        int n = arr.length;
+        return quickSelect(arr, 0, n - 1, n / 2);
+    }
 
+    private static int quickSelect(int[] arr, int left, int right, int k) {
+        if (left == right) {
+            return arr[left];
+        }
+
+        int pivotIndex = partition(arr, left, right);
+        if (k == pivotIndex) {
+            return arr[k];
+        } else if (k < pivotIndex) {
+            return quickSelect(arr, left, pivotIndex - 1, k);
+        } else {
+            return quickSelect(arr, pivotIndex + 1, right, k);
+        }
+    }
+
+    private static int partition(int[] arr, int left, int right) {
+        int pivot = arr[right];
+        int i = left;
+        for (int j = left; j < right; j++) {
+            if (arr[j] <= pivot) {
+                swap(arr, i, j);
+                i++;
+            }
+        }
+        swap(arr, i, right);
+        return i;
+    }
+
+    private static void swap(int[] arr, int i, int j) {
+        int temp = arr[i];
+        arr[i] = arr[j];
+        arr[j] = temp;
+    }
     public static int zigzag(int num) {
         if (num < 0) return ((-num)<<1)-1;
         else return num<<1;
@@ -178,26 +219,7 @@
     }
 
     // -----------------------------------------------------------------
-    public static int[] getAbsDeltaTsBlock(
-            int[] ts_block,
-            ArrayList<Integer> min_delta,
-            int supple_length) {
 
-        int[] ts_block_delta = new int[ts_block.length+supple_length-1];
-        int block_size = ts_block.length-1;
-
-        for (int i = 0; i < block_size; i++) {
-
-            int epsilon_v = ts_block[i+1] - ts_block[i];
-            epsilon_v = zigzag(epsilon_v);
-            ts_block_delta[i] = epsilon_v;
-        }
-        for(int i = block_size;i<block_size+supple_length;i++){
-            ts_block_delta[i] = 0;
-        }
-        min_delta.add(ts_block[0]);
-        return ts_block_delta;
-    }
     public static int[] getAbsDeltaTsBlock(
             int[] ts_block,
             int i,
@@ -309,7 +331,7 @@
 
                 cur_number = int_remaining.get(cur_number_i);
                 cur_number_i++;
-                tmp += (int) (cur_number >> (32 - remain_bits));
+                tmp += (cur_number >> (32 - remain_bits));
                 result_list.add(tmp);
                 cur_number <<= remain_bits;
                 cur_number &= 0xFFFFFFFFL;
@@ -322,7 +344,9 @@
 
     private static int BOSEncodeBits(int[] ts_block_delta,
                                      int final_k_start_value,
+                                     int final_x_l_plus,
                                      int final_k_end_value,
+                                     int final_x_u_minus,
                                      int max_delta_value,
                                      int[] min_delta,
                                      int encode_pos,
@@ -403,32 +427,49 @@
         int2Bytes(k_byte,encode_pos,cur_byte);
         encode_pos += 4;
 
-        int2Bytes(min_delta[0],encode_pos,cur_byte); // x0
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
         encode_pos += 4;
-        int2Bytes(min_delta[1],encode_pos,cur_byte); // x_min
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
         encode_pos += 4;
-        int2Bytes(final_k_start_value,encode_pos,cur_byte);
-        encode_pos += 4;
-        int bit_width_final = getBitWith(final_k_end_value - final_k_start_value-2);
-        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
-        encode_pos += 1;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
         int left_bit_width = getBitWith(final_k_start_value);//final_left_max
         int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
-        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        if (final_alpha == 0) { // 0
 
-            for (int i : bitmap_outlier) {
+        if(k1==0 && k2==0){
+            bit_width_final = getBitWith(max_delta_value);
+            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+            encode_pos += 1;
 
-                intByte2Bytes(i,encode_pos,cur_byte);
-                encode_pos += 1;
-            }
-        } else {
-            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
-            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//            return encode_pos;
         }
+        else{
+            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+            encode_pos += 4;
+            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+            encode_pos += 4;
+
+            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+            encode_pos += 1;
+            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+            encode_pos += 1;
+            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+            encode_pos += 1;
+            if (final_alpha == 0) { // 0
+
+                for (int i : bitmap_outlier) {
+
+                    intByte2Bytes(i,encode_pos,cur_byte);
+                    encode_pos += 1;
+                }
+            } else {
+                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            }
+        }
+
         encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
         if (k1 != 0)
             encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
@@ -438,7 +479,7 @@
 
     }
 
-    // sprintz need to substitute ---- start
+
     private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size, int remaining ,int encode_pos , byte[] cur_byte) {
 
         int[] min_delta = new int[3];
@@ -446,140 +487,126 @@
 
 
         block_size = remaining-1;
-
-
-
         int max_delta_value = min_delta[2];
-        int[] alpha_count_list = new int[getBitWith(max_delta_value)+1];//count(xmin) count(xmin + 2) count(xmin + 4)... count(xmax)
-        int[] alpha_box_count_list = new int[getBitWith(max_delta_value)];// count(xmin, xmin + 2), count(xmin + 2, xmin + 4)...
-        int[] gamma_count_list = new int[getBitWith(max_delta_value)+1];
-        int[] gamma_box_count_list = new int[getBitWith(max_delta_value)];
-        for(int value:ts_block_delta){
-            if (value == 0){
-                alpha_count_list[0]++;
-            }
-            else if (value == pow(2,getBitWith(value)-1) && value != 1){
-                alpha_count_list[getBitWith(value)-1]++;
-            }else {
-                alpha_box_count_list[getBitWith(value)-1]++;
-            }
-            if (value == max_delta_value){
-                gamma_count_list[0]++;
-            }
-            else if (max_delta_value - value == pow(2,getBitWith(max_delta_value-value)-1) && max_delta_value - value != 1){
-                gamma_count_list[getBitWith(max_delta_value-value)-1]++;
-            }else {
-                gamma_box_count_list[getBitWith(max_delta_value-value)-1]++;
-            }
+
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
+        encode_pos += 4;
+        int bit_width_final = getBitWith(max_delta_value);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        for(int i : ts_block_delta){
+            final_normal.add(i);
         }
+        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
 
-        int final_k_start_value = -1;
-        int final_k_end_value = max_delta_value+1;
-
-        int min_bits = 0;
-        min_bits += (getBitWith(final_k_end_value - final_k_start_value ) * (block_size));
-
-        int alpha_size = getBitWith(max_delta_value);
-        int cur_k1_close = 0;
-        for (int alpha = 1; alpha < alpha_size; alpha++) {
-            int k_start_value_close = (int) pow(2,alpha-1);
-            cur_k1_close +=  alpha_count_list[alpha-1];
-            if (alpha > 1) {
-                cur_k1_close += alpha_box_count_list[alpha - 2];
-            }
-            int cur_k2_close = 0;
-            int k_end_value_close;
-            int cur_bits;
-
-            for (int gamma = 1; (int) pow(2,gamma) + (int) pow(2,alpha) <= max_delta_value + 1; gamma++) {
-
-                k_end_value_close = max_delta_value - (int) pow(2,gamma-1);
-
-                cur_bits = 0;
-                cur_k2_close += gamma_count_list[gamma-1];
-                if (gamma > 1){
-                    cur_k2_close += gamma_box_count_list[gamma-2];
-                }
-
-                cur_bits += Math.min((cur_k1_close + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_close);
-                if (cur_k1_close != 0)
-                    cur_bits += cur_k1_close * alpha;
-                if (cur_k1_close + cur_k2_close != block_size)
-                    cur_bits += (block_size - cur_k1_close - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_close-2);
-                if (cur_k2_close != 0)
-                    cur_bits += cur_k2_close * gamma;
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k_start_value_close;
-                    final_k_end_value = k_end_value_close;
-                }
-
-                //C2
-                cur_bits = 0;
-                int cur_k1_open = cur_k1_close - alpha_count_list[alpha - 1];
-                int cur_k2_open = cur_k2_close - gamma_count_list[gamma - 1];
-                int k_start_value_open = k_start_value_close - 1;
-                int k_end_value_open = k_end_value_close + 1;
-                cur_bits += Math.min((cur_k1_open + cur_k2_open) * getBitWith(block_size-1), block_size + cur_k1_open + cur_k2_open);
-                if (cur_k1_open != 0)
-                    cur_bits += cur_k1_open * (alpha - 1);
-                if (cur_k1_open + cur_k2_open != block_size)
-                    cur_bits += (block_size - cur_k1_open - cur_k2_open) * getBitWith(k_end_value_open - k_start_value_open - 2);
-                if (cur_k2_open != 0)
-                    cur_bits += cur_k2_open * (gamma - 1);
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k_start_value_open;
-                    final_k_end_value = k_end_value_open;
-                }
-
-                //C3 k1 open k2 close
-                cur_bits = 0;
-                cur_bits += Math.min((cur_k1_open + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_open + cur_k2_close);
-                if (cur_k1_open != 0)
-                    cur_bits += cur_k1_open * (alpha - 1);
-                if (cur_k1_open + cur_k2_close != block_size)
-                    cur_bits += (block_size - cur_k1_open - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_open - 2);
-                if (cur_k2_close != 0)
-                    cur_bits += cur_k2_close * gamma;
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k_start_value_open;
-                    final_k_end_value = k_end_value_close;
-                }
-
-                //C4 k1 close k2 open
-                cur_bits = 0;
-                cur_bits += Math.min((cur_k1_close + cur_k2_open) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_open);
-                if (cur_k1_close != 0)
-                    cur_bits += cur_k1_close * alpha;
-                if (cur_k1_close + cur_k2_open != block_size)
-                    cur_bits += (block_size - cur_k1_close - cur_k2_open) * getBitWith(k_end_value_open - k_start_value_close - 2);
-                if (cur_k2_open != 0)
-                    cur_bits += cur_k2_open * (gamma - 1);
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k_start_value_close;
-                    final_k_end_value = k_end_value_open;
-                }
-
-
-            }
-        }
-
-        // RLE need to substitute ----- end
-
-
-        encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_k_end_value, max_delta_value,
-                min_delta, encode_pos , cur_byte);
 
         return encode_pos;
     }
 
+    public static int EncodeBits(int num,
+                                 int bit_width,
+                                 int encode_pos,
+                                 byte[] cur_byte,
+                                 int[] bit_index_list){
+        // 找到要插入的位的索引
+        int bit_index = bit_index_list[0] ;//cur_byte[encode_pos + 1];
+
+        // 计算数值的起始位位置
+        int remaining_bits = bit_width;
+
+        while (remaining_bits > 0) {
+            // 计算在当前字节中可以使用的位数
+            int available_bits = bit_index;
+            int bits_to_write = Math.min(available_bits, remaining_bits);
+
+            // 更新 bit_index
+            bit_index = available_bits - bits_to_write;
+
+            // 计算要写入的位的掩码和数值
+            int mask = (1 << bits_to_write) - 1;
+            int bits = (num >> (remaining_bits - bits_to_write)) & mask;
+
+            // 写入到当前位置
+            cur_byte[encode_pos] &= (byte) ~(mask << bit_index); // 清除对应位置的位
+            cur_byte[encode_pos] |= (byte) (bits << bit_index);
+
+            // 更新位宽和数值
+            remaining_bits -= bits_to_write;
+            if (bit_index == 0) {
+                bit_index = 8;
+                encode_pos++;
+            }
+        }
+        bit_index_list[0] = bit_index;
+//        cur_byte[encode_pos + 1] = (byte) bit_index;
+        return encode_pos;
+    }
+    private static int BOSBlockEncoderImprove(int[] ts_block, int block_i, int block_size, int remaining ,int encode_pos , byte[] cur_byte) {
+
+        int[] min_delta = new int[3];
+        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
+        encode_pos += 4;
+        int bit_width_final = getBitWith(min_delta[2]);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+//        ArrayList<Integer> final_normal = new ArrayList<>();
+        int[] bit_index_list = new int[1];
+        bit_index_list[0] = 8;
+        for(int value:ts_block_delta){
+            encode_pos = EncodeBits(value, bit_width_final, encode_pos, cur_byte, bit_index_list);
+        }
+        if(bit_index_list[0] != 8){
+            encode_pos ++;
+        }
+//        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+        return encode_pos;
+    }
+    public static int BOSEncoderImprove(
+            int[] data, int block_size, byte[] encoded_result) {
+        block_size++;
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+            encode_pos =  BOSBlockEncoderImprove(data, i, block_size, block_size,encode_pos,encoded_result);
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        }
+        else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+            encode_pos = BOSBlockEncoderImprove(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+        }
+
+
+        return encode_pos;
+    }
     public static int BOSEncoder(
             int[] data, int block_size, byte[] encoded_result) {
         block_size++;
@@ -638,14 +665,11 @@
 
 
     public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
-        int k_byte = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-        int k1_byte = (int) (k_byte % pow(2, 16));
-        int k1 = k1_byte / 2;
-        int final_alpha = k1_byte % 2;
 
-        int k2 = (int) (k_byte / pow(2, 16));
+        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
 
+        int bit_width_final = 0;
         int value0 = bytes2Integer(encoded, decode_pos, 4);
         decode_pos += 4;
         value_list[value_pos_arr[0]] =value0;
@@ -654,135 +678,21 @@
         int min_delta = bytes2Integer(encoded, decode_pos, 4);
         decode_pos += 4;
 
-        int final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
 
-        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        bit_width_final = bytes2Integer(encoded, decode_pos, 1);
         decode_pos += 1;
-
-        int left_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-        int right_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal;
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-
-        if (final_alpha == 0) {
-            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
-
-            for (int i = 0; i < bitmap_bytes; i++) {
-                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
-                decode_pos += 1;
-            }
-            int bitmap_outlier_i = 0;
-            int remaining_bits = 8;
-            int tmp = bitmap_outlier.get(bitmap_outlier_i);
-            bitmap_outlier_i++;
-            int i = 0;
-            while (i < block_size) {
-                if (remaining_bits > 1) {
-                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
-                    remaining_bits -= 1;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                    if (remaining_bits == 0) {
-                        remaining_bits = 8;
-                        if (bitmap_outlier_i >= bitmap_bytes) break;
-                        tmp = bitmap_outlier.get(bitmap_outlier_i);
-                        bitmap_outlier_i++;
-                    }
-                } else if (remaining_bits == 1) {
-                    int bit_i = tmp & 0x1;
-                    remaining_bits = 8;
-                    if (bitmap_outlier_i >= bitmap_bytes) break;
-                    tmp = bitmap_outlier.get(bitmap_outlier_i);
-                    bitmap_outlier_i++;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                }
-                i++;
-            }
-        } else {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
-            decode_pos = (decode_pos_result_left.get(0));
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
-            decode_pos = (decode_pos_result_right.get(0));
-        }
-
-
         ArrayList<Integer> decode_pos_normal = new ArrayList<>();
-        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size , decode_pos_normal);
 
         decode_pos = decode_pos_normal.get(0);
-        if (k1 != 0) {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
-            decode_pos = decode_pos_result_left.get(0);
-        }
-        if (k2 != 0) {
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
-            decode_pos = decode_pos_result_right.get(0);
-        }
-        int left_outlier_i = 0;
-        int right_outlier_i = 0;
+
         int normal_i = 0;
         int pre_v = value0;
-        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
 
 
         for (int i = 0; i < block_size; i++) {
-            int current_delta;
-            if (left_outlier_i >= k1) {
-                if (right_outlier_i >= k2) {
-                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta =  final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
-                    normal_i++;
-                }
-            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
-                current_delta =  final_left_outlier.get(left_outlier_i);
-                left_outlier_i++;
-            } else {
-
-                if (right_outlier_i >= k2) {
-                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta =  final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta =  final_normal.get(normal_i) + final_k_start_value+1;
-                    normal_i++;
-                }
-            }
-
-            pre_v = deZigzag(current_delta) + min_delta + pre_v;
+            int current_delta=  final_normal.get(normal_i);
+            pre_v = deZigzag(current_delta + min_delta)  + pre_v;
             value_list[value_pos_arr[0]] =pre_v;
             value_pos_arr[0] ++;
         }
@@ -804,7 +714,10 @@
         block_size --;
 
         int[] value_pos_arr = new int[1];
+//        System.out.println(length_all);
+//        System.out.println(encoded.length);
         for (int k = 0; k < block_num; k++) {
+//            System.out.println(k);
             decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list, block_size,value_pos_arr);
 
         }
@@ -822,10 +735,127 @@
         }
     }
 
+    public static int DecodeBits(byte[] cur_byte, int bit_width, int[] decode_pos_list) {
+        int decode_pos = decode_pos_list[0];
+        int bit_index = decode_pos_list[1];  //cur_byte[decode_pos + 1];
+        int remaining_bits = bit_width;
+        int num = 0;
+
+        while (remaining_bits > 0) {
+            int available_bits = bit_index;
+            int bits_to_read = Math.min(available_bits, remaining_bits);
+
+            // 计算要读取的位的掩码
+            int mask = (1 << bits_to_read) - 1;
+            int bits = (cur_byte[decode_pos] >> (available_bits - bits_to_read)) & mask;
+
+            // 将读取的位合并到结果中
+            num = (num << bits_to_read) | bits;
+
+            // 更新位宽和 bit_index
+            remaining_bits -= bits_to_read;
+            bit_index = available_bits - bits_to_read;
+
+            if (bit_index == 0) {
+                bit_index = 8;
+                decode_pos++;
+            }
+        }
+        decode_pos_list[0] = decode_pos;
+        decode_pos_list[1] = bit_index;
+
+        return num;
+    }
+    public static int BOSBlockDecoderImprove(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
+
+
+        int value0 = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        value_list[value_pos_arr[0]] =value0;
+        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        int[] decode_list = new int[2];
+        decode_list[0]= decode_pos;
+        decode_list[1]= 8;
+        int pre_v = value0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_delta = min_delta + DecodeBits(encoded, bit_width_final,  decode_list);
+            pre_v += deZigzag(cur_delta);
+            value_list[value_pos_arr[0]++] = pre_v;
+        }
+        if(decode_list[1]!=8){
+            return decode_list[0]+1;
+        }else {
+            return decode_list[0];
+        }
+//        value_pos_arr[0] = valuePos;
+//        return decode_list[0];
+
+//        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+//        ArrayList<Integer> final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size, decode_pos_normal);
+//
+//        decode_pos = decode_pos_normal.get(0);
+//        int normal_i = 0;
+////        int pre_v = value0;
+//
+//        for (int i = 0; i < block_size; i++) {
+//            int current_delta = min_delta + final_normal.get(normal_i) ;
+//            pre_v = current_delta + pre_v;
+//            value_list[value_pos_arr[0]] = pre_v;
+//            value_pos_arr[0]++;
+//        }
+//
+//        return decode_pos;
+    }
+    public static void BOSDecoderImprove(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        block_size--;
+
+        int[] value_pos_arr = new int[1];
+        for (int k = 0; k < block_num; k++) {
+
+
+            decode_pos = BOSBlockDecoderImprove(encoded, decode_pos, value_list, block_size,value_pos_arr);
+
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            remain_length --;
+            BOSBlockDecoderImprove(encoded, decode_pos, value_list, remain_length, value_pos_arr);
+        }
+    }
+
     public static void main(@org.jetbrains.annotations.NotNull String[] args) throws IOException {
-//                String parent_dir = "/Users/xiaojinzhao/Desktop/encoding-outlier/";// your data path
-        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
-        String output_parent_dir = parent_dir + "vldb/compression_ratio/sprintz_bws";
+        int repeatTime2 = 100;
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/sprintz";
         String input_parent_dir = parent_dir + "trans_data/";
         ArrayList<String> input_path_list = new ArrayList<>();
         ArrayList<String> output_path_list = new ArrayList<>();
@@ -874,7 +904,7 @@
         output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
 //        dataset_block_size.add(1024);
 
-//        for (int file_i = 8; file_i < 9; file_i++) {
+//        for (int file_i = 7; file_i < 8; file_i++) {
         for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
 
             String inputPath = input_path_list.get(file_i);
@@ -902,7 +932,7 @@
             assert tempList != null;
 
             for (File f : tempList) {
-
+//                f = tempList[1];
                 System.out.println(f);
                 InputStream inputStream = Files.newInputStream(f.toPath());
 
@@ -929,7 +959,7 @@
                 long decodeTime = 0;
                 double ratio = 0;
                 double compressed_size = 0;
-                int repeatTime2 = 100;
+
 
                 int length = 0;
 
@@ -949,17 +979,17 @@
                 e = System.nanoTime();
                 decodeTime += ((e - s) / repeatTime2);
 
-                    String[] record = {
-                            f.toString(),
-                            "SPRINTZ+BWS",
-                            String.valueOf(encodeTime),
-                            String.valueOf(decodeTime),
-                            String.valueOf(data1.size()),
-                            String.valueOf(compressed_size),
-                            String.valueOf(ratio)
-                    };
-                    writer.writeRecord(record);
-                    System.out.println(ratio);
+                String[] record = {
+                        f.toString(),
+                        "SPRINTZ",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
 
 
             }
@@ -968,4 +998,5 @@
         }
     }
 
+
 }
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSBImproveTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSBImproveTest.java
new file mode 100644
index 0000000..cecedce
--- /dev/null
+++ b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSBImproveTest.java
@@ -0,0 +1,2389 @@
+package org.apache.iotdb.tsfile.encoding;
+
+import com.csvreader.CsvReader;
+import com.csvreader.CsvWriter;
+import org.junit.Test;
+
+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.ArrayList;
+import java.util.Arrays;
+
+import static java.lang.Math.min;
+import static java.lang.Math.pow;
+
+public class TSDIFFBOSBImproveTest {
+
+    public static long combine2Int(int int1, int int2) {
+        return ((long) int1 << 32) | (int2 & 0xFFFFFFFFL);
+    }
+
+    public static int getTime(long long1) {
+        return ((int) (long1 >> 32));
+    }
+
+    public static int getValue(long long1) {
+        return ((int) (long1));
+    }
+
+    public static int getCount(long long1, int mask) {
+        return ((int) (long1 & mask));
+    }
+    public static int getUniqueValue(long long1, int left_shift) {
+        return ((int) ((long1) >> left_shift));
+    }
+
+    public static int getBitWith(int num) {
+        if (num == 0) return 1;
+        else return 32 - Integer.numberOfLeadingZeros(num);
+    }
+
+    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 int[] getAbsDeltaTsBlock(
+            int[] ts_block,
+            int i,
+            int block_size,
+            int remaining,
+            int[] min_delta) {
+        int[] ts_block_delta = new int[remaining-1];
+
+        int value_delta_min = Integer.MAX_VALUE;
+        int value_delta_max = Integer.MIN_VALUE;
+        int base = i*block_size+1;
+        int end = i*block_size+remaining;
+
+        int tmp_j_1 = ts_block[base-1];
+        min_delta[0] =tmp_j_1;
+        int j = base;
+        int tmp_j;
+
+        while(j<end){
+            tmp_j = ts_block[j];
+            int epsilon_v = tmp_j - tmp_j_1;
+            ts_block_delta[j-base] = epsilon_v;
+            if (epsilon_v < value_delta_min) {
+                value_delta_min = epsilon_v;
+            }
+            if (epsilon_v > value_delta_max) {
+                value_delta_max = epsilon_v;
+            }
+            tmp_j_1 = tmp_j;
+            j++;
+        }
+        j = 0;
+        end = remaining -1;
+        while(j<end){
+            ts_block_delta[j] = ts_block_delta[j] - value_delta_min;
+            j++;
+        }
+
+        min_delta[1] = value_delta_min;
+        min_delta[2] = (value_delta_max-value_delta_min);
+
+
+        return ts_block_delta;
+    }
+
+
+    public static int encodeOutlier2Bytes(
+            ArrayList<Integer> ts_block_delta,
+            int bit_width,
+            int encode_pos,  byte[] encoded_result) {
+
+        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
+
+        int n_k = ts_block_delta.size();
+        int n_k_b = n_k / 8;
+        long cur_remaining = 0; // encoded int
+        int cur_number_bits = 0; // the bit width used of encoded int
+        for (int i = n_k_b * 8; i < n_k; i++) {
+            long cur_value = ts_block_delta.get(i);
+            int cur_bit_width = bit_width; // remaining bit width of current value
+
+            if (cur_number_bits + bit_width >= 32) {
+                cur_remaining <<= (32 - cur_number_bits);
+                cur_bit_width = bit_width - 32 + cur_number_bits;
+                cur_remaining += ((cur_value >> cur_bit_width));
+                long2intBytes(cur_remaining,encode_pos,encoded_result);
+                encode_pos += 4;
+                cur_remaining = 0;
+                cur_number_bits = 0;
+            }
+
+            cur_remaining <<= cur_bit_width;
+            cur_number_bits += cur_bit_width;
+            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width)); //
+        }
+        cur_remaining <<= (32 - cur_number_bits);
+        long2intBytes(cur_remaining,encode_pos,encoded_result);
+        encode_pos += 4;
+        return encode_pos;
+
+    }
+
+
+    public static ArrayList<Integer> decodeOutlier2Bytes(
+            byte[] encoded,
+            int decode_pos,
+            int bit_width,
+            int length,
+            ArrayList<Integer> encoded_pos_result
+    ) {
+
+        int n_k_b = length / 8;
+        int remaining = length - n_k_b * 8;
+        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
+        decode_pos += n_k_b * bit_width;
+
+        ArrayList<Long> int_remaining = new ArrayList<>();
+        int int_remaining_size = remaining * bit_width / 32 + 1;
+        for (int j = 0; j < int_remaining_size; j++) {
+            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
+            decode_pos += 4;
+        }
+
+        int cur_remaining_bits = 32; // remaining bit width of current value
+        long cur_number = int_remaining.get(0);
+        int cur_number_i = 1;
+        for (int i = n_k_b * 8; i < length; i++) {
+            if (bit_width < cur_remaining_bits) {
+                int tmp = (int) (cur_number >> (32 - bit_width));
+                result_list.add(tmp);
+                cur_number <<= bit_width;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits -= bit_width;
+            } else {
+                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
+                int remain_bits = bit_width - cur_remaining_bits;
+                tmp <<= remain_bits;
+
+                cur_number = int_remaining.get(cur_number_i);
+                cur_number_i++;
+                tmp += (int) (cur_number >> (32 - remain_bits));
+                result_list.add(tmp);
+                cur_number <<= remain_bits;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits = 32 - remain_bits;
+            }
+        }
+        encoded_pos_result.add(decode_pos);
+        return result_list;
+    }
+
+    private static int BOSEncodeBits(int[] ts_block_delta,
+                                     int final_k_start_value,
+                                     int final_x_l_plus,
+                                     int final_k_end_value,
+                                     int final_x_u_minus,
+                                     int max_delta_value,
+                                     int[] min_delta,
+                                     int encode_pos,
+                                     byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        int k1 = 0;
+        int k2 = 0;
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+                final_normal.add(cur_value - final_x_l_plus);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+
+        if(k1==0 && k2==0){
+            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+            encode_pos += 1;
+
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//            return encode_pos;
+        }
+        else{
+            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+            encode_pos += 4;
+            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+            encode_pos += 4;
+
+            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+            encode_pos += 1;
+            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+            encode_pos += 1;
+            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+            encode_pos += 1;
+            if (final_alpha == 0) { // 0
+
+                for (int i : bitmap_outlier) {
+
+                    intByte2Bytes(i,encode_pos,cur_byte);
+                    encode_pos += 1;
+                }
+            } else {
+                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            }
+        }
+
+
+//        if(k1+k2!=block_size)
+        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+        if (k1 != 0)
+            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+        if (k2 != 0)
+            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+        return encode_pos;
+
+    }
+
+
+    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size, int remaining ,int encode_pos , byte[] cur_byte) {
+
+        int[] min_delta = new int[3];
+        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
+
+
+        block_size = remaining-1;
+        int max_delta_value = min_delta[2];
+        int[] value_list = new int[block_size];
+        int unique_value_count = 0;
+        int[] value_count_list = new int[max_delta_value+1];
+        for(int value:ts_block_delta){
+            if(value_count_list[value]==0){
+                value_count_list[value] = 1;
+                value_list[unique_value_count] = value;
+                unique_value_count ++;
+            }else{
+                value_count_list[value] ++;
+            }
+        }
+
+        int left_shift = getBitWith(block_size);
+        int mask =  (1 << left_shift) - 1;
+        long[] sorted_value_list = new long[unique_value_count];
+        int count = 0;
+
+        for(int i=0;i<unique_value_count;i++){
+            int value = value_list[i];
+            sorted_value_list[i] = (((long) value) << left_shift) + value_count_list[value];
+        }
+        Arrays.sort(sorted_value_list);
+
+        for(int i=0;i<unique_value_count;i++){
+            count += getCount(sorted_value_list[i], mask);
+            sorted_value_list[i] = (((long)getUniqueValue(sorted_value_list[i], left_shift) ) << left_shift) + count;//new_value_list[i]
+        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2 ) * (block_size));
+
+        int cur_k1 = 0;
+
+        int x_l_plus_value = 0; // x_l_plus
+        int x_u_minus_value = max_delta_value; // x_u_plus
+
+        for (int end_value_i = 1; end_value_i < unique_value_count; end_value_i++) {
+
+            x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+            int x_u_plus_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+            int cur_bits = 0;
+            int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value); // cur_k1 = 0
+            if (cur_k2 != 0)
+                cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus_value);
+
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_x_u_minus = x_u_minus_value;
+                final_k_end_value = x_u_plus_value;
+            }
+        }
+
+        int k_start_value = -1; // x_l_minus
+//        int beta_max_all = getBitWith(max_delta_value)+1;
+//        int[][] hash_table_count = new int[unique_value_count][beta_max_all];
+//        int[][] hash_table_value = new int[unique_value_count][beta_max_all];
+//        int cur_value = getUniqueValue(sorted_value_list[0], left_shift) ;
+//        int next_value = getUniqueValue(sorted_value_list[1], left_shift) ;
+//
+//        for (int value_i = 0; value_i < unique_value_count; value_i++) {
+//
+//
+//            next_value = getUniqueValue(sorted_value_list[value_i + 1], left_shift) ;
+//            long k_start_valueL = sorted_value_list[value_i];
+//            hash_table_count[value_i][0] = getCount(k_start_valueL,mask);
+//
+//            int beta_max = getBitWith(max_delta_value - cur_value);
+//            for(int beta = 1; beta <= beta_max; beta++){
+//
+//            }
+//            cur_value =  next_value ;
+//
+//        }
+
+
+        int gamma_max = getBitWith(max_delta_value);
+        int[] gamma_count_list = new int[gamma_max+1];
+        int[] x_u_minus_value_list = new int[gamma_max+1];
+        int[] x_u_plus_value_list = new int[gamma_max+1];
+        int end_i = unique_value_count - 1;
+        for(int gamma = 0; gamma <= gamma_max; gamma++) {
+            int x_u_plus_pow_beta = max_delta_value - (1<<gamma) + 1;
+//            int x_u_plus_pow_beta = (int) (max_delta_value - pow(2, gamma) + 1);
+//
+            for (; end_i > 0; end_i--) {
+                x_u_minus_value = getUniqueValue(sorted_value_list[end_i - 1], left_shift);
+                int x_u_plus_value = getUniqueValue(sorted_value_list[end_i], left_shift);
+                if (x_u_minus_value < x_u_plus_pow_beta && x_u_plus_value >= x_u_plus_pow_beta){
+                    gamma_count_list[gamma] = getCount(sorted_value_list[end_i-1],mask);
+                    x_u_minus_value_list[gamma] = x_u_minus_value;
+                    x_u_plus_value_list[gamma] = x_u_plus_value;
+                } else if (x_u_minus_value < x_u_plus_pow_beta) {
+                    break;
+                }
+            }
+        }
+        for(int gamma = 1; gamma < gamma_max; gamma++) {
+            if(gamma_count_list[gamma]==0){
+                gamma_count_list[gamma] = gamma_count_list[gamma-1];
+                x_u_minus_value_list[gamma] = x_u_minus_value_list[gamma-1];
+                x_u_plus_value_list[gamma] = x_u_plus_value_list[gamma-1];
+            }
+        }
+
+        for (int start_value_i = 0; start_value_i < unique_value_count-1; start_value_i++) {
+            long k_start_valueL = sorted_value_list[start_value_i];
+            k_start_value =  getUniqueValue(k_start_valueL, left_shift) ;
+            x_l_plus_value =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+
+
+            cur_k1 = getCount(k_start_valueL,mask);
+
+            int k_end_value;
+            int cur_bits;
+            int cur_k2;
+            k_end_value = max_delta_value + 1;
+
+            cur_bits = 0;
+            cur_k2 = 0;
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            cur_bits += cur_k1 * getBitWith(k_start_value);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k1) * getBitWith(k_end_value- x_l_plus_value); //cur_k2 =0
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_k_start_value = k_start_value;
+                final_x_l_plus = x_l_plus_value;
+                final_k_end_value = k_end_value;
+                final_x_u_minus = max_delta_value;
+            }
+
+            int beta_max = getBitWith(max_delta_value - x_l_plus_value);
+
+            int lower_outlier_cost = cur_k1 * getBitWith(k_start_value);
+
+
+
+            for(int gamma = 0; gamma < beta_max; gamma++){
+//                int x_u_plus_pow_beta = (int) (max_delta_value - pow(2,gamma)+1);
+                x_u_minus_value = x_u_minus_value_list[gamma];
+                k_end_value =  x_u_plus_value_list[gamma];
+                cur_bits = 0;
+                cur_k2 = block_size - gamma_count_list[gamma];
+
+                cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                cur_bits += lower_outlier_cost;
+                if (cur_k1 + cur_k2 != block_size)
+                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+                if (cur_k2 != 0)
+                    cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+
+
+                if (cur_bits < min_bits) {
+                    min_bits = cur_bits;
+                    final_k_start_value = k_start_value;
+                    final_x_l_plus = x_l_plus_value;
+                    final_k_end_value = k_end_value;
+                    final_x_u_minus = x_u_minus_value;
+                }
+
+            }
+//            end_value_i = unique_value_count - 1;
+//            for(int gamma = 0; gamma <= beta_max; gamma++){
+//                for (; end_value_i > start_value_i; end_value_i--) {
+//                    int x_u_plus_pow_beta = (int) (max_delta_value - pow(2,gamma)+1);
+//                    x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+//                    k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+//                    if(x_u_minus_value < x_u_plus_pow_beta && k_end_value >= x_u_plus_pow_beta){
+//                        cur_bits = 0;
+//                        cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+//
+//                        cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+//                        cur_bits += cur_k1 * getBitWith(k_start_value);
+//                        if (cur_k1 + cur_k2 != block_size)
+//                            cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+//                        if (cur_k2 != 0)
+//                            cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+//
+//
+//                        if (cur_bits < min_bits) {
+//                            min_bits = cur_bits;
+//                            final_k_start_value = k_start_value;
+//                            final_x_l_plus = x_l_plus_value;
+//                            final_k_end_value = k_end_value;
+//                            final_x_u_minus = x_u_minus_value;
+//                        }
+//                    } else if (x_u_minus_value < x_u_plus_pow_beta && k_end_value < x_u_plus_pow_beta) {
+//                        break;
+//                    }
+//                }
+//            }
+//
+
+        }
+
+        for(int beta = 0; beta < gamma_max; beta++){
+
+            int pow_beta = 1<<beta;
+            int start_value_i = 0;
+            int end_value_i = start_value_i+1;
+
+            for (; start_value_i < unique_value_count-1; start_value_i++) {
+                long x_l_minusL = sorted_value_list[start_value_i];
+                int x_l_minus =  getUniqueValue(x_l_minusL, left_shift) ;
+                int x_l_plus =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+                int x_u_plus_pow_beta = pow_beta+x_l_plus;
+                if(x_u_plus_pow_beta > max_delta_value) break;
+
+
+
+                cur_k1 = getCount(x_l_minusL,mask);
+                int lower_outlier_cost = cur_k1 * getBitWith(x_l_minus);
+
+                while ( end_value_i < unique_value_count) {
+//                    if(beta==3 && end_value_i==22)
+//                    {
+//                        System.out.println(x_l_minus);
+//                        System.out.println(x_l_plus);
+//                    }
+
+                    int x_u_minus = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+                    int x_u_plus = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+                    if(x_u_minus < x_u_plus_pow_beta && x_u_plus >= x_u_plus_pow_beta){
+                        int cur_bits = 0;
+                        int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+
+                        cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                        cur_bits += lower_outlier_cost;
+                        if (cur_k1 + cur_k2 != block_size)
+                            cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus - x_l_plus);
+                        if (cur_k2 != 0)
+                            cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus);
+
+
+                        if (cur_bits < min_bits) {
+                            min_bits = cur_bits;
+                            final_k_start_value = x_l_minus;
+                            final_x_l_plus = x_l_plus;
+                            final_k_end_value = x_u_plus;
+                            final_x_u_minus = x_u_minus;
+                        }
+                        break;
+                    }
+//                    else if (x_u_minus >= x_u_plus_pow_beta && x_u_plus >= x_u_plus_pow_beta) {
+//                        break;
+//                    }
+
+                    end_value_i++;
+                }
+            }
+
+        }
+
+        encode_pos = BOSEncodeBitsImprove(ts_block_delta,  final_k_start_value, final_x_l_plus, final_k_end_value, final_x_u_minus,
+                max_delta_value, min_delta, encode_pos , cur_byte);
+
+//        System.out.println(encode_pos);
+
+        return encode_pos;
+    }
+
+
+    public static int BOSEncoder(
+            int[] data, int block_size, byte[] encoded_result) {
+        block_size++;
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+            encode_pos =  BOSBlockEncoder(data, i, block_size, block_size,encode_pos,encoded_result);
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        }
+        else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+            encode_pos = BOSBlockEncoder(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+        }
+
+
+        return encode_pos;
+    }
+    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+        int value0 = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        value_list[value_pos_arr[0]] =value0;
+        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        if(k1!=0 || k2 != 0){
+            final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+            decode_pos += 4;
+
+            final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+            decode_pos += 4;
+
+            bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+
+            left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+            right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+
+            if (final_alpha == 0) {
+                int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
+                for (int i = 0; i < bitmap_bytes; i++) {
+                    bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                    decode_pos += 1;
+                }
+                int bitmap_outlier_i = 0;
+                int remaining_bits = 8;
+                int tmp = bitmap_outlier.get(bitmap_outlier_i);
+                bitmap_outlier_i++;
+                int i = 0;
+                while (i < block_size ) {
+                    if (remaining_bits > 1) {
+                        int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_i == 1) {
+                            int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                            remaining_bits -= 1;
+                            if (bit_left_right == 1) {
+                                final_left_outlier_index.add(i);
+                            } else {
+                                final_right_outlier_index.add(i);
+                            }
+                        }
+                        if (remaining_bits == 0) {
+                            remaining_bits = 8;
+                            if (bitmap_outlier_i >= bitmap_bytes) break;
+                            tmp = bitmap_outlier.get(bitmap_outlier_i);
+                            bitmap_outlier_i++;
+                        }
+                    } else if (remaining_bits == 1) {
+                        int bit_i = tmp & 0x1;
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                        if (bit_i == 1) {
+                            int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                            remaining_bits -= 1;
+                            if (bit_left_right == 1) {
+                                final_left_outlier_index.add(i);
+                            } else {
+                                final_right_outlier_index.add(i);
+                            }
+                        }
+                    }
+                    i++;
+                }
+            } else {
+                ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+                final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
+                decode_pos = (decode_pos_result_left.get(0));
+                ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+                final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
+                decode_pos = (decode_pos_result_right.get(0));
+            }
+        }else {
+            bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+        }
+
+
+
+
+        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+
+        decode_pos = decode_pos_normal.get(0);
+        if (k1 != 0) {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+            decode_pos = decode_pos_result_left.get(0);
+        }
+        if (k2 != 0) {
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+            decode_pos = decode_pos_result_right.get(0);
+        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+
+        for (int i = 0; i < block_size; i++) {
+            int current_delta;
+            if (left_outlier_i >= k1) {
+                if (right_outlier_i >= k2) {
+                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
+                    normal_i++;
+                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
+                    current_delta = min_delta + final_right_outlier.get(right_outlier_i) + final_k_end_value;
+                    right_outlier_i++;
+                } else {
+                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
+                    normal_i++;
+                }
+            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
+                current_delta = min_delta + final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+            } else {
+
+                if (right_outlier_i >= k2) {
+                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
+                    normal_i++;
+                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
+                    current_delta = min_delta + final_right_outlier.get(right_outlier_i) + final_k_end_value;
+                    right_outlier_i++;
+                } else {
+                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
+                    normal_i++;
+                }
+            }
+
+            pre_v = current_delta + pre_v;
+            value_list[value_pos_arr[0]] = pre_v;
+            value_pos_arr[0]++;
+        }
+        return decode_pos;
+    }
+
+    public static void BOSDecoder(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        block_size--;
+
+        int[] value_pos_arr = new int[1];
+        for (int k = 0; k < block_num; k++) {
+
+
+            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list, block_size,value_pos_arr);
+
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            remain_length --;
+            BOSBlockDecoder(encoded, decode_pos, value_list, remain_length, value_pos_arr);
+        }
+    }
+
+    public static int EncodeBits(int num,
+                                 int bit_width,
+                                 int encode_pos,
+                                 byte[] cur_byte,
+                                 int[] bit_index_list){
+        // 找到要插入的位的索引
+        int bit_index = bit_index_list[0] ;//cur_byte[encode_pos + 1];
+
+        // 计算数值的起始位位置
+        int remaining_bits = bit_width;
+
+        while (remaining_bits > 0) {
+            // 计算在当前字节中可以使用的位数
+            int available_bits = bit_index;
+            int bits_to_write = Math.min(available_bits, remaining_bits);
+
+            // 更新 bit_index
+            bit_index = available_bits - bits_to_write;
+
+            // 计算要写入的位的掩码和数值
+            int mask = (1 << bits_to_write) - 1;
+            int bits = (num >> (remaining_bits - bits_to_write)) & mask;
+
+            // 写入到当前位置
+            cur_byte[encode_pos] &= (byte) ~(mask << bit_index); // 清除对应位置的位
+            cur_byte[encode_pos] |= (byte) (bits << bit_index);
+
+            // 更新位宽和数值
+            remaining_bits -= bits_to_write;
+            if (bit_index == 0) {
+                bit_index = 8;
+                encode_pos++;
+            }
+        }
+        bit_index_list[0] = bit_index;
+//        cur_byte[encode_pos + 1] = (byte) bit_index;
+        return encode_pos;
+    }
+    private static int BOSEncodeBitsImprove(int[] ts_block_delta,
+                                            int final_k_start_value,
+                                            int final_x_l_plus,
+                                            int final_k_end_value,
+                                            int final_x_u_minus,
+                                            int max_delta_value,
+                                            int[] min_delta,
+                                            int encode_pos,
+                                            byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        int k1 = 0;
+        int k2 = 0;
+
+
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+//                encode_pos = EncodeBits(cur_value,left_bit_width,encode_pos,cur_byte);
+//                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+//                encode_pos = EncodeBits(cur_value- final_k_end_value,right_bit_width,encode_pos,cur_byte);
+//                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+//                final_normal.add(cur_value - final_x_l_plus);
+//                encode_pos = EncodeBits(cur_value- final_x_l_plus,right_bit_width,encode_pos,cur_byte);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+        int[] bit_index_list = new int[1];
+        bit_index_list[0] = 8;
+
+        if(final_k_start_value<0 && final_k_end_value > max_delta_value){
+//            int bit_width_final= getBitWith(final_x_u_minus - final_x_l_plus);
+//            cur_byte[encode_pos+1] = 8;
+            for (int cur_value : ts_block_delta) {
+                encode_pos = EncodeBits(cur_value, bit_width_final, encode_pos, cur_byte, bit_index_list);
+//                final_normal.add(cur_value);
+            }
+            if(bit_index_list[0] != 8){
+                encode_pos ++;
+            }
+//            cur_byte[encode_pos+1] = 0;
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+            return encode_pos;
+        }
+
+
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+        int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(final_k_end_value,encode_pos,cur_byte);
+        encode_pos += 4;
+
+//        bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//        encode_pos += 1;
+        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        if (final_alpha == 0) { // 0
+
+            for (int i : bitmap_outlier) {
+
+                intByte2Bytes(i,encode_pos,cur_byte);
+                encode_pos += 1;
+            }
+        } else {
+            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+        }
+//        cur_byte[encode_pos+1] = 8;
+//        bit_index_list[0] = 8;
+        for (int cur_value : ts_block_delta) {
+            if (cur_value <= final_k_start_value) {
+                encode_pos = EncodeBits(cur_value, left_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else if (cur_value >= final_k_end_value) {
+                encode_pos = EncodeBits(cur_value - final_k_end_value, right_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else {
+                encode_pos = EncodeBits(cur_value - final_x_l_plus, bit_width_final, encode_pos, cur_byte,bit_index_list);
+            }
+        }
+        if(bit_index_list[0] != 8){
+            encode_pos ++;
+        }
+
+//        cur_byte[encode_pos+1] = 0;
+
+//        if(k1==0 && k2==0){
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//
+//
+//        }
+//        else{
+//            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+//            encode_pos += 4;
+//            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+//            encode_pos += 4;
+//
+//            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            if (final_alpha == 0) { // 0
+//
+//                for (int i : bitmap_outlier) {
+//
+//                    intByte2Bytes(i,encode_pos,cur_byte);
+//                    encode_pos += 1;
+//                }
+//            } else {
+//                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//            }
+//        }
+
+
+//        if(k1+k2!=block_size)
+//        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//        if (k1 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+//        if (k2 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+        return encode_pos;
+
+    }
+
+    private static int BOSBlockEncoderImprove(int[] ts_block, int block_i, int block_size, int remaining ,int encode_pos , byte[] cur_byte) {
+
+        int[] min_delta = new int[3];
+        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
+
+
+        block_size = remaining-1;
+        int max_delta_value = min_delta[2];
+        int[] value_list = new int[block_size];
+        int unique_value_count = 0;
+        int[] value_count_list = new int[max_delta_value+1];
+        for(int value:ts_block_delta){
+            if(value_count_list[value]==0){
+                value_count_list[value] = 1;
+                value_list[unique_value_count] = value;
+                unique_value_count ++;
+            }else{
+                value_count_list[value] ++;
+            }
+        }
+
+        int left_shift = getBitWith(block_size);
+        int mask =  (1 << left_shift) - 1;
+        long[] sorted_value_list = new long[unique_value_count];
+        int count = 0;
+
+        for(int i=0;i<unique_value_count;i++){
+            int value = value_list[i];
+            sorted_value_list[i] = (((long) value) << left_shift) + value_count_list[value];
+        }
+        Arrays.sort(sorted_value_list);
+
+        for(int i=0;i<unique_value_count;i++){
+            count += getCount(sorted_value_list[i], mask);
+            sorted_value_list[i] = (((long)getUniqueValue(sorted_value_list[i], left_shift) ) << left_shift) + count;//new_value_list[i]
+        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2 ) * (block_size));
+
+        int cur_k1 = 0;
+
+        int x_l_plus_value = 0; // x_l_plus
+        int x_u_minus_value = max_delta_value; // x_u_plus
+
+        for (int end_value_i = 1; end_value_i < unique_value_count; end_value_i++) {
+
+            x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+            int x_u_plus_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+            int cur_bits = 0;
+            int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value); // cur_k1 = 0
+            if (cur_k2 != 0)
+                cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus_value);
+
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_x_u_minus = x_u_minus_value;
+                final_k_end_value = x_u_plus_value;
+            }
+        }
+
+        int k_start_value = -1; // x_l_minus
+//        int beta_max_all = getBitWith(max_delta_value)+1;
+//        int[][] hash_table_count = new int[unique_value_count][beta_max_all];
+//        int[][] hash_table_value = new int[unique_value_count][beta_max_all];
+//        int cur_value = getUniqueValue(sorted_value_list[0], left_shift) ;
+//        int next_value = getUniqueValue(sorted_value_list[1], left_shift) ;
+//
+//        for (int value_i = 0; value_i < unique_value_count; value_i++) {
+//
+//
+//            next_value = getUniqueValue(sorted_value_list[value_i + 1], left_shift) ;
+//            long k_start_valueL = sorted_value_list[value_i];
+//            hash_table_count[value_i][0] = getCount(k_start_valueL,mask);
+//
+//            int beta_max = getBitWith(max_delta_value - cur_value);
+//            for(int beta = 1; beta <= beta_max; beta++){
+//
+//            }
+//            cur_value =  next_value ;
+//
+//        }
+
+
+        int gamma_max = getBitWith(max_delta_value);
+        int[] gamma_count_list = new int[gamma_max+1];
+        int[] x_u_minus_value_list = new int[gamma_max+1];
+        int[] x_u_plus_value_list = new int[gamma_max+1];
+        int end_i = unique_value_count - 1;
+        for(int gamma = 0; gamma <= gamma_max; gamma++) {
+            int x_u_plus_pow_beta = max_delta_value - (1<<gamma) + 1;
+//            int x_u_plus_pow_beta = (int) (max_delta_value - pow(2, gamma) + 1);
+//
+            for (; end_i > 0; end_i--) {
+                x_u_minus_value = getUniqueValue(sorted_value_list[end_i - 1], left_shift);
+                int x_u_plus_value = getUniqueValue(sorted_value_list[end_i], left_shift);
+                if (x_u_minus_value < x_u_plus_pow_beta && x_u_plus_value >= x_u_plus_pow_beta){
+                    gamma_count_list[gamma] = getCount(sorted_value_list[end_i-1],mask);
+                    x_u_minus_value_list[gamma] = x_u_minus_value;
+                    x_u_plus_value_list[gamma] = x_u_plus_value;
+                } else if (x_u_minus_value < x_u_plus_pow_beta) {
+                    break;
+                }
+            }
+        }
+        for(int gamma = 1; gamma < gamma_max; gamma++) {
+            if(gamma_count_list[gamma]==0){
+                gamma_count_list[gamma] = gamma_count_list[gamma-1];
+                x_u_minus_value_list[gamma] = x_u_minus_value_list[gamma-1];
+                x_u_plus_value_list[gamma] = x_u_plus_value_list[gamma-1];
+            }
+        }
+
+        for (int start_value_i = 0; start_value_i < unique_value_count-1; start_value_i++) {
+            long k_start_valueL = sorted_value_list[start_value_i];
+            k_start_value =  getUniqueValue(k_start_valueL, left_shift) ;
+            x_l_plus_value =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+
+
+            cur_k1 = getCount(k_start_valueL,mask);
+
+            int k_end_value;
+            int cur_bits;
+            int cur_k2;
+            k_end_value = max_delta_value + 1;
+
+            cur_bits = 0;
+            cur_k2 = 0;
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            cur_bits += cur_k1 * getBitWith(k_start_value);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k1) * getBitWith(k_end_value- x_l_plus_value); //cur_k2 =0
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_k_start_value = k_start_value;
+                final_x_l_plus = x_l_plus_value;
+                final_k_end_value = k_end_value;
+                final_x_u_minus = max_delta_value;
+            }
+
+            int beta_max = getBitWith(max_delta_value - x_l_plus_value);
+
+            int lower_outlier_cost = cur_k1 * getBitWith(k_start_value);
+
+
+
+            for(int gamma = 0; gamma < beta_max; gamma++){
+//                int x_u_plus_pow_beta = (int) (max_delta_value - pow(2,gamma)+1);
+                x_u_minus_value = x_u_minus_value_list[gamma];
+                k_end_value =  x_u_plus_value_list[gamma];
+                cur_bits = 0;
+                cur_k2 = block_size - gamma_count_list[gamma];
+
+                cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                cur_bits += lower_outlier_cost;
+                if (cur_k1 + cur_k2 != block_size)
+                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+                if (cur_k2 != 0)
+                    cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+
+
+                if (cur_bits < min_bits) {
+                    min_bits = cur_bits;
+                    final_k_start_value = k_start_value;
+                    final_x_l_plus = x_l_plus_value;
+                    final_k_end_value = k_end_value;
+                    final_x_u_minus = x_u_minus_value;
+                }
+
+            }
+//            end_value_i = unique_value_count - 1;
+//            for(int gamma = 0; gamma <= beta_max; gamma++){
+//                for (; end_value_i > start_value_i; end_value_i--) {
+//                    int x_u_plus_pow_beta = (int) (max_delta_value - pow(2,gamma)+1);
+//                    x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+//                    k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+//                    if(x_u_minus_value < x_u_plus_pow_beta && k_end_value >= x_u_plus_pow_beta){
+//                        cur_bits = 0;
+//                        cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+//
+//                        cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+//                        cur_bits += cur_k1 * getBitWith(k_start_value);
+//                        if (cur_k1 + cur_k2 != block_size)
+//                            cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+//                        if (cur_k2 != 0)
+//                            cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+//
+//
+//                        if (cur_bits < min_bits) {
+//                            min_bits = cur_bits;
+//                            final_k_start_value = k_start_value;
+//                            final_x_l_plus = x_l_plus_value;
+//                            final_k_end_value = k_end_value;
+//                            final_x_u_minus = x_u_minus_value;
+//                        }
+//                    } else if (x_u_minus_value < x_u_plus_pow_beta && k_end_value < x_u_plus_pow_beta) {
+//                        break;
+//                    }
+//                }
+//            }
+//
+
+        }
+
+        for(int beta = 0; beta < gamma_max; beta++){
+
+            int pow_beta = 1<<beta;
+            int start_value_i = 0;
+            int end_value_i = start_value_i+1;
+
+            for (; start_value_i < unique_value_count-1; start_value_i++) {
+                long x_l_minusL = sorted_value_list[start_value_i];
+                int x_l_minus =  getUniqueValue(x_l_minusL, left_shift) ;
+                int x_l_plus =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+                int x_u_plus_pow_beta = pow_beta+x_l_plus;
+                if(x_u_plus_pow_beta > max_delta_value) break;
+
+
+
+                cur_k1 = getCount(x_l_minusL,mask);
+                int lower_outlier_cost = cur_k1 * getBitWith(x_l_minus);
+
+                while ( end_value_i < unique_value_count) {
+//                    if(beta==3 && end_value_i==22)
+//                    {
+//                        System.out.println(x_l_minus);
+//                        System.out.println(x_l_plus);
+//                    }
+
+                    int x_u_minus = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+                    int x_u_plus = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+                    if(x_u_minus < x_u_plus_pow_beta && x_u_plus >= x_u_plus_pow_beta){
+                        int cur_bits = 0;
+                        int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+
+                        cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                        cur_bits += lower_outlier_cost;
+                        if (cur_k1 + cur_k2 != block_size)
+                            cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus - x_l_plus);
+                        if (cur_k2 != 0)
+                            cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus);
+
+
+                        if (cur_bits < min_bits) {
+                            min_bits = cur_bits;
+                            final_k_start_value = x_l_minus;
+                            final_x_l_plus = x_l_plus;
+                            final_k_end_value = x_u_plus;
+                            final_x_u_minus = x_u_minus;
+                        }
+                        break;
+                    }
+//                    else if (x_u_minus >= x_u_plus_pow_beta && x_u_plus >= x_u_plus_pow_beta) {
+//                        break;
+//                    }
+
+                    end_value_i++;
+                }
+            }
+
+        }
+
+        encode_pos = BOSEncodeBitsImprove(ts_block_delta,  final_k_start_value, final_x_l_plus, final_k_end_value, final_x_u_minus,
+                max_delta_value, min_delta, encode_pos , cur_byte);
+
+//        System.out.println(encode_pos);
+
+        return encode_pos;
+    }
+
+
+    public static int BOSEncoderImprove(
+            int[] data, int block_size, byte[] encoded_result) {
+        block_size++;
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+            encode_pos =  BOSBlockEncoderImprove(data, i, block_size, block_size,encode_pos,encoded_result);
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+        }
+        else {
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+            encode_pos = BOSBlockEncoderImprove(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+        }
+        return encode_pos;
+    }
+
+
+    public static int DecodeBits(byte[] cur_byte, int bit_width, int[] decode_pos_list) {
+        int decode_pos = decode_pos_list[0];
+        int bit_index = decode_pos_list[1];  //cur_byte[decode_pos + 1];
+        int remaining_bits = bit_width;
+        int num = 0;
+
+        while (remaining_bits > 0) {
+            int available_bits = bit_index;
+            int bits_to_read = Math.min(available_bits, remaining_bits);
+
+            // 计算要读取的位的掩码
+            int mask = (1 << bits_to_read) - 1;
+            int bits = (cur_byte[decode_pos] >> (available_bits - bits_to_read)) & mask;
+
+            // 将读取的位合并到结果中
+            num = (num << bits_to_read) | bits;
+
+            // 更新位宽和 bit_index
+            remaining_bits -= bits_to_read;
+            bit_index = available_bits - bits_to_read;
+
+            if (bit_index == 0) {
+                bit_index = 8;
+                decode_pos++;
+            }
+        }
+        decode_pos_list[0] = decode_pos;
+        decode_pos_list[1] = bit_index;
+
+        return num;
+    }
+    public static int BOSBlockDecoderImprove(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+        int value0 = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        value_list[value_pos_arr[0]] =value0;
+        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        int[] decode_list = new int[2];
+        decode_list[0]= decode_pos;
+        decode_list[1]= 8;
+
+        int valuePos = value_pos_arr[0];
+
+        if(k1==0 && k2==0){
+            int pre_v = value0;
+            for (int i = 0; i < block_size; i++) {
+                int cur_delta = min_delta + DecodeBits(encoded, bit_width_final,  decode_list);
+                pre_v += cur_delta;
+                value_list[valuePos++] = pre_v;
+            }
+            value_pos_arr[0] = valuePos;
+            return decode_list[0];
+        }
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+//        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+//        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+//        bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+//        decode_pos += 1;
+
+        left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+        right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        if (final_alpha == 0) {
+            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
+            for (int i = 0; i < bitmap_bytes; i++) {
+                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                decode_pos += 1;
+            }
+            int bitmap_outlier_i = 0;
+            int remaining_bits = 8;
+            int tmp = bitmap_outlier.get(bitmap_outlier_i);
+            bitmap_outlier_i++;
+            int i = 0;
+            while (i < block_size ) {
+                if (remaining_bits > 1) {
+                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                    remaining_bits -= 1;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                    if (remaining_bits == 0) {
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                    }
+                } else if (remaining_bits == 1) {
+                    int bit_i = tmp & 0x1;
+                    remaining_bits = 8;
+                    if (bitmap_outlier_i >= bitmap_bytes) break;
+                    tmp = bitmap_outlier.get(bitmap_outlier_i);
+                    bitmap_outlier_i++;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                }
+                i++;
+            }
+        } else {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
+            decode_pos = (decode_pos_result_left.get(0));
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
+            decode_pos = (decode_pos_result_right.get(0));
+        }
+
+
+
+
+
+//        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+//        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+//
+//        decode_pos = decode_pos_normal.get(0);
+//        if (k1 != 0) {
+//            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+//            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+//            decode_pos = decode_pos_result_left.get(0);
+//        }
+//        if (k2 != 0) {
+//            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+//            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+//            decode_pos = decode_pos_result_right.get(0);
+//        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+// Precompute constants
+        int normalOffset = min_delta + final_k_start_value;
+        int rightOutlierOffset = min_delta + final_k_end_value;
+
+// Initialize indices and pre-fetch next outlier positions
+        int leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+        int rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+        decode_list[0]= decode_pos;
+//        decode_list[1]= 8;
+        // Use a local variable for the position
+        for (int i = 0; i < block_size; i++) {
+            int currentDelta;
+            if (i == leftOutlierNextIndex) {
+                // Process left outlier
+                currentDelta = min_delta + DecodeBits(encoded, left_bit_width,  decode_list); // final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+                leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+            } else if (i == rightOutlierNextIndex) {
+                // Process right outlier
+                currentDelta = rightOutlierOffset + DecodeBits(encoded, right_bit_width,  decode_list);// final_right_outlier.get(right_outlier_i);
+                right_outlier_i++;
+                rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+            } else {
+                // Process normal value
+                currentDelta = normalOffset + DecodeBits(encoded, bit_width_final,  decode_list);
+                normal_i++;
+            }
+
+            // Update the cumulative value and store it
+            pre_v += currentDelta;
+            value_list[valuePos++] = pre_v;
+        }
+        value_pos_arr[0] = valuePos;
+        if(decode_list[1]!=8){
+            return decode_list[0]+1;
+        }else {
+            return decode_list[0];
+        }
+//        decode_pos = decode_list[0];
+// Update the position in the array
+
+
+//        return decode_pos;
+    }
+
+    public static void BOSDecoderImprove(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        block_size--;
+
+        int[] value_pos_arr = new int[1];
+        for (int k = 0; k < block_num; k++) {
+
+
+            decode_pos = BOSBlockDecoderImprove(encoded, decode_pos, value_list, block_size,value_pos_arr);
+
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            remain_length --;
+            BOSBlockDecoderImprove(encoded, decode_pos, value_list, remain_length, value_pos_arr);
+        }
+    }
+
+    @Test
+    public void BOSDecodeImproveTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R1O4_decode_time/compression_ratio/bos_b";
+//        String output_parent_dir = parent_dir + "icde0802/compression_ratio/test";
+
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[2];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "TS_2DIFF+BOS-B",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void BOSEncodeImproveTest() throws IOException {
+//        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/bos_b_improve";
+//        String output_parent_dir = parent_dir + "icde0802/compression_ratio/test";
+
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 200;
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[2];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "TS_2DIFF+BOS-B",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void BOSVaryBlockSize() throws IOException, InterruptedException {
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/block_size_bos_improve";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+        }
+
+        output_path_list.add(output_parent_dir + "/CS-Sensors_ratio.csv"); // 0
+        output_path_list.add(output_parent_dir + "/Metro-Traffic_ratio.csv");// 1
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+
+        int repeatTime2 = 100;
+//        int[] file_i_list = {0,9,10};
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//        for(int file_i :file_i_list){
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+
+            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",
+                    "Block 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<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+
+//                for (int block_size_i = 6; block_size_i > 5; block_size_i--) {
+                for (int block_size_i = 13; block_size_i > 5; block_size_i--) {
+                    int block_size = (int) Math.pow(2, block_size_i);
+                    System.out.println(block_size);
+                    long encodeTime = 0;
+                    long decodeTime = 0;
+                    double ratio = 0;
+                    double compressed_size = 0;
+
+
+                    long s = System.nanoTime();
+                    for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                        compressed_size = BOSEncoderImprove(data2_arr, block_size, encoded_result);
+                    }
+
+                    long e = System.nanoTime();
+                    encodeTime += ((e - s) / repeatTime2);
+                    double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                    ratio += ratioTmp;
+                    s = System.nanoTime();
+                    for (int repeat = 0; repeat < repeatTime2; repeat++)
+                        BOSDecoderImprove(encoded_result);
+                    e = System.nanoTime();
+                    decodeTime += ((e - s) / repeatTime2);
+
+                    String[] record = {
+                            f.toString(),
+                            "TS_2DIFF+BOS-B-Improve",
+                            String.valueOf(encodeTime),
+                            String.valueOf(decodeTime),
+                            String.valueOf(data1.size()),
+                            String.valueOf(compressed_size),
+                            String.valueOf(block_size_i),
+                            String.valueOf(ratio)
+                    };
+                    writer.writeRecord(record);
+                    System.out.println(ratio);
+
+                }
+//                Thread.sleep(10000);
+            }
+            writer.close();
+
+        }
+    }
+
+    @Test
+    public void BOSOUOTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R2O3_lower_outlier_compare/compression_ratio/bos";
+//        String output_parent_dir = parent_dir + "icde0802/compression_ratio/test";
+
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 200;
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[2];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoder(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "TS_2DIFF+BOS-B",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
+
+}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSHTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSHTest.java
deleted file mode 100644
index 59ad144..0000000
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSHTest.java
+++ /dev/null
@@ -1,1422 +0,0 @@
-package org.apache.iotdb.tsfile.encoding;
-
-import com.csvreader.CsvReader;
-import com.csvreader.CsvWriter;
-import org.junit.Test;
-
-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.ArrayList;
-
-import static java.lang.Math.*;
-
-public class TSDIFFBOSHTest {
-
-    public static long combine2Int(int int1, int int2) {
-        return ((long) int1 << 32) | (int2 & 0xFFFFFFFFL);
-    }
-
-    public static int getTime(long long1) {
-        return ((int) (long1 >> 32));
-    }
-
-    public static int getValue(long long1) {
-        return ((int) (long1));
-    }
-
-    public static int getCount(long long1, int mask) {
-        return ((int) (long1 & mask));
-    }
-    public static int getUniqueValue(long long1, int left_shift) {
-        return ((int) ((long1) >> left_shift));
-    }
-
-    public static int getBitWith(int num) {
-        if (num == 0) return 1;
-        else return 32 - Integer.numberOfLeadingZeros(num);
-    }
-
-    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 int[] getAbsDeltaTsBlock(
-            int[] ts_block,
-            int[] min_delta,
-            int supple_length) {
-        int block_size = ts_block.length-1;
-        int[] ts_block_delta = new int[ts_block.length+supple_length-1];
-
-
-        int value_delta_min = Integer.MAX_VALUE;
-        int value_delta_max = Integer.MIN_VALUE;
-        for (int i = 0; i < block_size; i++) {
-
-            int epsilon_v = ts_block[i+1] - ts_block[i];
-
-            if (epsilon_v < value_delta_min) {
-                value_delta_min = epsilon_v;
-            }
-            if (epsilon_v > value_delta_max) {
-                value_delta_max = epsilon_v;
-            }
-
-        }
-        min_delta[0] = (ts_block[0]);
-        min_delta[1] = (value_delta_min);
-        min_delta[2] = (value_delta_max-value_delta_min);
-
-        for (int i = 0; i  < block_size; i++) {
-            int epsilon_v = ts_block[i+1] - value_delta_min - ts_block[i];
-            ts_block_delta[i] = epsilon_v;
-        }
-        for(int i = block_size;i<block_size+supple_length;i++){
-            ts_block_delta[i] = 0;
-        }
-        return ts_block_delta;
-    }
-
-    public static int[] getAbsDeltaTsBlock(
-            int[] ts_block,
-            int i,
-            int block_size,
-            int remaining,
-            int[] min_delta) {
-        int[] ts_block_delta = new int[remaining-1];
-
-        int value_delta_min = Integer.MAX_VALUE;
-        int value_delta_max = Integer.MIN_VALUE;
-        int base = i*block_size+1;
-        int end = i*block_size+remaining;
-
-        int tmp_j_1 = ts_block[base-1];
-        min_delta[0] =tmp_j_1;
-        int j = base;
-        int tmp_j;
-
-        while(j<end){
-            tmp_j = ts_block[j];
-            int epsilon_v = tmp_j - tmp_j_1;
-            ts_block_delta[j-base] = epsilon_v;
-            if (epsilon_v < value_delta_min) {
-                value_delta_min = epsilon_v;
-            }
-            if (epsilon_v > value_delta_max) {
-                value_delta_max = epsilon_v;
-            }
-            tmp_j_1 = tmp_j;
-            j++;
-        }
-        j = 0;
-        end = remaining -1;
-        while(j<end){
-            ts_block_delta[j] = ts_block_delta[j] - value_delta_min;
-            j++;
-        }
-
-        min_delta[1] = value_delta_min;
-        min_delta[2] = (value_delta_max-value_delta_min);
-
-
-        return ts_block_delta;
-    }
-
-    public static int encodeOutlier2Bytes(
-            ArrayList<Integer> ts_block_delta,
-            int bit_width,
-            int encode_pos,  byte[] encoded_result) {
-
-        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
-
-        int n_k = ts_block_delta.size();
-        int n_k_b = n_k / 8;
-        long cur_remaining = 0; // encoded int
-        int cur_number_bits = 0; // the bit width used of encoded int
-        for (int i = n_k_b * 8; i < n_k; i++) {
-            long cur_value = ts_block_delta.get(i);
-            int cur_bit_width = bit_width; // remaining bit width of current value
-
-            if (cur_number_bits + bit_width >= 32) {
-                cur_remaining <<= (32 - cur_number_bits);
-                cur_bit_width = bit_width - 32 + cur_number_bits;
-                cur_remaining += ((cur_value >> cur_bit_width));
-                long2intBytes(cur_remaining,encode_pos,encoded_result);
-                encode_pos += 4;
-                cur_remaining = 0;
-                cur_number_bits = 0;
-            }
-
-            cur_remaining <<= cur_bit_width;
-            cur_number_bits += cur_bit_width;
-            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width)); //
-        }
-        cur_remaining <<= (32 - cur_number_bits);
-        long2intBytes(cur_remaining,encode_pos,encoded_result);
-        encode_pos += 4;
-        return encode_pos;
-
-    }
-
-
-    public static ArrayList<Integer> decodeOutlier2Bytes(
-            byte[] encoded,
-            int decode_pos,
-            int bit_width,
-            int length,
-            ArrayList<Integer> encoded_pos_result
-    ) {
-
-        int n_k_b = length / 8;
-        int remaining = length - n_k_b * 8;
-        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
-        decode_pos += n_k_b * bit_width;
-
-        ArrayList<Long> int_remaining = new ArrayList<>();
-        int int_remaining_size = remaining * bit_width / 32 + 1;
-        for (int j = 0; j < int_remaining_size; j++) {
-            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
-            decode_pos += 4;
-        }
-
-        int cur_remaining_bits = 32; // remaining bit width of current value
-        long cur_number = int_remaining.get(0);
-        int cur_number_i = 1;
-        for (int i = n_k_b * 8; i < length; i++) {
-            if (bit_width < cur_remaining_bits) {
-                int tmp = (int) (cur_number >> (32 - bit_width));
-                result_list.add(tmp);
-                cur_number <<= bit_width;
-                cur_number &= 0xFFFFFFFFL;
-                cur_remaining_bits -= bit_width;
-            } else {
-                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
-                int remain_bits = bit_width - cur_remaining_bits;
-                tmp <<= remain_bits;
-
-                cur_number = int_remaining.get(cur_number_i);
-                cur_number_i++;
-                tmp += (int) (cur_number >> (32 - remain_bits));
-                result_list.add(tmp);
-                cur_number <<= remain_bits;
-                cur_number &= 0xFFFFFFFFL;
-                cur_remaining_bits = 32 - remain_bits;
-            }
-        }
-        encoded_pos_result.add(decode_pos);
-        return result_list;
-    }
-
-    private static int BOSEncodeBits(int[] ts_block_delta,
-                                     int final_k_start_value,
-                                     int final_k_end_value,
-                                     int max_delta_value,
-                                     int[] min_delta,
-                                     int encode_pos,
-                                     byte[] cur_byte) {
-        int block_size = ts_block_delta.length;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal = new ArrayList<>();
-        int k1 = 0;
-        int k2 = 0;
-
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-        int index_bitmap_outlier = 0;
-        int cur_index_bitmap_outlier_bits = 0;
-        for (int i = 0; i < block_size; i++) {
-            int cur_value = ts_block_delta[i];
-            if ( cur_value<= final_k_start_value) {
-                final_left_outlier.add(cur_value);
-                final_left_outlier_index.add(i);
-                if (cur_index_bitmap_outlier_bits % 8 != 7) {
-                    index_bitmap_outlier <<= 2;
-                    index_bitmap_outlier += 3;
-                    cur_index_bitmap_outlier_bits += 2;
-                } else {
-                    index_bitmap_outlier <<= 1;
-                    index_bitmap_outlier += 1;
-                    bitmap_outlier.add(index_bitmap_outlier);
-                    index_bitmap_outlier = 1;
-                    cur_index_bitmap_outlier_bits = 1;
-                }
-                k1++;
-
-
-            } else if (cur_value >= final_k_end_value) {
-                final_right_outlier.add(cur_value - final_k_end_value);
-                final_right_outlier_index.add(i);
-                if (cur_index_bitmap_outlier_bits % 8 != 7) {
-                    index_bitmap_outlier <<= 2;
-                    index_bitmap_outlier += 2;
-                    cur_index_bitmap_outlier_bits += 2;
-                } else {
-                    index_bitmap_outlier <<= 1;
-                    index_bitmap_outlier += 1;
-                    bitmap_outlier.add(index_bitmap_outlier);
-                    index_bitmap_outlier = 0;
-                    cur_index_bitmap_outlier_bits = 1;
-                }
-                k2++;
-
-            } else {
-                final_normal.add(cur_value - final_k_start_value-1);
-                index_bitmap_outlier <<= 1;
-                cur_index_bitmap_outlier_bits += 1;
-            }
-            if (cur_index_bitmap_outlier_bits % 8 == 0) {
-                bitmap_outlier.add(index_bitmap_outlier);
-                index_bitmap_outlier = 0;
-            }
-        }
-        if (cur_index_bitmap_outlier_bits % 8 != 0) {
-
-            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
-
-            index_bitmap_outlier &= 0xFF;
-            bitmap_outlier.add(index_bitmap_outlier);
-        }
-
-        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
-
-
-        int k_byte = (k1 << 1);
-        k_byte += final_alpha;
-        k_byte += (k2 << 16);
-
-
-        int2Bytes(k_byte,encode_pos,cur_byte);
-        encode_pos += 4;
-
-        int2Bytes(min_delta[0],encode_pos,cur_byte);
-        encode_pos += 4;
-        int2Bytes(min_delta[1],encode_pos,cur_byte);
-        encode_pos += 4;
-        int2Bytes(final_k_start_value,encode_pos,cur_byte);
-        encode_pos += 4;
-        int bit_width_final = getBitWith(final_k_end_value - final_k_start_value-2);
-        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
-        encode_pos += 1;
-        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
-        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
-        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        if (final_alpha == 0) { // 0
-
-            for (int i : bitmap_outlier) {
-
-                intByte2Bytes(i,encode_pos,cur_byte);
-                encode_pos += 1;
-            }
-        } else {
-            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
-            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
-        }
-        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
-        if (k1 != 0)
-            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
-        if (k2 != 0)
-            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
-        return encode_pos;
-
-    }
-
-    private static void calculateBits(int k1, int k2, int block_size, int alpha, int gamma, int k1_start, int k2_end, int min_bits, int[] result){
-        int cur_bits = 0;
-        cur_bits += Math.min((k1 + k2) * getBitWith(block_size - 1), block_size + k1 + k2);
-        if(k1!=0)
-            cur_bits += k1*alpha;
-        if (k1 + k2 != block_size)
-            cur_bits += (block_size - k1 - k2) *
-                    getBitWith(k2_end -k1_start - 2);
-        if(k2!=0)
-            cur_bits += k2 * gamma;
-        if (cur_bits < min_bits) {
-            result[0] = cur_bits;
-            result[1] = k1_start;
-            result[2] = k2_end;
-        }
-    }
-
-    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size, int remaining, int encode_pos, byte[] cur_byte) {
-
-        int[] min_delta = new int[3];
-        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
-
-        block_size = remaining - 1;
-        int max_delta_value = min_delta[2];
-
-        int boundary_index = (int) ((double) block_size / (double) (getBitWith(block_size-1)-1));
-
-        int max_bit_width = getBitWith(max_delta_value) + 1;
-        int[] lambda_list = {getBitWith(block_size-1),1};
-        int lambda_0 = lambda_list[0];
-
-        int count_x_min = 0;
-        int count_x_max = 0;
-        GroupL[] groupL = new GroupL[max_bit_width];
-        GroupU[] groupU = new GroupU[max_bit_width];
-        for (int i = 0; i < max_bit_width; i++) {
-            int[] numbers = new int[block_size];
-            int count = 0;
-            groupL[i] = new GroupL(numbers, count, i);
-            int[] numbersU = new int[block_size];
-            groupU[i] = new GroupU(numbersU, count, i);
-        }
-        for (int value : ts_block_delta) {
-            int alpha_i = getBitWith(value);
-            if (value == 0) {
-                count_x_min++;
-            } else {
-                groupL[alpha_i].addNumber(value); // (x_min+2^{alpha_i-1},x_min+2^{alpha_i})
-            }
-            int gamma_i = getBitWith(max_delta_value - value);
-            if (value == max_delta_value) {
-                count_x_max++;
-            } else {
-                groupU[gamma_i].addNumber(value);// (x_max-2^{gamma_i},x_max-2^{gamma_i-1})
-            }
-        }
-        int[] alpha_list = new int[max_bit_width];
-        int num_of_alpha_list = 0;
-        int[] gamma_list = new int[max_bit_width];
-        int num_of_gamma_list = 0;
-        for (int i = 1; i < max_bit_width; i++) {
-            if(groupL[i].count!=0){
-                groupL[i].setCount_array();
-                alpha_list[num_of_alpha_list] = i;
-                num_of_alpha_list ++;
-            }
-            if(groupU[i].count!=0){
-                groupU[i].setCount_array(max_delta_value);
-                gamma_list[num_of_gamma_list] = i;
-                num_of_gamma_list ++;
-            }
-        }
-
-
-        int final_k_start_value = -1;//getUniqueValue(sorted_value_list[0], left_shift);
-        int final_k_end_value = max_delta_value + 1;
-
-        int min_bits = 0;
-        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2) * (block_size));
-
-        int alpha_size = getBitWith(max(max_delta_value-1,0));
-
-        if( num_of_alpha_list ==0 && num_of_gamma_list==0){
-            encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_k_end_value, max_delta_value,
-                    min_delta, encode_pos , cur_byte);
-            return  encode_pos;
-        }
-
-
-        // -------------x_min-------------------
-        // lower: x_min
-        // upper: x_max
-        int k1 =    count_x_min;
-        int k1_start = 0;
-        int k2 = count_x_max;
-        int k2_end = max_delta_value;
-        int cur_bits = Math.min((k1 + k2) * getBitWith(block_size - 1), block_size + k1 + k2);
-        cur_bits += k1;
-        cur_bits += k2;
-        cur_bits += (block_size - k1 - k2) * getBitWith(k2_end - k1_start - 2);
-        if (cur_bits < min_bits) {
-            min_bits = cur_bits;
-            final_k_start_value = k1_start;
-            final_k_end_value = k2_end;
-        }
-
-        // lower: x_min
-        // upper:  x_max - 1, x_max - 2, x_max - 4  ...
-        //(x_max - 2^{gamma}, x_max - 2^{gamma-1} ]
-
-        for (int gamma_i = 0; gamma_i < num_of_gamma_list-1; gamma_i++) {
-
-            int gamma = gamma_list[gamma_i];
-
-            int gap_gamma = (int) pow(2, gamma - 1);
-            k2_end = max_delta_value - gap_gamma; // x_max - 2^{gamma-1}  gamma : 1 to alpha_size-1
-
-            GroupU cur_group_gamma = groupU[gamma];
-
-            long[] gamma_sorted = cur_group_gamma.sorted_value_list;
-            int gamma_unique_number = cur_group_gamma.unique_number;
-            int cur_gamma_count = cur_group_gamma.count;
-
-            for(int unique_i=0;unique_i<gamma_unique_number;unique_i++){
-                int unique_i_cur_k2 = k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-                int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);
-
-
-                cur_bits = 0;
-                cur_bits += k1;
-                cur_bits += Math.min((k1 + unique_i_cur_k2) * getBitWith(block_size - 1), block_size + k1 + unique_i_cur_k2);
-
-                if (k1 + unique_i_cur_k2 != block_size)
-                    cur_bits += (block_size - k1 - unique_i_cur_k2) *
-                            getBitWith(k2_end - x_u_i - 2);
-                cur_bits += unique_i_cur_k2 * gamma;//min_upper_outlier
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start;
-                    final_k_end_value = k2_end - x_u_i;
-                }
-            }
-            k2 += cur_gamma_count;
-
-        }
-
-        // lower: x_min
-        // k2_end = x_max - 2^{alpha_size-1}
-        // upper: (0,x_max - 2^{alpha_size-1}]
-
-        int gap_gamma = (int) pow(2,alpha_size-1);
-        k2_end = max_delta_value - gap_gamma;
-        GroupU cur_group_gamma = groupU[alpha_size];
-
-        long[] gamma_sorted = cur_group_gamma.sorted_value_list;
-        int gamma_unique_number = cur_group_gamma.unique_number;
-
-        for(int unique_i=0;unique_i<gamma_unique_number-1;unique_i++){
-            int  unique_i_cur_k2 = k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-            int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);
-
-
-            cur_bits = 0;
-            cur_bits += k1;
-            cur_bits += Math.min((k1 + unique_i_cur_k2) * getBitWith(block_size - 1), block_size + k1 + unique_i_cur_k2);
-
-            if (k1 + unique_i_cur_k2 != block_size)
-                cur_bits += (block_size - k1 - unique_i_cur_k2) *
-                        getBitWith(k2_end - x_u_i - 2);
-            cur_bits += unique_i_cur_k2 * alpha_size;
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k1_start;
-                final_k_end_value = k2_end - x_u_i;
-            }
-        }
-
-        // -------------x_min-------------------
-
-
-
-
-        // [x_min+2^{alpha-1},x_min+2^{alpha}) alpha = 1 to alphasize - 1
-        // -----------------[x_min+2^{alpha-1},x_min+2^{alpha})-------------------
-        // alpha_size = getBitWith(max_delta_value);
-
-        for (int alpha_i = 0; alpha_i < num_of_alpha_list-1; alpha_i++) {
-
-            int alpha = alpha_list[alpha_i];
-            int gap_alpha = (int) pow(2,alpha-1);
-            k1_start = gap_alpha;
-            GroupL cur_group_alpha = groupL[alpha];
-
-
-            // lower: [x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-            // upper: x_max
-
-            int alpha_value_count = cur_group_alpha.count;
-            long[] alpha_sorted = cur_group_alpha.sorted_value_list;
-            int alpha_unique_number = cur_group_alpha.unique_number;
-
-            // k1; count[x_min, x_min+2^{alpha-1}]
-            for (int unique_j=0;unique_j<alpha_unique_number;unique_j++) {
-
-                int unique_i_cur_k1 = k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);//alpha_unique_count_array[unique_j];// gamma_box_count_list[gamma];
-                int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);//alpha_unique_number_array[unique_j];
-                k2 = count_x_max;
-                k2_end = max_delta_value;
-                cur_bits = Math.min((unique_i_cur_k1 + k2) * getBitWith(block_size - 1), block_size + unique_i_cur_k1 + k2);
-                cur_bits += unique_i_cur_k1 * alpha;
-                cur_bits += k2;
-                if (unique_i_cur_k1 + k2 != block_size)
-                    cur_bits += (block_size - unique_i_cur_k1 - k2) * getBitWith(k2_end - k1_start - x_l_i - 2);
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start + x_l_i;
-                    final_k_end_value = k2_end;
-                }
-            }
-
-
-            int pow_2_alpha = (int) pow(2, alpha);
-            // lower: [x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-            // upper: (x_max - 2^{gamma}, x_max - 2^{gamma-1}]:  k2_end - gap_gamma, k2_end
-
-
-            int cur_k1 = k1; //count[x_min, x_min+2^{alpha-1}]
-
-            // lower: (x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-            // upper:  (x_max - 2^{gamma}, x_max - 2^{gamma-1}]:  k2_end - gap_gamma, k2_end
-            // gamma size : x_min+2^{alpha} <= x_max - 2^{gamma} => 2^{gamma} <= x_max - 2^{alpha}
-            int gamma_size = (int) (log(max_delta_value - (int) pow(2, alpha)) / log(2));
-
-            int max_pow_2_lambda = (int) pow(2, lambda_0);
-            int max_lambda = lambda_0;
-            int cur_k2 = k2; // count(x_max)
-            int gamma_i = 0;
-            for (; gamma_i < num_of_gamma_list; gamma_i++) {
-                int gamma = gamma_list[gamma_i];
-                if(gamma > gamma_size){
-                    break;
-                }
-
-                // k1: count[x_min,x_min+2^{alpha-1}]
-
-                gap_gamma = (int) pow(2, gamma - 1);
-                k2_end = max_delta_value - gap_gamma;
-                cur_group_gamma = groupU[gamma]; // (x_max - 2^{gamma}, x_max - 2^{gamma-1})
-                int gamma_value_count = cur_group_gamma.count;
-                gamma_sorted = cur_group_gamma.sorted_value_list;
-                gamma_unique_number = cur_group_gamma.unique_number;
-
-
-                int pow_2_gamma = gap_gamma*2;
-
-                // prop 5.7
-
-                int cur_k1_start = k1_start + gap_alpha - 1;
-                int cur_k2_end = k2_end - gap_gamma + 1;
-                int cur_k2_start_of_lambda = cur_k2 + gamma_value_count;// count[x_max - 2^{gamma}+1, x_max]
-                int cur_k1_start_of_lambda = k1 + alpha_value_count; // count[x_min, 2^{alpha}-1]
-
-                cur_bits = 0;
-                cur_bits +=  Math.min((cur_k1_start_of_lambda + cur_k2_start_of_lambda) * lambda_0, block_size + cur_k1_start_of_lambda + cur_k2_start_of_lambda); // (lambda * (cur_cur_k1 + cur_k2_start_of_lambda) + zeta);
-                cur_bits += (cur_k1_start_of_lambda * alpha);
-                cur_bits += (cur_k2_start_of_lambda * gamma);
-                cur_bits += ((block_size - cur_k1_start_of_lambda - cur_k2_start_of_lambda) * getBitWith(cur_k2_end - cur_k1_start - 2));
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = cur_k1_start;
-                    final_k_end_value = cur_k2_end;
-                }
-
-                // prop 5.4
-                int prop_5_4_k1 = cur_k1 + alpha_value_count; //count[x_min, x_min+2^{alpha}-1]
-
-                cur_bits = 0;
-                cur_bits += Math.min((prop_5_4_k1 + cur_k2) * lambda_0, block_size + prop_5_4_k1 + cur_k2); //(lambda * (prop_5_4_k1 + prop_5_4_k2) + zeta);
-                cur_bits += (prop_5_4_k1 * alpha);
-                cur_bits += (cur_k2 * gamma);
-                cur_bits += ((block_size - prop_5_4_k1 - cur_k2) * getBitWith(k2_end - k1_start - gap_alpha  - 1));
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start + gap_alpha - 1;
-                    final_k_end_value = k2_end;
-                }
-
-                // prop 5.5
-                int prop_5_5_k2 = cur_k2 + gamma_value_count; // count[x_max - 2^{gamma}+1,x_max}
-
-                cur_bits = 0;
-                cur_bits += Math.min((cur_k1 + prop_5_5_k2) * lambda_0, block_size + cur_k1 + prop_5_5_k2);// (lambda * (prop_5_5_k1 + prop_5_5_k2) + zeta);
-                cur_bits += (cur_k1 * alpha);
-                cur_bits += (prop_5_5_k2 * gamma);
-                cur_bits += ((block_size - cur_k1 - prop_5_5_k2) * getBitWith(k2_end - gap_gamma - k1_start - 1));
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start;
-                    final_k_end_value = k2_end - gap_gamma + 1;
-                }
-
-                // prop 5.6
-
-                cur_bits = 0;
-                cur_bits += Math.min((cur_k1 + cur_k2) * lambda_0, block_size + cur_k1 + cur_k2);//(lambda * (prop_5_6_k1 + prop_5_6_k2) + zeta);
-                cur_bits += (cur_k1 * alpha);
-                cur_bits += (cur_k2 * gamma);
-                cur_bits += ((block_size - cur_k1 - cur_k2) * getBitWith(k2_end - k1_start - 2));
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k1_start;
-                    final_k_end_value = k2_end;
-                }
-
-
-
-                if ((max_pow_2_lambda + 1) * pow_2_alpha + pow_2_gamma <= max_delta_value
-                        && pow_2_alpha + (max_pow_2_lambda + 1) * pow_2_gamma <= max_delta_value) {
-
-
-                }
-                else {
-
-                    // lower: (x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-                    // upper:  (x_max - 2^{gamma}, x_max - 2^{gamma-1}):  k2_end - gap_gamma, k2_end
-                    // beta: getBitWidth(x_max - 2^{gamma} -(x_min+2^{alpha})) to getBitWidth(x_max - 2^{gamma-1}-(x_min+2^{alpha-1}) )
-                    int min_beta = getBitWith(max_delta_value-pow_2_gamma-pow_2_alpha);
-                    int max_beta = getBitWith(k2_end-k1_start);
-
-
-
-                    for(int beta = min_beta;beta <= max_beta;beta++) {
-                        int pow_2_beta = (int) pow(2, beta);
-                        if (beta >= alpha + max_lambda && beta <= gamma + 1 && pow_2_beta + pow_2_alpha + gap_gamma >= max_delta_value) {
-
-                        }
-                        else if (beta <= alpha + 1 && beta >= gamma + max_lambda && pow_2_beta + pow_2_alpha / 2 + pow_2_gamma >= max_delta_value) {
-
-                        }
-                        else if (beta <= alpha + 1 && beta <= gamma + 1 && pow_2_beta + pow_2_alpha / 2 + gap_gamma > max_delta_value) {
-
-                        } else {
-                            int cur_cur_k1;
-                            for (int unique_j = 0; unique_j < alpha_unique_number; unique_j++) {
-                                cur_cur_k1 = cur_k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);//alpha_unique_count_array[unique_j];// gamma_box_count_list[gamma];
-                                int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);//alpha_unique_number_array[unique_j];
-
-                                int cur_cur_k2 ; // count[x_max - 2^{gamma-1}, x_max]
-
-                                int x_u_i_start =  Math.max(0, k2_end - ( pow_2_beta + k1_start + x_l_i + 2));
-                                int x_u_i_end = Math.min(k2_end -( pow_2_beta/2 + k1_start + x_l_i + 2),gap_gamma-1);
-
-
-                                for (int unique_i = 0; unique_i < gamma_unique_number; unique_i++) {
-                                    int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);//<=x_u_i_end
-                                    if(x_u_i < x_u_i_start){
-                                        continue;
-                                    }
-                                    if(x_u_i > x_u_i_end){
-                                        break;
-                                    }
-                                    cur_cur_k2 = cur_k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-
-                                    cur_bits = 0;
-                                    cur_bits += Math.min((cur_cur_k1 + cur_cur_k2) * lambda_0, block_size + cur_cur_k1 + cur_cur_k2);
-                                    // (lambda * (cur_k1_start_of_lambda + cur_cur_k2) + zeta); // Math.min((cur_k1 + cur_cur_k2) * getBitWith(block_size - 1), block_size + cur_k1 + cur_k2);
-                                    cur_bits += cur_cur_k1 * alpha;
-                                    if (cur_cur_k1 + cur_cur_k2 != block_size)
-                                        cur_bits += (block_size - cur_cur_k1 - cur_cur_k2) *
-                                                getBitWith(k2_end - x_u_i - k1_start - x_l_i - 2);
-                                    cur_bits += cur_cur_k2 * gamma;
-                                    if (cur_bits < min_bits) {
-                                        min_bits = cur_bits;
-                                        final_k_start_value = k1_start + x_l_i;
-                                        final_k_end_value = k2_end - x_u_i;
-                                    }
-
-                                }
-                            }
-                        }
-
-                    }
-
-                }
-
-                cur_k2 = cur_k2 + gamma_value_count; // += count(x_max - 2^{gamma}, x_max - 2^{gamma-1})
-
-                if(cur_k1+cur_k2>boundary_index){
-                    max_pow_2_lambda = (int) pow(2, 1);
-                    max_lambda = 1;
-                }
-
-            }
-
-
-            k2 = cur_k2;
-
-            // gamma:  gamma_size+1 to ....
-            // gamma size : x_min+2^{alpha} <= x_max - 2^{gamma} => 2^{gamma} <= x_max - 2^{alpha}
-            //k2_end = x_max - 2^{gamma-1} ; gamma : 1 to gamma_size
-            // lower: [x_min+2^{alpha-1},x_min+2^{alpha}) : k1_start, k1_start + gap_alpha
-            // upper:  (x_max - 2^{gamma}, x_max - 2^{gamma-1}]
-
-
-            for (; gamma_i < num_of_gamma_list; gamma_i++) {
-                int gamma = gamma_list[gamma_i];
-                gap_gamma = (int) pow(2, gamma-1);
-                cur_group_gamma = groupU[gamma];
-                k2_end = max_delta_value - gap_gamma;
-
-                if(k2_end <= k1_start){
-                    break;
-                }
-                int gamma_value_count = cur_group_gamma.count;
-
-                gamma_unique_number = cur_group_gamma.unique_number;
-                gamma_sorted = cur_group_gamma.sorted_value_list;
-
-                for (int unique_j=0;unique_j<alpha_unique_number;unique_j++) {
-                    int unique_j_cur_k1 = cur_k1+ cur_group_alpha.getCount(alpha_sorted[unique_j]);// gamma_box_count_list[gamma];
-                    int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);
-
-
-                    for (int unique_i = 0; unique_i < gamma_unique_number; unique_i++) {
-                        int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);
-                        if(k2_end - x_u_i <= k1_start+x_l_i){
-                            break;
-                        }
-                        int unique_i_cur_k2 = cur_k2+ cur_group_gamma.getCount(gamma_sorted[unique_i]);
-                        cur_bits = 0;
-                        cur_bits += Math.min((unique_j_cur_k1 + unique_i_cur_k2) * getBitWith(block_size - 1), block_size + unique_j_cur_k1 + unique_i_cur_k2);
-                        cur_bits += unique_j_cur_k1*alpha;
-                        if (unique_j_cur_k1 + unique_i_cur_k2 != block_size)
-                            cur_bits += (block_size - unique_j_cur_k1 - unique_i_cur_k2) *
-                                    getBitWith(k2_end - x_u_i-k1_start-x_l_i - 2);
-                        cur_bits += unique_i_cur_k2 * gamma;
-                        if (cur_bits < min_bits) {
-                            min_bits = cur_bits;
-                            final_k_start_value = k1_start + x_l_i;
-                            final_k_end_value = k2_end - x_u_i;
-                        }
-                    }
-
-                }
-                cur_k2 += gamma_value_count;
-            }
-
-            k1 += alpha_value_count;
-        }
-        // -------------------[x_min+2^{alpha-1},x_min+2^{alpha})-----------------
-
-
-        //  [x_min+2^{alpha_size-1},x_max)
-        // ----------------[x_min+2^{alpha_size-1},x_max)--------------------
-
-        // x_min+2^{alpha_size-1} < x_max && x_min+2^{alpha_size} >= x_max
-        // alpha_size - 1  < log(xmax) && alpha_size >= log(xmax)
-        // alpha_size = \lceil log(x_max-1+1) \rceil
-
-        alpha_size = alpha_list[num_of_alpha_list-1];
-        int gap_alpha = (int) pow(2,alpha_size-1);
-        k1_start = gap_alpha;
-        GroupL cur_group_alpha = groupL[alpha_size];
-        int alpha_value_count = cur_group_alpha.count;
-
-
-        // lower: [x_min+2^{alpha_size-1},x_max)
-        // ----------------- [x_min+2^{alpha_size-1},x_max)----------------------
-        long[] alpha_sorted = cur_group_alpha.sorted_value_list;
-        int alpha_unique_number = cur_group_alpha.unique_number;
-
-        int x_l_i_end = max_delta_value - k1_start; // [1, x_max - x_min+2^{alpha_size-1})
-        for (int unique_j=0;unique_j<alpha_unique_number;unique_j++) {
-
-            int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);
-            if (x_l_i >= x_l_i_end) {
-                break;
-            }
-            int unique_j_cur_k1 = k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);// gamma_box_count_list[gamma];
-
-            // lower: [x_min+2^{alpha_size-1},x_max) : k1_start, k1_start + gap_alpha
-            // upper: x_max
-            k2 = count_x_max;
-            k2_end = max_delta_value;
-
-            cur_bits = 0;
-            cur_bits += Math.min((unique_j_cur_k1 + k2) * getBitWith(block_size - 1), block_size + unique_j_cur_k1 + k2);
-            cur_bits += unique_j_cur_k1 * alpha_size;
-            cur_bits += k2;
-            if (unique_j_cur_k1 + k2 != block_size)
-                cur_bits += (block_size - unique_j_cur_k1 - k2) * getBitWith(k2_end - k1_start - x_l_i - 2);
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k1_start + x_l_i;
-                final_k_end_value = k2_end;
-            }
-        }
-        // lower: (x_min+2^{alpha_size-1},x_max)
-        // upper: (x_max - 2^{gamma}, x_max)
-        // gamma:  gamma_size+1 to ....
-        // lower: (x_min+2^{alpha_size-1},x_max) : k1_start, k1_start + gap_alpha
-        // upper:  (x_max - 2^{gamma}, x_max - 2^{gamma-1}] : k2_end - gap_gamma, k2_end
-
-        int max_pow_2_lambda = (int) pow(2, lambda_0);
-        int max_lambda = lambda_0;
-        for (int gamma_i = 0; gamma_i < num_of_gamma_list; gamma_i++) {
-            int gamma =  gamma_list[gamma_i];
-            gap_gamma = (int) pow(2, gamma-1);
-            k2_end = max_delta_value - gap_gamma; // x_max - 2^{gamma} ;
-
-            if(k2_end<=k1_start){
-                break;
-            }
-            cur_group_gamma = groupU[gamma];
-
-            int gamma_value_count = cur_group_gamma.count;
-            gamma_sorted = cur_group_gamma.sorted_value_list;
-            gamma_unique_number = cur_group_gamma.unique_number;
-
-            int pow_2_gamma = gap_gamma*2;
-            for (int unique_j=0;unique_j<alpha_unique_number;unique_j++) {
-                int x_l_i = cur_group_alpha.getUniqueValue(alpha_sorted[unique_j]);
-                int x_u_i_end = k2_end - k1_start - x_l_i; // x_u_i>= k2_end - k1_start - x_l_i; break ;
-
-                if(x_u_i_end <= 0 || x_l_i >= x_l_i_end){
-                    break;
-                }
-                int unique_j_cur_k1 = k1 + cur_group_alpha.getCount(alpha_sorted[unique_j]);// gamma_box_count_list[gamma];
-                x_u_i_end = Math.min(x_u_i_end,gap_gamma);
-
-
-                for(int unique_i=0;unique_i<gamma_unique_number;unique_i++){
-
-                    int x_u_i = cur_group_gamma.getUniqueValue(gamma_sorted[unique_i]);
-                    if(x_u_i>=x_u_i_end){
-                        break;
-                    }
-
-                    int unique_i_cur_k2 = k2 + cur_group_gamma.getCount(gamma_sorted[unique_i]);
-                    cur_bits = 0;
-                    cur_bits += Math.min((unique_j_cur_k1 + unique_i_cur_k2) * getBitWith(block_size - 1), block_size + unique_j_cur_k1 + unique_i_cur_k2);
-                    cur_bits += unique_j_cur_k1*alpha_size;
-                    if (unique_j_cur_k1 + unique_i_cur_k2 != block_size)
-                        cur_bits += (block_size - unique_j_cur_k1 - unique_i_cur_k2) *
-                                getBitWith(k2_end - x_u_i-k1_start-x_l_i - 2);
-                    cur_bits += unique_i_cur_k2 * gamma;
-                    if (cur_bits < min_bits) {
-                        min_bits = cur_bits;
-                        final_k_start_value = k1_start + x_l_i;
-                        final_k_end_value = k2_end - x_u_i;
-                    }
-                }
-            }
-            k2 += gamma_value_count;
-
-
-
-        }
-        // ------------------ [x_min+2^{alpha_size-1},x_max)--------------------
-        encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_k_end_value, max_delta_value,
-                min_delta, encode_pos , cur_byte);
-
-        return encode_pos;
-    }
-
-    public static int minNumberIndex(int alpha, int beta, int gamma){
-        if(alpha<beta && beta < gamma){
-            return 1; // prop 4.2
-        } else if (alpha>beta && beta > gamma) {
-            return 2;// prop 4.3
-        } else if (beta<alpha && beta <gamma) {
-            return 3;// prop 4.4
-        }else{
-            return 0; // alpha=beta=gamma
-        }
-    }
-
-    public static int BOSEncoder(
-            int[] data, int block_size, byte[] encoded_result) {
-        block_size++;
-
-        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;
-
-        for (int i = 0; i < block_num; i++) {
-            encode_pos =  BOSBlockEncoder(data, i, block_size, block_size,encode_pos,encoded_result);
-        }
-
-        int remaining_length = length_all - block_num * block_size;
-        if (remaining_length <= 3) {
-            for (int i = remaining_length; i > 0; i--) {
-                int2Bytes(data[data.length - i], encode_pos, encoded_result);
-                encode_pos += 4;
-            }
-
-        }
-        else {
-
-            int start = block_num * block_size;
-            int remaining = length_all-start;
-
-
-            encode_pos = BOSBlockEncoder(data, block_num, block_size,remaining, encode_pos,encoded_result);
-
-        }
-
-
-        return encode_pos;
-    }
-
-    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
-
-        int k_byte = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-        int k1_byte = (int) (k_byte % pow(2, 16));
-        int k1 = k1_byte / 2;
-        int final_alpha = k1_byte % 2;
-
-        int k2 = (int) (k_byte / pow(2, 16));
-
-        int value0 = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-        value_list[value_pos_arr[0]] =value0;
-        value_pos_arr[0] ++;
-
-        int min_delta = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        int left_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-        int right_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal= new ArrayList<>();;
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-
-
-        if (final_alpha == 0) {
-            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
-            for (int i = 0; i < bitmap_bytes; i++) {
-                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
-                decode_pos += 1;
-            }
-            int bitmap_outlier_i = 0;
-            int remaining_bits = 8;
-            int tmp = bitmap_outlier.get(bitmap_outlier_i);
-            bitmap_outlier_i++;
-            int i = 0;
-            while (i < block_size ) {
-                if (remaining_bits > 1) {
-                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
-                    remaining_bits -= 1;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                    if (remaining_bits == 0) {
-                        remaining_bits = 8;
-                        if (bitmap_outlier_i >= bitmap_bytes) break;
-                        tmp = bitmap_outlier.get(bitmap_outlier_i);
-                        bitmap_outlier_i++;
-                    }
-                } else if (remaining_bits == 1) {
-                    int bit_i = tmp & 0x1;
-                    remaining_bits = 8;
-                    if (bitmap_outlier_i >= bitmap_bytes) break;
-                    tmp = bitmap_outlier.get(bitmap_outlier_i);
-                    bitmap_outlier_i++;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                }
-                i++;
-            }
-        } else {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
-            decode_pos = (decode_pos_result_left.get(0));
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
-            decode_pos = (decode_pos_result_right.get(0));
-        }
-
-
-        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
-        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
-
-        decode_pos = decode_pos_normal.get(0);
-        if (k1 != 0) {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
-            decode_pos = decode_pos_result_left.get(0);
-        }
-        if (k2 != 0) {
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
-            decode_pos = decode_pos_result_right.get(0);
-        }
-        int left_outlier_i = 0;
-        int right_outlier_i = 0;
-        int normal_i = 0;
-        int pre_v = value0;
-        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
-
-
-        for (int i = 0; i < block_size; i++) {
-            int current_delta;
-            if (left_outlier_i >= k1) {
-                if (right_outlier_i >= k2) {
-                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta = min_delta + final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
-                    normal_i++;
-                }
-            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
-                current_delta = min_delta + final_left_outlier.get(left_outlier_i);
-                left_outlier_i++;
-            } else {
-
-                if (right_outlier_i >= k2) {
-                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta = min_delta + final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
-                    normal_i++;
-                }
-            }
-
-            pre_v = current_delta + pre_v;
-            value_list[value_pos_arr[0]] = pre_v;
-            value_pos_arr[0]++;
-        }
-        return decode_pos;
-    }
-
-    public static void BOSDecoder(byte[] encoded) {
-
-        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[] value_list = new int[length_all+block_size];
-        block_size--;
-
-        int[] value_pos_arr = new int[1];
-        for (int k = 0; k < block_num; k++) {
-
-
-            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list, block_size,value_pos_arr);
-
-        }
-
-        if (remain_length <= 3) {
-            for (int i = 0; i < remain_length; i++) {
-                int value_end = bytes2Integer(encoded, decode_pos, 4);
-                decode_pos += 4;
-                value_list[value_pos_arr[0]] = value_end;
-                value_pos_arr[0]++;
-            }
-        } else {
-            remain_length --;
-            BOSBlockDecoder(encoded, decode_pos, value_list, remain_length, value_pos_arr);
-        }
-    }
-
-    @Test
-    public void PruneBOSTest() throws IOException {
-        String parent_dir = "/Users/xiaojinzhao/Desktop/encoding-outlier/"; // your data path
-        String output_parent_dir = parent_dir + "vldb/compression_ratio/pruning_bos";
-        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<>();
-        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");
-
-        for (String value : dataset_name) {
-            input_path_list.add(input_parent_dir + value);
-            dataset_block_size.add(1024);
-        }
-
-        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(2048);
-        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
-//        dataset_block_size.add(1024);
-        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
-//        dataset_block_size.add(1024);
-        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
-//        dataset_block_size.add(1024);
-
-        int repeatTime2 = 100;
-
-        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
-
-            String inputPath = input_path_list.get(file_i);
-            System.out.println(inputPath);
-            String Output = output_path_list.get(file_i);
-
-            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) {
-//                f= tempList[1];
-
-                System.out.println(f);
-                InputStream inputStream = Files.newInputStream(f.toPath());
-
-                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
-                ArrayList<Integer> data1 = new ArrayList<>();
-                ArrayList<Integer> data2 = new ArrayList<>();
-
-
-                loader.readHeaders();
-                while (loader.readRecord()) {
-                    data1.add(Integer.valueOf(loader.getValues()[0]));
-                    data2.add(Integer.valueOf(loader.getValues()[1]));
-                }
-                inputStream.close();
-                int[] data2_arr = new int[data1.size()];
-                for(int i = 0;i<data2.size();i++){
-                    data2_arr[i] = data2.get(i);
-                }
-                byte[] encoded_result = new byte[data2_arr.length*4];
-                long encodeTime = 0;
-                long decodeTime = 0;
-                double ratio = 0;
-                double compressed_size = 0;
-
-
-                int length = 0;
-
-                long s = System.nanoTime();
-                for (int repeat = 0; repeat < repeatTime2; repeat++) {
-                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
-                }
-
-                long e = System.nanoTime();
-                encodeTime += ((e - s) / repeatTime2);
-                compressed_size += length;
-                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
-                ratio += ratioTmp;
-                s = System.nanoTime();
-                for (int repeat = 0; repeat < repeatTime2; repeat++)
-                    BOSDecoder(encoded_result);
-                e = System.nanoTime();
-                decodeTime += ((e - s) / repeatTime2);
-
-
-                String[] record = {
-                        f.toString(),
-                        "TS_2DIFF+BOS-P",
-                        String.valueOf(encodeTime),
-                        String.valueOf(decodeTime),
-                        String.valueOf(data1.size()),
-                        String.valueOf(compressed_size),
-                        String.valueOf(ratio)
-                };
-                writer.writeRecord(record);
-                System.out.println(ratio);
-            }
-            writer.close();
-
-        }
-    }
-
-
-}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSLTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSLTest.java
deleted file mode 100644
index 7217efc..0000000
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSLTest.java
+++ /dev/null
@@ -1,1284 +0,0 @@
-package org.apache.iotdb.tsfile.encoding;
-
-import com.csvreader.CsvReader;
-import com.csvreader.CsvWriter;
-import org.junit.Test;
-
-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.ArrayList;
-
-
-import static java.lang.Math.pow;
-
-public class TSDIFFBOSLTest {
-
-    public static long combine2Int(int int1, int int2) {
-        return ((long) int1 << 32) | (int2 & 0xFFFFFFFFL);
-    }
-
-    public static int getTime(long long1) {
-        return ((int) (long1 >> 32));
-    }
-
-    public static int getValue(long long1) {
-        return ((int) (long1));
-    }
-
-    public static int getCount(long long1, int mask) {
-        return ((int) (long1 & mask));
-    }
-    public static int getUniqueValue(long long1, int left_shift) {
-        return ((int) ((long1) >> left_shift));
-    }
-
-    public static int getBitWith(int num) {
-        if (num == 0) return 1;
-        else return 32 - Integer.numberOfLeadingZeros(num);
-    }
-
-    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 ;
-                }
-            }
-        }
-    }
-
-    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 int[] getAbsDeltaTsBlock(
-            int[] ts_block,
-            int[] min_delta,
-            int supple_length) {
-        int block_size = ts_block.length-1;
-        int[] ts_block_delta = new int[ts_block.length+supple_length-1];
-
-
-        int value_delta_min = Integer.MAX_VALUE;
-        int value_delta_max = Integer.MIN_VALUE;
-        for (int i = 0; i < block_size; i++) {
-
-            int epsilon_v = ts_block[i+1] - ts_block[i];
-
-            if (epsilon_v < value_delta_min) {
-                value_delta_min = epsilon_v;
-            }
-            if (epsilon_v > value_delta_max) {
-                value_delta_max = epsilon_v;
-            }
-
-        }
-        min_delta[0] = (ts_block[0]);
-        min_delta[1] = (value_delta_min);
-        min_delta[2] = (value_delta_max-value_delta_min);
-
-        for (int i = 0; i  < block_size; i++) {
-            int epsilon_v = ts_block[i+1] - value_delta_min - ts_block[i];
-            ts_block_delta[i] = epsilon_v;
-        }
-        for(int i = block_size;i<block_size+supple_length;i++){
-            ts_block_delta[i] = 0;
-        }
-        return ts_block_delta;
-    }
-
-    public static int[] getAbsDeltaTsBlock(
-            int[] ts_block,
-            int i,
-            int block_size,
-            int remaining,
-            int[] min_delta) {
-        int[] ts_block_delta = new int[remaining-1];
-
-        int value_delta_min = Integer.MAX_VALUE;
-        int value_delta_max = Integer.MIN_VALUE;
-        int base = i*block_size+1;
-        int end = i*block_size+remaining;
-
-        int tmp_j_1 = ts_block[base-1];
-        min_delta[0] =tmp_j_1;
-        int j = base;
-        int tmp_j;
-
-        while(j<end){
-            tmp_j = ts_block[j];
-            int epsilon_v = tmp_j - tmp_j_1;
-            ts_block_delta[j-base] = epsilon_v;
-            if (epsilon_v < value_delta_min) {
-                value_delta_min = epsilon_v;
-            }
-            if (epsilon_v > value_delta_max) {
-                value_delta_max = epsilon_v;
-            }
-            tmp_j_1 = tmp_j;
-            j++;
-        }
-        j = 0;
-        end = remaining -1;
-        while(j<end){
-            ts_block_delta[j] = ts_block_delta[j] - value_delta_min;
-            j++;
-        }
-
-        min_delta[1] = value_delta_min;
-        min_delta[2] = (value_delta_max-value_delta_min);
-
-
-        return ts_block_delta;
-    }
-
-
-    public static int encodeOutlier2Bytes(
-            ArrayList<Integer> ts_block_delta,
-            int bit_width,
-            int encode_pos,  byte[] encoded_result) {
-
-        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
-
-        int n_k = ts_block_delta.size();
-        int n_k_b = n_k / 8;
-        long cur_remaining = 0; // encoded int
-        int cur_number_bits = 0; // the bit width used of encoded int
-        for (int i = n_k_b * 8; i < n_k; i++) {
-            long cur_value = ts_block_delta.get(i);
-            int cur_bit_width = bit_width; // remaining bit width of current value
-
-            if (cur_number_bits + bit_width >= 32) {
-                cur_remaining <<= (32 - cur_number_bits);
-                cur_bit_width = bit_width - 32 + cur_number_bits;
-                cur_remaining += ((cur_value >> cur_bit_width));
-                long2intBytes(cur_remaining,encode_pos,encoded_result);
-                encode_pos += 4;
-                cur_remaining = 0;
-                cur_number_bits = 0;
-            }
-
-            cur_remaining <<= cur_bit_width;
-            cur_number_bits += cur_bit_width;
-            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width)); //
-        }
-        cur_remaining <<= (32 - cur_number_bits);
-        long2intBytes(cur_remaining,encode_pos,encoded_result);
-        encode_pos += 4;
-        return encode_pos;
-
-    }
-
-
-    public static ArrayList<Integer> decodeOutlier2Bytes(
-            byte[] encoded,
-            int decode_pos,
-            int bit_width,
-            int length,
-            ArrayList<Integer> encoded_pos_result
-    ) {
-
-        int n_k_b = length / 8;
-        int remaining = length - n_k_b * 8;
-        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
-        decode_pos += n_k_b * bit_width;
-
-        ArrayList<Long> int_remaining = new ArrayList<>();
-        int int_remaining_size = remaining * bit_width / 32 + 1;
-        for (int j = 0; j < int_remaining_size; j++) {
-            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
-            decode_pos += 4;
-        }
-
-        int cur_remaining_bits = 32; // remaining bit width of current value
-        long cur_number = int_remaining.get(0);
-        int cur_number_i = 1;
-        for (int i = n_k_b * 8; i < length; i++) {
-            if (bit_width < cur_remaining_bits) {
-                int tmp = (int) (cur_number >> (32 - bit_width));
-                result_list.add(tmp);
-                cur_number <<= bit_width;
-                cur_number &= 0xFFFFFFFFL;
-                cur_remaining_bits -= bit_width;
-            } else {
-                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
-                int remain_bits = bit_width - cur_remaining_bits;
-                tmp <<= remain_bits;
-
-                cur_number = int_remaining.get(cur_number_i);
-                cur_number_i++;
-                tmp += (int) (cur_number >> (32 - remain_bits));
-                result_list.add(tmp);
-                cur_number <<= remain_bits;
-                cur_number &= 0xFFFFFFFFL;
-                cur_remaining_bits = 32 - remain_bits;
-            }
-        }
-        encoded_pos_result.add(decode_pos);
-        return result_list;
-    }
-
-    private static int BOSEncodeBits(int[] ts_block_delta,
-                                     int final_k_start_value,
-                                     int final_k_end_value,
-                                     int max_delta_value,
-                                     int[] min_delta,
-                                     int encode_pos,
-                                     byte[] cur_byte) {
-        int block_size = ts_block_delta.length;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal = new ArrayList<>();
-        int k1 = 0;
-        int k2 = 0;
-
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-        int index_bitmap_outlier = 0;
-        int cur_index_bitmap_outlier_bits = 0;
-        for (int i = 0; i < block_size; i++) {
-            int cur_value = ts_block_delta[i];
-            if ( cur_value<= final_k_start_value) {
-                final_left_outlier.add(cur_value);
-                final_left_outlier_index.add(i);
-                if (cur_index_bitmap_outlier_bits % 8 != 7) {
-                    index_bitmap_outlier <<= 2;
-                    index_bitmap_outlier += 3;
-                    cur_index_bitmap_outlier_bits += 2;
-                } else {
-                    index_bitmap_outlier <<= 1;
-                    index_bitmap_outlier += 1;
-                    bitmap_outlier.add(index_bitmap_outlier);
-                    index_bitmap_outlier = 1;
-                    cur_index_bitmap_outlier_bits = 1;
-                }
-                k1++;
-
-
-            } else if (cur_value >= final_k_end_value) {
-                final_right_outlier.add(cur_value - final_k_end_value);
-                final_right_outlier_index.add(i);
-                if (cur_index_bitmap_outlier_bits % 8 != 7) {
-                    index_bitmap_outlier <<= 2;
-                    index_bitmap_outlier += 2;
-                    cur_index_bitmap_outlier_bits += 2;
-                } else {
-                    index_bitmap_outlier <<= 1;
-                    index_bitmap_outlier += 1;
-                    bitmap_outlier.add(index_bitmap_outlier);
-                    index_bitmap_outlier = 0;
-                    cur_index_bitmap_outlier_bits = 1;
-                }
-                k2++;
-
-            } else {
-                final_normal.add(cur_value - final_k_start_value-1);
-                index_bitmap_outlier <<= 1;
-                cur_index_bitmap_outlier_bits += 1;
-            }
-            if (cur_index_bitmap_outlier_bits % 8 == 0) {
-                bitmap_outlier.add(index_bitmap_outlier);
-                index_bitmap_outlier = 0;
-            }
-        }
-        if (cur_index_bitmap_outlier_bits % 8 != 0) {
-
-            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
-
-            index_bitmap_outlier &= 0xFF;
-            bitmap_outlier.add(index_bitmap_outlier);
-        }
-
-        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
-
-
-        int k_byte = (k1 << 1);
-        k_byte += final_alpha;
-        k_byte += (k2 << 16);
-
-
-        int2Bytes(k_byte,encode_pos,cur_byte);
-        encode_pos += 4;
-
-        int2Bytes(min_delta[0],encode_pos,cur_byte);
-        encode_pos += 4;
-        int2Bytes(min_delta[1],encode_pos,cur_byte);
-        encode_pos += 4;
-        int2Bytes(final_k_start_value,encode_pos,cur_byte);
-        encode_pos += 4;
-        int bit_width_final = getBitWith(final_k_end_value - final_k_start_value-2);
-        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
-        encode_pos += 1;
-        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
-        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
-        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        if (final_alpha == 0) { // 0
-
-            for (int i : bitmap_outlier) {
-
-                intByte2Bytes(i,encode_pos,cur_byte);
-                encode_pos += 1;
-            }
-        } else {
-            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
-            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
-        }
-        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
-        if (k1 != 0)
-            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
-        if (k2 != 0)
-            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
-        return encode_pos;
-
-    }
-
-
-    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size, int remaining ,int encode_pos , byte[] cur_byte) {
-
-        int[] min_delta = new int[3];
-        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
-
-
-        block_size = remaining-1;
-        int max_delta_value = min_delta[2];
-        int max_bit = getBitWith(max_delta_value);
-        int[] alpha_count_list = new int[max_bit+1];//count(xmin) count(xmin + 1) count(xmin + 2)... count(xmin + 8) ... count(xmin + 2^(i - 1))
-        int[] alpha_box_count_list = new int[max_bit+1];// count(xmin, xmin + 1), count(xmin +1, xmin + 2)... count (xmin + 2^(i - 1), xmin + 2^i)
-        int[] gamma_count_list = new int[max_bit+1];//count(xmax) count(xmax - 1)... count(xmax - 2^(i - 1))
-        int[] gamma_box_count_list = new int[max_bit+1]; // count (xmax - 2^i, xmin - 2^(i-1))
-        for(int value:ts_block_delta){
-            if (value == 0){
-                alpha_count_list[0]++;
-            }
-            else if (value == pow(2,getBitWith(value)-1)){
-                alpha_count_list[getBitWith(value)]++;
-            }else {
-                alpha_box_count_list[getBitWith(value)]++;
-            }
-            if (value == max_delta_value){
-                gamma_count_list[0]++;
-            }
-            else if (max_delta_value - value == pow(2,getBitWith(max_delta_value-value)-1)){
-                gamma_count_list[getBitWith(max_delta_value-value)]++;
-            }else {
-                gamma_box_count_list[getBitWith(max_delta_value-value)]++;
-            }
-        }
-
-        int final_k_start_value = -1;
-        int final_k_end_value = max_delta_value+1;
-
-        int min_bits = 0;
-        min_bits += (getBitWith(final_k_end_value - final_k_start_value -2) * (block_size));
-        // lower: x_min
-        //  -------------------------------
-        int cur_k1_close = alpha_count_list[0]; // lower: x_min
-        int k_start_value_close = 0;
-
-        int cur_bits;
-        int alpha_2_pow = 1;
-        int gamma_size = (int) (Math.log(max_delta_value - alpha_2_pow - 1)/Math.log(2));
-        int cur_k2_close = gamma_count_list[0];
-        cur_k2_close += gamma_count_list[1];
-        cur_k2_close += gamma_box_count_list[0];
-        for (int gamma = 1;  gamma<=gamma_size;gamma++){
-            int k_end_value_close = max_delta_value - (int) pow(2,gamma);
-
-            cur_k2_close += gamma_count_list[gamma+1];
-            cur_k2_close += gamma_box_count_list[gamma];
-            cur_bits = cur_k1_close;
-            cur_bits += Math.min((cur_k1_close + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_close);
-            if (cur_k1_close + cur_k2_close != block_size)
-                cur_bits += (block_size - cur_k1_close - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_close - 2);
-            if (cur_k2_close != 0)
-                cur_bits += cur_k2_close * (gamma + 1);
-
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_close;
-                final_k_end_value = k_end_value_close;
-            }
-
-            int cur_k2_open = cur_k2_close - gamma_count_list[gamma+1];
-            int k_end_value_open = k_end_value_close + 1;
-
-            //C4 k1 close k2 open
-            cur_bits = cur_k1_close;
-            cur_bits += Math.min((cur_k1_close + cur_k2_open) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_open);
-
-            if (cur_k1_close + cur_k2_open != block_size)
-                cur_bits += (block_size - cur_k1_close - cur_k2_open) * getBitWith(k_end_value_open - k_start_value_close - 2);
-            if (cur_k2_open != 0)
-                cur_bits += cur_k2_open * gamma;
-
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_close;
-                final_k_end_value = k_end_value_open;
-            }
-        }
-
-        // lower: x_min +1
-        //  -------------------------------
-        cur_k1_close += alpha_count_list[1]; // lower outliers: x_min +1
-        cur_k1_close += alpha_box_count_list[0];
-        k_start_value_close = 1;
-        cur_k2_close = gamma_count_list[0];
-        cur_k2_close += gamma_count_list[1];
-        cur_k2_close += gamma_box_count_list[0];
-        for (int gamma = 1;  gamma<=gamma_size;gamma++){
-            int k_end_value_close = max_delta_value - (int) pow(2,gamma);
-
-            cur_k2_close += gamma_count_list[gamma+1];
-            cur_k2_close += gamma_box_count_list[gamma];
-            cur_bits = cur_k1_close;
-            cur_bits += Math.min((cur_k1_close + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_close);
-            if (cur_k1_close + cur_k2_close != block_size)
-                cur_bits += (block_size - cur_k1_close - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_close - 2);
-            if (cur_k2_close != 0)
-                cur_bits += cur_k2_close * (gamma + 1);
-
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_close;
-                final_k_end_value = k_end_value_close;
-            }
-
-            int cur_k2_open = cur_k2_close - gamma_count_list[gamma+1];
-            int k_end_value_open = k_end_value_close + 1;
-
-            //C4 k1 close k2 open
-            cur_bits = cur_k1_close;
-            cur_bits += Math.min((cur_k1_close + cur_k2_open) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_open);
-
-            if (cur_k1_close + cur_k2_open != block_size)
-                cur_bits += (block_size - cur_k1_close - cur_k2_open) * getBitWith(k_end_value_open - k_start_value_close - 2);
-            if (cur_k2_open != 0)
-                cur_bits += cur_k2_open * gamma;
-
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_close;
-                final_k_end_value = k_end_value_open;
-            }
-        }
-        // lower: x_min + 2 ^alpha
-        //  -------------------------------
-
-        for (int alpha = 1; alpha  <= max_bit-1; alpha++) {
-            //C1 k1 close k2 close
-            k_start_value_close = (int) pow(2,alpha);
-            int pow_2_alpha_i = alpha_count_list[alpha+1];
-            int pow_2_alpha_i_1_to_2_alpha_i = alpha_box_count_list[alpha];
-            cur_k1_close += pow_2_alpha_i;
-            cur_k1_close += pow_2_alpha_i_1_to_2_alpha_i;
-
-
-
-
-            alpha_2_pow = (int)pow(2,alpha);
-            gamma_size = (int) (Math.log(max_delta_value - alpha_2_pow - 1)/Math.log(2));
-
-            // upper outliers: x_max
-            cur_k2_close = gamma_count_list[0];
-            int k_end_value_close= max_delta_value;
-
-            cur_bits=cur_k2_close;
-            cur_bits += Math.min((cur_k1_close + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_close);
-            if (cur_k1_close != 0)
-                cur_bits += cur_k1_close * (alpha + 1);
-            if (cur_k1_close + cur_k2_close != block_size)
-                cur_bits += (block_size - cur_k1_close - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_close - 2);
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_close;
-                final_k_end_value = k_end_value_close;
-            }
-
-            int cur_k1_open = cur_k1_close - alpha_count_list[alpha+1];
-            int k_start_value_open = k_start_value_close - 1;
-            cur_bits=cur_k2_close;
-            cur_bits += Math.min((cur_k1_open + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_open + cur_k2_close);
-            if (cur_k1_open != 0)
-                cur_bits += cur_k1_open * (alpha);
-            if (cur_k1_open + cur_k2_close != block_size)
-                cur_bits += (block_size - cur_k1_open - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_open - 2);
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_open;
-                final_k_end_value = k_end_value_close;
-            }
-            // upper outliers:  x_max -1
-            cur_k2_close += gamma_count_list[1];
-            cur_k2_close += gamma_box_count_list[0];
-            k_end_value_close = max_delta_value-1;
-            cur_bits=cur_k2_close;
-            cur_bits += Math.min((cur_k1_close + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_close);
-            if (cur_k1_close != 0)
-                cur_bits += cur_k1_close * (alpha + 1);
-            if (cur_k1_close + cur_k2_close != block_size)
-                cur_bits += (block_size - cur_k1_close - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_close - 2);
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_close;
-                final_k_end_value = k_end_value_close;
-            }
-
-            cur_k1_open = cur_k1_close - alpha_count_list[alpha+1];
-            k_start_value_open = k_start_value_close - 1;
-            cur_bits=cur_k2_close;
-            cur_bits += Math.min((cur_k1_open + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_open + cur_k2_close);
-            if (cur_k1_open != 0)
-                cur_bits += cur_k1_open * (alpha);
-            if (cur_k1_open + cur_k2_close != block_size)
-                cur_bits += (block_size - cur_k1_open - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_open - 2);
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value_open;
-                final_k_end_value = k_end_value_close;
-            }
-            // upper outliers:  x_max -2^gamma
-            for (int gamma = 1;  gamma<=gamma_size;gamma++){
-                int flag = 0;
-                k_end_value_close = max_delta_value - (int) pow(2,gamma);
-                cur_bits = 0;
-                int pow_2_gamma_i = gamma_count_list[gamma+1];
-                int pow_2_gamma_i_1_to_2_gamma_i = gamma_box_count_list[gamma];
-                cur_k2_close += pow_2_gamma_i;
-                cur_k2_close += pow_2_gamma_i_1_to_2_gamma_i;
-                cur_bits += Math.min((cur_k1_close + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_close);
-                if (cur_k1_close != 0)
-                    cur_bits += cur_k1_close * (alpha + 1);
-                if (cur_k1_close + cur_k2_close != block_size)
-                    cur_bits += (block_size - cur_k1_close - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_close - 2);
-                if (cur_k2_close != 0)
-                    cur_bits += cur_k2_close * (gamma + 1);
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    flag = 1;
-                }
-
-                //C2 k1open k2open
-                cur_bits = 0;
-                 cur_k1_open = cur_k1_close - alpha_count_list[alpha+1];
-                int cur_k2_open = cur_k2_close - gamma_count_list[gamma+1];
-                 k_start_value_open = k_start_value_close - 1;
-                int k_end_value_open = k_end_value_close + 1;
-                cur_bits += Math.min((cur_k1_open + cur_k2_open) * getBitWith(block_size-1), block_size + cur_k1_open + cur_k2_open);
-                if (cur_k1_open != 0)
-                    cur_bits += cur_k1_open * alpha;
-                if (cur_k1_open + cur_k2_open != block_size)
-                    cur_bits += (block_size - cur_k1_open - cur_k2_open) * getBitWith(k_end_value_open - k_start_value_open - 2);
-                if (cur_k2_open != 0)
-                    cur_bits += cur_k2_open * gamma;
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    flag = 2;
-                }
-
-                //C3 k1 open k2 close
-                cur_bits = 0;
-                cur_bits += Math.min((cur_k1_open + cur_k2_close) * getBitWith(block_size-1), block_size + cur_k1_open + cur_k2_close);
-                if (cur_k1_open != 0)
-                    cur_bits += cur_k1_open * alpha;
-                if (cur_k1_open + cur_k2_close != block_size)
-                    cur_bits += (block_size - cur_k1_open - cur_k2_close) * getBitWith(k_end_value_close - k_start_value_open - 2);
-                if (cur_k2_close != 0)
-                    cur_bits += cur_k2_close * (gamma + 1);
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    flag = 3;
-                }
-
-                //C4 k1 close k2 open
-                cur_bits = 0;
-                cur_bits += Math.min((cur_k1_close + cur_k2_open) * getBitWith(block_size-1), block_size + cur_k1_close + cur_k2_open);
-                if (cur_k1_close != 0)
-                    cur_bits += cur_k1_close * (alpha + 1);
-                if (cur_k1_close + cur_k2_open != block_size)
-                    cur_bits += (block_size - cur_k1_close - cur_k2_open) * getBitWith(k_end_value_open - k_start_value_close - 2);
-                if (cur_k2_open != 0)
-                    cur_bits += cur_k2_open * gamma;
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    flag = 4;
-                }
-                if(flag == 1){
-                    final_k_start_value = k_start_value_close;
-                    final_k_end_value = k_end_value_close;
-                } else if (flag == 2) {
-                    final_k_start_value = k_start_value_open;
-                    final_k_end_value = k_end_value_open;
-                } else if (flag == 3) {
-                    final_k_start_value = k_start_value_open;
-                    final_k_end_value = k_end_value_close;
-                } else if (flag == 4) {
-                    final_k_start_value = k_start_value_close;
-                    final_k_end_value = k_end_value_open;
-                }
-
-            }
-        }
-        encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_k_end_value, max_delta_value,
-                min_delta, encode_pos , cur_byte);
-
-        return encode_pos;
-    }
-
-
-    public static int BOSEncoder(
-            int[] data, int block_size, byte[] encoded_result) {
-        block_size++;
-
-        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;
-
-        for (int i = 0; i < block_num; i++) {
-            encode_pos =  BOSBlockEncoder(data, i, block_size, block_size,encode_pos,encoded_result);
-        }
-
-        int remaining_length = length_all - block_num * block_size;
-        if (remaining_length <= 3) {
-            for (int i = remaining_length; i > 0; i--) {
-                int2Bytes(data[data.length - i], encode_pos, encoded_result);
-                encode_pos += 4;
-            }
-
-        }
-        else {
-
-            int start = block_num * block_size;
-            int remaining = length_all-start;
-
-
-            encode_pos = BOSBlockEncoder(data, block_num, block_size,remaining, encode_pos,encoded_result);
-
-        }
-
-
-        return encode_pos;
-    }
-
-    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
-
-
-        int k_byte = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-        int k1_byte = (int) (k_byte % pow(2, 16));
-        int k1 = k1_byte / 2;
-        int final_alpha = k1_byte % 2;
-
-        int k2 = (int) (k_byte / pow(2, 16));
-
-        int value0 = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-        value_list[value_pos_arr[0]] =value0;
-        value_pos_arr[0] ++;
-
-        int min_delta = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        int left_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-        int right_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal= new ArrayList<>();;
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-
-
-        if (final_alpha == 0) {
-            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
-            for (int i = 0; i < bitmap_bytes; i++) {
-                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
-                decode_pos += 1;
-            }
-            int bitmap_outlier_i = 0;
-            int remaining_bits = 8;
-            int tmp = bitmap_outlier.get(bitmap_outlier_i);
-            bitmap_outlier_i++;
-            int i = 0;
-            while (i < block_size ) {
-                if (remaining_bits > 1) {
-                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
-                    remaining_bits -= 1;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                    if (remaining_bits == 0) {
-                        remaining_bits = 8;
-                        if (bitmap_outlier_i >= bitmap_bytes) break;
-                        tmp = bitmap_outlier.get(bitmap_outlier_i);
-                        bitmap_outlier_i++;
-                    }
-                } else if (remaining_bits == 1) {
-                    int bit_i = tmp & 0x1;
-                    remaining_bits = 8;
-                    if (bitmap_outlier_i >= bitmap_bytes) break;
-                    tmp = bitmap_outlier.get(bitmap_outlier_i);
-                    bitmap_outlier_i++;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                }
-                i++;
-            }
-        } else {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
-            decode_pos = (decode_pos_result_left.get(0));
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
-            decode_pos = (decode_pos_result_right.get(0));
-        }
-
-
-        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
-        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
-
-        decode_pos = decode_pos_normal.get(0);
-        if (k1 != 0) {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
-            decode_pos = decode_pos_result_left.get(0);
-        }
-        if (k2 != 0) {
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
-            decode_pos = decode_pos_result_right.get(0);
-        }
-        int left_outlier_i = 0;
-        int right_outlier_i = 0;
-        int normal_i = 0;
-        int pre_v = value0;
-        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
-
-
-        for (int i = 0; i < block_size; i++) {
-            int current_delta;
-            if (left_outlier_i >= k1) {
-                if (right_outlier_i >= k2) {
-                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta = min_delta + final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
-                    normal_i++;
-                }
-            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
-                current_delta = min_delta + final_left_outlier.get(left_outlier_i);
-                left_outlier_i++;
-            } else {
-
-                if (right_outlier_i >= k2) {
-                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta = min_delta + final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
-                    normal_i++;
-                }
-            }
-
-            pre_v = current_delta + pre_v;
-            value_list[value_pos_arr[0]] = pre_v;
-            value_pos_arr[0]++;
-        }
-        return decode_pos;
-    }
-
-    public static void BOSDecoder(byte[] encoded) {
-
-        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[] value_list = new int[length_all+block_size];
-        block_size--;
-
-        int[] value_pos_arr = new int[1];
-        for (int k = 0; k < block_num; k++) {
-
-
-            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list, block_size,value_pos_arr);
-
-        }
-
-        if (remain_length <= 3) {
-            for (int i = 0; i < remain_length; i++) {
-                int value_end = bytes2Integer(encoded, decode_pos, 4);
-                decode_pos += 4;
-                value_list[value_pos_arr[0]] = value_end;
-                value_pos_arr[0]++;
-            }
-        } else {
-            remain_length --;
-            BOSBlockDecoder(encoded, decode_pos, value_list, remain_length, value_pos_arr);
-        }
-    }
-
-    @Test
-    public void BWSTest() throws IOException {
-        String parent_dir = "/Users/xiaojinzhao/Desktop/encoding-outlier/"; // your data path
-        String output_parent_dir = parent_dir + "vldb/compression_ratio/bws";
-        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<>();
-        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");
-
-        for (String value : dataset_name) {
-            input_path_list.add(input_parent_dir + value);
-            dataset_block_size.add(1024);
-        }
-
-        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(2048);
-        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
-//        dataset_block_size.add(1024);
-        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
-//        dataset_block_size.add(1024);
-        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
-//        dataset_block_size.add(1024);
-
-        int repeatTime2 = 100;
-
-        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
-
-            String inputPath = input_path_list.get(file_i);
-            System.out.println(inputPath);
-            String Output = output_path_list.get(file_i);
-
-            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<Integer> data1 = new ArrayList<>();
-                ArrayList<Integer> data2 = new ArrayList<>();
-
-
-                loader.readHeaders();
-                while (loader.readRecord()) {
-                    data1.add(Integer.valueOf(loader.getValues()[0]));
-                    data2.add(Integer.valueOf(loader.getValues()[1]));
-                }
-                inputStream.close();
-                int[] data2_arr = new int[data1.size()];
-                for(int i = 0;i<data2.size();i++){
-                    data2_arr[i] = data2.get(i);
-                }
-                byte[] encoded_result = new byte[data2_arr.length*4];
-                long encodeTime = 0;
-                long decodeTime = 0;
-                double ratio = 0;
-                double compressed_size = 0;
-
-
-                int length = 0;
-
-                long s = System.nanoTime();
-                for (int repeat = 0; repeat < repeatTime2; repeat++) {
-                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
-                }
-
-                long e = System.nanoTime();
-                encodeTime += ((e - s) / repeatTime2);
-                compressed_size += length;
-                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
-                ratio += ratioTmp;
-                s = System.nanoTime();
-                for (int repeat = 0; repeat < repeatTime2; repeat++)
-                    BOSDecoder(encoded_result);
-                e = System.nanoTime();
-                decodeTime += ((e - s) / repeatTime2);
-
-
-                String[] record = {
-                        f.toString(),
-                        "TS_2DIFF+BWS",
-                        String.valueOf(encodeTime),
-                        String.valueOf(decodeTime),
-                        String.valueOf(data1.size()),
-                        String.valueOf(compressed_size),
-                        String.valueOf(ratio)
-                };
-                writer.writeRecord(record);
-                System.out.println(ratio);
-
-            }
-            writer.close();
-
-        }
-    }
-
-    @Test
-    public void BOSVaryBlockSize() throws IOException {
-        String parent_dir = "/Users/xiaojinzhao/Desktop/encoding-outlier/"; // your data path
-        String output_parent_dir = parent_dir + "vldb/compression_ratio/block_size_bws";
-        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<>();
-        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");
-
-        for (String value : dataset_name) {
-            input_path_list.add(input_parent_dir + value);
-        }
-
-        output_path_list.add(output_parent_dir + "/CS-Sensors_ratio.csv"); // 0
-        output_path_list.add(output_parent_dir + "/Metro-Traffic_ratio.csv");// 1
-        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
-
-        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
-
-        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
-
-        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
-
-        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
-
-        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
-
-        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
-
-        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
-
-        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
-
-        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
-
-        int repeatTime2 = 500;
-        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
-
-            String inputPath = input_path_list.get(file_i);
-            System.out.println(inputPath);
-            String Output = output_path_list.get(file_i);
-
-
-            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",
-                    "Block 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<Integer> data1 = new ArrayList<>();
-                ArrayList<Integer> data2 = new ArrayList<>();
-
-
-                loader.readHeaders();
-
-                while (loader.readRecord()) {
-                    data1.add(Integer.valueOf(loader.getValues()[0]));
-                    data2.add(Integer.valueOf(loader.getValues()[1]));
-                }
-                inputStream.close();
-                int[] data2_arr = new int[data1.size()];
-                for(int i = 0;i<data2.size();i++){
-                    data2_arr[i] = data2.get(i);
-                }
-                byte[] encoded_result = new byte[data2_arr.length*4];
-
-                for (int block_size_i = 13; block_size_i > 4; block_size_i--) {
-                    int block_size = (int) Math.pow(2, block_size_i);
-                    System.out.println(block_size);
-                    long encodeTime = 0;
-                    long decodeTime = 0;
-                    double ratio = 0;
-                    double compressed_size = 0;
-
-
-                    long s = System.nanoTime();
-                    for (int repeat = 0; repeat < repeatTime2; repeat++) {
-                        compressed_size = BOSEncoder(data2_arr, block_size, encoded_result);
-                    }
-
-                    long e = System.nanoTime();
-                    encodeTime += ((e - s) / repeatTime2);
-                    double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
-                    ratio += ratioTmp;
-                    s = System.nanoTime();
-                    for (int repeat = 0; repeat < repeatTime2; repeat++)
-                        BOSDecoder(encoded_result);
-                    e = System.nanoTime();
-                    decodeTime += ((e - s) / repeatTime2);
-
-                    String[] record = {
-                            f.toString(),
-                            "TS_2DIFF+BOS-L",
-                            String.valueOf(encodeTime),
-                            String.valueOf(decodeTime),
-                            String.valueOf(data1.size()),
-                            String.valueOf(compressed_size),
-                            String.valueOf(block_size_i),
-                            String.valueOf(ratio)
-                    };
-                    writer.writeRecord(record);
-                    System.out.println(ratio);
-
-                }
-
-            }
-            writer.close();
-
-        }
-    }
-
-}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSMImproveTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSMImproveTest.java
new file mode 100644
index 0000000..e218148
--- /dev/null
+++ b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSMImproveTest.java
@@ -0,0 +1,3016 @@
+package org.apache.iotdb.tsfile.encoding;
+
+import com.csvreader.CsvReader;
+import com.csvreader.CsvWriter;
+import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
+import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
+import java.nio.channels.Channels;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
+import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
+import org.apache.iotdb.tsfile.compress.ICompressor;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.junit.Test;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import static java.lang.Math.*;
+import static org.apache.iotdb.tsfile.constant.TestConstant.random;
+
+public class TSDIFFBOSMImproveTest {
+
+    public static long combine2Int(int int1, int int2) {
+        return ((long) int1 << 32) | (int2 & 0xFFFFFFFFL);
+    }
+
+    public static int getTime(long long1) {
+        return ((int) (long1 >> 32));
+    }
+
+    public static int getValue(long long1) {
+        return ((int) (long1));
+    }
+
+    public static int getCount(long long1, int mask) {
+        return ((int) (long1 & mask));
+    }
+    public static int getUniqueValue(long long1, int left_shift) {
+        return ((int) ((long1) >> left_shift));
+    }
+
+    public static int getBitWith(int num) {
+        if (num == 0) return 1;
+        else return 32 - Integer.numberOfLeadingZeros(num);
+    }
+
+    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 int[] getAbsDeltaTsBlock(
+            int[] ts_block,
+            int[] min_delta,
+            int supple_length) {
+        int block_size = ts_block.length-1;
+        int[] ts_block_delta = new int[ts_block.length+supple_length-1];
+
+
+        int value_delta_min = Integer.MAX_VALUE;
+        int value_delta_max = Integer.MIN_VALUE;
+        for (int i = 0; i < block_size; i++) {
+
+            int epsilon_v = ts_block[i+1] - ts_block[i];
+
+            if (epsilon_v < value_delta_min) {
+                value_delta_min = epsilon_v;
+            }
+            if (epsilon_v > value_delta_max) {
+                value_delta_max = epsilon_v;
+            }
+
+        }
+        min_delta[0] = (ts_block[0]);
+        min_delta[1] = (value_delta_min);
+        min_delta[2] = (value_delta_max-value_delta_min);
+
+        for (int i = 0; i  < block_size; i++) {
+            int epsilon_v = ts_block[i+1] - value_delta_min - ts_block[i];
+            ts_block_delta[i] = epsilon_v;
+        }
+        for(int i = block_size;i<block_size+supple_length;i++){
+            ts_block_delta[i] = 0;
+        }
+        return ts_block_delta;
+    }
+
+    public static int[] getAbsDeltaTsBlock(
+            int[] ts_block,
+            int i,
+            int block_size,
+            int remaining,
+            int[] min_delta) {
+        int[] ts_block_delta = new int[remaining-1];
+
+        int value_delta_min = Integer.MAX_VALUE;
+        int value_delta_max = Integer.MIN_VALUE;
+        int base = i*block_size+1;
+        int end = i*block_size+remaining;
+
+        int tmp_j_1 = ts_block[base-1];
+        min_delta[0] =tmp_j_1;
+        int j = base;
+        int tmp_j;
+
+        while(j<end){
+            tmp_j = ts_block[j];
+            int epsilon_v = tmp_j - tmp_j_1;
+            ts_block_delta[j-base] = epsilon_v;
+            if (epsilon_v < value_delta_min) {
+                value_delta_min = epsilon_v;
+            }
+            if (epsilon_v > value_delta_max) {
+                value_delta_max = epsilon_v;
+            }
+            tmp_j_1 = tmp_j;
+            j++;
+        }
+        j = 0;
+        end = remaining -1;
+        while(j<end){
+            ts_block_delta[j] = ts_block_delta[j] - value_delta_min;
+            j++;
+        }
+
+        min_delta[1] = value_delta_min;
+        min_delta[2] = (value_delta_max-value_delta_min);
+
+
+        return ts_block_delta;
+    }
+
+    public static int encodeOutlier2Bytes(
+            ArrayList<Integer> ts_block_delta,
+            int bit_width,
+            int encode_pos,  byte[] encoded_result) {
+
+        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
+
+        int n_k = ts_block_delta.size();
+        int n_k_b = n_k / 8;
+        long cur_remaining = 0; // encoded int
+        int cur_number_bits = 0; // the bit width used of encoded int
+        for (int i = n_k_b * 8; i < n_k; i++) {
+            long cur_value = ts_block_delta.get(i);
+            int cur_bit_width = bit_width; // remaining bit width of current value
+
+            if (cur_number_bits + bit_width >= 32) {
+                cur_remaining <<= (32 - cur_number_bits);
+                cur_bit_width = bit_width - 32 + cur_number_bits;
+                cur_remaining += ((cur_value >> cur_bit_width));
+                long2intBytes(cur_remaining,encode_pos,encoded_result);
+                encode_pos += 4;
+                cur_remaining = 0;
+                cur_number_bits = 0;
+            }
+
+            cur_remaining <<= cur_bit_width;
+            cur_number_bits += cur_bit_width;
+            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width)); //
+        }
+        cur_remaining <<= (32 - cur_number_bits);
+        long2intBytes(cur_remaining,encode_pos,encoded_result);
+        encode_pos += 4;
+        return encode_pos;
+
+    }
+
+
+    public static ArrayList<Integer> decodeOutlier2Bytes(
+            byte[] encoded,
+            int decode_pos,
+            int bit_width,
+            int length,
+            ArrayList<Integer> encoded_pos_result
+    ) {
+
+        int n_k_b = length / 8;
+        int remaining = length - n_k_b * 8;
+        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
+        decode_pos += n_k_b * bit_width;
+
+        ArrayList<Long> int_remaining = new ArrayList<>();
+        int int_remaining_size = remaining * bit_width / 32 + 1;
+        for (int j = 0; j < int_remaining_size; j++) {
+            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
+            decode_pos += 4;
+        }
+
+        int cur_remaining_bits = 32; // remaining bit width of current value
+        long cur_number = int_remaining.get(0);
+        int cur_number_i = 1;
+        for (int i = n_k_b * 8; i < length; i++) {
+            if (bit_width < cur_remaining_bits) {
+                int tmp = (int) (cur_number >> (32 - bit_width));
+                result_list.add(tmp);
+                cur_number <<= bit_width;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits -= bit_width;
+            } else {
+                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
+                int remain_bits = bit_width - cur_remaining_bits;
+                tmp <<= remain_bits;
+
+                cur_number = int_remaining.get(cur_number_i);
+                cur_number_i++;
+                tmp += (int) (cur_number >> (32 - remain_bits));
+                result_list.add(tmp);
+                cur_number <<= remain_bits;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits = 32 - remain_bits;
+            }
+        }
+        encoded_pos_result.add(decode_pos);
+        return result_list;
+    }
+    private static int BOSEncodeBits(int[] ts_block_delta,
+                                     int final_k_start_value,
+                                     int final_x_l_plus,
+                                     int final_k_end_value,
+                                     int final_x_u_minus,
+                                     int max_delta_value,
+                                     int[] min_delta,
+                                     int encode_pos,
+                                     byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        int k1 = 0;
+        int k2 = 0;
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+                final_normal.add(cur_value - final_x_l_plus);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+
+        if(k1==0 && k2==0){
+            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+            encode_pos += 1;
+
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//            return encode_pos;
+        }
+        else{
+            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+            encode_pos += 4;
+            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+            encode_pos += 4;
+
+            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+            encode_pos += 1;
+            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+            encode_pos += 1;
+            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+            encode_pos += 1;
+            if (final_alpha == 0) { // 0
+
+                for (int i : bitmap_outlier) {
+
+                    intByte2Bytes(i,encode_pos,cur_byte);
+                    encode_pos += 1;
+                }
+            } else {
+                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            }
+        }
+
+
+//        if(k1+k2!=block_size)
+        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+        if (k1 != 0)
+            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+        if (k2 != 0)
+            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+        return encode_pos;
+
+    }
+
+    private static void calculateBits(int k1, int k2, int block_size, int alpha, int gamma, int k1_start, int k2_end, int min_bits, int[] result){
+        int cur_bits = 0;
+        cur_bits += Math.min((k1 + k2) * getBitWith(block_size - 1), block_size + k1 + k2);
+        if(k1!=0)
+            cur_bits += k1*alpha;
+        if (k1 + k2 != block_size)
+            cur_bits += (block_size - k1 - k2) *
+                    getBitWith(k2_end -k1_start - 2);
+        if(k2!=0)
+            cur_bits += k2 * gamma;
+        if (cur_bits < min_bits) {
+            result[0] = cur_bits;
+            result[1] = k1_start;
+            result[2] = k2_end;
+        }
+    }
+
+
+    public static int findMedian(int[] arr) {
+        if (arr == null || arr.length == 0) {
+            throw new IllegalArgumentException("数组不能为空");
+        }
+        int n = arr.length;
+        if (n > 400){
+            return quickSelect(arr, 0, 99, 50);
+        }else if (n > 100){
+            return quickSelect(arr, 0, (n - 1)/4, n / 8);
+        }else {
+            return quickSelect(arr, 0, n - 1, n / 2);
+        }
+    }
+
+//    private static int quickSelect(int[] arr, int left, int right, int k){
+//        int pivotV=arr[left+random.nextInt(right-left+1)],tmpV;
+//        int posEqual=left,posSmaller=left; // a[left,posEqual): = pivotV; a[posEqual,posSmaller): < pivotV
+//        for(int i=left;i<=right;i++){
+//            if(arr[i]==pivotV){
+//                tmpV=arr[i];
+//                arr[i]=arr[posSmaller];
+//                arr[posSmaller]=arr[posEqual];
+//                arr[posEqual]=tmpV;
+//                posEqual++;
+//                posSmaller++;
+//            }else
+//            if(arr[i]<pivotV){
+//                tmpV=arr[posSmaller];
+//                arr[posSmaller]=arr[i];
+//                arr[i]=tmpV;
+//                posSmaller++;
+//            }
+//        }
+//        if(k+(posEqual-left)<=posSmaller-1)return quickSelect(arr,posEqual,posSmaller-1,k+(posEqual-left));
+//        else if(k<=posSmaller-1)return pivotV;
+//        else return quickSelect(arr,posSmaller,right,k);
+//    }
+    private static int quickSelect(int[] arr, int left, int right, int k) {
+        if (left == right) {
+            return arr[left];
+        }
+        if (areAllElementsEqual(arr, left, right)) {
+            return arr[left];
+        }
+        int pivotIndex = left + random.nextInt(right - left + 1);
+        swap(arr, pivotIndex, right);
+
+        pivotIndex = partition(arr, left, right);
+        if (abs(pivotIndex - k) < (right - left)/6) {
+            return arr[k];
+        } else if (k <= pivotIndex - (right - left)/6) {
+            return quickSelect(arr, left, pivotIndex - 1, k);
+        } else {
+            return quickSelect(arr, pivotIndex + 1, right, k);
+        }
+    }
+    private static boolean areAllElementsEqual(int[] arr, int left, int right) {
+        for (int i = left + 1; i <= right; i++) {
+            if (arr[i] != arr[left]) {
+                return false;
+            }
+        }
+        return true;
+    }
+    private static int partition(int[] arr, int left, int right) {
+        int pivot = arr[right];
+        int i = left;
+        for (int j = left; j < right; j++) {
+            if (arr[j] <= pivot) {
+                swap(arr, i, j);
+                i++;
+            }
+        }
+        swap(arr, i, right);
+        return i;
+    }
+
+    private static void swap(int[] arr, int i, int j) {
+        int temp = arr[i];
+        arr[i] = arr[j];
+        arr[j] = temp;
+    }
+
+    public static long compress(byte[] data) throws IOException {
+        File file = new File("example.7z");
+        file.createNewFile();
+        Path path = Paths.get("example.7z");
+        SeekableByteChannel channel = Files.newByteChannel(path, StandardOpenOption.READ, StandardOpenOption.WRITE);
+        SevenZOutputFile szof = new SevenZOutputFile(channel);
+        SevenZArchiveEntry entry = szof.createArchiveEntry(null, "entryName");
+        szof.putArchiveEntry(entry);
+        szof.write(data);
+        szof.closeArchiveEntry();
+        return channel.size();
+    }
+
+    public static int EncodeBits(int num,
+                                 int bit_width,
+                                 int encode_pos,
+                                 byte[] cur_byte,
+                                 int[] bit_index_list){
+        // 找到要插入的位的索引
+        int bit_index = bit_index_list[0] ;//cur_byte[encode_pos + 1];
+
+        // 计算数值的起始位位置
+        int remaining_bits = bit_width;
+
+        while (remaining_bits > 0) {
+            // 计算在当前字节中可以使用的位数
+            int available_bits = bit_index;
+            int bits_to_write = Math.min(available_bits, remaining_bits);
+
+            // 更新 bit_index
+            bit_index = available_bits - bits_to_write;
+
+            // 计算要写入的位的掩码和数值
+            int mask = (1 << bits_to_write) - 1;
+            int bits = (num >> (remaining_bits - bits_to_write)) & mask;
+
+            // 写入到当前位置
+            cur_byte[encode_pos] &= (byte) ~(mask << bit_index); // 清除对应位置的位
+            cur_byte[encode_pos] |= (byte) (bits << bit_index);
+
+            // 更新位宽和数值
+            remaining_bits -= bits_to_write;
+            if (bit_index == 0) {
+                bit_index = 8;
+                encode_pos++;
+            }
+        }
+        bit_index_list[0] = bit_index;
+//        cur_byte[encode_pos + 1] = (byte) bit_index;
+        return encode_pos;
+    }
+    private static int BOSEncodeBitsImprove(int[] ts_block_delta,
+                                            int final_k_start_value,
+                                            int final_x_l_plus,
+                                            int final_k_end_value,
+                                            int final_x_u_minus,
+                                            int max_delta_value,
+                                            int[] min_delta,
+                                            int encode_pos,
+                                            byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        int k1 = 0;
+        int k2 = 0;
+
+
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+//                encode_pos = EncodeBits(cur_value,left_bit_width,encode_pos,cur_byte);
+//                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+//                encode_pos = EncodeBits(cur_value- final_k_end_value,right_bit_width,encode_pos,cur_byte);
+//                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+//                final_normal.add(cur_value - final_x_l_plus);
+//                encode_pos = EncodeBits(cur_value- final_x_l_plus,right_bit_width,encode_pos,cur_byte);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+        int[] bit_index_list = new int[1];
+        bit_index_list[0] = 8;
+
+        if(final_k_start_value<0 && final_k_end_value > max_delta_value){
+//            int bit_width_final= getBitWith(final_x_u_minus - final_x_l_plus);
+//            cur_byte[encode_pos+1] = 8;
+            for (int cur_value : ts_block_delta) {
+                encode_pos = EncodeBits(cur_value, bit_width_final, encode_pos, cur_byte, bit_index_list);
+//                final_normal.add(cur_value);
+            }
+            if(bit_index_list[0] != 8){
+                encode_pos ++;
+            }
+//            cur_byte[encode_pos+1] = 0;
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+            return encode_pos;
+        }
+
+
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+        int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(final_k_end_value,encode_pos,cur_byte);
+        encode_pos += 4;
+
+//        bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//        encode_pos += 1;
+        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        if (final_alpha == 0) { // 0
+
+            for (int i : bitmap_outlier) {
+
+                intByte2Bytes(i,encode_pos,cur_byte);
+                encode_pos += 1;
+            }
+        } else {
+            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+        }
+//        cur_byte[encode_pos+1] = 8;
+//        bit_index_list[0] = 8;
+        for (int cur_value : ts_block_delta) {
+            if (cur_value <= final_k_start_value) {
+                encode_pos = EncodeBits(cur_value, left_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else if (cur_value >= final_k_end_value) {
+                encode_pos = EncodeBits(cur_value - final_k_end_value, right_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else {
+                encode_pos = EncodeBits(cur_value - final_x_l_plus, bit_width_final, encode_pos, cur_byte,bit_index_list);
+            }
+        }
+        if(bit_index_list[0] != 8){
+            encode_pos ++;
+        }
+
+//        cur_byte[encode_pos+1] = 0;
+
+//        if(k1==0 && k2==0){
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//
+//
+//        }
+//        else{
+//            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+//            encode_pos += 4;
+//            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+//            encode_pos += 4;
+//
+//            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            if (final_alpha == 0) { // 0
+//
+//                for (int i : bitmap_outlier) {
+//
+//                    intByte2Bytes(i,encode_pos,cur_byte);
+//                    encode_pos += 1;
+//                }
+//            } else {
+//                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//            }
+//        }
+
+
+//        if(k1+k2!=block_size)
+//        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//        if (k1 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+//        if (k2 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+        return encode_pos;
+
+    }
+
+    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size, int remaining, int encode_pos, byte[] cur_byte) {
+
+        int[] min_delta = new int[3];
+        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
+//        System.out.println(Arrays.toString(ts_block_delta));
+
+        block_size = remaining - 1;
+        int max_delta_value = min_delta[2];
+
+
+        int max_bit_width = getBitWith(max_delta_value) + 1;
+
+
+        int[] findMedianArray = new int[block_size];
+        System.arraycopy(ts_block_delta, 0, findMedianArray, 0, block_size);
+
+        int median = findMedian(findMedianArray);
+
+
+
+        //        int xl=  median;
+        //        int xu = median;
+        // xl = 2 median - xu
+        // xl = xu - 2 ^ beta
+        int left_number = 0;
+        int right_number = 0;
+
+        int length_outlier = block_size;
+//        for(int value:findMedianArray){
+//            if(value <=median) left_number++;
+//            if (value >= median)  right_number ++;
+//        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = (getBitWith(final_k_end_value - final_k_start_value - 2) * (block_size));
+//        min_bits +=;
+
+
+        int[] count_left = new int[max_bit_width];
+        int[] count_right = new int[max_bit_width];
+        int count_0 = 0;
+
+
+        for(int i=0;i<length_outlier;i++){
+            int cur_value = ts_block_delta[i];
+            if(cur_value > median){
+                int beta = getBitWith(cur_value - median) ;
+                count_right[beta] ++;
+            } else if (cur_value < median) {
+                int beta = getBitWith(median - cur_value) ;
+                count_left[beta] ++;
+            }else{
+                count_0 ++;
+            }
+        }
+
+
+        for(int beta = max_bit_width - 1; beta > 0 ; beta --){
+            left_number += count_left[beta];
+            right_number += count_right[beta];
+            int pow_beta = 1 << (beta-1);
+            int xu = min(max_delta_value+1, median + pow_beta) ;
+            int xl = max(median - pow_beta,-1);
+            int cur_bits = Math.min((left_number + right_number) * getBitWith(block_size - 1), block_size + left_number + right_number);
+            cur_bits += left_number * getBitWith(xl);
+            cur_bits += right_number * getBitWith(max_delta_value - xu);
+            cur_bits += (block_size - left_number - right_number) * getBitWith(xu - xl - 2);
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+
+                final_k_start_value = xl;
+                final_x_l_plus = xl + 1;
+                final_k_end_value = xu;
+                final_x_u_minus = xu -1;
+            }
+
+        }
+//        if(min_bits == bp_cost){
+//
+//        }
+//        else
+//        System.out.println(min_bits/8);
+        encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_x_l_plus, final_k_end_value, final_x_u_minus,
+                max_delta_value, min_delta, encode_pos , cur_byte);
+
+
+        return encode_pos;
+    }
+
+    public static int minNumberIndex(int alpha, int beta, int gamma){
+        if(alpha<beta && beta < gamma){
+            return 1; // prop 4.2
+        } else if (alpha>beta && beta > gamma) {
+            return 2;// prop 4.3
+        } else if (beta<alpha && beta <gamma) {
+            return 3;// prop 4.4
+        }else{
+            return 0; // alpha=beta=gamma
+        }
+    }
+
+    private static void addToArchiveCompression(SevenZOutputFile out, File file, String dir) {
+        String name = dir + File.separator + file.getName();
+        if(dir.equals(".")) {
+            name = file.getName();
+        }
+        if (file.isFile()){
+            SevenZArchiveEntry entry = null;
+            FileInputStream in = null;
+            try {
+                entry = out.createArchiveEntry(file, name);
+                out.putArchiveEntry(entry);
+                in = new FileInputStream(file);
+                byte[] b = new byte[1024];
+                int count = 0;
+                while ((count = in.read(b)) > 0) {
+                    out.write(b, 0, count);
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    out.closeArchiveEntry();
+                    in.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+
+            }
+        } else if (file.isDirectory()) {
+            File[] children = file.listFiles();
+            if (children != null){
+                for (File child : children){
+                    addToArchiveCompression(out, child, name);
+                }
+            }
+        } else {
+            System.out.println(file.getName() + " is not supported");
+        }
+    }
+
+    public static int BOSEncoder(
+            int[] data, int block_size, byte[] encoded_result) {
+        block_size++;
+
+        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;
+
+
+//        for (int i = 0; i < 1; i++) {
+        for (int i = 0; i < block_num; i++) {
+//            int start_encode_pos = encode_pos;
+            encode_pos =  BOSBlockEncoder(data, i, block_size, block_size,encode_pos,encoded_result);
+//            System.out.println(encode_pos-start_encode_pos);
+//            System.out.println("------------------------------------------");
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        }
+        else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+
+
+            encode_pos = BOSBlockEncoder(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+        }
+
+
+        return encode_pos;
+    }
+
+    private static int BOSBlockEncoderImprove(int[] ts_block, int block_i, int block_size, int remaining, int encode_pos, byte[] cur_byte) {
+
+        int[] min_delta = new int[3];
+        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
+//        System.out.println(Arrays.toString(ts_block_delta));
+
+        block_size = remaining - 1;
+        int max_delta_value = min_delta[2];
+
+
+        int max_bit_width = getBitWith(max_delta_value) + 1;
+
+
+        int[] findMedianArray = new int[block_size];
+        System.arraycopy(ts_block_delta, 0, findMedianArray, 0, block_size);
+
+        int median = findMedian(findMedianArray);
+
+
+
+        //        int xl=  median;
+        //        int xu = median;
+        // xl = 2 median - xu
+        // xl = xu - 2 ^ beta
+        int left_number = 0;
+        int right_number = 0;
+
+        int length_outlier = block_size;
+//        for(int value:findMedianArray){
+//            if(value <=median) left_number++;
+//            if (value >= median)  right_number ++;
+//        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = (getBitWith(final_k_end_value - final_k_start_value - 2) * (block_size));
+//        min_bits +=;
+
+
+        int[] count_left = new int[max_bit_width];
+        int[] count_right = new int[max_bit_width];
+        int count_0 = 0;
+
+
+        for(int i=0;i<length_outlier;i++){
+            int cur_value = ts_block_delta[i];
+            if(cur_value > median){
+                int beta = getBitWith(cur_value - median) ;
+                count_right[beta] ++;
+            } else if (cur_value < median) {
+                int beta = getBitWith(median - cur_value) ;
+                count_left[beta] ++;
+            }else{
+                count_0 ++;
+            }
+        }
+
+
+        for(int beta = max_bit_width - 1; beta > 0 ; beta --){
+            left_number += count_left[beta];
+            right_number += count_right[beta];
+            int pow_beta = 1<< (beta-1);
+            int xu = min(max_delta_value+1, median + pow_beta) ;
+            int xl = max(median - pow_beta,-1);
+            int cur_bits = Math.min((left_number + right_number) * getBitWith(block_size - 1), block_size + left_number + right_number);
+            cur_bits += left_number * getBitWith(xl);
+            cur_bits += right_number * getBitWith(max_delta_value - xu);
+            cur_bits += (block_size - left_number - right_number) * getBitWith(xu - xl - 2);
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+
+                final_k_start_value = xl;
+                final_x_l_plus = xl + 1;
+                final_k_end_value = xu;
+                final_x_u_minus = xu -1;
+            }
+
+        }
+//        if(min_bits == bp_cost){
+//
+//        }
+//        else
+//        System.out.println(min_bits/8);
+        encode_pos = BOSEncodeBitsImprove(ts_block_delta,  final_k_start_value, final_x_l_plus, final_k_end_value, final_x_u_minus,
+                max_delta_value, min_delta, encode_pos , cur_byte);
+
+
+        return encode_pos;
+    }
+
+    public static int BOSEncoderImprove(
+            int[] data, int block_size, byte[] encoded_result) {
+        block_size++;
+
+        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;
+//        int[] test_block = new int[block_size];
+//        System.arraycopy(data, 0, test_block, 0, block_size);
+//        System.out.println(Arrays.toString(test_block));
+//        for (int i = 0; i < 1; i++) {
+        for (int i = 0; i < block_num; i++) {
+//            int start_encode_pos = encode_pos;
+            encode_pos =  BOSBlockEncoderImprove(data, i, block_size, block_size,encode_pos,encoded_result);
+//            System.out.println(encode_pos-start_encode_pos);
+//            System.out.println("------------------------------------------");
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        }
+        else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+
+
+            encode_pos = BOSBlockEncoderImprove(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+        }
+
+
+        return encode_pos;
+    }
+
+    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+        int value0 = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        value_list[value_pos_arr[0]] =value0;
+        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        if(k1!=0 || k2 != 0){
+             final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+            decode_pos += 4;
+
+            final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+            decode_pos += 4;
+
+            bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+
+            left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+            right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+
+            if (final_alpha == 0) {
+                int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
+                for (int i = 0; i < bitmap_bytes; i++) {
+                    bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                    decode_pos += 1;
+                }
+                int bitmap_outlier_i = 0;
+                int remaining_bits = 8;
+                int tmp = bitmap_outlier.get(bitmap_outlier_i);
+                bitmap_outlier_i++;
+                int i = 0;
+                while (i < block_size ) {
+                    if (remaining_bits > 1) {
+                        int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_i == 1) {
+                            int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                            remaining_bits -= 1;
+                            if (bit_left_right == 1) {
+                                final_left_outlier_index.add(i);
+                            } else {
+                                final_right_outlier_index.add(i);
+                            }
+                        }
+                        if (remaining_bits == 0) {
+                            remaining_bits = 8;
+                            if (bitmap_outlier_i >= bitmap_bytes) break;
+                            tmp = bitmap_outlier.get(bitmap_outlier_i);
+                            bitmap_outlier_i++;
+                        }
+                    } else if (remaining_bits == 1) {
+                        int bit_i = tmp & 0x1;
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                        if (bit_i == 1) {
+                            int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                            remaining_bits -= 1;
+                            if (bit_left_right == 1) {
+                                final_left_outlier_index.add(i);
+                            } else {
+                                final_right_outlier_index.add(i);
+                            }
+                        }
+                    }
+                    i++;
+                }
+            } else {
+                ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+                final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
+                decode_pos = (decode_pos_result_left.get(0));
+                ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+                final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
+                decode_pos = (decode_pos_result_right.get(0));
+            }
+        }else {
+            bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+            decode_pos += 1;
+        }
+
+
+
+
+        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+
+        decode_pos = decode_pos_normal.get(0);
+        if (k1 != 0) {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+            decode_pos = decode_pos_result_left.get(0);
+        }
+        if (k2 != 0) {
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+            decode_pos = decode_pos_result_right.get(0);
+        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+
+        for (int i = 0; i < block_size; i++) {
+            int current_delta;
+            if (left_outlier_i >= k1) {
+                if (right_outlier_i >= k2) {
+                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
+                    normal_i++;
+                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
+                    current_delta = min_delta + final_right_outlier.get(right_outlier_i) + final_k_end_value;
+                    right_outlier_i++;
+                } else {
+                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
+                    normal_i++;
+                }
+            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
+                current_delta = min_delta + final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+            } else {
+
+                if (right_outlier_i >= k2) {
+                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
+                    normal_i++;
+                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
+                    current_delta = min_delta + final_right_outlier.get(right_outlier_i) + final_k_end_value;
+                    right_outlier_i++;
+                } else {
+                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
+                    normal_i++;
+                }
+            }
+
+            pre_v = current_delta + pre_v;
+            value_list[value_pos_arr[0]] = pre_v;
+            value_pos_arr[0]++;
+        }
+        return decode_pos;
+    }
+    public static int DecodeBits(byte[] cur_byte, int bit_width, int[] decode_pos_list) {
+        int decode_pos = decode_pos_list[0];
+        int bit_index = decode_pos_list[1];  //cur_byte[decode_pos + 1];
+        int remaining_bits = bit_width;
+        int num = 0;
+
+        while (remaining_bits > 0) {
+            int available_bits = bit_index;
+            int bits_to_read = Math.min(available_bits, remaining_bits);
+
+            // 计算要读取的位的掩码
+            int mask = (1 << bits_to_read) - 1;
+            int bits = (cur_byte[decode_pos] >> (available_bits - bits_to_read)) & mask;
+
+            // 将读取的位合并到结果中
+            num = (num << bits_to_read) | bits;
+
+            // 更新位宽和 bit_index
+            remaining_bits -= bits_to_read;
+            bit_index = available_bits - bits_to_read;
+
+            if (bit_index == 0) {
+                bit_index = 8;
+                decode_pos++;
+            }
+        }
+        decode_pos_list[0] = decode_pos;
+        decode_pos_list[1] = bit_index;
+
+        return num;
+    }
+    public static int BOSBlockDecoderImprove(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+        int value0 = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        value_list[value_pos_arr[0]] =value0;
+        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        int[] decode_list = new int[2];
+        decode_list[0]= decode_pos;
+        decode_list[1]= 8;
+
+        int valuePos = value_pos_arr[0];
+
+        if(k1==0 && k2==0){
+            int pre_v = value0;
+            for (int i = 0; i < block_size; i++) {
+                int cur_delta = min_delta + DecodeBits(encoded, bit_width_final,  decode_list);
+                pre_v += cur_delta;
+                value_list[valuePos++] = pre_v;
+            }
+            value_pos_arr[0] = valuePos;
+            return decode_list[0];
+        }
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+//        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+//        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+//        bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+//        decode_pos += 1;
+
+        left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+        right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        if (final_alpha == 0) {
+            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
+            for (int i = 0; i < bitmap_bytes; i++) {
+                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                decode_pos += 1;
+            }
+            int bitmap_outlier_i = 0;
+            int remaining_bits = 8;
+            int tmp = bitmap_outlier.get(bitmap_outlier_i);
+            bitmap_outlier_i++;
+            int i = 0;
+            while (i < block_size ) {
+                if (remaining_bits > 1) {
+                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                    remaining_bits -= 1;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                    if (remaining_bits == 0) {
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                    }
+                } else if (remaining_bits == 1) {
+                    int bit_i = tmp & 0x1;
+                    remaining_bits = 8;
+                    if (bitmap_outlier_i >= bitmap_bytes) break;
+                    tmp = bitmap_outlier.get(bitmap_outlier_i);
+                    bitmap_outlier_i++;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                }
+                i++;
+            }
+        } else {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
+            decode_pos = (decode_pos_result_left.get(0));
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
+            decode_pos = (decode_pos_result_right.get(0));
+        }
+
+
+
+
+
+//        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+//        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+//
+//        decode_pos = decode_pos_normal.get(0);
+//        if (k1 != 0) {
+//            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+//            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+//            decode_pos = decode_pos_result_left.get(0);
+//        }
+//        if (k2 != 0) {
+//            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+//            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+//            decode_pos = decode_pos_result_right.get(0);
+//        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+// Precompute constants
+        int normalOffset = min_delta + final_k_start_value;
+        int rightOutlierOffset = min_delta + final_k_end_value;
+
+// Initialize indices and pre-fetch next outlier positions
+        int leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+        int rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+        decode_list[0]= decode_pos;
+//        decode_list[1]= 8;
+        // Use a local variable for the position
+        for (int i = 0; i < block_size; i++) {
+            int currentDelta;
+            if (i == leftOutlierNextIndex) {
+                // Process left outlier
+                currentDelta = min_delta + DecodeBits(encoded, left_bit_width,  decode_list); // final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+                leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+            } else if (i == rightOutlierNextIndex) {
+                // Process right outlier
+                currentDelta = rightOutlierOffset + DecodeBits(encoded, right_bit_width,  decode_list);// final_right_outlier.get(right_outlier_i);
+                right_outlier_i++;
+                rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+            } else {
+                // Process normal value
+                currentDelta = normalOffset + DecodeBits(encoded, bit_width_final,  decode_list);
+                normal_i++;
+            }
+
+            // Update the cumulative value and store it
+            pre_v += currentDelta;
+            value_list[valuePos++] = pre_v;
+        }
+        value_pos_arr[0] = valuePos;
+        if(decode_list[1]!=8){
+            return decode_list[0]+1;
+        }else {
+            return decode_list[0];
+        }
+//        decode_pos = decode_list[0];
+// Update the position in the array
+
+
+//        return decode_pos;
+    }
+
+    public static void BOSDecoder(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        block_size--;
+
+        int[] value_pos_arr = new int[1];
+        for (int k = 0; k < block_num; k++) {
+            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list, block_size,value_pos_arr);
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            remain_length --;
+            BOSBlockDecoder(encoded, decode_pos, value_list, remain_length, value_pos_arr);
+        }
+    }
+    public static void BOSDecoderImprove(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        block_size--;
+
+        int[] value_pos_arr = new int[1];
+        for (int k = 0; k < block_num; k++) {
+
+
+            decode_pos = BOSBlockDecoderImprove(encoded, decode_pos, value_list, block_size,value_pos_arr);
+
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            remain_length --;
+            BOSBlockDecoderImprove(encoded, decode_pos, value_list, remain_length, value_pos_arr);
+        }
+//        int[] test_block = new int[block_size];
+//        System.arraycopy(value_list, 0, test_block, 0, block_size);
+//        System.out.println(Arrays.toString(test_block));
+//        System.out.println(value_list[1000]);
+    }
+
+    @Test
+    public void BOSImproveEncodeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/bos_m_improve";
+//        String output_parent_dir = parent_dir + "icde0802/compression_ratio/test";
+//        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R2O3_lower_outlier_compare/compression_ratio/bos";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+
+//        for (int file_i = 0; file_i < 1; file_i++) {
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f= tempList[1];
+
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "TS_2DIFF+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+
+            }
+            writer.close();
+
+        }
+    }
+    @Test
+    public void BOSImproveDecodeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R1O4_decode_time/compression_ratio/bos_m";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[2];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "TS_2DIFF+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void BOSPreviousDecodeTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/bos_m";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[2];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoder(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "TS_2DIFF+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void compressBOSTest() throws IOException {
+//        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R3O2_compare_compression/compression_ratio/bos_m_comp";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        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(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 5;
+//        for (int file_i = 8; file_i < 9; file_i++) {
+
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+//        for (int file_i = input_path_list.size()-1; file_i >=0 ; file_i--) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            File file = new File(inputPath);
+            File[] tempList = file.listFiles();
+
+            CsvWriter writer = new CsvWriter(Output, ',', StandardCharsets.UTF_8);
+
+            String[] head = {
+                    "Input Direction",
+                    "Encoding Algorithm",
+//                    "Compress 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<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+                inputStream.close();
+
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                double ratio = 0;
+                double compressed_size = 0;
+                long compressTime = encodeTime;
+                s = System.nanoTime();
+                byte[] compressed = new byte[0];
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    BZip2CompressorOutputStream bzip2Out = new BZip2CompressorOutputStream(baos);
+                    bzip2Out.write(encoded_result);
+                    bzip2Out.finish();
+                    compressed = baos.toByteArray();
+                }
+                e = System.nanoTime();
+                compressTime += ((e - s) / repeatTime2);
+
+                // test compression ratio and compressed size
+                compressed_size += compressed.length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+//                    for (int repeat = 0; repeat < repeatTime2; repeat++)
+//                        BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "BOS+"+ "7-Zip",
+                        String.valueOf(compressTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void compressBOSTest2() throws IOException {
+//        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R3O2_compare_compression/compression_ratio/bos_m_lz4_comp";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        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(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 500;
+//        for (int file_i = 8; file_i < 9; file_i++) {
+        CompressionType[] compressList = {
+                CompressionType.LZ4,
+        };
+
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+//        for (int file_i = input_path_list.size()-1; file_i >=0 ; file_i--) {
+
+            String inputPath = input_path_list.get(file_i);
+//            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            File file = new File(inputPath);
+            File[] tempList = file.listFiles();
+
+            CsvWriter writer = new CsvWriter(Output, ',', StandardCharsets.UTF_8);
+
+            String[] head = {
+                    "Input Direction",
+                    "Encoding Algorithm",
+//                    "Compress 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<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+                inputStream.close();
+
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+
+                for (CompressionType comp : compressList) {
+                    double ratio = 0;
+                    double compressed_size = 0;
+                    long compressTime = encodeTime;
+//                    compressTime += ((e - s) / repeatTime2);
+                    System.out.println(compressTime);
+
+                    s = System.nanoTime();
+                    ICompressor compressor = ICompressor.getCompressor(comp);
+                    byte[] compressed = new byte[0];
+                    for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                        compressed = compressor.compress(encoded_result);
+                    }
+                    e = System.nanoTime();
+                    compressTime += ((e - s) / repeatTime2);
+
+                    System.out.println(compressTime-encodeTime);
+                    // test compression ratio and compressed size
+                    compressed_size += compressed.length;
+                    double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                    ratio += ratioTmp;
+                    s = System.nanoTime();
+//                    for (int repeat = 0; repeat < repeatTime2; repeat++)
+//                        BOSDecoderImprove(encoded_result);
+                    e = System.nanoTime();
+                    decodeTime += ((e - s) / repeatTime2);
+
+
+                    String[] record = {
+                            f.toString(),
+                            "BOS+"+ comp,
+                            String.valueOf(compressTime),
+                            String.valueOf(decodeTime),
+                            String.valueOf(data1.size()),
+                            String.valueOf(compressed_size),
+                            String.valueOf(ratio)
+                    };
+                    writer.writeRecord(record);
+//                    System.out.println(ratio);
+                }
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void ExpTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+//        String output_parent_dir = parent_dir + "icde0802/compression_ratio/exp_test";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R2O3_lower_outlier_compare/compression_ratio/bos";
+        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<>();
+        dataset_name.add("Synthetic_Exp_100");
+        dataset_name.add("Synthetic_Exp_1000");
+        dataset_name.add("Synthetic_Exp_10000");
+        dataset_name.add("Synthetic_Exp_100000");
+        dataset_name.add("Synthetic_Exp_1000000");
+        dataset_name.add("Synthetic_Normal_100");
+        dataset_name.add("Synthetic_Normal_1000");
+        dataset_name.add("Synthetic_Normal_10000");
+        dataset_name.add("Synthetic_Normal_100000");
+        dataset_name.add("Synthetic_Normal_1000000");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        output_path_list.add(output_parent_dir + "/Exp_100.csv"); // 0
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/Exp_1000.csv");// 1
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Exp_10000.csv");// 2
+        output_path_list.add(output_parent_dir + "/Exp_100000.csv");// 2
+        output_path_list.add(output_parent_dir + "/Exp_1000000.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Normal_100.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Normal_1000.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/Normal_10000.csv");//5
+        output_path_list.add(output_parent_dir + "/Normal_100000.csv");//5
+        output_path_list.add(output_parent_dir + "/Normal_1000000.csv");//5
+//        dataset_block_size.add(2048);
+
+        int repeatTime2 = 100;
+
+//        for (int file_i = 0; file_i < 1; file_i++) {
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+                if(f.toString().contains(".DS")) continue;
+//                f= tempList[1];
+
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoderImprove(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "TS_2DIFF+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+
+            }
+            writer.close();
+
+        }
+    }
+
+    @Test
+    public void BOSVaryBlockSize() throws IOException {
+        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+//        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String output_parent_dir = parent_dir + "icde0802/compression_ratio/block_size_bos_m";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/block_size_bos_m";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+        }
+
+        output_path_list.add(output_parent_dir + "/CS-Sensors_ratio.csv"); // 0
+        output_path_list.add(output_parent_dir + "/Metro-Traffic_ratio.csv");// 1
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+
+        int repeatTime2 = 100;
+//        int[] file_i_list = {0,9,10};
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//        for(int file_i :file_i_list){
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+
+            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",
+                    "Block 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<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+
+//                for (int block_size_i = 5; block_size_i < 14; block_size_i++) {
+                for (int block_size_i = 13; block_size_i > 4; block_size_i--) {
+//                for (int block_size_i = 10; block_size_i > 9; block_size_i--) {
+                    int block_size = (int) Math.pow(2, block_size_i);
+                    System.out.println(block_size);
+                    long encodeTime = 0;
+                    long decodeTime = 0;
+                    double ratio = 0;
+                    double compressed_size = 0;
+
+
+                    long s = System.nanoTime();
+                    for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                        compressed_size = BOSEncoderImprove(data2_arr, block_size, encoded_result);
+                    }
+
+                    long e = System.nanoTime();
+                    encodeTime += ((e - s) / repeatTime2);
+                    double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                    ratio += ratioTmp;
+                    s = System.nanoTime();
+                    for (int repeat = 0; repeat < repeatTime2; repeat++)
+                        BOSDecoderImprove(encoded_result);
+                    e = System.nanoTime();
+                    decodeTime += ((e - s) / repeatTime2);
+
+                    String[] record = {
+                            f.toString(),
+                            "TS_2DIFF+BOS-M",
+                            String.valueOf(encodeTime),
+                            String.valueOf(decodeTime),
+                            String.valueOf(data1.size()),
+                            String.valueOf(compressed_size),
+                            String.valueOf(block_size_i),
+                            String.valueOf(ratio)
+                    };
+                    writer.writeRecord(record);
+                    System.out.println(ratio);
+
+                }
+
+            }
+            writer.close();
+
+        }
+    }
+
+
+    @Test
+    public void BOSQueryTest() throws IOException, InterruptedException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R2O2_query_processing/time/bos_m";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 500;
+//        for (int file_i = 1; file_i < 2; file_i++) {
+
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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",
+                    "Insert Time",
+                    "Query Time",
+                    "Points",
+                    "Compressed Size",
+                    "Compression Ratio"
+            };
+            writer.writeRecord(head); // write header to output file
+
+            assert tempList != null;
+
+            for (File f : tempList) {
+//                f=tempList[2];
+                System.out.println(f);
+//                Thread.sleep(5000);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                String file_bin_str = "icde0802/supply_experiment/R2O2_query_processing/time/str_1.bin";
+                long input_time = 0;
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    long start_encode = System.nanoTime();
+                    length =  BOSEncoderImprove(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                    long end_encode = System.nanoTime();
+                    try (FileOutputStream fos = new FileOutputStream(parent_dir +file_bin_str)) {
+                        // 只写入前length个元素
+                        fos.write(encoded_result, 0, length);
+                    } catch (IOException ioe) {
+                        ioe.printStackTrace();
+                    }
+                    long end_io = System.nanoTime();
+                    encodeTime += (end_encode - start_encode);
+                    input_time += (end_io - end_encode);
+                }
+
+
+                long e = System.nanoTime();
+                encodeTime = (encodeTime / repeatTime2);
+                input_time = (input_time / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+
+                long output_time = 0;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++){
+                    long start_io = System.nanoTime();
+
+                    try (FileInputStream fis = new FileInputStream(parent_dir +file_bin_str)) {
+                        // 读取数据到byte数组中
+                        int bytesRead = fis.read(encoded_result);
+//                        System.out.println("Number of bytes read: " + bytesRead);
+                    } catch (IOException ioe) {
+                        ioe.printStackTrace();
+                    }
+                    long start_decode = System.nanoTime();
+                    BOSDecoderImprove(encoded_result);
+                    long end_decode = System.nanoTime();
+                    decodeTime += (end_decode - start_decode);
+                    output_time += (start_decode - start_io);
+                }
+
+                e = System.nanoTime();
+                decodeTime = (decodeTime / repeatTime2);
+                output_time = (output_time / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "TS_2DIFF+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(input_time),
+                        String.valueOf(output_time),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void BOSMOUOTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R2O5_skew_distribution/compression_ratio/bos_m_improve";
+//        String output_parent_dir = parent_dir + "icde0802/compression_ratio/test";
+//        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R2O3_lower_outlier_compare/compression_ratio/bos";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 200;
+
+//        for (int file_i = 6; file_i < 7; file_i++) {
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+            if(file_i == 4 ) repeatTime2 = 1;
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f= tempList[1];
+
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoder(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "TS_2DIFF+BOS-M",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+
+            }
+            writer.close();
+
+        }
+    }
+}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSVImproveDecodeTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSVImproveDecodeTest.java
new file mode 100644
index 0000000..3aa69b3
--- /dev/null
+++ b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSVImproveDecodeTest.java
@@ -0,0 +1,1895 @@
+package org.apache.iotdb.tsfile.encoding;
+
+import com.csvreader.CsvReader;
+import com.csvreader.CsvWriter;
+import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
+import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
+import org.apache.iotdb.tsfile.compress.ICompressor;
+import org.apache.iotdb.tsfile.compress.IUnCompressor;
+import org.apache.iotdb.tsfile.encoding.decoder.Decoder;
+import org.apache.iotdb.tsfile.encoding.encoder.Encoder;
+import org.apache.iotdb.tsfile.encoding.encoder.FloatEncoder;
+import org.apache.iotdb.tsfile.encoding.encoder.TSEncodingBuilder;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+import org.junit.Test;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import static java.lang.Math.pow;
+//import static org.apache.iotdb.tsfile.encoding.CompressTest.addToArchiveCompression;
+
+public class TSDIFFBOSVImproveDecodeTest {
+
+    public static long combine2Int(int int1, int int2) {
+        return ((long) int1 << 32) | (int2 & 0xFFFFFFFFL);
+    }
+
+    public static int getTime(long long1) {
+        return ((int) (long1 >> 32));
+    }
+
+    public static int getValue(long long1) {
+        return ((int) (long1));
+    }
+
+    public static int getCount(long long1, int mask) {
+        return ((int) (long1 & mask));
+    }
+    public static int getUniqueValue(long long1, int left_shift) {
+        return ((int) ((long1) >> left_shift));
+    }
+
+    public static int getBitWith(int num) {
+        if (num == 0) return 1;
+        else return 32 - Integer.numberOfLeadingZeros(num);
+    }
+
+    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 int[] getAbsDeltaTsBlock(
+            int[] ts_block,
+            int i,
+            int block_size,
+            int remaining,
+            int[] min_delta) {
+        int[] ts_block_delta = new int[remaining-1];
+
+        int value_delta_min = Integer.MAX_VALUE;
+        int value_delta_max = Integer.MIN_VALUE;
+        int base = i*block_size+1;
+        int end = i*block_size+remaining;
+
+        int tmp_j_1 = ts_block[base-1];
+        min_delta[0] =tmp_j_1;
+        int j = base;
+        int tmp_j;
+
+        while(j<end){
+            tmp_j = ts_block[j];
+            int epsilon_v = tmp_j - tmp_j_1;
+            ts_block_delta[j-base] = epsilon_v;
+            if (epsilon_v < value_delta_min) {
+                value_delta_min = epsilon_v;
+            }
+            if (epsilon_v > value_delta_max) {
+                value_delta_max = epsilon_v;
+            }
+            tmp_j_1 = tmp_j;
+            j++;
+        }
+        j = 0;
+        end = remaining -1;
+        while(j<end){
+            ts_block_delta[j] = ts_block_delta[j] - value_delta_min;
+            j++;
+        }
+
+        min_delta[1] = value_delta_min;
+        min_delta[2] = (value_delta_max-value_delta_min);
+
+
+        return ts_block_delta;
+    }
+
+
+    public static int encodeOutlier2Bytes(
+            ArrayList<Integer> ts_block_delta,
+            int bit_width,
+            int encode_pos,  byte[] encoded_result) {
+
+        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
+
+        int n_k = ts_block_delta.size();
+        int n_k_b = n_k / 8;
+        long cur_remaining = 0; // encoded int
+        int cur_number_bits = 0; // the bit width used of encoded int
+        for (int i = n_k_b * 8; i < n_k; i++) {
+            long cur_value = ts_block_delta.get(i);
+            int cur_bit_width = bit_width; // remaining bit width of current value
+
+            if (cur_number_bits + bit_width >= 32) {
+                cur_remaining <<= (32 - cur_number_bits);
+                cur_bit_width = bit_width - 32 + cur_number_bits;
+                cur_remaining += ((cur_value >> cur_bit_width));
+                long2intBytes(cur_remaining,encode_pos,encoded_result);
+                encode_pos += 4;
+                cur_remaining = 0;
+                cur_number_bits = 0;
+            }
+
+            cur_remaining <<= cur_bit_width;
+            cur_number_bits += cur_bit_width;
+            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width)); //
+        }
+        cur_remaining <<= (32 - cur_number_bits);
+        long2intBytes(cur_remaining,encode_pos,encoded_result);
+        encode_pos += 4;
+        return encode_pos;
+
+    }
+
+
+    public static ArrayList<Integer> decodeOutlier2Bytes(
+            byte[] encoded,
+            int decode_pos,
+            int bit_width,
+            int length,
+            ArrayList<Integer> encoded_pos_result
+    ) {
+
+        int n_k_b = length / 8;
+        int remaining = length - n_k_b * 8;
+        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
+        decode_pos += n_k_b * bit_width;
+
+        ArrayList<Long> int_remaining = new ArrayList<>();
+        int int_remaining_size = remaining * bit_width / 32 + 1;
+        for (int j = 0; j < int_remaining_size; j++) {
+            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
+            decode_pos += 4;
+        }
+
+        int cur_remaining_bits = 32; // remaining bit width of current value
+        long cur_number = int_remaining.get(0);
+        int cur_number_i = 1;
+        for (int i = n_k_b * 8; i < length; i++) {
+            if (bit_width < cur_remaining_bits) {
+                int tmp = (int) (cur_number >> (32 - bit_width));
+                result_list.add(tmp);
+                cur_number <<= bit_width;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits -= bit_width;
+            } else {
+                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
+                int remain_bits = bit_width - cur_remaining_bits;
+                tmp <<= remain_bits;
+
+                cur_number = int_remaining.get(cur_number_i);
+                cur_number_i++;
+                tmp += (int) (cur_number >> (32 - remain_bits));
+                result_list.add(tmp);
+                cur_number <<= remain_bits;
+                cur_number &= 0xFFFFFFFFL;
+                cur_remaining_bits = 32 - remain_bits;
+            }
+        }
+        encoded_pos_result.add(decode_pos);
+        return result_list;
+    }
+
+    public static int EncodeBits(int num,
+                                 int bit_width,
+                                 int encode_pos,
+                                 byte[] cur_byte,
+                                 int[] bit_index_list){
+        // 找到要插入的位的索引
+        int bit_index = bit_index_list[0] ;//cur_byte[encode_pos + 1];
+
+        // 计算数值的起始位位置
+        int remaining_bits = bit_width;
+
+        while (remaining_bits > 0) {
+            // 计算在当前字节中可以使用的位数
+            int available_bits = bit_index;
+            int bits_to_write = Math.min(available_bits, remaining_bits);
+
+            // 更新 bit_index
+            bit_index = available_bits - bits_to_write;
+
+            // 计算要写入的位的掩码和数值
+            int mask = (1 << bits_to_write) - 1;
+            int bits = (num >> (remaining_bits - bits_to_write)) & mask;
+
+            // 写入到当前位置
+            cur_byte[encode_pos] &= (byte) ~(mask << bit_index); // 清除对应位置的位
+            cur_byte[encode_pos] |= (byte) (bits << bit_index);
+
+            // 更新位宽和数值
+            remaining_bits -= bits_to_write;
+            if (bit_index == 0) {
+                bit_index = 8;
+                encode_pos++;
+            }
+        }
+        bit_index_list[0] = bit_index;
+//        cur_byte[encode_pos + 1] = (byte) bit_index;
+        return encode_pos;
+    }
+    private static int BOSEncodeBits(int[] ts_block_delta,
+                                     int final_k_start_value,
+                                     int final_x_l_plus,
+                                     int final_k_end_value,
+                                     int final_x_u_minus,
+                                     int max_delta_value,
+                                     int[] min_delta,
+                                     int encode_pos,
+                                     byte[] cur_byte) {
+        int block_size = ts_block_delta.length;
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+        ArrayList<Integer> final_normal = new ArrayList<>();
+        int k1 = 0;
+        int k2 = 0;
+
+
+
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int index_bitmap_outlier = 0;
+        int cur_index_bitmap_outlier_bits = 0;
+        for (int i = 0; i < block_size; i++) {
+            int cur_value = ts_block_delta[i];
+            if ( cur_value<= final_k_start_value) {
+//                encode_pos = EncodeBits(cur_value,left_bit_width,encode_pos,cur_byte);
+//                final_left_outlier.add(cur_value);
+                final_left_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 3;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 1;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k1++;
+
+
+            } else if (cur_value >= final_k_end_value) {
+//                encode_pos = EncodeBits(cur_value- final_k_end_value,right_bit_width,encode_pos,cur_byte);
+//                final_right_outlier.add(cur_value - final_k_end_value);
+                final_right_outlier_index.add(i);
+                if (cur_index_bitmap_outlier_bits % 8 != 7) {
+                    index_bitmap_outlier <<= 2;
+                    index_bitmap_outlier += 2;
+                    cur_index_bitmap_outlier_bits += 2;
+                } else {
+                    index_bitmap_outlier <<= 1;
+                    index_bitmap_outlier += 1;
+                    bitmap_outlier.add(index_bitmap_outlier);
+                    index_bitmap_outlier = 0;
+                    cur_index_bitmap_outlier_bits = 1;
+                }
+                k2++;
+
+            } else {
+//                final_normal.add(cur_value - final_x_l_plus);
+//                encode_pos = EncodeBits(cur_value- final_x_l_plus,right_bit_width,encode_pos,cur_byte);
+                index_bitmap_outlier <<= 1;
+                cur_index_bitmap_outlier_bits += 1;
+            }
+            if (cur_index_bitmap_outlier_bits % 8 == 0) {
+                bitmap_outlier.add(index_bitmap_outlier);
+                index_bitmap_outlier = 0;
+            }
+        }
+        if (cur_index_bitmap_outlier_bits % 8 != 0) {
+
+            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
+
+            index_bitmap_outlier &= 0xFF;
+            bitmap_outlier.add(index_bitmap_outlier);
+        }
+
+        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
+
+
+        int k_byte = (k1 << 1);
+        k_byte += final_alpha;
+        k_byte += (k2 << 16);
+
+        int2Bytes(k_byte,encode_pos,cur_byte);
+        encode_pos += 4;
+
+
+        int2Bytes(min_delta[0],encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(min_delta[1],encode_pos,cur_byte);
+        encode_pos += 4;
+
+        int bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+        encode_pos += 1;
+        int[] bit_index_list = new int[1];
+        bit_index_list[0] = 8;
+
+        if(final_k_start_value<0 && final_k_end_value > max_delta_value){
+//            int bit_width_final= getBitWith(final_x_u_minus - final_x_l_plus);
+//            cur_byte[encode_pos+1] = 8;
+            for (int cur_value : ts_block_delta) {
+                encode_pos = EncodeBits(cur_value, bit_width_final, encode_pos, cur_byte, bit_index_list);
+//                final_normal.add(cur_value);
+            }
+            if(bit_index_list[0] != 8){
+                encode_pos ++;
+            }
+//            cur_byte[encode_pos+1] = 0;
+//            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+            return encode_pos;
+        }
+
+
+        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
+        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
+        int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+        encode_pos += 4;
+        int2Bytes(final_k_end_value,encode_pos,cur_byte);
+        encode_pos += 4;
+
+//        bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//        encode_pos += 1;
+        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+        encode_pos += 1;
+
+        if (final_alpha == 0) { // 0
+
+            for (int i : bitmap_outlier) {
+
+                intByte2Bytes(i,encode_pos,cur_byte);
+                encode_pos += 1;
+            }
+        } else {
+            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+        }
+//        cur_byte[encode_pos+1] = 8;
+//        bit_index_list[0] = 8;
+        for (int cur_value : ts_block_delta) {
+            if (cur_value <= final_k_start_value) {
+                encode_pos = EncodeBits(cur_value, left_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else if (cur_value >= final_k_end_value) {
+                encode_pos = EncodeBits(cur_value - final_k_end_value, right_bit_width, encode_pos, cur_byte,bit_index_list);
+            } else {
+                encode_pos = EncodeBits(cur_value - final_x_l_plus, bit_width_final, encode_pos, cur_byte,bit_index_list);
+            }
+        }
+        if(bit_index_list[0] != 8){
+            encode_pos ++;
+        }
+
+//        cur_byte[encode_pos+1] = 0;
+
+//        if(k1==0 && k2==0){
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//
+//
+//        }
+//        else{
+//            int2Bytes(final_x_l_plus,encode_pos,cur_byte);
+//            encode_pos += 4;
+//            int2Bytes(final_k_end_value,encode_pos,cur_byte);
+//            encode_pos += 4;
+//
+//            bit_width_final = getBitWith(final_x_u_minus - final_x_l_plus);
+//            intByte2Bytes(bit_width_final,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(left_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            intByte2Bytes(right_bit_width,encode_pos,cur_byte);
+//            encode_pos += 1;
+//            if (final_alpha == 0) { // 0
+//
+//                for (int i : bitmap_outlier) {
+//
+//                    intByte2Bytes(i,encode_pos,cur_byte);
+//                    encode_pos += 1;
+//                }
+//            } else {
+//                encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//                encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
+//            }
+//        }
+
+
+//        if(k1+k2!=block_size)
+//        encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
+//        if (k1 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
+//        if (k2 != 0)
+//            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
+        return encode_pos;
+
+    }
+
+
+    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size, int remaining ,int encode_pos , byte[] cur_byte) {
+
+        int[] min_delta = new int[3];
+        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
+
+
+        block_size = remaining-1;
+        int max_delta_value = min_delta[2];
+        int[] value_list = new int[block_size];
+        int unique_value_count = 0;
+        int[] value_count_list = new int[max_delta_value+1];
+        for(int value:ts_block_delta){
+            if(value_count_list[value]==0){
+                value_count_list[value] = 1;
+                value_list[unique_value_count] = value;
+                unique_value_count ++;
+            }else{
+                value_count_list[value] ++;
+            }
+        }
+
+        int left_shift = getBitWith(block_size);
+        int mask =  (1 << left_shift) - 1;
+        long[] sorted_value_list = new long[unique_value_count];
+        int count = 0;
+
+        for(int i=0;i<unique_value_count;i++){
+            int value = value_list[i];
+            sorted_value_list[i] = (((long) value) << left_shift) + value_count_list[value];
+        }
+        Arrays.sort(sorted_value_list);
+
+        for(int i=0;i<unique_value_count;i++){
+            count += getCount(sorted_value_list[i], mask);
+            sorted_value_list[i] = (((long)getUniqueValue(sorted_value_list[i], left_shift) ) << left_shift) + count;//new_value_list[i]
+        }
+
+
+        int final_k_start_value = -1; // x_l_minus
+        int final_x_l_plus = 0; // x_l_plus
+        int final_k_end_value = max_delta_value+1; // x_u_plus
+        int final_x_u_minus = max_delta_value; // x_u_minus
+
+        int min_bits = 0;
+        min_bits += (getBitWith(final_k_end_value - final_k_start_value - 2 ) * (block_size));
+
+        int cur_k1 = 0;
+
+        int x_l_plus_value = 0; // x_l_plus
+        int x_u_minus_value = max_delta_value; // x_u_plus
+
+        for (int end_value_i = 1; end_value_i < unique_value_count; end_value_i++) {
+
+            x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+            int x_u_plus_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+            int cur_bits = 0;
+            int cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value); // cur_k1 = 0
+            if (cur_k2 != 0)
+                cur_bits += cur_k2 * getBitWith(max_delta_value - x_u_plus_value);
+
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_x_u_minus = x_u_minus_value;
+                final_k_end_value = x_u_plus_value;
+            }
+        }
+
+        int k_start_value = -1; // x_l_minus
+
+        for (int start_value_i = 0; start_value_i < unique_value_count-1; start_value_i++) {
+            long k_start_valueL = sorted_value_list[start_value_i];
+            k_start_value =  getUniqueValue(k_start_valueL, left_shift) ;
+            x_l_plus_value =  getUniqueValue(sorted_value_list[start_value_i+1], left_shift) ;
+
+
+            cur_k1 = getCount(k_start_valueL,mask);
+
+            int k_end_value;
+            int cur_bits;
+            int cur_k2;
+            k_end_value = max_delta_value + 1;
+
+            cur_bits = 0;
+            cur_k2 = 0;
+            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
+            cur_bits += cur_k1 * getBitWith(k_start_value);
+            if (cur_k1 + cur_k2 != block_size)
+                cur_bits += (block_size - cur_k1) * getBitWith(k_end_value- x_l_plus_value); //cur_k2 =0
+
+            if (cur_bits < min_bits) {
+                min_bits = cur_bits;
+                final_k_start_value = k_start_value;
+                final_x_l_plus = x_l_plus_value;
+                final_k_end_value = k_end_value;
+                final_x_u_minus = max_delta_value;
+            }
+
+            for (int end_value_i = start_value_i + 1; end_value_i < unique_value_count; end_value_i++) {
+
+                x_u_minus_value = getUniqueValue(sorted_value_list[end_value_i-1], left_shift);
+                k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
+
+                cur_bits = 0;
+                cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
+
+                cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
+                cur_bits += cur_k1 * getBitWith(k_start_value);
+                if (cur_k1 + cur_k2 != block_size)
+                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(x_u_minus_value - x_l_plus_value);
+                if (cur_k2 != 0)
+                    cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
+
+
+                if (cur_bits < min_bits) {
+                    min_bits = cur_bits;
+
+                    final_k_start_value = k_start_value;
+                    final_x_l_plus = x_l_plus_value;
+                    final_k_end_value = k_end_value;
+                    final_x_u_minus = x_u_minus_value;
+                }
+
+            }
+        }
+//        System.out.println(min_bits/4);
+        encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_x_l_plus, final_k_end_value, final_x_u_minus,
+                max_delta_value, min_delta, encode_pos , cur_byte);
+//        System.out.println(encode_pos);
+//        System.out.println(encode_pos);
+        return encode_pos;
+    }
+
+
+    public static int BOSEncoder(
+            int[] data, int block_size, byte[] encoded_result) {
+        block_size++;
+
+        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;
+
+        for (int i = 0; i < block_num; i++) {
+//            int start_encode_pos = encode_pos;
+            encode_pos =  BOSBlockEncoder(data, i, block_size, block_size,encode_pos,encoded_result);
+//            System.out.println(encode_pos-start_encode_pos);
+//            System.out.println("------------------------------------------");
+        }
+
+        int remaining_length = length_all - block_num * block_size;
+        if (remaining_length <= 3) {
+            for (int i = remaining_length; i > 0; i--) {
+                int2Bytes(data[data.length - i], encode_pos, encoded_result);
+                encode_pos += 4;
+            }
+
+        }
+        else {
+
+            int start = block_num * block_size;
+            int remaining = length_all-start;
+            encode_pos = BOSBlockEncoder(data, block_num, block_size,remaining, encode_pos,encoded_result);
+
+        }
+
+
+        return encode_pos;
+    }
+
+
+    public static int DecodeBits(byte[] cur_byte, int bit_width, int[] decode_pos_list) {
+        int decode_pos = decode_pos_list[0];
+        int bit_index = decode_pos_list[1];  //cur_byte[decode_pos + 1];
+        int remaining_bits = bit_width;
+        int num = 0;
+
+        while (remaining_bits > 0) {
+            int available_bits = bit_index;
+            int bits_to_read = Math.min(available_bits, remaining_bits);
+
+            // 计算要读取的位的掩码
+            int mask = (1 << bits_to_read) - 1;
+            int bits = (cur_byte[decode_pos] >> (available_bits - bits_to_read)) & mask;
+
+            // 将读取的位合并到结果中
+            num = (num << bits_to_read) | bits;
+
+            // 更新位宽和 bit_index
+            remaining_bits -= bits_to_read;
+            bit_index = available_bits - bits_to_read;
+
+            if (bit_index == 0) {
+                bit_index = 8;
+                decode_pos++;
+            }
+        }
+        decode_pos_list[0] = decode_pos;
+        decode_pos_list[1] = bit_index;
+
+        return num;
+    }
+    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
+
+        int k_byte = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        int k1_byte = (int) (k_byte % pow(2, 16));
+        int k1 = k1_byte / 2;
+        int final_alpha = k1_byte % 2;
+
+        int k2 = (int) (k_byte / pow(2, 16));
+
+        int value0 = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+        value_list[value_pos_arr[0]] =value0;
+        value_pos_arr[0] ++;
+
+        int min_delta = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        int[] decode_list = new int[2];
+        decode_list[0]= decode_pos;
+        decode_list[1]= 8;
+
+        int valuePos = value_pos_arr[0];
+
+        if(k1==0 && k2==0){
+            int pre_v = value0;
+            for (int i = 0; i < block_size; i++) {
+                int cur_delta = min_delta + DecodeBits(encoded, bit_width_final,  decode_list);
+                pre_v += cur_delta;
+                value_list[valuePos++] = pre_v;
+            }
+            value_pos_arr[0] = valuePos;
+            return decode_list[0];
+        }
+
+        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
+        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
+//        ArrayList<Integer> final_left_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_right_outlier = new ArrayList<>();
+//        ArrayList<Integer> final_normal= new ArrayList<>();;
+        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
+        int final_k_start_value = 0;
+        int final_k_end_value = 0;
+//        int bit_width_final = 0;
+        int left_bit_width = 0;
+        int right_bit_width = 0;
+
+        final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+        final_k_end_value = bytes2Integer(encoded, decode_pos, 4);
+        decode_pos += 4;
+
+//        bit_width_final = bytes2Integer(encoded, decode_pos, 1);
+//        decode_pos += 1;
+
+        left_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+        right_bit_width = bytes2Integer(encoded, decode_pos, 1);
+        decode_pos += 1;
+
+        if (final_alpha == 0) {
+            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
+            for (int i = 0; i < bitmap_bytes; i++) {
+                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
+                decode_pos += 1;
+            }
+            int bitmap_outlier_i = 0;
+            int remaining_bits = 8;
+            int tmp = bitmap_outlier.get(bitmap_outlier_i);
+            bitmap_outlier_i++;
+            int i = 0;
+            while (i < block_size ) {
+                if (remaining_bits > 1) {
+                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
+                    remaining_bits -= 1;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                    if (remaining_bits == 0) {
+                        remaining_bits = 8;
+                        if (bitmap_outlier_i >= bitmap_bytes) break;
+                        tmp = bitmap_outlier.get(bitmap_outlier_i);
+                        bitmap_outlier_i++;
+                    }
+                } else if (remaining_bits == 1) {
+                    int bit_i = tmp & 0x1;
+                    remaining_bits = 8;
+                    if (bitmap_outlier_i >= bitmap_bytes) break;
+                    tmp = bitmap_outlier.get(bitmap_outlier_i);
+                    bitmap_outlier_i++;
+                    if (bit_i == 1) {
+                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
+                        remaining_bits -= 1;
+                        if (bit_left_right == 1) {
+                            final_left_outlier_index.add(i);
+                        } else {
+                            final_right_outlier_index.add(i);
+                        }
+                    }
+                }
+                i++;
+            }
+        } else {
+            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
+            decode_pos = (decode_pos_result_left.get(0));
+            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
+            decode_pos = (decode_pos_result_right.get(0));
+        }
+
+
+
+
+
+//        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
+//        final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
+//
+//        decode_pos = decode_pos_normal.get(0);
+//        if (k1 != 0) {
+//            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
+//            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
+//            decode_pos = decode_pos_result_left.get(0);
+//        }
+//        if (k2 != 0) {
+//            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
+//            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
+//            decode_pos = decode_pos_result_right.get(0);
+//        }
+        int left_outlier_i = 0;
+        int right_outlier_i = 0;
+        int normal_i = 0;
+        int pre_v = value0;
+//        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
+
+// Precompute constants
+        int normalOffset = min_delta + final_k_start_value;
+        int rightOutlierOffset = min_delta + final_k_end_value;
+
+// Initialize indices and pre-fetch next outlier positions
+        int leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+        int rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+        decode_list[0]= decode_pos;
+//        decode_list[1]= 8;
+        // Use a local variable for the position
+        for (int i = 0; i < block_size; i++) {
+            int currentDelta;
+            if (i == leftOutlierNextIndex) {
+                // Process left outlier
+                currentDelta = min_delta + DecodeBits(encoded, left_bit_width,  decode_list); // final_left_outlier.get(left_outlier_i);
+                left_outlier_i++;
+                leftOutlierNextIndex = (left_outlier_i < k1) ? final_left_outlier_index.get(left_outlier_i) : Integer.MAX_VALUE;
+            } else if (i == rightOutlierNextIndex) {
+                // Process right outlier
+                currentDelta = rightOutlierOffset + DecodeBits(encoded, right_bit_width,  decode_list);// final_right_outlier.get(right_outlier_i);
+                right_outlier_i++;
+                rightOutlierNextIndex = (right_outlier_i < k2) ? final_right_outlier_index.get(right_outlier_i) : Integer.MAX_VALUE;
+            } else {
+                // Process normal value
+                currentDelta = normalOffset + DecodeBits(encoded, bit_width_final,  decode_list);
+                normal_i++;
+            }
+
+            // Update the cumulative value and store it
+            pre_v += currentDelta;
+            value_list[valuePos++] = pre_v;
+        }
+        value_pos_arr[0] = valuePos;
+        if(decode_list[1]!=8){
+            return decode_list[0]+1;
+        }else {
+            return decode_list[0];
+        }
+//        decode_pos = decode_list[0];
+// Update the position in the array
+
+
+//        return decode_pos;
+    }
+
+    public static void BOSDecoder(byte[] encoded) {
+
+        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[] value_list = new int[length_all+block_size];
+        block_size--;
+
+        int[] value_pos_arr = new int[1];
+        for (int k = 0; k < block_num; k++) {
+
+
+            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list, block_size,value_pos_arr);
+
+        }
+
+        if (remain_length <= 3) {
+            for (int i = 0; i < remain_length; i++) {
+                int value_end = bytes2Integer(encoded, decode_pos, 4);
+                decode_pos += 4;
+                value_list[value_pos_arr[0]] = value_end;
+                value_pos_arr[0]++;
+            }
+        } else {
+            remain_length --;
+            BOSBlockDecoder(encoded, decode_pos, value_list, remain_length, value_pos_arr);
+        }
+    }
+
+    @Test
+    public void BOSOptimalTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R1O4_decode_time/compression_ratio/bos_v";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 1; file_i < 2; file_i++) {
+
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            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) {
+//                f=tempList[2];
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+//                        String value = loader.getValues()[index];
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+//                        data.add(Integer.valueOf(value));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                double ratio = 0;
+                double compressed_size = 0;
+
+
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+                compressed_size += length;
+                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+                s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++)
+                    BOSDecoder(encoded_result);
+                e = System.nanoTime();
+                decodeTime += ((e - s) / repeatTime2);
+
+
+                String[] record = {
+                        f.toString(),
+                        "TS_2DIFF+BOS-V",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+//                break;
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void BOSVaryBlockSize() throws IOException, InterruptedException {
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/"; // your data path
+//        String output_parent_dir = parent_dir + "icde0802/compression_ratio/block_size_bos_v";
+        String output_parent_dir = parent_dir + "icde0802/compression_ratio/block_size_bos_v";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+        }
+
+        output_path_list.add(output_parent_dir + "/CS-Sensors_ratio.csv"); // 0
+        output_path_list.add(output_parent_dir + "/Metro-Traffic_ratio.csv");// 1
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+
+        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
+
+        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
+
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+
+        int repeatTime2 = 20;
+        int[] file_i_list = {0,9,10};
+//        for (int file_i = 9; file_i < 10; file_i++) {
+//        for(int file_i :file_i_list){
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+
+            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",
+                    "Block Size",
+                    "Compression Ratio"
+            };
+            writer.writeRecord(head); // write header to output file
+
+            assert tempList != null;
+
+            for (File f : tempList) {
+                System.out.println(f);
+                Thread.sleep(10000);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+
+                loader.readHeaders();
+
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+                inputStream.close();
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+
+//                for (int block_size_i = 5; block_size_i <14; block_size_i++) {
+                for (int block_size_i = 13; block_size_i > 4; block_size_i--) {
+                    int block_size = (int) Math.pow(2, block_size_i);
+                    System.out.println(block_size);
+                    long encodeTime = 0;
+                    long decodeTime = 0;
+                    double ratio = 0;
+                    double compressed_size = 0;
+
+
+                    long s = System.nanoTime();
+                    for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                        compressed_size = BOSEncoder(data2_arr, block_size, encoded_result);
+                    }
+
+                    long e = System.nanoTime();
+                    encodeTime += ((e - s) / repeatTime2);
+                    double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                    ratio += ratioTmp;
+                    s = System.nanoTime();
+                    for (int repeat = 0; repeat < repeatTime2; repeat++)
+                        BOSDecoder(encoded_result);
+                    e = System.nanoTime();
+                    decodeTime += ((e - s) / repeatTime2);
+
+                    String[] record = {
+                            f.toString(),
+                            "TS_2DIFF+BOS-V",
+                            String.valueOf(encodeTime),
+                            String.valueOf(decodeTime),
+                            String.valueOf(data1.size()),
+                            String.valueOf(compressed_size),
+                            String.valueOf(block_size_i),
+                            String.valueOf(ratio)
+                    };
+                    writer.writeRecord(record);
+                    System.out.println(ratio);
+
+                }
+
+            }
+            writer.close();
+
+        }
+    }
+
+    private static void addToArchiveCompression(SevenZOutputFile out, File file, String dir) {
+        String name = dir + File.separator + file.getName();
+        if(dir.equals(".")) {
+            name = file.getName();
+        }
+        if (file.isFile()){
+            SevenZArchiveEntry entry = null;
+            FileInputStream in = null;
+            try {
+                entry = out.createArchiveEntry(file, name);
+                out.putArchiveEntry(entry);
+                in = new FileInputStream(file);
+                byte[] b = new byte[1024];
+                int count = 0;
+                while ((count = in.read(b)) > 0) {
+                    out.write(b, 0, count);
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    out.closeArchiveEntry();
+                    in.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+
+            }
+        } else if (file.isDirectory()) {
+            File[] children = file.listFiles();
+            if (children != null){
+                for (File child : children){
+                    addToArchiveCompression(out, child, name);
+                }
+            }
+        } else {
+            System.out.println(file.getName() + " is not supported");
+        }
+    }
+
+    @Test
+    public void compressBOSTest() throws IOException {
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";// your data path
+//        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R3O2_compare_compression/compression_ratio/bos_v_comp";
+        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<>();
+        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");
+
+        for (String value : dataset_name) {
+            input_path_list.add(input_parent_dir + value);
+            dataset_block_size.add(1024);
+        }
+
+        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(2048);
+        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
+//        dataset_block_size.add(2048);
+        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(1024);
+        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
+//        dataset_block_size.add(1024);
+        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
+//        dataset_block_size.add(2048);
+        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
+//        dataset_block_size.add(1024);
+
+        int repeatTime2 = 100;
+//        for (int file_i = 8; file_i < 9; file_i++) {
+        CompressionType[] compressList = {
+                CompressionType.LZ4,
+                CompressionType.LZMA2,
+        };
+
+        for (int file_i = input_path_list.size()-1; file_i >=0 ; file_i--) {
+
+            String inputPath = input_path_list.get(file_i);
+            System.out.println(inputPath);
+            String Output = output_path_list.get(file_i);
+
+            File file = new File(inputPath);
+            File[] tempList = file.listFiles();
+
+            CsvWriter writer = new CsvWriter(Output, ',', StandardCharsets.UTF_8);
+
+            String[] head = {
+                    "Input Direction",
+                    "Encoding Algorithm",
+//                    "Compress 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<Integer> data1 = new ArrayList<>();
+                ArrayList<Integer> data2 = new ArrayList<>();
+
+                loader.readHeaders();
+                while (loader.readRecord()) {
+                    data1.add(Integer.valueOf(loader.getValues()[0]));
+                    data2.add(Integer.valueOf(loader.getValues()[1]));
+                }
+                inputStream.close();
+
+                int[] data2_arr = new int[data1.size()];
+                for(int i = 0;i<data2.size();i++){
+                    data2_arr[i] = data2.get(i);
+                }
+                byte[] encoded_result = new byte[data2_arr.length*4];
+                long encodeTime = 0;
+                long decodeTime = 0;
+                int length = 0;
+
+                long s = System.nanoTime();
+                for (int repeat = 0; repeat < repeatTime2; repeat++) {
+                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
+                }
+                long e = System.nanoTime();
+                encodeTime += ((e - s) / repeatTime2);
+
+                for (CompressionType comp : compressList) {
+                    double ratio = 0;
+                    double compressed_size = 0;
+                    ICompressor compressor = ICompressor.getCompressor(comp);
+                    byte[] compressed = compressor.compress(encoded_result);
+
+                    // test compression ratio and compressed size
+                    compressed_size += compressed.length;
+                    double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
+                    ratio += ratioTmp;
+                    s = System.nanoTime();
+                    for (int repeat = 0; repeat < repeatTime2; repeat++)
+                        BOSDecoder(encoded_result);
+                    e = System.nanoTime();
+                    decodeTime += ((e - s) / repeatTime2);
+
+
+                    String[] record = {
+                            f.toString(),
+                            "BOS+"+ comp,
+                            String.valueOf(encodeTime),
+                            String.valueOf(decodeTime),
+                            String.valueOf(data1.size()),
+                            String.valueOf(compressed_size),
+                            String.valueOf(ratio)
+                    };
+                    writer.writeRecord(record);
+                    System.out.println(ratio);
+                }
+                double ratio = 0;
+                double compressed_size = 0;
+                File outfile = new File(parent_dir + "icde0802/example.bin");
+
+                // 使用FileOutputStream将byte数组写入文件
+                try (FileOutputStream fos = new FileOutputStream(outfile)) {
+                    fos.write(encoded_result);
+                } catch (IOException e2) {
+                    // 处理可能的I/O异常
+                    e2.printStackTrace();
+                }
+
+                File input = new File(parent_dir + "icde0802/example.bin");
+                File output = new File(parent_dir + "icde0802/example.7z");
+                SevenZOutputFile out = new SevenZOutputFile(output);
+
+                addToArchiveCompression(out, input, ".");
+                out.closeArchiveEntry();
+
+                long compressed = output.length();
+
+
+                // test compression ratio and compressed size
+                compressed_size += compressed;
+                double ratioTmp =
+                        (double) compressed / (double) (double) (data1.size() * Integer.BYTES);
+                ratio += ratioTmp;
+
+
+                String[] record = {
+                        f.toString(),
+                        "BOS+7-Zip",
+                        String.valueOf(encodeTime),
+                        String.valueOf(decodeTime),
+                        String.valueOf(data1.size()),
+                        String.valueOf(compressed_size),
+                        String.valueOf(ratio)
+                };
+                writer.writeRecord(record);
+                System.out.println(ratio);
+            }
+            writer.close();
+        }
+    }
+
+    @Test
+    public void compressionBPTest() throws IOException {
+
+        String parent_dir = "/Users/xiaojinzhao/Documents/GitHub/encoding-outlier/";
+//    String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
+        String output_parent_dir = parent_dir + "icde0802/supply_experiment/R3O2_compare_compression/compression_ratio/bp_comp/";
+        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<>();
+        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");
+
+
+        for (String item : dataset_name) {
+            input_path_list.add(input_parent_dir + item);
+        }
+
+        output_path_list.add(output_parent_dir + "CS-Sensors_ratio.csv"); // 0
+
+        output_path_list.add(output_parent_dir + "Metro-Traffic_ratio.csv");// 1
+
+        output_path_list.add(output_parent_dir + "USGS-Earthquakes_ratio.csv");// 2
+
+        output_path_list.add(output_parent_dir + "YZ-Electricity_ratio.csv"); // 3
+
+        output_path_list.add(output_parent_dir + "GW-Magnetic_ratio.csv"); //4
+
+        output_path_list.add(output_parent_dir + "TY-Fuel_ratio.csv");//5
+
+        output_path_list.add(output_parent_dir + "Cyber-Vehicle_ratio.csv"); //6
+
+        output_path_list.add(output_parent_dir + "Vehicle-Charge_ratio.csv");//7
+
+        output_path_list.add(output_parent_dir + "Nifty-Stocks_ratio.csv");//8
+
+        output_path_list.add(output_parent_dir + "TH-Climate_ratio.csv");//9
+
+        output_path_list.add(output_parent_dir + "TY-Transport_ratio.csv");//10
+
+        output_path_list.add(output_parent_dir + "EPM-Education_ratio.csv");//11
+
+//    for (int file_i = 7; file_i < 8; file_i++) {
+        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
+            String inputPath = input_path_list.get(file_i);
+            String Output = output_path_list.get(file_i);
+
+            // speed
+            int repeatTime = 100; // set repeat time
+            String dataTypeName = "int"; // set dataType
+
+            File file = new File(inputPath);
+            File[] tempList = file.listFiles();
+
+            // select encoding algorithms
+            TSEncoding[] encodingList = {
+                    TSEncoding.PLAIN ,
+//                    TSEncoding.TS_2DIFF,
+//                    TSEncoding.RLE,
+//                    TSEncoding.SPRINTZ,
+//                    TSEncoding.GORILLA,
+//                    TSEncoding.RLBE,
+//                    TSEncoding.CHIMP,
+//              TSEncoding.BUFF
+            };
+
+            CompressionType[] compressList = {
+//                    CompressionType.UNCOMPRESSED,
+                    CompressionType.LZ4,
+                    CompressionType.LZMA2,
+
+            };
+            CsvWriter writer = new CsvWriter(Output, ',', StandardCharsets.UTF_8);
+
+            String[] head = {
+                    "Input Direction",
+                    "Encoding Algorithm",
+//                    "Compress Algorithm",
+                    "Encoding Time",
+                    "Decoding Time",
+                    "Points",
+                    "Compressed Size",
+                    "Compression Ratio"
+//                    "Input Direction",
+//                    "Column Index",
+//                    "Encoding Algorithm",
+//                    "Compress Algorithm",
+//                    "Encoding Time",
+//                    "Decoding Time",
+//                    "Compress Time",
+//                    "Uncompress Time",
+//                    "Points",
+//                    "Compressed Size",
+//                    "Compression Ratio"
+            };
+            writer.writeRecord(head); // write header to output file
+
+            assert tempList != null;
+            ArrayList<Integer> columnIndexes = new ArrayList<>(); // set the column indexes of compressed
+            for (int i = 0; i < 2; i++) {
+                columnIndexes.add(i, i);
+            }
+            for (File f : tempList) {
+                System.out.println(f);
+                InputStream inputStream = Files.newInputStream(f.toPath());
+                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                ArrayList<String> data = new ArrayList<>();
+
+                for (int index : columnIndexes) {
+                    if (index == 0){
+                        continue;
+                    }
+                    int max_precision = 2;
+                    if (file_i == 3){
+                        max_precision = 4;
+                    } else if (file_i == 4 ||file_i == 5) {
+                        max_precision = 3;
+                    }
+                    loader.readHeaders();
+                    data.clear();
+                    while (loader.readRecord()) {
+                        String v = loader.getValues()[index];
+
+                        data.add(v);
+                        if (!v.matches("-?\\d+")){
+                            dataTypeName = "float";
+                        }
+                    }
+                    inputStream.close();
+
+                    switch (dataTypeName) {
+                        case "int":
+                        {
+                            TSDataType dataType = TSDataType.INT32; // set TSDataType
+                            ArrayList<Integer> tmp = new ArrayList<>();
+                            for (String value : data) {
+                                tmp.add(Integer.valueOf(value));
+                            }
+                            // Iterate over each encoding algorithm
+                            for (TSEncoding encoding : encodingList) {
+                                Encoder encoder =
+                                        TSEncodingBuilder.getEncodingBuilder(encoding).getEncoder(dataType);
+                                Decoder decoder = Decoder.getDecoderByType(encoding, dataType);
+                                long encodeTime = 0;
+                                long decodeTime = 0;
+
+                                // Iterate over each compression algorithm
+                                for (CompressionType comp : compressList) {
+                                    ICompressor compressor = ICompressor.getCompressor(comp);
+                                    IUnCompressor unCompressor = IUnCompressor.getUnCompressor(comp);
+
+                                    double ratio = 0;
+                                    double compressed_size = 0;
+
+                                    long compressTime = 0;
+                                    long uncompressTime = 0;
+
+                                    // repeat many times to test time
+                                    for (int i = 0; i < repeatTime; i++) {
+                                        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+                                        // test encode time
+                                        long s = System.nanoTime();
+                                        for (int val : tmp) {
+                                            encoder.encode(val, buffer);
+                                        }
+
+                                        encoder.flush(buffer);
+                                        long e = System.nanoTime();
+                                        encodeTime += (e - s);
+
+                                        // test compress time
+                                        byte[] elems = buffer.toByteArray();
+                                        s = System.nanoTime();
+                                        byte[] compressed = compressor.compress(elems);
+                                        e = System.nanoTime();
+                                        compressTime += (e - s);
+
+                                        // test compression ratio and compressed size
+                                        compressed_size += compressed.length;
+                                        double ratioTmp =
+                                                (double) compressed.length / (double) (tmp.size() * Integer.BYTES);
+                                        ratio += ratioTmp;
+
+                                        // test uncompress time
+                                        s = System.nanoTime();
+                                        unCompressor.uncompress(compressed);
+                                        e = System.nanoTime();
+                                        uncompressTime += (e - s);
+
+                                        // test decode time
+                                        ByteBuffer ebuffer = ByteBuffer.wrap(buffer.toByteArray());
+                                        s = System.nanoTime();
+                                        while (decoder.hasNext(ebuffer)) {
+                                            decoder.readInt(ebuffer);
+                                        }
+                                        e = System.nanoTime();
+                                        decodeTime += (e - s);
+
+                                        buffer.close();
+                                    }
+
+                                    ratio /= repeatTime;
+                                    compressed_size /= repeatTime;
+                                    encodeTime /= repeatTime;
+                                    decodeTime /= repeatTime;
+
+                                    String[] record = {
+                                            f.toString(),
+                                            comp.toString(),
+                                            String.valueOf(encodeTime),
+                                            String.valueOf(decodeTime),
+                                            String.valueOf(data.size()),
+                                            String.valueOf(compressed_size),
+                                            String.valueOf(ratio)
+//                                            f.toString(),
+//                                            String.valueOf(index),
+//                                            encoding.toString(),
+//                                            comp.toString(),
+//                                            String.valueOf(encodeTime),
+//                                            String.valueOf(decodeTime),
+//                                            String.valueOf(compressTime),
+//                                            String.valueOf(uncompressTime),
+//                                            String.valueOf(data.size()),
+//                                            String.valueOf(compressed_size),
+//                                            String.valueOf(ratio)
+                                    };
+                                    System.out.println(ratio);
+                                    writer.writeRecord(record);
+                                }
+                            }
+                            tmp.clear();
+                            break;
+                        }
+
+                        // write info to file
+                        case "float":
+                        {
+                            System.out.println("get float");
+                            TSDataType dataType = TSDataType.FLOAT;
+                            ArrayList<Float> tmp = new ArrayList<>();
+                            data.removeIf(String::isEmpty);
+                            for (String datum : data) {
+                                tmp.add(Float.valueOf(datum));
+                            }
+
+                            // Iterate over each encoding algorithm
+                            for (TSEncoding encoding : encodingList) {
+                                Encoder encoder;
+                                encoder = TSEncodingBuilder.getEncodingBuilder(encoding).getEncoder(dataType);
+                                if (encoding == TSEncoding.TS_2DIFF){
+                                    encoder = new FloatEncoder(TSEncoding.TS_2DIFF, dataType, max_precision);
+                                } else if (encoding == TSEncoding.RLE){
+                                    encoder = new FloatEncoder(TSEncoding.RLE, dataType, max_precision);
+                                }
+
+                                Decoder decoder = Decoder.getDecoderByType(encoding, dataType);
+
+                                long encodeTime = 0;
+                                long decodeTime = 0;
+                                // Iterate over each compression algorithm
+                                for (CompressionType comp : compressList) {
+                                    ICompressor compressor = ICompressor.getCompressor(comp);
+                                    IUnCompressor unCompressor = IUnCompressor.getUnCompressor(comp);
+                                    long compressTime = 0;
+                                    long uncompressTime = 0;
+                                    double ratio = 0;
+                                    double compressed_size = 0;
+
+                                    // repeat many times to test time
+                                    for (int i = 0; i < repeatTime; i++) {
+                                        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+                                        // test encode time
+                                        long s = System.nanoTime();
+                                        for (float val : tmp) {
+                                            encoder.encode(val, buffer);
+                                        }
+                                        encoder.flush(buffer);
+                                        long e = System.nanoTime();
+                                        encodeTime += (e - s);
+
+                                        // test compress time
+                                        byte[] elems = buffer.toByteArray();
+                                        s = System.nanoTime();
+                                        byte[] compressed = compressor.compress(elems);
+                                        e = System.nanoTime();
+                                        compressTime += (e - s);
+
+                                        // test compression ratio and compressed size
+                                        compressed_size += compressed.length;
+                                        double ratioTmp =
+                                                (double) compressed.length / (double) (tmp.size() * Float.BYTES);
+                                        ratio += ratioTmp;
+
+                                        // test uncompress time
+                                        s = System.nanoTime();
+                                        unCompressor.uncompress(compressed);
+                                        e = System.nanoTime();
+                                        uncompressTime += (e - s);
+
+                                        // test decode time
+                                        ByteBuffer ebuffer = ByteBuffer.wrap(buffer.toByteArray());
+                                        while (decoder.hasNext(ebuffer)) {
+                                            decoder.readFloat(ebuffer);
+                                        }
+                                        e = System.nanoTime();
+                                        decodeTime += (e - s);
+
+                                        buffer.close();
+                                    }
+                                    ratio /= repeatTime;
+                                    compressed_size /= repeatTime;
+                                    encodeTime /= repeatTime;
+                                    decodeTime /= repeatTime;
+
+                                    // write info to file
+                                    String[] record = {
+                                            f.toString(),
+                                            comp.toString(),
+                                            String.valueOf(encodeTime),
+                                            String.valueOf(decodeTime),
+                                            String.valueOf(data.size()),
+                                            String.valueOf(compressed_size),
+                                            String.valueOf(ratio)
+//                                            f.toString(),
+//                                            String.valueOf(index),
+//                                            encoding.toString(),
+//                                            comp.toString(),
+//                                            String.valueOf(encodeTime),
+//                                            String.valueOf(decodeTime),
+//                                            String.valueOf(compressTime),
+//                                            String.valueOf(uncompressTime),
+//                                            String.valueOf(data.size()),
+//                                            String.valueOf(compressed_size),
+//                                            String.valueOf(ratio)
+                                    };
+                                    System.out.println(ratio);
+                                    writer.writeRecord(record);
+                                }
+                            }
+                            break;
+                        }
+                    }
+                    inputStream = Files.newInputStream(f.toPath());
+                    loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
+                }
+            }
+            writer.close();
+        }
+    }
+
+}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSVTest.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSVTest.java
deleted file mode 100644
index df560a1..0000000
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/TSDIFFBOSVTest.java
+++ /dev/null
@@ -1,1089 +0,0 @@
-package org.apache.iotdb.tsfile.encoding;
-
-import com.csvreader.CsvReader;
-import com.csvreader.CsvWriter;
-import org.junit.Test;
-
-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.ArrayList;
-import java.util.Arrays;
-
-
-import static java.lang.Math.pow;
-
-public class TSDIFFBOSVTest {
-
-    public static long combine2Int(int int1, int int2) {
-        return ((long) int1 << 32) | (int2 & 0xFFFFFFFFL);
-    }
-
-    public static int getTime(long long1) {
-        return ((int) (long1 >> 32));
-    }
-
-    public static int getValue(long long1) {
-        return ((int) (long1));
-    }
-
-    public static int getCount(long long1, int mask) {
-        return ((int) (long1 & mask));
-    }
-    public static int getUniqueValue(long long1, int left_shift) {
-        return ((int) ((long1) >> left_shift));
-    }
-
-    public static int getBitWith(int num) {
-        if (num == 0) return 1;
-        else return 32 - Integer.numberOfLeadingZeros(num);
-    }
-
-    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 int[] getAbsDeltaTsBlock(
-            int[] ts_block,
-            int i,
-            int block_size,
-            int remaining,
-            int[] min_delta) {
-        int[] ts_block_delta = new int[remaining-1];
-
-        int value_delta_min = Integer.MAX_VALUE;
-        int value_delta_max = Integer.MIN_VALUE;
-        int base = i*block_size+1;
-        int end = i*block_size+remaining;
-
-        int tmp_j_1 = ts_block[base-1];
-        min_delta[0] =tmp_j_1;
-        int j = base;
-        int tmp_j;
-
-        while(j<end){
-            tmp_j = ts_block[j];
-            int epsilon_v = tmp_j - tmp_j_1;
-            ts_block_delta[j-base] = epsilon_v;
-            if (epsilon_v < value_delta_min) {
-                value_delta_min = epsilon_v;
-            }
-            if (epsilon_v > value_delta_max) {
-                value_delta_max = epsilon_v;
-            }
-            tmp_j_1 = tmp_j;
-            j++;
-        }
-        j = 0;
-        end = remaining -1;
-        while(j<end){
-            ts_block_delta[j] = ts_block_delta[j] - value_delta_min;
-            j++;
-        }
-
-        min_delta[1] = value_delta_min;
-        min_delta[2] = (value_delta_max-value_delta_min);
-
-
-        return ts_block_delta;
-    }
-
-
-    public static int encodeOutlier2Bytes(
-            ArrayList<Integer> ts_block_delta,
-            int bit_width,
-            int encode_pos,  byte[] encoded_result) {
-
-        encode_pos = bitPacking(ts_block_delta, 0, bit_width, encode_pos, encoded_result);
-
-        int n_k = ts_block_delta.size();
-        int n_k_b = n_k / 8;
-        long cur_remaining = 0; // encoded int
-        int cur_number_bits = 0; // the bit width used of encoded int
-        for (int i = n_k_b * 8; i < n_k; i++) {
-            long cur_value = ts_block_delta.get(i);
-            int cur_bit_width = bit_width; // remaining bit width of current value
-
-            if (cur_number_bits + bit_width >= 32) {
-                cur_remaining <<= (32 - cur_number_bits);
-                cur_bit_width = bit_width - 32 + cur_number_bits;
-                cur_remaining += ((cur_value >> cur_bit_width));
-                long2intBytes(cur_remaining,encode_pos,encoded_result);
-                encode_pos += 4;
-                cur_remaining = 0;
-                cur_number_bits = 0;
-            }
-
-            cur_remaining <<= cur_bit_width;
-            cur_number_bits += cur_bit_width;
-            cur_remaining += (((cur_value << (32 - cur_bit_width)) & 0xFFFFFFFFL) >> (32 - cur_bit_width)); //
-        }
-        cur_remaining <<= (32 - cur_number_bits);
-        long2intBytes(cur_remaining,encode_pos,encoded_result);
-        encode_pos += 4;
-        return encode_pos;
-
-    }
-
-
-    public static ArrayList<Integer> decodeOutlier2Bytes(
-            byte[] encoded,
-            int decode_pos,
-            int bit_width,
-            int length,
-            ArrayList<Integer> encoded_pos_result
-    ) {
-
-        int n_k_b = length / 8;
-        int remaining = length - n_k_b * 8;
-        ArrayList<Integer> result_list = new ArrayList<>(decodeBitPacking(encoded, decode_pos, bit_width, n_k_b * 8 + 1));
-        decode_pos += n_k_b * bit_width;
-
-        ArrayList<Long> int_remaining = new ArrayList<>();
-        int int_remaining_size = remaining * bit_width / 32 + 1;
-        for (int j = 0; j < int_remaining_size; j++) {
-            int_remaining.add(bytesLong2Integer(encoded, decode_pos));
-            decode_pos += 4;
-        }
-
-        int cur_remaining_bits = 32; // remaining bit width of current value
-        long cur_number = int_remaining.get(0);
-        int cur_number_i = 1;
-        for (int i = n_k_b * 8; i < length; i++) {
-            if (bit_width < cur_remaining_bits) {
-                int tmp = (int) (cur_number >> (32 - bit_width));
-                result_list.add(tmp);
-                cur_number <<= bit_width;
-                cur_number &= 0xFFFFFFFFL;
-                cur_remaining_bits -= bit_width;
-            } else {
-                int tmp = (int) (cur_number >> (32 - cur_remaining_bits));
-                int remain_bits = bit_width - cur_remaining_bits;
-                tmp <<= remain_bits;
-
-                cur_number = int_remaining.get(cur_number_i);
-                cur_number_i++;
-                tmp += (int) (cur_number >> (32 - remain_bits));
-                result_list.add(tmp);
-                cur_number <<= remain_bits;
-                cur_number &= 0xFFFFFFFFL;
-                cur_remaining_bits = 32 - remain_bits;
-            }
-        }
-        encoded_pos_result.add(decode_pos);
-        return result_list;
-    }
-
-    private static int BOSEncodeBits(int[] ts_block_delta,
-                                     int final_k_start_value,
-                                     int final_k_end_value,
-                                     int max_delta_value,
-                                     int[] min_delta,
-                                     int encode_pos,
-                                     byte[] cur_byte) {
-        int block_size = ts_block_delta.length;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal = new ArrayList<>();
-        int k1 = 0;
-        int k2 = 0;
-
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-        int index_bitmap_outlier = 0;
-        int cur_index_bitmap_outlier_bits = 0;
-        for (int i = 0; i < block_size; i++) {
-            int cur_value = ts_block_delta[i];
-            if ( cur_value<= final_k_start_value) {
-                final_left_outlier.add(cur_value);
-                final_left_outlier_index.add(i);
-                if (cur_index_bitmap_outlier_bits % 8 != 7) {
-                    index_bitmap_outlier <<= 2;
-                    index_bitmap_outlier += 3;
-                    cur_index_bitmap_outlier_bits += 2;
-                } else {
-                    index_bitmap_outlier <<= 1;
-                    index_bitmap_outlier += 1;
-                    bitmap_outlier.add(index_bitmap_outlier);
-                    index_bitmap_outlier = 1;
-                    cur_index_bitmap_outlier_bits = 1;
-                }
-                k1++;
-
-
-            } else if (cur_value >= final_k_end_value) {
-                final_right_outlier.add(cur_value - final_k_end_value);
-                final_right_outlier_index.add(i);
-                if (cur_index_bitmap_outlier_bits % 8 != 7) {
-                    index_bitmap_outlier <<= 2;
-                    index_bitmap_outlier += 2;
-                    cur_index_bitmap_outlier_bits += 2;
-                } else {
-                    index_bitmap_outlier <<= 1;
-                    index_bitmap_outlier += 1;
-                    bitmap_outlier.add(index_bitmap_outlier);
-                    index_bitmap_outlier = 0;
-                    cur_index_bitmap_outlier_bits = 1;
-                }
-                k2++;
-
-            } else {
-                final_normal.add(cur_value - final_k_start_value-1);
-                index_bitmap_outlier <<= 1;
-                cur_index_bitmap_outlier_bits += 1;
-            }
-            if (cur_index_bitmap_outlier_bits % 8 == 0) {
-                bitmap_outlier.add(index_bitmap_outlier);
-                index_bitmap_outlier = 0;
-            }
-        }
-        if (cur_index_bitmap_outlier_bits % 8 != 0) {
-
-            index_bitmap_outlier <<= (8 - cur_index_bitmap_outlier_bits % 8);
-
-            index_bitmap_outlier &= 0xFF;
-            bitmap_outlier.add(index_bitmap_outlier);
-        }
-
-        int final_alpha = ((k1 + k2) * getBitWith(block_size-1)) <= (block_size + k1 + k2) ? 1 : 0;
-
-
-        int k_byte = (k1 << 1);
-        k_byte += final_alpha;
-        k_byte += (k2 << 16);
-
-
-        int2Bytes(k_byte,encode_pos,cur_byte);
-        encode_pos += 4;
-
-        int2Bytes(min_delta[0],encode_pos,cur_byte);
-        encode_pos += 4;
-        int2Bytes(min_delta[1],encode_pos,cur_byte);
-        encode_pos += 4;
-        int2Bytes(final_k_start_value,encode_pos,cur_byte);
-        encode_pos += 4;
-        int bit_width_final = getBitWith(final_k_end_value - final_k_start_value-2);
-        intByte2Bytes(bit_width_final,encode_pos,cur_byte);
-        encode_pos += 1;
-        int left_bit_width = getBitWith(final_k_start_value);//final_left_max
-        int right_bit_width = getBitWith(max_delta_value - final_k_end_value);//final_right_min
-        intByte2Bytes(left_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        intByte2Bytes(right_bit_width,encode_pos,cur_byte);
-        encode_pos += 1;
-        if (final_alpha == 0) { // 0
-
-            for (int i : bitmap_outlier) {
-
-                intByte2Bytes(i,encode_pos,cur_byte);
-                encode_pos += 1;
-            }
-        } else {
-            encode_pos = encodeOutlier2Bytes(final_left_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
-            encode_pos = encodeOutlier2Bytes(final_right_outlier_index, getBitWith(block_size-1),encode_pos,cur_byte);
-        }
-//        if(k1+k2!=block_size)
-            encode_pos = encodeOutlier2Bytes(final_normal, bit_width_final,encode_pos,cur_byte);
-        if (k1 != 0)
-            encode_pos = encodeOutlier2Bytes(final_left_outlier, left_bit_width,encode_pos,cur_byte);
-        if (k2 != 0)
-            encode_pos = encodeOutlier2Bytes(final_right_outlier, right_bit_width,encode_pos,cur_byte);
-        return encode_pos;
-
-    }
-
-
-    private static int BOSBlockEncoder(int[] ts_block, int block_i, int block_size, int remaining ,int encode_pos , byte[] cur_byte) {
-
-        int[] min_delta = new int[3];
-        int[] ts_block_delta = getAbsDeltaTsBlock(ts_block, block_i, block_size, remaining, min_delta);
-
-
-        block_size = remaining-1;
-        int max_delta_value = min_delta[2];
-        int[] value_list = new int[block_size];
-        int unique_value_count = 0;
-        int[] value_count_list = new int[max_delta_value+1];
-        for(int value:ts_block_delta){
-            if(value_count_list[value]==0){
-                value_count_list[value] = 1;
-                value_list[unique_value_count] = value;
-                unique_value_count ++;
-            }else{
-                value_count_list[value] ++;
-            }
-        }
-
-        int left_shift = getBitWith(block_size);
-        int mask =  (1 << left_shift) - 1;
-        long[] sorted_value_list = new long[unique_value_count];
-        int count = 0;
-
-        for(int i=0;i<unique_value_count;i++){
-            int value = value_list[i];
-            sorted_value_list[i] = (((long) value) << left_shift) + value_count_list[value];
-        }
-        Arrays.sort(sorted_value_list);
-
-        for(int i=0;i<unique_value_count;i++){
-            count += getCount(sorted_value_list[i], mask);
-            sorted_value_list[i] = (((long)getUniqueValue(sorted_value_list[i], left_shift) ) << left_shift) + count;//new_value_list[i]
-        }
-
-
-        int final_k_start_value = -1;
-        int final_k_end_value = max_delta_value+1;
-
-        int min_bits = 0;
-        min_bits += (getBitWith(final_k_end_value - final_k_start_value ) * (block_size));
-
-        for (int end_value_i = 1; end_value_i < unique_value_count; end_value_i++) {
-
-            int k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
-
-            int cur_bits = 0;
-            int cur_k2;
-            int cur_k1 = 0;
-            int k_start_value = -1;
-            cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
-            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
-            if (cur_k1 + cur_k2 != block_size)
-                cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(k_end_value- k_start_value -2);
-            if (cur_k2 != 0)
-                cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value + 1);//min_upper_outlier
-
-
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_end_value = k_end_value;
-            }
-        }
-
-
-        int start_value_size =  unique_value_count;
-        for (int start_value_i = 0; start_value_i < start_value_size; start_value_i++) {
-            int k_start_value =  getUniqueValue(sorted_value_list[start_value_i], left_shift) ;
-
-            int cur_k1 = getCount(sorted_value_list[start_value_i],mask);
-
-            int k_end_value;
-            int cur_bits;
-            int cur_k2;
-            k_end_value = max_delta_value + 1;
-
-            cur_bits = 0;
-            cur_k2 = 0;
-            cur_bits += Math.min((cur_k2 + cur_k1) * getBitWith(block_size-1), block_size + cur_k2 + cur_k1);
-            if (cur_k1 != 0)
-                cur_bits += cur_k1 * getBitWith(k_start_value + 1);
-            if (cur_k1 + cur_k2 != block_size)
-                cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(k_end_value- k_start_value -2);
-
-
-
-            if (cur_bits < min_bits) {
-                min_bits = cur_bits;
-                final_k_start_value = k_start_value;
-                final_k_end_value = k_end_value;
-            }
-
-            for (int end_value_i = start_value_i + 1; end_value_i < unique_value_count; end_value_i++) {
-
-                k_end_value = getUniqueValue(sorted_value_list[end_value_i], left_shift);
-
-                cur_bits = 0;
-                cur_k2 = block_size - getCount(sorted_value_list[end_value_i-1],mask);
-
-                cur_bits += Math.min((cur_k1 + cur_k2) * getBitWith(block_size-1), block_size + cur_k1 + cur_k2);
-                if (cur_k1 != 0)
-                    cur_bits += cur_k1 * getBitWith(k_start_value);
-                if (cur_k1 + cur_k2 != block_size)
-                    cur_bits += (block_size - cur_k1 - cur_k2) * getBitWith(k_end_value - k_start_value-2);
-                if (cur_k2 != 0)
-                    cur_bits += cur_k2 * getBitWith(max_delta_value - k_end_value);
-
-
-                if (cur_bits < min_bits) {
-                    min_bits = cur_bits;
-                    final_k_start_value = k_start_value;
-                    final_k_end_value = k_end_value;
-                }
-
-            }
-        }
-
-
-        encode_pos = BOSEncodeBits(ts_block_delta,  final_k_start_value, final_k_end_value, max_delta_value,
-                min_delta, encode_pos , cur_byte);
-
-        return encode_pos;
-    }
-
-
-    public static int BOSEncoder(
-            int[] data, int block_size, byte[] encoded_result) {
-        block_size++;
-
-        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;
-
-        for (int i = 0; i < block_num; i++) {
-            encode_pos =  BOSBlockEncoder(data, i, block_size, block_size,encode_pos,encoded_result);
-        }
-
-        int remaining_length = length_all - block_num * block_size;
-        if (remaining_length <= 3) {
-            for (int i = remaining_length; i > 0; i--) {
-                int2Bytes(data[data.length - i], encode_pos, encoded_result);
-                encode_pos += 4;
-            }
-
-        }
-        else {
-
-            int start = block_num * block_size;
-            int remaining = length_all-start;
-            encode_pos = BOSBlockEncoder(data, block_num, block_size,remaining, encode_pos,encoded_result);
-
-        }
-
-
-        return encode_pos;
-    }
-
-    public static int BOSBlockDecoder(byte[] encoded, int decode_pos, int[] value_list, int block_size, int[] value_pos_arr) {
-
-
-        int k_byte = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-        int k1_byte = (int) (k_byte % pow(2, 16));
-        int k1 = k1_byte / 2;
-        int final_alpha = k1_byte % 2;
-
-        int k2 = (int) (k_byte / pow(2, 16));
-
-        int value0 = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-        value_list[value_pos_arr[0]] =value0;
-        value_pos_arr[0] ++;
-
-        int min_delta = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int final_k_start_value = bytes2Integer(encoded, decode_pos, 4);
-        decode_pos += 4;
-
-        int bit_width_final = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        int left_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-        int right_bit_width = bytes2Integer(encoded, decode_pos, 1);
-        decode_pos += 1;
-
-        ArrayList<Integer> final_left_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier_index = new ArrayList<>();
-        ArrayList<Integer> final_left_outlier = new ArrayList<>();
-        ArrayList<Integer> final_right_outlier = new ArrayList<>();
-        ArrayList<Integer> final_normal= new ArrayList<>();;
-        ArrayList<Integer> bitmap_outlier = new ArrayList<>();
-
-
-        if (final_alpha == 0) {
-            int bitmap_bytes = (int) Math.ceil((double) (block_size + k1 + k2) / (double) 8);
-            for (int i = 0; i < bitmap_bytes; i++) {
-                bitmap_outlier.add(bytes2Integer(encoded, decode_pos, 1));
-                decode_pos += 1;
-            }
-            int bitmap_outlier_i = 0;
-            int remaining_bits = 8;
-            int tmp = bitmap_outlier.get(bitmap_outlier_i);
-            bitmap_outlier_i++;
-            int i = 0;
-            while (i < block_size ) {
-                if (remaining_bits > 1) {
-                    int bit_i = (tmp >> (remaining_bits - 1)) & 0x1;
-                    remaining_bits -= 1;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                    if (remaining_bits == 0) {
-                        remaining_bits = 8;
-                        if (bitmap_outlier_i >= bitmap_bytes) break;
-                        tmp = bitmap_outlier.get(bitmap_outlier_i);
-                        bitmap_outlier_i++;
-                    }
-                } else if (remaining_bits == 1) {
-                    int bit_i = tmp & 0x1;
-                    remaining_bits = 8;
-                    if (bitmap_outlier_i >= bitmap_bytes) break;
-                    tmp = bitmap_outlier.get(bitmap_outlier_i);
-                    bitmap_outlier_i++;
-                    if (bit_i == 1) {
-                        int bit_left_right = (tmp >> (remaining_bits - 1)) & 0x1;
-                        remaining_bits -= 1;
-                        if (bit_left_right == 1) {
-                            final_left_outlier_index.add(i);
-                        } else {
-                            final_right_outlier_index.add(i);
-                        }
-                    }
-                }
-                i++;
-            }
-        } else {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k1, decode_pos_result_left);
-            decode_pos = (decode_pos_result_left.get(0));
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier_index = decodeOutlier2Bytes(encoded, decode_pos, getBitWith(block_size-1), k2, decode_pos_result_right);
-            decode_pos = (decode_pos_result_right.get(0));
-        }
-
-
-        ArrayList<Integer> decode_pos_normal = new ArrayList<>();
-//        if(k1+k2!=block_size)
-            final_normal = decodeOutlier2Bytes(encoded, decode_pos, bit_width_final, block_size - k1 - k2, decode_pos_normal);
-
-        decode_pos = decode_pos_normal.get(0);
-        if (k1 != 0) {
-            ArrayList<Integer> decode_pos_result_left = new ArrayList<>();
-            final_left_outlier = decodeOutlier2Bytes(encoded, decode_pos, left_bit_width, k1, decode_pos_result_left);
-            decode_pos = decode_pos_result_left.get(0);
-        }
-        if (k2 != 0) {
-            ArrayList<Integer> decode_pos_result_right = new ArrayList<>();
-            final_right_outlier = decodeOutlier2Bytes(encoded, decode_pos, right_bit_width, k2, decode_pos_result_right);
-            decode_pos = decode_pos_result_right.get(0);
-        }
-        int left_outlier_i = 0;
-        int right_outlier_i = 0;
-        int normal_i = 0;
-        int pre_v = value0;
-        int final_k_end_value = (int) (final_k_start_value + pow(2, bit_width_final));
-
-
-        for (int i = 0; i < block_size; i++) {
-            int current_delta;
-            if (left_outlier_i >= k1) {
-                if (right_outlier_i >= k2) {
-                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta = min_delta + final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
-                    normal_i++;
-                }
-            } else if (i == final_left_outlier_index.get(left_outlier_i)) {
-                current_delta = min_delta + final_left_outlier.get(left_outlier_i);
-                left_outlier_i++;
-            } else {
-
-                if (right_outlier_i >= k2) {
-                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
-                    normal_i++;
-                } else if (i == final_right_outlier_index.get(right_outlier_i)) {
-                    current_delta = min_delta + final_right_outlier.get(right_outlier_i) + final_k_end_value;
-                    right_outlier_i++;
-                } else {
-                    current_delta = min_delta + final_normal.get(normal_i) + final_k_start_value;
-                    normal_i++;
-                }
-            }
-
-            pre_v = current_delta + pre_v;
-            value_list[value_pos_arr[0]] = pre_v;
-            value_pos_arr[0]++;
-        }
-        return decode_pos;
-    }
-
-    public static void BOSDecoder(byte[] encoded) {
-
-        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[] value_list = new int[length_all+block_size];
-        block_size--;
-
-        int[] value_pos_arr = new int[1];
-        for (int k = 0; k < block_num; k++) {
-
-
-            decode_pos = BOSBlockDecoder(encoded, decode_pos, value_list, block_size,value_pos_arr);
-
-        }
-
-        if (remain_length <= 3) {
-            for (int i = 0; i < remain_length; i++) {
-                int value_end = bytes2Integer(encoded, decode_pos, 4);
-                decode_pos += 4;
-                value_list[value_pos_arr[0]] = value_end;
-                value_pos_arr[0]++;
-            }
-        } else {
-            remain_length --;
-            BOSBlockDecoder(encoded, decode_pos, value_list, remain_length, value_pos_arr);
-        }
-    }
-
-    @Test
-    public void BOSOptimalTest() throws IOException {
-//        String parent_dir = "/Users/xiaojinzhao/Desktop/encoding-outlier/"; // your data path
-        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
-        String output_parent_dir = parent_dir + "vldb/compression_ratio/bos";
-        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<>();
-        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");
-
-        for (String value : dataset_name) {
-            input_path_list.add(input_parent_dir + value);
-            dataset_block_size.add(1024);
-        }
-
-        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(2048);
-        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
-//        dataset_block_size.add(1024);
-        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
-//        dataset_block_size.add(1024);
-        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
-//        dataset_block_size.add(2048);
-        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
-//        dataset_block_size.add(1024);
-
-        int repeatTime2 = 100;
-        for (int file_i = 8; file_i < 9; file_i++) {
-//
-//        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
-
-            String inputPath = input_path_list.get(file_i);
-            System.out.println(inputPath);
-            String Output = output_path_list.get(file_i);
-
-            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) {
-//                f=tempList[2];
-                System.out.println(f);
-                InputStream inputStream = Files.newInputStream(f.toPath());
-
-                CsvReader loader = new CsvReader(inputStream, StandardCharsets.UTF_8);
-                ArrayList<Integer> data1 = new ArrayList<>();
-                ArrayList<Integer> data2 = new ArrayList<>();
-
-
-                loader.readHeaders();
-                while (loader.readRecord()) {
-//                        String value = loader.getValues()[index];
-                    data1.add(Integer.valueOf(loader.getValues()[0]));
-                    data2.add(Integer.valueOf(loader.getValues()[1]));
-//                        data.add(Integer.valueOf(value));
-                }
-                inputStream.close();
-                int[] data2_arr = new int[data1.size()];
-                for(int i = 0;i<data2.size();i++){
-                    data2_arr[i] = data2.get(i);
-                }
-                byte[] encoded_result = new byte[data2_arr.length*4];
-                long encodeTime = 0;
-                long decodeTime = 0;
-                double ratio = 0;
-                double compressed_size = 0;
-
-
-                int length = 0;
-
-                long s = System.nanoTime();
-                for (int repeat = 0; repeat < repeatTime2; repeat++) {
-                    length =  BOSEncoder(data2_arr, dataset_block_size.get(file_i), encoded_result);
-                }
-
-                long e = System.nanoTime();
-                encodeTime += ((e - s) / repeatTime2);
-                compressed_size += length;
-                double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
-                ratio += ratioTmp;
-                s = System.nanoTime();
-                for (int repeat = 0; repeat < repeatTime2; repeat++)
-                    BOSDecoder(encoded_result);
-                e = System.nanoTime();
-                decodeTime += ((e - s) / repeatTime2);
-
-
-                String[] record = {
-                        f.toString(),
-                        "TS_2DIFF+BOS-O",
-                        String.valueOf(encodeTime),
-                        String.valueOf(decodeTime),
-                        String.valueOf(data1.size()),
-                        String.valueOf(compressed_size),
-                        String.valueOf(ratio)
-                };
-                writer.writeRecord(record);
-                System.out.println(ratio);
-//                break;
-            }
-            writer.close();
-        }
-    }
-
-    @Test
-    public void BOSVaryBlockSize() throws IOException {
-        String parent_dir = "/Users/zihanguo/Downloads/R/outlier/outliier_code/encoding-outlier/";
-//        String parent_dir = "/Users/xiaojinzhao/Desktop/encoding-outlier/"; // your data path
-        String output_parent_dir = parent_dir + "vldb/compression_ratio/block_size_bos";
-        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<>();
-        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");
-
-        for (String value : dataset_name) {
-            input_path_list.add(input_parent_dir + value);
-        }
-
-        output_path_list.add(output_parent_dir + "/CS-Sensors_ratio.csv"); // 0
-        output_path_list.add(output_parent_dir + "/Metro-Traffic_ratio.csv");// 1
-        output_path_list.add(output_parent_dir + "/USGS-Earthquakes_ratio.csv");// 2
-
-        output_path_list.add(output_parent_dir + "/YZ-Electricity_ratio.csv"); // 3
-
-        output_path_list.add(output_parent_dir + "/GW-Magnetic_ratio.csv"); //4
-
-        output_path_list.add(output_parent_dir + "/TY-Fuel_ratio.csv");//5
-
-        output_path_list.add(output_parent_dir + "/Cyber-Vehicle_ratio.csv"); //6
-
-        output_path_list.add(output_parent_dir + "/Vehicle-Charge_ratio.csv");//7
-
-        output_path_list.add(output_parent_dir + "/Nifty-Stocks_ratio.csv");//8
-
-        output_path_list.add(output_parent_dir + "/TH-Climate_ratio.csv");//9
-
-        output_path_list.add(output_parent_dir + "/TY-Transport_ratio.csv");//10
-
-        output_path_list.add(output_parent_dir + "/EPM-Education_ratio.csv");//11
-
-        int repeatTime2 = 100;
-//        for (int file_i = 9; file_i < 10; file_i++) {
-        for (int file_i = 0; file_i < input_path_list.size(); file_i++) {
-
-            String inputPath = input_path_list.get(file_i);
-            System.out.println(inputPath);
-            String Output = output_path_list.get(file_i);
-
-
-            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",
-                    "Block 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<Integer> data1 = new ArrayList<>();
-                ArrayList<Integer> data2 = new ArrayList<>();
-
-
-                loader.readHeaders();
-
-                while (loader.readRecord()) {
-                    data1.add(Integer.valueOf(loader.getValues()[0]));
-                    data2.add(Integer.valueOf(loader.getValues()[1]));
-                }
-                inputStream.close();
-                int[] data2_arr = new int[data1.size()];
-                for(int i = 0;i<data2.size();i++){
-                    data2_arr[i] = data2.get(i);
-                }
-                byte[] encoded_result = new byte[data2_arr.length*4];
-
-//                for (int block_size_i = 6; block_size_i > 5; block_size_i--) {
-                for (int block_size_i = 13; block_size_i > 4; block_size_i--) {
-                    int block_size = (int) Math.pow(2, block_size_i);
-                    System.out.println(block_size);
-                    long encodeTime = 0;
-                    long decodeTime = 0;
-                    double ratio = 0;
-                    double compressed_size = 0;
-
-
-                    long s = System.nanoTime();
-                    for (int repeat = 0; repeat < repeatTime2; repeat++) {
-                        compressed_size = BOSEncoder(data2_arr, block_size, encoded_result);
-                    }
-
-                    long e = System.nanoTime();
-                    encodeTime += ((e - s) / repeatTime2);
-                    double ratioTmp = compressed_size / (double) (data1.size() * Integer.BYTES);
-                    ratio += ratioTmp;
-                    s = System.nanoTime();
-                    for (int repeat = 0; repeat < repeatTime2; repeat++)
-                        BOSDecoder(encoded_result);
-                    e = System.nanoTime();
-                    decodeTime += ((e - s) / repeatTime2);
-
-                    String[] record = {
-                            f.toString(),
-                            "TS_2DIFF+BOS-V",
-                            String.valueOf(encodeTime),
-                            String.valueOf(decodeTime),
-                            String.valueOf(data1.size()),
-                            String.valueOf(compressed_size),
-                            String.valueOf(block_size_i),
-                            String.valueOf(ratio)
-                    };
-                    writer.writeRecord(record);
-                    System.out.println(ratio);
-
-                }
-
-            }
-            writer.close();
-
-        }
-    }
-
-
-
-}
diff --git a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/myPFOR.java b/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/myPFOR.java
deleted file mode 100644
index 03b33ab..0000000
--- a/iotdb-core/tsfile/src/test/java/org/apache/iotdb/tsfile/encoding/myPFOR.java
+++ /dev/null
@@ -1,333 +0,0 @@
-package org.apache.iotdb.tsfile.encoding;
-
-
-import com.kamikaze.pfordelta.Simple16;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Random;
-
-public class myPFOR {
-    // NOTE: we expect the blockSize is always < (1<<(31-POSSIBLE_B_BITS)).
-    // For example, in the current default settings,
-    // the blockSize < (1<<(31-5)), that is, < 2^27, the commonly used block
-    // size is 128 or 256.
-
-    // All possible values of b in the PForDelta algorithm
-    private static final int[] POSSIBLE_B = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
-            10, 11, 12, 13, 16, 20, 28};
-    private static final int MAX_BITS = 32;
-
-    private static final int HEADER_NUM = 4;
-    private static final int HEADER_SIZE = MAX_BITS * HEADER_NUM;
-    private static int min = Integer.MAX_VALUE;
-
-    public static int[] compressOneBlockOpt(final int[] inBlock,
-                                            int blockSize) {
-        // find the best b that may lead to the smallest overall
-        // compressed size
-        int[] inBlock2 = new int[blockSize];
-        min = Integer.MAX_VALUE;
-        for (int k : inBlock) {
-            if (k < min) {
-                min = k;
-            }
-        }
-        for (int j = 0; j < inBlock.length; j++){
-            inBlock2[j] = inBlock[j] - min;
-        }
-        int currentB = POSSIBLE_B[0];
-        int[] outBlock = null;
-        int tmpB = currentB;
-        int optSize = estimateCompressedSize(inBlock2, tmpB,
-                blockSize);
-        for (int i = 1; i < POSSIBLE_B.length; ++i) {
-            tmpB = POSSIBLE_B[i];
-            int curSize = estimateCompressedSize(inBlock2,
-                    tmpB, blockSize);
-            if (curSize < optSize) {
-                currentB = tmpB;
-                optSize = curSize;
-            }
-        }
-        // 使用相同的b分block压缩
-        outBlock = compressOneBlock(inBlock2, currentB, blockSize);
-
-        return outBlock;
-    }
-
-    public static int decompressOneBlock(int[] outBlock, final int[] inBlock,
-                                         int blockSize) {
-        int[] expAux = new int[blockSize];
-
-        int expNum = inBlock[1];
-        int bits = inBlock[0];
-        int index_first_exp = inBlock[2];
-        min = inBlock[3];
-
-        int offset = HEADER_SIZE;
-        int compressedBits = 0;
-        if (bits == 0) {
-            Arrays.fill(outBlock, 0);
-        } else {
-
-            compressedBits = decompressBBitSlots(outBlock, inBlock,
-                    blockSize, bits);
-        }
-        offset += compressedBits;
-
-
-        if (expNum > 0) {
-            compressedBits = decompressBlockByS16(expAux, inBlock,
-                    offset, expNum);
-            offset += compressedBits;
-
-            int exp_index = index_first_exp;
-            int shift;
-            for (int i = 0; i < expNum; i++) {
-                int exp_value = expAux[i];
-                shift = outBlock[exp_index];
-                outBlock[exp_index] = exp_value;
-                exp_index += (shift + 1);
-            }
-
-        }
-
-        for (int i = 0; i < blockSize; i++){
-            outBlock[i] += min;
-        }
-        return offset;
-    }
-
-    public static int estimateCompressedSize(int[] inputBlock, int bits,
-                                             int blockSize)  {
-        int maxNoExp = (1 << bits) - 1;
-        // Size of the header and the bits-bit slots
-        int outputOffset = HEADER_SIZE + bits * blockSize;
-        int expNum = 0;
-
-        for (int i = 0; i < blockSize; ++i) {
-            if (inputBlock[i] > maxNoExp) {
-                expNum++;
-            }
-        }
-        outputOffset += (expNum << 5);
-
-        return outputOffset;
-    }
-
-    public static int[] compressOneBlock(int[] inputBlock, int bits,
-                                         int blockSize)  {
-        int maxCompBitSize = HEADER_SIZE + blockSize
-                * (MAX_BITS + MAX_BITS + MAX_BITS) + 32;
-
-        int[] tmpCompressedBlock = new int[(maxCompBitSize >>> 5)];
-
-        int outputOffset = HEADER_SIZE;
-        int expUpperBound = 1 << bits;
-        int expNum = 0;
-        int expNum_more = 0;
-        ArrayList<Integer> exp_index = new ArrayList<>();
-        ArrayList<Integer> exp_index_more = new ArrayList<>();
-        ArrayList<Integer> shift = new ArrayList<>();
-        ArrayList<Integer> exp_value = new ArrayList<>();
-        ArrayList<Integer> exp_value_more = new ArrayList<>();
-        for (int i = 0; i < inputBlock.length; i++) {
-            if (inputBlock[i] >= expUpperBound) {
-                expNum++;
-                exp_value.add(inputBlock[i]);
-                exp_index.add(i);
-            }
-        }
-
-        if (expNum == 0){
-
-            for (int i = 0; i < blockSize; i++){
-                writeBits(tmpCompressedBlock, inputBlock[i], outputOffset, bits);
-                outputOffset += bits;
-            }
-        } else if (expNum == 1) {
-
-            for (int i = 0; i < blockSize; i++){
-                if (i != exp_index.get(0)){
-                    writeBits(tmpCompressedBlock, inputBlock[i], outputOffset, bits);
-                }else {
-                    writeBits(tmpCompressedBlock, 0, outputOffset, bits);
-                }
-                outputOffset += bits;
-            }
-        }else {
-
-            exp_index_more.add(exp_index.get(0));
-            exp_value_more.add(exp_value.get(0));
-            expNum_more++;
-            for (int i = 0; i < expNum - 1; i++){
-                if (exp_index.get(i + 1) - exp_index.get(i) <= (1 << bits)){
-
-                    exp_index_more.add(exp_index.get(i + 1));
-                    exp_value_more.add(exp_value.get(i + 1));
-                    expNum_more++;
-                    shift.add(exp_index.get(i + 1) - exp_index.get(i) - 1);
-                }else {
-
-                    int tag = exp_index.get(i);
-                    while (exp_index.get(i + 1) - tag > (1 << bits)){
-
-                        tag += (1 << bits);
-                        expNum_more++;
-                        exp_index_more.add(tag);
-                        exp_value_more.add(inputBlock[tag]);
-                        shift.add((1 << bits) - 1);
-                    }
-
-                    exp_index_more.add(exp_index.get(i + 1));
-                    exp_value_more.add(exp_value.get(i + 1));
-                    expNum_more++;
-                    shift.add(exp_index.get(i + 1) - tag - 1);
-                }
-            }
-            shift.add(0);
-
-            int j = 0;
-            for (int i = 0; i < blockSize; i++){
-                if (j < expNum_more && exp_index_more.get(j) == i){
-
-                    writeBits(tmpCompressedBlock, shift.get(j), outputOffset, bits);
-                    j++;
-                }else {
-
-                    writeBits(tmpCompressedBlock, inputBlock[i], outputOffset, bits);
-                }
-                outputOffset += bits;
-            }
-        }
-
-        tmpCompressedBlock[0] = bits;
-        tmpCompressedBlock[1] = expNum;
-        if (tmpCompressedBlock[1] > 1){
-            tmpCompressedBlock[1] = expNum_more;
-        }
-        if (expNum > 0){
-            tmpCompressedBlock[2] = exp_index.get(0);
-        }else{
-            tmpCompressedBlock[2] = 0;
-        }
-        tmpCompressedBlock[3] = min;
-
-        if (expNum == 1){
-            int[] expAux = new int[1];
-            expAux[0] = exp_value.get(0);
-            int compressedBitSize = compressBlockByS16(
-                    tmpCompressedBlock, outputOffset, expAux,
-                    expNum);
-            outputOffset += compressedBitSize;
-        }
-        else if (expNum > 1) {
-
-            int[] expAux = new int[expNum_more];
-            for (int i = 0; i < expNum_more; i++){
-                expAux[i] = exp_value_more.get(i);
-            }
-            int compressedBitSize = compressBlockByS16(
-                    tmpCompressedBlock, outputOffset, expAux,
-                    expNum_more);
-            outputOffset += compressedBitSize;
-        }
-
-        int compressedSizeInInts = (outputOffset + 31) >>> 5;
-        int[] compBlock;
-        compBlock = new int[compressedSizeInInts];
-        System.arraycopy(tmpCompressedBlock, 0, compBlock, 0,
-                compressedSizeInInts);
-
-        return compBlock;
-    }
-    public static int decompressBBitSlots(int[] outDecompSlots,
-                                          int[] inCompBlock, int blockSize, int bits) {
-        int compressedBitSize = 0;
-        int offset = HEADER_SIZE;
-        for (int i = 0; i < blockSize; i++) {
-            outDecompSlots[i] = readBits(inCompBlock, offset, bits);
-            offset += bits;
-        }
-        compressedBitSize = bits * blockSize;
-
-        return compressedBitSize;
-    }
-
-    private static int compressBlockByS16(int[] outCompBlock,
-                                          int outStartOffsetInBits, int[] inBlock, int blockSize) {
-        int outOffset = (outStartOffsetInBits + 31) >>> 5;
-        int num, inOffset = 0, numLeft;
-        for (numLeft = blockSize; numLeft > 0; numLeft -= num) {
-            num = Simple16.s16Compress(outCompBlock, outOffset,
-                    inBlock, inOffset, numLeft, blockSize);
-            outOffset++;
-            inOffset += num;
-        }
-        int compressedBitSize = (outOffset << 5) - outStartOffsetInBits;
-        return compressedBitSize;
-    }
-
-    public static int decompressBlockByS16(int[] outDecompBlock,
-                                           int[] inCompBlock, int inStartOffsetInBits, int blockSize) {
-        int inOffset = (inStartOffsetInBits + 31) >>> 5;
-        int num, outOffset = 0, numLeft;
-        for (numLeft = blockSize; numLeft > 0; numLeft -= num) {
-            num = Simple16.s16Decompress(outDecompBlock, outOffset,
-                    inCompBlock, inOffset, numLeft);
-            outOffset += num;
-            inOffset++;
-        }
-        int compressedBitSize = (inOffset << 5) - inStartOffsetInBits;
-        return compressedBitSize;
-    }
-
-    public static void writeBits(int[] out, int val, int outOffset,
-                                 int bits) {
-        if (bits == 0)
-            return;
-        final int index = outOffset >>> 5;
-        final int skip = outOffset & 0x1f;
-        val &= (0xffffffff >>> (32 - bits));
-        out[index] |= (val << skip);
-        if (32 - skip < bits) {
-            out[index + 1] |= (val >>> (32 - skip));
-        }
-    }
-
-    public static int readBits(int[] in, final int inOffset,
-                               final int bits) {
-        final int index = inOffset >>> 5;
-        final int skip = inOffset & 0x1f;
-        int val = in[index] >>> skip;
-        if (32 - skip < bits) {
-            val |= (in[index + 1] << (32 - skip));
-        }
-        return val & (0xffffffff >>> (32 - bits));
-    }
-
-    public static void main(@NotNull String[] args) throws IOException {
-        int length = 75809;
-        int width = 10000000;
-        int[] timeSeries = new int[length];
-        Random rand = new Random();
-
-        for (int i = 0; i < length; i++) {
-            timeSeries[i] = rand.nextInt(width) - width/2;
-        }
-        int[] outBlock;
-        outBlock = compressOneBlockOpt(timeSeries,length);
-        int[] uncompressed = new int[length];
-        int size = decompressOneBlock(uncompressed,outBlock,length);
-        System.out.println(size);
-        System.out.println(uncompressed.length);
-        for (int i = 0; i < length; i++){
-            if (timeSeries[i] != uncompressed[i]){
-                System.out.println(i);
-            }
-        }
-    }
-}