/* example illustrating in-place compression and decompression */ #include #include #include #include #include #include "zfp.h" /* compress and decompress contiguous blocks */ static int process(double* buffer, uint blocks, double tolerance) { zfp_stream* zfp; /* compressed stream */ bitstream* stream; /* bit stream to write to or read from */ size_t* offset; /* per-block bit offset in compressed stream */ double* ptr; /* pointer to block being processed */ size_t bufsize; /* byte size of uncompressed storage */ size_t zfpsize; /* byte size of compressed stream */ uint minbits; /* min bits per block */ uint maxbits; /* max bits per block */ uint maxprec; /* max precision */ int minexp; /* min bit plane encoded */ uint bits; /* size of compressed block */ uint i; /* maintain offset to beginning of each variable-length block */ offset = malloc(blocks * sizeof(size_t)); /* associate bit stream with same storage as input */ bufsize = blocks * 4 * 4 * sizeof(*buffer); stream = stream_open(buffer, bufsize); /* allocate meta data for a compressed stream */ zfp = zfp_stream_open(stream); /* set tolerance for fixed-accuracy mode */ zfp_stream_set_accuracy(zfp, tolerance); /* set maxbits to guard against prematurely overwriting the input */ zfp_stream_params(zfp, &minbits, &maxbits, &maxprec, &minexp); maxbits = 4 * 4 * sizeof(*buffer) * CHAR_BIT; zfp_stream_set_params(zfp, minbits, maxbits, maxprec, minexp); /* compress one block at a time in sequential order */ ptr = buffer; for (i = 0; i < blocks; i++) { offset[i] = stream_wtell(stream); bits = (uint)zfp_encode_block_double_2(zfp, ptr); if (!bits) { fprintf(stderr, "compression failed\n"); return 0; } printf("block #%u offset=%4u size=%4u\n", i, (uint)offset[i], bits); ptr += 4 * 4; } /* important: flush any buffered compressed bits */ stream_flush(stream); /* print out size */ zfpsize = stream_size(stream); printf("compressed %u bytes to %u bytes\n", (uint)bufsize, (uint)zfpsize); /* decompress one block at a time in reverse order */ for (i = blocks; i--;) { ptr -= 4 * 4; stream_rseek(stream, offset[i]); if (!zfp_decode_block_double_2(zfp, ptr)) { fprintf(stderr, "decompression failed\n"); return 0; } } /* clean up */ zfp_stream_close(zfp); stream_close(stream); free(offset); return 1; } int main(int argc, char* argv[]) { double tolerance = 1e-6; double* array; double* buffer; uint bx = 2; uint by = 4; uint nx = 4 * bx; uint ny = 4 * by; uint blocks = bx * by; uint x, y; uint i, j, k; int status; switch (argc) { case 2: if (sscanf(argv[1], "%lf", &tolerance) != 1) goto usage; /* FALLTHROUGH */ case 1: break; default: usage: fprintf(stderr, "Usage: inline [tolerance]\n"); return EXIT_FAILURE; } printf("tolerance=%g\n", tolerance); /* initialize array to be compressed */ printf("original %ux%u array:\n", nx, ny); array = malloc(nx * ny * sizeof(double)); for (y = 0; y < ny; y++) { for (x = 0; x < nx; x++) { double u = 2 * (x + 0.5) / nx; double v = asin(1.0) * (y + 0.5); double f = exp(-u * u) * sin(v) / v; printf("%9.6f%c", f, x == nx - 1 ? '\n' : ' '); array[x + nx * y] = f; } } /* reorganize array into 4x4 blocks */ buffer = malloc(blocks * 4 * 4 * sizeof(double)); for (k = 0; k < blocks; k++) for (j = 0; j < 4; j++) for (i = 0; i < 4; i++) { uint x = 4 * (k & 1) + i; uint y = 4 * (k / 2) + j; buffer[i + 4 * (j + 4 * k)] = array[x + nx * y]; } status = process(buffer, blocks, tolerance); if (status) { /* reorganize blocks into array */ for (k = 0; k < blocks; k++) for (j = 0; j < 4; j++) for (i = 0; i < 4; i++) { uint x = 4 * (k & 1) + i; uint y = 4 * (k / 2) + j; array[x + nx * y] = buffer[i + 4 * (j + 4 * k)]; } /* print out modified array*/ printf("decompressed %ux%u array:\n", nx, ny); for (y = 0; y < ny; y++) for (x = 0; x < nx; x++) printf("%9.6f%c", array[x + nx * y], x == nx - 1 ? '\n' : ' '); } free(buffer); free(array); return status ? EXIT_SUCCESS : EXIT_FAILURE; }