Index: thirdparty/SZ/sz/src/szd_double.c
===================================================================
--- thirdparty/SZ/sz/src/szd_double.c	(revision 2c47b734c78138a26f64051bee9d14ecd93594b3)
+++ thirdparty/SZ/sz/src/szd_double.c	(revision 9ee2ce3c0d78f4ec0c8dee6bba00cac6e8b2f339)
@@ -17,4 +17,5 @@
 #include "szd_double_pwr.h"
 #include "szd_double_ts.h"
+#include "utility.h"
 
 int SZ_decompress_args_double(double** newData, size_t r5, size_t r4, size_t r3, size_t r2, size_t r1, unsigned char* cmpBytes, size_t cmpSize)
@@ -30,8 +31,8 @@
 	if(cmpSize!=12+4+MetaDataByteLength && cmpSize!=12+8+MetaDataByteLength)
 	{
-		int isZlib = isZlibFormat(cmpBytes[0], cmpBytes[1]);
+		confparams_dec->losslessCompressor = is_lossless_compressed_data(cmpBytes, cmpSize);
 		if(confparams_dec->szMode!=SZ_TEMPORAL_COMPRESSION)
 		{
-			if(isZlib)
+			if(confparams_dec->losslessCompressor!=-1)
 				confparams_dec->szMode = SZ_BEST_COMPRESSION;
 			else
@@ -47,5 +48,5 @@
 			if(targetUncompressSize<MIN_ZLIB_DEC_ALLOMEM_BYTES) //Considering the minimum size
 				targetUncompressSize = MIN_ZLIB_DEC_ALLOMEM_BYTES; 			
-			tmpSize = zlib_uncompress5(cmpBytes, (unsigned long)cmpSize, &szTmpBytes, (unsigned long)targetUncompressSize+4+MetaDataByteLength+exe_params->SZ_SIZE_TYPE);			
+			tmpSize = sz_lossless_decompress(confparams_dec->losslessCompressor, cmpBytes, (unsigned long)cmpSize, &szTmpBytes, (unsigned long)targetUncompressSize+4+MetaDataByteLength+exe_params->SZ_SIZE_TYPE);			
 			//szTmpBytes = (unsigned char*)malloc(sizeof(unsigned char)*tmpSize);
 			//memcpy(szTmpBytes, tmpBytes, tmpSize);
@@ -81,20 +82,43 @@
 		}		
 	}
-	else if (dim == 1)
-		getSnapshotData_double_1D(newData,r1,tdps, errBoundMode);
-	else
-	if (dim == 2)
-		getSnapshotData_double_2D(newData,r2,r1,tdps, errBoundMode);
-	else
-	if (dim == 3)
-		getSnapshotData_double_3D(newData,r3,r2,r1,tdps, errBoundMode);
-	else
-	if (dim == 4)
-		getSnapshotData_double_4D(newData,r4,r3,r2,r1,tdps, errBoundMode);
-	else
+	else 
 	{
-		printf("Error: currently support only at most 4 dimensions!\n");
-		status = SZ_DERR;
-	}
+		if(tdps->raBytes_size > 0) //v2.0
+		{
+			if (dim == 1)
+				getSnapshotData_double_1D(newData,r1,tdps, errBoundMode);
+			else if(dim == 2)
+				decompressDataSeries_double_2D_nonblocked_with_blocked_regression(newData, r2, r1, tdps->raBytes);
+			else if(dim == 3)
+				decompressDataSeries_double_3D_nonblocked_with_blocked_regression(newData, r3, r2, r1, tdps->raBytes);
+			else if(dim == 4)
+				decompressDataSeries_double_3D_nonblocked_with_blocked_regression(newData, r4*r3, r2, r1, tdps->raBytes);
+			else
+			{
+				printf("Error: currently support only at most 4 dimensions!\n");
+				status = SZ_DERR;
+			}	
+		}
+		else //1.4.13
+		{
+			if (dim == 1)
+				getSnapshotData_double_1D(newData,r1,tdps, errBoundMode);
+			else
+			if (dim == 2)
+				getSnapshotData_double_2D(newData,r2,r1,tdps, errBoundMode);
+			else
+			if (dim == 3)
+				getSnapshotData_double_3D(newData,r3,r2,r1,tdps, errBoundMode);
+			else
+			if (dim == 4)
+				getSnapshotData_double_4D(newData,r4,r3,r2,r1,tdps, errBoundMode);			
+			else
+			{
+				printf("Error: currently support only at most 4 dimensions!\n");
+				status = SZ_DERR;
+			}			
+		}
+	}	
+
 	free_TightDataPointStorageD2(tdps);
 	if(confparams_dec->szMode!=SZ_BEST_SPEED && cmpSize!=12+MetaDataByteLength+exe_params->SZ_SIZE_TYPE)
@@ -1648,6 +1672,6 @@
 			else 
 			{
-				//decompressDataSeries_double_1D_pwr(data, dataSeriesLength, tdps);
-				decompressDataSeries_double_1D_pwrgroup(data, dataSeriesLength, tdps);
+				decompressDataSeries_double_1D_pwr_pre_log(data, dataSeriesLength, tdps);
+				//decompressDataSeries_double_1D_pwrgroup(data, dataSeriesLength, tdps);
 			}
 			return;
@@ -1672,5 +1696,6 @@
 				decompressDataSeries_double_1D(&decmpData, dataSeriesLength, tdps);
 			else 
-				decompressDataSeries_double_1D_pwr(&decmpData, dataSeriesLength, tdps);
+				//decompressDataSeries_double_1D_pwr(&decmpData, dataSeriesLength, tdps);
+				decompressDataSeries_double_1D_pwr_pre_log(&decmpData, dataSeriesLength, tdps);
 			// insert the decompressed data
 			size_t k = 0;
@@ -1712,5 +1737,6 @@
 			}
 			else 
-				decompressDataSeries_double_2D_pwr(data, r1, r2, tdps);
+				//decompressDataSeries_double_2D_pwr(data, r1, r2, tdps);
+				decompressDataSeries_double_2D_pwr_pre_log(data, r1, r2, tdps);
 			return;
 		} else {
@@ -1734,5 +1760,6 @@
 				decompressDataSeries_double_2D(&decmpData, r1, r2, tdps);
 			else 
-				decompressDataSeries_double_2D_pwr(&decmpData, r1, r2, tdps);
+				//decompressDataSeries_double_2D_pwr(&decmpData, r1, r2, tdps);
+				decompressDataSeries_double_2D_pwr_pre_log(&decmpData, r1, r2, tdps);
 			// insert the decompressed data
 			size_t k = 0;
@@ -1774,5 +1801,6 @@
 			}
 			else 
-				decompressDataSeries_double_3D_pwr(data, r1, r2, r3, tdps);
+				//decompressDataSeries_double_3D_pwr(data, r1, r2, r3, tdps);
+				decompressDataSeries_double_3D_pwr_pre_log(data, r1, r2, r3, tdps);
 			return;
 		} else {
@@ -1796,5 +1824,6 @@
 				decompressDataSeries_double_3D(&decmpData, r1, r2, r3, tdps);
 			else 
-				decompressDataSeries_double_3D_pwr(&decmpData, r1, r2, r3, tdps);			
+				//decompressDataSeries_double_3D_pwr(&decmpData, r1, r2, r3, tdps);			
+				decompressDataSeries_double_3D_pwr_pre_log(&decmpData, r1, r2, r3, tdps);			
 			// insert the decompressed data
 			size_t k = 0;
@@ -1837,5 +1866,6 @@
 			else 
 			{
-				decompressDataSeries_double_3D_pwr(data, r1*r2, r3, r4, tdps);
+				//decompressDataSeries_double_3D_pwr(data, r1*r2, r3, r4, tdps);
+				decompressDataSeries_double_3D_pwr_pre_log(data, r1*r2, r3, r4, tdps);
 				//ToDO
 				//decompressDataSeries_double_4D_pwr(data, r1, r2, r3, r4, tdps);
@@ -1859,5 +1889,6 @@
 				decompressDataSeries_double_4D(&decmpData, r1, r2, r3, r4, tdps);
 			else
-				decompressDataSeries_double_3D_pwr(&decmpData, r1*r2, r3, r4, tdps);
+				//decompressDataSeries_double_3D_pwr(&decmpData, r1*r2, r3, r4, tdps);
+				decompressDataSeries_double_3D_pwr_pre_log(&decmpData, r1*r2, r3, r4, tdps);
 				//ToDo
 				//decompressDataSeries_double_4D_pwr(&decmpData, r1, r2, r3, r4, tdps);
@@ -1874,2 +1905,2718 @@
 	}
 }
+
+void decompressDataSeries_double_2D_nonblocked_with_blocked_regression(double** data, size_t r1, size_t r2, unsigned char* comp_data){
+
+	size_t dim0_offset = r2;
+	size_t num_elements = r1 * r2;
+
+	*data = (double*)malloc(sizeof(double)*num_elements);
+
+	unsigned char * comp_data_pos = comp_data;
+
+	size_t block_size = bytesToInt_bigEndian(comp_data_pos);
+	comp_data_pos += sizeof(int);
+	// calculate block dims
+	size_t num_x, num_y;
+	SZ_COMPUTE_3D_NUMBER_OF_BLOCKS(r1, num_x, block_size);
+	SZ_COMPUTE_3D_NUMBER_OF_BLOCKS(r2, num_y, block_size);
+
+	size_t split_index_x, split_index_y;
+	size_t early_blockcount_x, early_blockcount_y;
+	size_t late_blockcount_x, late_blockcount_y;
+	SZ_COMPUTE_BLOCKCOUNT(r1, num_x, split_index_x, early_blockcount_x, late_blockcount_x);
+	SZ_COMPUTE_BLOCKCOUNT(r2, num_y, split_index_y, early_blockcount_y, late_blockcount_y);
+
+	size_t num_blocks = num_x * num_y;
+
+	double realPrecision = bytesToDouble(comp_data_pos);
+	comp_data_pos += sizeof(double);
+	unsigned int intervals = bytesToInt_bigEndian(comp_data_pos);
+	comp_data_pos += sizeof(int);
+
+	updateQuantizationInfo(intervals);
+
+	unsigned int tree_size = bytesToInt_bigEndian(comp_data_pos);
+	comp_data_pos += sizeof(int);
+
+	int stateNum = 2*intervals;
+	HuffmanTree* huffmanTree = createHuffmanTree(stateNum);
+	
+	int nodeCount = bytesToInt_bigEndian(comp_data_pos);
+	
+	node root = reconstruct_HuffTree_from_bytes_anyStates(huffmanTree,comp_data_pos+sizeof(int), nodeCount);
+	comp_data_pos += sizeof(int) + tree_size;
+
+	double mean;
+	unsigned char use_mean;
+	memcpy(&use_mean, comp_data_pos, sizeof(unsigned char));
+	comp_data_pos += sizeof(unsigned char);
+	memcpy(&mean, comp_data_pos, sizeof(double));
+	comp_data_pos += sizeof(double);
+	size_t reg_count = 0;
+
+	unsigned char * indicator;
+	size_t indicator_bitlength = (num_blocks - 1)/8 + 1;
+	convertByteArray2IntArray_fast_1b(num_blocks, comp_data_pos, indicator_bitlength, &indicator);
+	comp_data_pos += indicator_bitlength;
+	for(size_t i=0; i<num_blocks; i++){
+		if(!indicator[i]) reg_count ++;
+	}
+	//printf("reg_count: %ld\n", reg_count);
+
+	int coeff_intvRadius[3];
+	int * coeff_result_type = (int *) malloc(num_blocks*3*sizeof(int));
+	int * coeff_type[3];
+	double precision[3];
+	double * coeff_unpred_data[3];
+	if(reg_count > 0){
+		for(int i=0; i<3; i++){
+			precision[i] = bytesToDouble(comp_data_pos);
+			comp_data_pos += sizeof(double);
+			coeff_intvRadius[i] = bytesToInt_bigEndian(comp_data_pos);
+			comp_data_pos += sizeof(int);
+			unsigned int tree_size = bytesToInt_bigEndian(comp_data_pos);
+			comp_data_pos += sizeof(int);
+			int stateNum = 2*coeff_intvRadius[i]*2;
+			HuffmanTree* huffmanTree = createHuffmanTree(stateNum);	
+			int nodeCount = bytesToInt_bigEndian(comp_data_pos);
+			node root = reconstruct_HuffTree_from_bytes_anyStates(huffmanTree, comp_data_pos+sizeof(int), nodeCount);
+			comp_data_pos += sizeof(int) + tree_size;
+
+			coeff_type[i] = coeff_result_type + i * num_blocks;
+			size_t typeArray_size = bytesToSize(comp_data_pos);
+			decode(comp_data_pos + sizeof(size_t), reg_count, root, coeff_type[i]);
+			comp_data_pos += sizeof(size_t) + typeArray_size;
+			int coeff_unpred_count = bytesToInt_bigEndian(comp_data_pos);
+			comp_data_pos += sizeof(int);
+			coeff_unpred_data[i] = (double *) comp_data_pos;
+			comp_data_pos += coeff_unpred_count * sizeof(double);
+			SZ_ReleaseHuffman(huffmanTree);
+		}
+	}
+	double last_coefficients[3] = {0.0};
+	int coeff_unpred_data_count[3] = {0};
+	int coeff_index = 0;
+	updateQuantizationInfo(intervals);
+
+	size_t total_unpred;
+	memcpy(&total_unpred, comp_data_pos, sizeof(size_t));
+	comp_data_pos += sizeof(size_t);
+	double * unpred_data = (double *) comp_data_pos;
+	comp_data_pos += total_unpred * sizeof(double);
+
+	int * result_type = (int *) malloc(num_elements * sizeof(int));
+	decode(comp_data_pos, num_elements, root, result_type);
+	SZ_ReleaseHuffman(huffmanTree);
+	
+	int intvRadius = exe_params->intvRadius;
+	
+	int * type;
+
+	double * data_pos = *data;
+	size_t offset_x, offset_y;
+	size_t current_blockcount_x, current_blockcount_y;
+	size_t cur_unpred_count;
+
+	unsigned char * indicator_pos = indicator;
+	if(use_mean){
+		type = result_type;
+		for(size_t i=0; i<num_x; i++){
+			for(size_t j=0; j<num_y; j++){
+				offset_x = (i < split_index_x) ? i * early_blockcount_x : i * late_blockcount_x + split_index_x;
+				offset_y = (j < split_index_y) ? j * early_blockcount_y : j * late_blockcount_y + split_index_y;
+				data_pos = *data + offset_x * dim0_offset + offset_y;
+
+				current_blockcount_x = (i < split_index_x) ? early_blockcount_x : late_blockcount_x;
+				current_blockcount_y = (j < split_index_y) ? early_blockcount_y : late_blockcount_y;
+
+				size_t current_block_elements = current_blockcount_x * current_blockcount_y;
+				if(*indicator_pos){
+					// decompress by SZ
+
+					double * block_data_pos = data_pos;
+					double pred;
+					size_t index = 0;
+					int type_;
+					// d11 is current data
+					size_t unpredictable_count = 0;
+					double d00, d01, d10;
+					for(size_t ii=0; ii<current_blockcount_x; ii++){
+						for(size_t jj=0; jj<current_blockcount_y; jj++){
+							type_ = type[index];
+							if(type_ == intvRadius){
+								*block_data_pos = mean;
+							}
+							else if(type_ == 0){
+								*block_data_pos = unpred_data[unpredictable_count ++];
+							}
+							else{
+								d00 = d01 = d10 = 1;
+								if(i == 0 && ii == 0){
+									d00 = d01 = 0;
+								}
+								if(j == 0 && jj == 0){
+									d00 = d10 = 0;
+								}
+								if(d00){
+									d00 = block_data_pos[- dim0_offset - 1];
+								}
+								if(d01){
+									d01 = block_data_pos[- dim0_offset];
+								}
+								if(d10){
+									d10 = block_data_pos[- 1];
+								}
+								if(type_ < intvRadius) type_ += 1;
+								pred = d10 + d01 - d00;
+								*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+							}
+							index ++;
+							block_data_pos ++;
+						}
+						block_data_pos += dim0_offset - current_blockcount_y;
+					}
+					cur_unpred_count = unpredictable_count;
+				}
+				else{
+					// decompress by regression
+					{
+						//restore regression coefficients
+						double pred;
+						int type_;
+						for(int e=0; e<3; e++){
+							type_ = coeff_type[e][coeff_index];
+							if (type_ != 0){
+								pred = last_coefficients[e];
+								last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+							}
+							else{
+								last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+								coeff_unpred_data_count[e] ++;
+							}
+						}
+						coeff_index ++;
+					}
+					{
+						double * block_data_pos = data_pos;
+						double pred;
+						int type_;
+						size_t index = 0;
+						size_t unpredictable_count = 0;
+						for(size_t ii=0; ii<current_blockcount_x; ii++){
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								type_ = type[index];
+								if (type_ != 0){
+									pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2];
+									*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+								}
+								else{
+									*block_data_pos = unpred_data[unpredictable_count ++];
+								}
+
+								index ++;	
+								block_data_pos ++;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+				}
+
+				type += current_block_elements;
+				indicator_pos ++;
+				unpred_data += cur_unpred_count;
+			}
+		}
+	}
+	else{
+		type = result_type;
+		for(size_t i=0; i<num_x; i++){
+			for(size_t j=0; j<num_y; j++){
+				offset_x = (i < split_index_x) ? i * early_blockcount_x : i * late_blockcount_x + split_index_x;
+				offset_y = (j < split_index_y) ? j * early_blockcount_y : j * late_blockcount_y + split_index_y;
+				data_pos = *data + offset_x * dim0_offset + offset_y;
+
+				current_blockcount_x = (i < split_index_x) ? early_blockcount_x : late_blockcount_x;
+				current_blockcount_y = (j < split_index_y) ? early_blockcount_y : late_blockcount_y;
+
+				size_t current_block_elements = current_blockcount_x * current_blockcount_y;
+				if(*indicator_pos){
+					// decompress by SZ
+					
+					double * block_data_pos = data_pos;
+					double pred;
+					size_t index = 0;
+					int type_;
+					// d11 is current data
+					size_t unpredictable_count = 0;
+					double d00, d01, d10;
+					for(size_t ii=0; ii<current_blockcount_x; ii++){
+						for(size_t jj=0; jj<current_blockcount_y; jj++){
+							type_ = type[index];
+							if(type_ == 0){
+								*block_data_pos = unpred_data[unpredictable_count ++];
+							}
+							else{
+								d00 = d01 = d10 = 1;
+								if(i == 0 && ii == 0){
+									d00 = d01 = 0;
+								}
+								if(j == 0 && jj == 0){
+									d00 = d10 = 0;
+								}
+								if(d00){
+									d00 = block_data_pos[- dim0_offset - 1];
+								}
+								if(d01){
+									d01 = block_data_pos[- dim0_offset];
+								}
+								if(d10){
+									d10 = block_data_pos[- 1];
+								}
+								pred = d10 + d01 - d00;
+								*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+							}
+							index ++;
+							block_data_pos ++;
+						}
+						block_data_pos += dim0_offset - current_blockcount_y;
+					}
+					cur_unpred_count = unpredictable_count;
+				}
+				else{
+					// decompress by regression
+					{
+						//restore regression coefficients
+						double pred;
+						int type_;
+						for(int e=0; e<3; e++){
+							type_ = coeff_type[e][coeff_index];
+							if (type_ != 0){
+								pred = last_coefficients[e];
+								last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+							}
+							else{
+								last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+								coeff_unpred_data_count[e] ++;
+							}
+						}
+						coeff_index ++;
+					}
+					{
+						double * block_data_pos = data_pos;
+						double pred;
+						int type_;
+						size_t index = 0;
+						size_t unpredictable_count = 0;
+						for(size_t ii=0; ii<current_blockcount_x; ii++){
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								type_ = type[index];
+								if (type_ != 0){
+									pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2];
+									*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+								}
+								else{
+									*block_data_pos = unpred_data[unpredictable_count ++];
+								}
+								index ++;	
+								block_data_pos ++;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+				}
+
+				type += current_block_elements;
+				indicator_pos ++;
+				unpred_data += cur_unpred_count;
+			}
+		}
+	}
+	free(coeff_result_type);
+
+	free(indicator);
+	free(result_type);
+}
+
+
+void decompressDataSeries_double_3D_nonblocked_with_blocked_regression(double** data, size_t r1, size_t r2, size_t r3, unsigned char* comp_data){
+
+	size_t dim0_offset = r2 * r3;
+	size_t dim1_offset = r3;
+	size_t num_elements = r1 * r2 * r3;
+
+	*data = (double*)malloc(sizeof(double)*num_elements);
+
+	unsigned char * comp_data_pos = comp_data;
+
+	size_t block_size = bytesToInt_bigEndian(comp_data_pos);
+	comp_data_pos += sizeof(int);
+	// calculate block dims
+	size_t num_x, num_y, num_z;
+	SZ_COMPUTE_3D_NUMBER_OF_BLOCKS(r1, num_x, block_size);
+	SZ_COMPUTE_3D_NUMBER_OF_BLOCKS(r2, num_y, block_size);
+	SZ_COMPUTE_3D_NUMBER_OF_BLOCKS(r3, num_z, block_size);
+
+	size_t split_index_x, split_index_y, split_index_z;
+	size_t early_blockcount_x, early_blockcount_y, early_blockcount_z;
+	size_t late_blockcount_x, late_blockcount_y, late_blockcount_z;
+	SZ_COMPUTE_BLOCKCOUNT(r1, num_x, split_index_x, early_blockcount_x, late_blockcount_x);
+	SZ_COMPUTE_BLOCKCOUNT(r2, num_y, split_index_y, early_blockcount_y, late_blockcount_y);
+	SZ_COMPUTE_BLOCKCOUNT(r3, num_z, split_index_z, early_blockcount_z, late_blockcount_z);
+
+	size_t num_blocks = num_x * num_y * num_z;
+
+	double realPrecision = bytesToDouble(comp_data_pos);
+	comp_data_pos += sizeof(double);
+	unsigned int intervals = bytesToInt_bigEndian(comp_data_pos);
+	comp_data_pos += sizeof(int);
+
+	updateQuantizationInfo(intervals);
+
+	unsigned int tree_size = bytesToInt_bigEndian(comp_data_pos);
+	comp_data_pos += sizeof(int);
+	
+	int stateNum = 2*intervals;
+	HuffmanTree* huffmanTree = createHuffmanTree(stateNum);	
+	
+	int nodeCount = bytesToInt_bigEndian(comp_data_pos);
+	node root = reconstruct_HuffTree_from_bytes_anyStates(huffmanTree,comp_data_pos+4, nodeCount);
+	comp_data_pos += sizeof(int) + tree_size;
+
+	double mean;
+	unsigned char use_mean;
+	memcpy(&use_mean, comp_data_pos, sizeof(unsigned char));
+	comp_data_pos += sizeof(unsigned char);
+	memcpy(&mean, comp_data_pos, sizeof(double));
+	comp_data_pos += sizeof(double);
+	size_t reg_count = 0;
+
+	unsigned char * indicator;
+	size_t indicator_bitlength = (num_blocks - 1)/8 + 1;
+	convertByteArray2IntArray_fast_1b(num_blocks, comp_data_pos, indicator_bitlength, &indicator);
+	comp_data_pos += indicator_bitlength;
+	for(size_t i=0; i<num_blocks; i++){
+		if(!indicator[i]) reg_count ++;
+	}
+
+	int coeff_intvRadius[4];
+	int * coeff_result_type = (int *) malloc(num_blocks*4*sizeof(int));
+	int * coeff_type[4];
+	double precision[4];
+	double * coeff_unpred_data[4];
+	if(reg_count > 0){
+		for(int i=0; i<4; i++){
+			precision[i] = bytesToDouble(comp_data_pos);
+			comp_data_pos += sizeof(double);
+			coeff_intvRadius[i] = bytesToInt_bigEndian(comp_data_pos);
+			comp_data_pos += sizeof(int);
+			unsigned int tree_size = bytesToInt_bigEndian(comp_data_pos);
+			comp_data_pos += sizeof(int);
+			int stateNum = 2*coeff_intvRadius[i]*2;
+			HuffmanTree* huffmanTree = createHuffmanTree(stateNum);	
+			int nodeCount = bytesToInt_bigEndian(comp_data_pos);
+			node root = reconstruct_HuffTree_from_bytes_anyStates(huffmanTree, comp_data_pos+4, nodeCount);
+			comp_data_pos += sizeof(int) + tree_size;
+
+			coeff_type[i] = coeff_result_type + i * num_blocks;
+			size_t typeArray_size = bytesToSize(comp_data_pos);
+			decode(comp_data_pos + sizeof(size_t), reg_count, root, coeff_type[i]);
+			comp_data_pos += sizeof(size_t) + typeArray_size;
+			int coeff_unpred_count = bytesToInt_bigEndian(comp_data_pos);
+			comp_data_pos += sizeof(int);
+			coeff_unpred_data[i] = (double *) comp_data_pos;
+			comp_data_pos += coeff_unpred_count * sizeof(double);
+			SZ_ReleaseHuffman(huffmanTree);
+		}
+	}
+	double last_coefficients[4] = {0.0};
+	int coeff_unpred_data_count[4] = {0};
+	int coeff_index = 0;
+	updateQuantizationInfo(intervals);
+
+	size_t total_unpred;
+	memcpy(&total_unpred, comp_data_pos, sizeof(size_t));
+	comp_data_pos += sizeof(size_t);
+	double * unpred_data = (double *) comp_data_pos;
+	comp_data_pos += total_unpred * sizeof(double);
+
+	int * result_type = (int *) malloc(num_elements * sizeof(int));
+	decode(comp_data_pos, num_elements, root, result_type);
+	SZ_ReleaseHuffman(huffmanTree);
+	
+	int intvRadius = exe_params->intvRadius;
+	
+	int * type;
+	double * data_pos = *data;
+	size_t offset_x, offset_y, offset_z;
+	size_t current_blockcount_x, current_blockcount_y, current_blockcount_z;
+	size_t cur_unpred_count;
+	unsigned char * indicator_pos = indicator;
+	if(use_mean){
+		// type = result_type;
+
+		// for(size_t i=0; i<num_x; i++){
+		// 	for(size_t j=0; j<num_y; j++){
+		// 		for(size_t k=0; k<num_z; k++){
+		// 			offset_x = (i < split_index_x) ? i * early_blockcount_x : i * late_blockcount_x + split_index_x;
+		// 			offset_y = (j < split_index_y) ? j * early_blockcount_y : j * late_blockcount_y + split_index_y;
+		// 			offset_z = (k < split_index_z) ? k * early_blockcount_z : k * late_blockcount_z + split_index_z;
+		// 			data_pos = *data + offset_x * dim0_offset + offset_y * dim1_offset + offset_z;
+
+		// 			current_blockcount_x = (i < split_index_x) ? early_blockcount_x : late_blockcount_x;
+		// 			current_blockcount_y = (j < split_index_y) ? early_blockcount_y : late_blockcount_y;
+		// 			current_blockcount_z = (k < split_index_z) ? early_blockcount_z : late_blockcount_z;
+
+		// 			// type_offset = offset_x * dim0_offset +  offset_y * current_blockcount_x * dim1_offset + offset_z * current_blockcount_x * current_blockcount_y;
+		// 			// type = result_type + type_offset;
+		// 			size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+		// 			// index = i * num_y * num_z + j * num_z + k;
+
+		// 			// printf("i j k: %ld %ld %ld\toffset: %ld %ld %ld\tindicator: %ld\n", i, j, k, offset_x, offset_y, offset_z, indicator[index]);
+		// 			if(*indicator_pos){
+		// 				// decompress by SZ
+		// 				// cur_unpred_count = decompressDataSeries_double_3D_blocked_nonblock_pred(data_pos, r1, r2, r3, current_blockcount_x, current_blockcount_y, current_blockcount_z, i, j, k, realPrecision, type, unpred_data);
+		// 				double * block_data_pos = data_pos;
+		// 				double pred;
+		// 				size_t index = 0;
+		// 				int type_;
+		// 				// d111 is current data
+		// 				size_t unpredictable_count = 0;
+		// 				double d000, d001, d010, d011, d100, d101, d110;
+		// 				for(size_t ii=0; ii<current_blockcount_x; ii++){
+		// 					for(size_t jj=0; jj<current_blockcount_y; jj++){
+		// 						for(size_t kk=0; kk<current_blockcount_z; kk++){
+		// 							type_ = type[index];
+		// 							if(type_ == intvRadius){
+		// 								*block_data_pos = mean;
+		// 							}
+		// 							else if(type_ == 0){
+		// 								*block_data_pos = unpred_data[unpredictable_count ++];
+		// 							}
+		// 							else{
+		// 								d000 = d001 = d010 = d011 = d100 = d101 = d110 = 1;
+		// 								if(i == 0 && ii == 0){
+		// 									d000 = d001 = d010 = d011 = 0;
+		// 								}
+		// 								if(j == 0 && jj == 0){
+		// 									d000 = d001 = d100 = d101 = 0;
+		// 								}
+		// 								if(k == 0 && kk == 0){
+		// 									d000 = d010 = d100 = d110 = 0;
+		// 								}
+		// 								if(d000){
+		// 									d000 = block_data_pos[- dim0_offset - dim1_offset - 1];
+		// 								}
+		// 								if(d001){
+		// 									d001 = block_data_pos[- dim0_offset - dim1_offset];
+		// 								}
+		// 								if(d010){
+		// 									d010 = block_data_pos[- dim0_offset - 1];
+		// 								}
+		// 								if(d011){
+		// 									d011 = block_data_pos[- dim0_offset];
+		// 								}
+		// 								if(d100){
+		// 									d100 = block_data_pos[- dim1_offset - 1];
+		// 								}
+		// 								if(d101){
+		// 									d101 = block_data_pos[- dim1_offset];
+		// 								}
+		// 								if(d110){
+		// 									d110 = block_data_pos[- 1];
+		// 								}
+		// 								if(type_ < intvRadius) type_ += 1;
+		// 								pred = d110 + d101 + d011 - d100 - d010 - d001 + d000;
+		// 								*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+		// 							}
+		// 							index ++;
+		// 							block_data_pos ++;
+		// 						}
+		// 						block_data_pos += dim1_offset - current_blockcount_z;
+		// 					}
+		// 					block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+		// 				}
+		// 				cur_unpred_count = unpredictable_count;
+		// 			}
+		// 			else{
+		// 				// decompress by regression
+		// 				{
+		// 					//restore regression coefficients
+		// 					double pred;
+		// 					int type_;
+		// 					for(int e=0; e<4; e++){
+		// 						// if(i == 0 && j == 0 && k == 19){
+		// 						// 	printf("~\n");
+		// 						// }
+		// 						type_ = coeff_type[e][coeff_index];
+		// 						if (type_ != 0){
+		// 							pred = last_coefficients[e];
+		// 							last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+		// 						}
+		// 						else{
+		// 							last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+		// 							coeff_unpred_data_count[e] ++;
+		// 						}
+		// 						if(fabs(last_coefficients[e]) > 10000){
+		// 							printf("%d %d %d-%d: pred %.4f type %d precision %.4g last_coefficients %.4g\n", i, j, k, e, pred, type_, precision[e], last_coefficients[e]);
+		// 							exit(0);
+		// 						}
+		// 					}
+		// 					coeff_index ++;
+		// 				}
+		// 				{
+		// 					double * block_data_pos = data_pos;
+		// 					double pred;
+		// 					int type_;
+		// 					size_t index = 0;
+		// 					size_t unpredictable_count = 0;
+		// 					for(size_t ii=0; ii<current_blockcount_x; ii++){
+		// 						for(size_t jj=0; jj<current_blockcount_y; jj++){
+		// 							for(size_t kk=0; kk<current_blockcount_z; kk++){
+		// 								if(block_data_pos - (*data) == 19470788){
+		// 									printf("dec stop\n");
+		// 								}
+
+		// 								type_ = type[index];
+		// 								if (type_ != 0){
+		// 									pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+		// 									*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+		// 								}
+		// 								else{
+		// 									*block_data_pos = unpred_data[unpredictable_count ++];
+		// 								}
+		// 								index ++;	
+		// 								block_data_pos ++;
+		// 							}
+		// 							block_data_pos += dim1_offset - current_blockcount_z;
+		// 						}
+		// 						block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+		// 					}
+		// 					cur_unpred_count = unpredictable_count;
+		// 				}
+		// 			}
+
+		// 			type += current_block_elements;
+		// 			indicator_pos ++;
+		// 			unpred_data += cur_unpred_count;
+		// 			// decomp_unpred += cur_unpred_count;
+		// 			// printf("block comp done, data_offset from %ld to %ld: diff %ld\n", *data, data_pos, data_pos - *data);
+		// 			// fflush(stdout);
+		// 		}
+		// 	}
+		// }
+
+		type = result_type;
+		// i == 0
+		{
+			// j == 0
+			{
+				// k == 0
+				{
+					data_pos = *data;
+
+					current_blockcount_x = early_blockcount_x;
+					current_blockcount_y = early_blockcount_y;
+					current_blockcount_z = early_blockcount_z;
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						// ii == 0
+						{
+							// jj == 0
+							{
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = 0;
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							for(size_t jj=1; jj<current_blockcount_y; jj++){
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- dim1_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] - block_data_pos[- dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;						
+						}
+						for(size_t ii=1; ii<current_blockcount_x; ii++){
+							// jj == 0
+							{
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- dim0_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							for(size_t jj=1; jj<current_blockcount_y; jj++){
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - dim1_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				} // end k == 0
+				// i == 0 j == 0 k != 0
+				for(size_t k=1; k<num_z; k++){
+					offset_z = (k < split_index_z) ? k * early_blockcount_z : k * late_blockcount_z + split_index_z;
+					data_pos = *data + offset_z;
+
+					current_blockcount_x = early_blockcount_x;
+					current_blockcount_y = early_blockcount_y;
+					current_blockcount_z = (k < split_index_z) ? early_blockcount_z : late_blockcount_z;
+
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						// ii == 0
+						{
+							// jj == 0
+							{
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							for(size_t jj=1; jj<current_blockcount_y; jj++){
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] - block_data_pos[- dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						for(size_t ii=1; ii<current_blockcount_x; ii++){
+							// jj == 0
+							{
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							for(size_t jj=1; jj<current_blockcount_y; jj++){
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				}
+			}// end j==0
+			for(size_t j=1; j<num_y; j++){
+				// k == 0
+				{
+					offset_y = (j < split_index_y) ? j * early_blockcount_y : j * late_blockcount_y + split_index_y;
+					data_pos = *data + offset_y * dim1_offset;
+
+					current_blockcount_x = early_blockcount_x;
+					current_blockcount_y = (j < split_index_y) ? early_blockcount_y : late_blockcount_y;
+					current_blockcount_z = early_blockcount_z;
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						// ii == 0
+						{
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- dim1_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] - block_data_pos[- dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						for(size_t ii=1; ii<current_blockcount_x; ii++){
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - dim1_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				} // end k == 0
+				for(size_t k=1; k<num_z; k++){
+					offset_y = (j < split_index_y) ? j * early_blockcount_y : j * late_blockcount_y + split_index_y;
+					offset_z = (k < split_index_z) ? k * early_blockcount_z : k * late_blockcount_z + split_index_z;
+					data_pos = *data + offset_y * dim1_offset + offset_z;
+
+					current_blockcount_x = early_blockcount_x;
+					current_blockcount_y = (j < split_index_y) ? early_blockcount_y : late_blockcount_y;
+					current_blockcount_z = (k < split_index_z) ? early_blockcount_z : late_blockcount_z;
+
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						// ii == 0
+						{
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] - block_data_pos[- dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						for(size_t ii=1; ii<current_blockcount_x; ii++){
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				}
+			}
+		} // end i==0
+		for(size_t i=1; i<num_x; i++){
+			// j == 0
+			{
+				// k == 0
+				{
+					offset_x = (i < split_index_x) ? i * early_blockcount_x : i * late_blockcount_x + split_index_x;
+					data_pos = *data + offset_x * dim0_offset;
+
+					current_blockcount_x = (i < split_index_x) ? early_blockcount_x : late_blockcount_x;
+					current_blockcount_y = early_blockcount_y;
+					current_blockcount_z = early_blockcount_z;
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						for(size_t ii=0; ii<current_blockcount_x; ii++){
+							// jj == 0
+							{
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- dim0_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							for(size_t jj=1; jj<current_blockcount_y; jj++){
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - dim1_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				} // end k == 0
+				for(size_t k=1; k<num_z; k++){
+					offset_x = (i < split_index_x) ? i * early_blockcount_x : i * late_blockcount_x + split_index_x;
+					offset_z = (k < split_index_z) ? k * early_blockcount_z : k * late_blockcount_z + split_index_z;
+					data_pos = *data + offset_x * dim0_offset + offset_z;
+
+					current_blockcount_x = (i < split_index_x) ? early_blockcount_x : late_blockcount_x;
+					current_blockcount_y = early_blockcount_y;
+					current_blockcount_z = (k < split_index_z) ? early_blockcount_z : late_blockcount_z;
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						for(size_t ii=0; ii<current_blockcount_x; ii++){
+							// jj == 0
+							{
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							for(size_t jj=1; jj<current_blockcount_y; jj++){
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				}
+			}// end j = 0
+			for(size_t j=1; j<num_y; j++){
+				// k == 0
+				{
+					offset_x = (i < split_index_x) ? i * early_blockcount_x : i * late_blockcount_x + split_index_x;
+					offset_y = (j < split_index_y) ? j * early_blockcount_y : j * late_blockcount_y + split_index_y;
+					data_pos = *data + offset_x * dim0_offset + offset_y * dim1_offset;
+
+					current_blockcount_x = (i < split_index_x) ? early_blockcount_x : late_blockcount_x;
+					current_blockcount_y = (j < split_index_y) ? early_blockcount_y : late_blockcount_y;
+					current_blockcount_z = early_blockcount_z;
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						for(size_t ii=0; ii<current_blockcount_x; ii++){
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - dim1_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				} // end k == 0
+				for(size_t k=1; k<num_z; k++){
+					offset_x = (i < split_index_x) ? i * early_blockcount_x : i * late_blockcount_x + split_index_x;
+					offset_y = (j < split_index_y) ? j * early_blockcount_y : j * late_blockcount_y + split_index_y;
+					offset_z = (k < split_index_z) ? k * early_blockcount_z : k * late_blockcount_z + split_index_z;
+					data_pos = *data + offset_x * dim0_offset + offset_y * dim1_offset + offset_z;
+
+					current_blockcount_x = (i < split_index_x) ? early_blockcount_x : late_blockcount_x;
+					current_blockcount_y = (j < split_index_y) ? early_blockcount_y : late_blockcount_y;
+					current_blockcount_z = (k < split_index_z) ? early_blockcount_z : late_blockcount_z;
+
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						for(size_t ii=0; ii<current_blockcount_x; ii++){
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == intvRadius){
+										*block_data_pos = mean;
+									}
+									else if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										if(type_ < intvRadius) type_ += 1;
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				}
+			}
+		}
+	}
+	else{
+		type = result_type;
+		// i == 0
+		{
+			// j == 0
+			{
+				// k == 0
+				{
+					data_pos = *data;
+
+					current_blockcount_x = early_blockcount_x;
+					current_blockcount_y = early_blockcount_y;
+					current_blockcount_z = early_blockcount_z;
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						// ii == 0
+						{
+							// jj == 0
+							{
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = 0;
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							for(size_t jj=1; jj<current_blockcount_y; jj++){
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- dim1_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] - block_data_pos[- dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;						
+						}
+						for(size_t ii=1; ii<current_blockcount_x; ii++){
+							// jj == 0
+							{
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- dim0_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							for(size_t jj=1; jj<current_blockcount_y; jj++){
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - dim1_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				} // end k == 0
+				// i == 0 j == 0 k != 0
+				for(size_t k=1; k<num_z; k++){
+					offset_z = (k < split_index_z) ? k * early_blockcount_z : k * late_blockcount_z + split_index_z;
+					data_pos = *data + offset_z;
+
+					current_blockcount_x = early_blockcount_x;
+					current_blockcount_y = early_blockcount_y;
+					current_blockcount_z = (k < split_index_z) ? early_blockcount_z : late_blockcount_z;
+
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						// ii == 0
+						{
+							// jj == 0
+							{
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							for(size_t jj=1; jj<current_blockcount_y; jj++){
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] - block_data_pos[- dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						for(size_t ii=1; ii<current_blockcount_x; ii++){
+							// jj == 0
+							{
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							for(size_t jj=1; jj<current_blockcount_y; jj++){
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				}
+			}// end j==0
+			for(size_t j=1; j<num_y; j++){
+				// k == 0
+				{
+					offset_y = (j < split_index_y) ? j * early_blockcount_y : j * late_blockcount_y + split_index_y;
+					data_pos = *data + offset_y * dim1_offset;
+
+					current_blockcount_x = early_blockcount_x;
+					current_blockcount_y = (j < split_index_y) ? early_blockcount_y : late_blockcount_y;
+					current_blockcount_z = early_blockcount_z;
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						// ii == 0
+						{
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- dim1_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] - block_data_pos[- dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						for(size_t ii=1; ii<current_blockcount_x; ii++){
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - dim1_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				} // end k == 0
+				for(size_t k=1; k<num_z; k++){
+					offset_y = (j < split_index_y) ? j * early_blockcount_y : j * late_blockcount_y + split_index_y;
+					offset_z = (k < split_index_z) ? k * early_blockcount_z : k * late_blockcount_z + split_index_z;
+					data_pos = *data + offset_y * dim1_offset + offset_z;
+
+					current_blockcount_x = early_blockcount_x;
+					current_blockcount_y = (j < split_index_y) ? early_blockcount_y : late_blockcount_y;
+					current_blockcount_z = (k < split_index_z) ? early_blockcount_z : late_blockcount_z;
+
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						// ii == 0
+						{
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] - block_data_pos[- dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						for(size_t ii=1; ii<current_blockcount_x; ii++){
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				}
+			}
+		} // end i==0
+		for(size_t i=1; i<num_x; i++){
+			// j == 0
+			{
+				// k == 0
+				{
+					offset_x = (i < split_index_x) ? i * early_blockcount_x : i * late_blockcount_x + split_index_x;
+					data_pos = *data + offset_x * dim0_offset;
+
+					current_blockcount_x = (i < split_index_x) ? early_blockcount_x : late_blockcount_x;
+					current_blockcount_y = early_blockcount_y;
+					current_blockcount_z = early_blockcount_z;
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						for(size_t ii=0; ii<current_blockcount_x; ii++){
+							// jj == 0
+							{
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- dim0_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							for(size_t jj=1; jj<current_blockcount_y; jj++){
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - dim1_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				} // end k == 0
+				for(size_t k=1; k<num_z; k++){
+					offset_x = (i < split_index_x) ? i * early_blockcount_x : i * late_blockcount_x + split_index_x;
+					offset_z = (k < split_index_z) ? k * early_blockcount_z : k * late_blockcount_z + split_index_z;
+					data_pos = *data + offset_x * dim0_offset + offset_z;
+
+					current_blockcount_x = (i < split_index_x) ? early_blockcount_x : late_blockcount_x;
+					current_blockcount_y = early_blockcount_y;
+					current_blockcount_z = (k < split_index_z) ? early_blockcount_z : late_blockcount_z;
+
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						for(size_t ii=0; ii<current_blockcount_x; ii++){
+							// jj == 0
+							{
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							for(size_t jj=1; jj<current_blockcount_y; jj++){
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				}
+			}// end j = 0
+			for(size_t j=1; j<num_y; j++){
+				// k == 0
+				{
+					offset_x = (i < split_index_x) ? i * early_blockcount_x : i * late_blockcount_x + split_index_x;
+					offset_y = (j < split_index_y) ? j * early_blockcount_y : j * late_blockcount_y + split_index_y;
+					data_pos = *data + offset_x * dim0_offset + offset_y * dim1_offset;
+
+					current_blockcount_x = (i < split_index_x) ? early_blockcount_x : late_blockcount_x;
+					current_blockcount_y = (j < split_index_y) ? early_blockcount_y : late_blockcount_y;
+					current_blockcount_z = early_blockcount_z;
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						for(size_t ii=0; ii<current_blockcount_x; ii++){
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								{
+									// kk == 0
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim0_offset - dim1_offset];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								for(size_t kk=1; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				} // end k == 0
+				for(size_t k=1; k<num_z; k++){
+					offset_x = (i < split_index_x) ? i * early_blockcount_x : i * late_blockcount_x + split_index_x;
+					offset_y = (j < split_index_y) ? j * early_blockcount_y : j * late_blockcount_y + split_index_y;
+					offset_z = (k < split_index_z) ? k * early_blockcount_z : k * late_blockcount_z + split_index_z;
+					data_pos = *data + offset_x * dim0_offset + offset_y * dim1_offset + offset_z;
+
+					current_blockcount_x = (i < split_index_x) ? early_blockcount_x : late_blockcount_x;
+					current_blockcount_y = (j < split_index_y) ? early_blockcount_y : late_blockcount_y;
+					current_blockcount_z = (k < split_index_z) ? early_blockcount_z : late_blockcount_z;
+
+					size_t current_block_elements = current_blockcount_x * current_blockcount_y * current_blockcount_z;
+					if(*indicator_pos){
+						// decompress by SZ
+						double * block_data_pos = data_pos;
+						double pred;
+						size_t index = 0;
+						int type_;
+						size_t unpredictable_count = 0;
+						for(size_t ii=0; ii<current_blockcount_x; ii++){
+							for(size_t jj=0; jj<current_blockcount_y; jj++){
+								for(size_t kk=0; kk<current_blockcount_z; kk++){
+									type_ = type[index];
+									if(type_ == 0){
+										*block_data_pos = unpred_data[unpredictable_count ++];
+									}
+									else{
+										pred = block_data_pos[- 1] + block_data_pos[- dim1_offset] + block_data_pos[- dim0_offset] - block_data_pos[- dim1_offset - 1] - block_data_pos[- dim0_offset - 1] - block_data_pos[- dim0_offset - dim1_offset] + block_data_pos[- dim0_offset - dim1_offset - 1];
+										*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+									}
+									index ++;
+									block_data_pos ++;
+								}
+								block_data_pos += dim1_offset - current_blockcount_z;
+							}
+							block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+						}
+						cur_unpred_count = unpredictable_count;
+					}
+					else{
+						// decompress by regression
+						{
+							//restore regression coefficients
+							double pred;
+							int type_;
+							for(int e=0; e<4; e++){
+								type_ = coeff_type[e][coeff_index];
+								if (type_ != 0){
+									pred = last_coefficients[e];
+									last_coefficients[e] = pred + 2 * (type_ - coeff_intvRadius[e]) * precision[e];
+								}
+								else{
+									last_coefficients[e] = coeff_unpred_data[e][coeff_unpred_data_count[e]];
+									coeff_unpred_data_count[e] ++;
+								}
+							}
+							coeff_index ++;
+						}
+						{
+							double * block_data_pos = data_pos;
+							double pred;
+							int type_;
+							size_t index = 0;
+							size_t unpredictable_count = 0;
+							for(size_t ii=0; ii<current_blockcount_x; ii++){
+								for(size_t jj=0; jj<current_blockcount_y; jj++){
+									for(size_t kk=0; kk<current_blockcount_z; kk++){
+										type_ = type[index];
+										if (type_ != 0){
+											pred = last_coefficients[0] * ii + last_coefficients[1] * jj + last_coefficients[2] * kk + last_coefficients[3];
+											*block_data_pos = pred + 2 * (type_ - intvRadius) * realPrecision;
+										}
+										else{
+											*block_data_pos = unpred_data[unpredictable_count ++];
+										}
+										index ++;	
+										block_data_pos ++;
+									}
+									block_data_pos += dim1_offset - current_blockcount_z;
+								}
+								block_data_pos += dim0_offset - current_blockcount_y * dim1_offset;
+							}
+							cur_unpred_count = unpredictable_count;
+						}
+					}
+					indicator_pos ++;
+					type += current_block_elements;
+					unpred_data += cur_unpred_count;
+				}
+			}
+		}
+	}
+
+	free(coeff_result_type);
+
+	free(indicator);
+	free(result_type);
+}
