summaryrefslogtreecommitdiff
path: root/hrtc_wrapper.cpp
diff options
context:
space:
mode:
authorJan Huwald <jh@sotun.de>2016-01-11 11:52:36 (GMT)
committerJan Huwald <jh@sotun.de>2016-01-11 12:19:06 (GMT)
commit2281eb34dca09f067ea77b1906cfac15d7b8955c (patch)
treea6a62aa8a22c642bb16e1a1aee21f7926ccdf311 /hrtc_wrapper.cpp
Initial release of the HRTC libraryHEADmaster
Diffstat (limited to 'hrtc_wrapper.cpp')
-rw-r--r--hrtc_wrapper.cpp222
1 files changed, 222 insertions, 0 deletions
diff --git a/hrtc_wrapper.cpp b/hrtc_wrapper.cpp
new file mode 100644
index 0000000..02b9b24
--- /dev/null
+++ b/hrtc_wrapper.cpp
@@ -0,0 +1,222 @@
+/* Copyright 2014-2016 Jan Huwald, Stephan Richter
+
+ This file is part of HRTC.
+
+ HRTC is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ HRTC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program (see file LICENSE). If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "common.hpp"
+#include "compressor.hpp"
+#include "decompressor.hpp"
+
+
+extern "C" {
+ #include <tng/tng_io.h>
+}
+
+ template<typename T>
+ tng_function_status typed_hrtc_compress(const tng_trajectory_t tng_data,
+ const int64_t n_frames,
+ const int64_t n_particles,
+ char **data,
+ int64_t *new_len) {
+ int64_t dimensions;
+ double bound = 0,error = 0,quantum = 0;
+
+ {// this block: read number of dimensions + read box shape to calculate bound
+ // this is done here, because tng_data_block_write does not know about
+ // these things and thus cannot pass it
+ char type;
+ union data_values **box_data = 0;
+ int64_t dummy,current_dimension;
+
+ tng_function_status stat=tng_data_get(tng_data,TNG_TRAJ_BOX_SHAPE,&box_data,&dummy,&dimensions,&type);
+ assert(stat == TNG_SUCCESS);
+ assert(dimensions>0);
+
+ double val = 0; // current dimension value in loop
+ for (current_dimension=0; current_dimension<dimensions;current_dimension++){
+ val=(type==TNG_DOUBLE_DATA)?box_data[0][current_dimension].d:box_data[0][current_dimension].f;
+ assert(val>0);
+ bound = max(val,bound);
+ }
+ }
+
+ { // this block: set error and quantum using precision from tng_environment
+ double precision;
+ tng_function_status stat = tng_compression_precision_get(tng_data,&precision);
+ assert(precision!=0);
+ quantum=1/precision;
+ assert(stat == TNG_SUCCESS);
+ error = quantum/2;
+ assert(error>0);
+ assert(quantum>0);
+ }
+
+ char* result = nullptr;
+ size_t result_size=sizeof(double); // for quantum
+ result=(char*) malloc(result_size); // allocate memory for one double
+ memcpy(result,&quantum,result_size); // copy double to result data
+
+ int integerEncoder = 5; // pareto optimal / good space-time tradeoff
+ int numberOfTrajectories=n_particles*dimensions;
+
+ CompressorState<T> compressor(numberOfTrajectories,
+ error,
+ bound,
+ quantum,
+ 1024 /* chunk size */,
+ integer_encoding::EncodingFactory::create(integerEncoder),
+ [&](char* buf, ChunkSize chunkSize) {
+ auto offset=result_size;
+ result_size+= sizeof(chunkSize) + chunkSize.compressed;
+ result = (char*) realloc(result,result_size);
+// printf("chunksize: %d (raw) => %d (compressed), offset: %d\n",chunkSize.raw,chunkSize.compressed,offset);
+ memcpy((void*)(result+offset),(void*)&chunkSize,sizeof(chunkSize));
+ offset+=sizeof(chunkSize);
+ memcpy((void*)(result+offset),(void*)buf,chunkSize.compressed);
+ });
+
+ auto traj_data=(T*) *data;
+ for (int64_t frame_number=0;frame_number<n_frames;frame_number++){ // loop through frames
+ compressor.addFrame(traj_data+frame_number*numberOfTrajectories);
+ }
+ compressor.finish();
+
+ free(*data);
+ *data = (char *)result;
+ *new_len = result_size;
+
+ return TNG_SUCCESS;
+ }
+
+ template<typename T>
+ tng_function_status typed_hrtc_uncompress(const tng_trajectory_t tng_data,
+ char **data) {
+
+
+ int64_t dimensions,number_of_frames,number_of_particles;
+ double bound = 0,error = 0,quantum = 0;
+
+ int integerEncoder = 5; // pareto optimal / good space-time tradeoff
+
+ {// this block: read number of dimensions + number of frames + box shape to calculate bound
+ char type;
+ union data_values **box_data = 0;
+ int64_t current_dimension;
+
+ tng_function_status stat=tng_data_get(tng_data,TNG_TRAJ_BOX_SHAPE,&box_data,&number_of_frames,&dimensions,&type);
+ assert(stat == TNG_SUCCESS);
+ assert(dimensions>0);
+ assert(number_of_frames>0);
+
+ double val = 0; // current dimension value in loop
+ for (current_dimension=0; current_dimension<dimensions;current_dimension++){
+ val=(type==TNG_DOUBLE_DATA)?box_data[0][current_dimension].d:box_data[0][current_dimension].f;
+ assert(val>0);
+ bound = max(val,bound);
+ }
+ }
+
+ { // this block: determine number of particles
+ tng_function_status stat = tng_num_molecules_get(tng_data, &number_of_particles);
+ assert(stat == TNG_SUCCESS);
+ assert(number_of_particles>0);
+ }
+
+ { // this block: determine number of frames per frameset
+ tng_function_status stat = tng_num_frames_per_frame_set_get(tng_data, &number_of_frames);
+ assert(stat == TNG_SUCCESS);
+ assert(number_of_frames>0);
+ }
+
+
+ int number_of_trajectories=number_of_particles*dimensions;
+ auto src_buf = *data;
+
+
+ { // this block: read quantum from data blob, set error
+ quantum = *((double*) src_buf); // reading quantum from tip of data blob
+ src_buf+=sizeof(double); // moving pointer ahead
+ error = quantum/2;
+ assert(error>0);
+ assert(quantum>0);
+ }
+
+ DecompressorState<T> decompressor(number_of_trajectories,
+ quantum,
+ 1024 /* chunk size */,
+ integer_encoding::EncodingFactory::create(integerEncoder),
+ [&](char* buf) -> ChunkSize {
+ ChunkSize chunkSize = *((ChunkSize*) src_buf);
+ src_buf += sizeof(chunkSize);
+// printf("chunksize: %d (compressed) => %d (raw)\n",chunkSize.compressed,chunkSize.raw);
+// printf("src_buf: %d\n",src_buf-*data);
+ memcpy(buf,src_buf,chunkSize.compressed);
+ src_buf += chunkSize.compressed;
+
+ return chunkSize;
+ });
+
+ auto result = (T*) malloc(number_of_frames * number_of_trajectories * sizeof(T));
+ auto result_pos = result;
+
+ for (int i=0; i<number_of_frames;i++){
+ assert(decompressor.readFrame(result_pos)); // should not be activated unless all frames have been read.
+ result_pos += number_of_trajectories;
+ }
+ assert(!decompressor.readFrame(result_pos)); // if we have not read all frames, something went wrong
+
+ free(*data);
+
+ *data = (char *)result;
+
+ return TNG_SUCCESS;
+ }
+
+extern "C" {
+ tng_function_status hrtc_compress(const tng_trajectory_t tng_data,
+ const int64_t n_frames,
+ const int64_t n_particles,
+ const char type,
+ char **data,
+ int64_t *new_len) {
+ switch (type){
+ case TNG_DOUBLE_DATA:
+ return typed_hrtc_compress<double>(tng_data,n_frames,n_particles,data,new_len);
+ case TNG_FLOAT_DATA:
+ return typed_hrtc_compress<float>(tng_data,n_frames,n_particles,data,new_len);
+ default:
+ return TNG_FAILURE;
+ }
+ }
+
+ /* decompression */
+ tng_function_status hrtc_uncompress(const tng_trajectory_t tng_data,
+ const char type,
+ char **data) {
+ switch (type){
+ case TNG_DOUBLE_DATA:
+ return typed_hrtc_uncompress<double>(tng_data,data);
+ case TNG_FLOAT_DATA:
+ return typed_hrtc_uncompress<float>(tng_data,data);
+ default:
+ return TNG_FAILURE;
+ }
+ }
+
+ void hrtc_version(){
+ cout << hrtc_version_string() << "\n";
+ }
+}
contact: Jan Huwald // Impressum