-
Notifications
You must be signed in to change notification settings - Fork 0
/
zfpmodule.c
135 lines (102 loc) · 3.83 KB
/
zfpmodule.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <Python.h>
#include "numpy/arrayobject.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zfp.h"
#include "zfpmodule.h"
/* ==== Set up the methods table ====================== */
static PyMethodDef zfpmodule_methods[] = {
{"compress_block", compress_block, METH_VARARGS},
{NULL, NULL} /* Sentinel - marks the end of this structure */
};
/* ==== Initialize the C_test functions ====================== */
PyMODINIT_FUNC initzfpmodule(void) {
(void) Py_InitModule("zfpmodule", zfpmodule_methods);
import_array(); // Must be present for NumPy. Called first after above line.
}
static PyObject * compress_block(PyObject *self, PyObject *args){
PyArrayObject *arrayin;
PyArrayObject *arrayout;
double *original, *original_transform, *final;
int nx, ny, nz;
double rate;
int decompress;
int status = 0; /* return value: 0 = success */
zfp_type type; /* array scalar type */
zfp_field* field; /* array meta data */
zfp_field* fieldout; /* array meta data */
zfp_stream* zfp; /* compressed stream */
void* buffer; /* storage for compressed stream */
size_t bufsize; /* byte size of compressed buffer */
bitstream* stream; /* bit stream to write to or read from */
size_t zfpsize; /* byte size of compressed stream */
int i;
double max;
if (!PyArg_ParseTuple(args, "O!O!d", &PyArray_Type, &arrayin, &PyArray_Type, &arrayout, &rate))
return NULL;
if (arrayin->nd != 1 || arrayin->descr->type_num != PyArray_DOUBLE) {
PyErr_SetString(PyExc_ValueError, "arrayin must be one-dimensional and of type double");
return NULL;
}
if (arrayout->nd != 1 || arrayout->descr->type_num != PyArray_DOUBLE) {
PyErr_SetString(PyExc_ValueError, "arrayout must be one-dimensional and of type double");
return NULL;
}
nx = 4;
ny = 4;
nz = 4;
if( nx * ny * nz != arrayin->dimensions[0] || nx * ny * nz != arrayout->dimensions[0] ){
PyErr_SetString(PyExc_ValueError, "Arrayout or arrayin has wrong number of elements (nx * ny * nz)");
return NULL;
}
original = (double*)arrayin->data;
original_transform = (double *) malloc(sizeof(double) * nx * ny * nz);
max = original[0];
for (i = 1 ;i < nx * ny * nz; i++) {
max = max < original[i] ? original[i]: max;
}
for (i = 0; i < nx * ny * nz; i++) {
original_transform[i] = log(original[i] <= 0.0 ? 1e-200 : original[i]);
}
final = (double*)arrayout->data;
/* allocate meta data for the 3D array a[nz][ny][nx] */
type = zfp_type_double;
field = zfp_field_3d(original_transform, type, nx, ny, nz);
fieldout = zfp_field_3d(final, type, nx, ny, nz);
/* allocate meta data for a compressed stream */
zfp = zfp_stream_open(NULL);
/* set compression mode and parameters via one of three functions */
zfp_stream_set_rate(zfp, rate, type, 3, 0);
/* zfp_stream_set_precision(zfp, precision); */
/* zfp_stream_set_accuracy(zfp, tolerance);*/
/* allocate buffer for compressed data */
bufsize = zfp_stream_maximum_size(zfp, field);
// printf("bufsize %d\n", bufsize);
buffer = malloc(bufsize);
/* associate bit stream with allocated buffer */
stream = stream_open(buffer, bufsize);
zfp_stream_set_bit_stream(zfp, stream);
zfp_stream_rewind(zfp);
zfpsize = zfp_compress(zfp, field);
if (!zfpsize) {
status = 1;
}
zfp_stream_rewind(zfp);
zfp_decompress(zfp, fieldout);
for (i = 0 ;i < nx * ny * nz; i++) {
final[i] = exp(final[i]);
}
// for (i = 0; i < nx * ny * nz; i++) {
// printf("%g %g %g %g\n", original[i], final[i], original[i] - final[i], fabs(original[i] - final[i])/original[i] );
// }
/* clean up */
zfp_field_free(field);
zfp_field_free(fieldout);
zfp_stream_close(zfp);
stream_close(stream);
free(buffer);
free(original_transform);
return PyFloat_FromDouble(0);
}