Coverage Report

Created: 2025-07-18 06:49

/src/c-blosc2/plugins/codecs/zfp/blosc2-zfp.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
  Copyright (c) 2021  Blosc Development Team <blosc@blosc.org>
3
  https://blosc.org
4
  License: BSD 3-Clause (see LICENSE.txt)
5
*/
6
7
#include "zfp.h"
8
#include "blosc2-zfp.h"
9
#include "../plugins/codecs/zfp/zfp-private.h"
10
#include "context.h"
11
#include "blosc2.h"
12
#include "b2nd.h"
13
14
#include <assert.h>
15
#include <math.h>
16
#include <stdlib.h>
17
#include <string.h>
18
19
20
int zfp_acc_compress(const uint8_t *input, int32_t input_len, uint8_t *output,
21
0
                     int32_t output_len, uint8_t meta, blosc2_cparams *cparams, const void *chunk) {
22
0
  BLOSC_UNUSED_PARAM(chunk);
23
0
  ZFP_ERROR_NULL(input);
24
0
  ZFP_ERROR_NULL(output);
25
0
  ZFP_ERROR_NULL(cparams);
26
0
  ZFP_ERROR_NULL(cparams->schunk);
27
28
0
  double tol = (int8_t) meta;
29
0
  int8_t ndim;
30
0
  int64_t *shape = malloc(8 * sizeof(int64_t));
31
0
  int32_t *chunkshape = malloc(8 * sizeof(int32_t));
32
0
  int32_t *blockshape = malloc(8 * sizeof(int32_t));
33
0
  uint8_t *smeta;
34
0
  int32_t smeta_len;
35
0
  if (blosc2_meta_get(cparams->schunk, "b2nd", &smeta, &smeta_len) < 0) {
36
0
    free(shape);
37
0
    free(chunkshape);
38
0
    free(blockshape);
39
0
    BLOSC_TRACE_ERROR("b2nd layer not found!");
40
0
    return BLOSC2_ERROR_FAILURE;
41
0
  }
42
0
  b2nd_deserialize_meta(smeta, smeta_len, &ndim, shape, chunkshape, blockshape, NULL, NULL);
43
0
  free(smeta);
44
45
0
  for(int i = 0; i < ndim; i++) {
46
0
    if (blockshape[i] < 4) {
47
0
      BLOSC_TRACE_ERROR("ZFP does not support blocks smaller than cells (4x...x4");
48
0
      return BLOSC2_ERROR_FAILURE;
49
0
    }
50
0
  }
51
52
0
  zfp_type type;     /* array scalar type */
53
0
  zfp_field *field;  /* array meta data */
54
0
  zfp_stream *zfp;   /* stream containing the real output buffer */
55
0
  zfp_stream *zfp_aux;   /* auxiliary compressed stream */
56
0
  bitstream *stream; /* bit stream to write to or read from */
57
0
  bitstream *stream_aux; /* auxiliary bit stream to write to or read from */
58
0
  size_t zfpsize;    /* byte size of compressed stream */
59
0
  double tolerance = pow(10, tol);
60
61
0
  int32_t typesize = cparams->typesize;
62
63
0
  switch (typesize) {
64
0
    case sizeof(float):
65
0
      type = zfp_type_float;
66
0
      break;
67
0
    case sizeof(double):
68
0
      type = zfp_type_double;
69
0
      break;
70
0
    default:
71
0
      free(shape);
72
0
      free(chunkshape);
73
0
      free(blockshape);
74
0
      BLOSC_TRACE_ERROR("ZFP is not available for typesize: %d", typesize);
75
0
      return BLOSC2_ERROR_FAILURE;
76
0
  }
77
78
0
  zfp = zfp_stream_open(NULL);
79
0
  zfp_stream_set_accuracy(zfp, tolerance);
80
0
  stream = stream_open(output, output_len);
81
0
  zfp_stream_set_bit_stream(zfp, stream);
82
0
  zfp_stream_rewind(zfp);
83
84
0
  switch (ndim) {
85
0
    case 1:
86
0
      field = zfp_field_1d((void *) input, type, blockshape[0]);
87
0
      break;
88
0
    case 2:
89
0
      field = zfp_field_2d((void *) input, type, blockshape[1], blockshape[0]);
90
0
      break;
91
0
    case 3:
92
0
      field = zfp_field_3d((void *) input, type, blockshape[2], blockshape[1], blockshape[0]);
93
0
      break;
94
0
    case 4:
95
0
      field = zfp_field_4d((void *) input, type, blockshape[3], blockshape[2], blockshape[1], blockshape[0]);
96
0
      break;
97
0
    default:
98
0
      free(shape);
99
0
      free(chunkshape);
100
0
      free(blockshape);
101
0
      BLOSC_TRACE_ERROR("ZFP is not available for ndims: %d", ndim);
102
0
      return BLOSC2_ERROR_FAILURE;
103
0
  }
104
105
0
  int zfp_maxout = (int) zfp_stream_maximum_size(zfp, field);
106
0
  zfp_stream_close(zfp);
107
0
  stream_close(stream);
108
0
  uint8_t *aux_out = malloc(zfp_maxout);
109
0
  zfp_aux = zfp_stream_open(NULL);
110
0
  zfp_stream_set_accuracy(zfp_aux, tolerance);
111
0
  stream_aux = stream_open(aux_out, zfp_maxout);
112
0
  zfp_stream_set_bit_stream(zfp_aux, stream_aux);
113
0
  zfp_stream_rewind(zfp_aux);
114
115
0
  zfpsize = zfp_compress(zfp_aux, field);
116
117
  /* clean up */
118
0
  zfp_field_free(field);
119
0
  zfp_stream_close(zfp_aux);
120
0
  stream_close(stream_aux);
121
0
  free(shape);
122
0
  free(chunkshape);
123
0
  free(blockshape);
124
125
0
  if (zfpsize == 0) {
126
0
    BLOSC_TRACE_ERROR("\n ZFP: Compression failed\n");
127
0
    free(aux_out);
128
0
    return (int) zfpsize;
129
0
  }
130
0
  if ((int32_t) zfpsize >= input_len) {
131
0
    BLOSC_TRACE_ERROR("\n ZFP: Compressed data is bigger than input! \n");
132
0
    free(aux_out);
133
0
    return 0;
134
0
  }
135
136
0
  memcpy(output, aux_out, zfpsize);
137
0
  free(aux_out);
138
139
0
  return (int) zfpsize;
140
0
}
141
142
int zfp_acc_decompress(const uint8_t *input, int32_t input_len, uint8_t *output,
143
0
                       int32_t output_len, uint8_t meta, blosc2_dparams *dparams, const void *chunk) {
144
0
  ZFP_ERROR_NULL(input);
145
0
  ZFP_ERROR_NULL(output);
146
0
  ZFP_ERROR_NULL(dparams);
147
0
  ZFP_ERROR_NULL(dparams->schunk);
148
0
  BLOSC_UNUSED_PARAM(chunk);
149
150
0
  blosc2_schunk *sc = dparams->schunk;
151
0
  int32_t typesize = sc->typesize;
152
153
0
  double tol = (int8_t) meta;
154
0
  int8_t ndim;
155
0
  int64_t *shape = malloc(8 * sizeof(int64_t));
156
0
  int32_t *chunkshape = malloc(8 * sizeof(int32_t));
157
0
  int32_t *blockshape = malloc(8 * sizeof(int32_t));
158
0
  uint8_t *smeta;
159
0
  int32_t smeta_len;
160
0
  if (blosc2_meta_get(sc, "b2nd", &smeta, &smeta_len) < 0) {
161
0
    BLOSC_TRACE_ERROR("Cannot access b2nd meta info");
162
0
    free(shape);
163
0
    free(chunkshape);
164
0
    free(blockshape);
165
0
    return BLOSC2_ERROR_FAILURE;
166
0
  }
167
0
  b2nd_deserialize_meta(smeta, smeta_len, &ndim, shape, chunkshape, blockshape, NULL, NULL);
168
0
  free(smeta);
169
170
0
  zfp_type type;     /* array scalar type */
171
0
  zfp_field *field;  /* array meta data */
172
0
  zfp_stream *zfp;   /* compressed stream */
173
0
  bitstream *stream; /* bit stream to write to or read from */
174
0
  size_t zfpsize;    /* byte size of compressed stream */
175
0
  double tolerance = pow(10, tol);
176
177
0
  switch (typesize) {
178
0
    case sizeof(float):
179
0
      type = zfp_type_float;
180
0
      break;
181
0
    case sizeof(double):
182
0
      type = zfp_type_double;
183
0
      break;
184
0
    default:
185
0
      free(shape);
186
0
      free(chunkshape);
187
0
      free(blockshape);
188
0
      BLOSC_TRACE_ERROR("ZFP is not available for typesize: %d", typesize);
189
0
      return BLOSC2_ERROR_FAILURE;
190
0
  }
191
192
0
  zfp = zfp_stream_open(NULL);
193
0
  zfp_stream_set_accuracy(zfp, tolerance);
194
0
  stream = stream_open((void *) input, input_len);
195
0
  zfp_stream_set_bit_stream(zfp, stream);
196
0
  zfp_stream_rewind(zfp);
197
198
0
  switch (ndim) {
199
0
    case 1:
200
0
      field = zfp_field_1d((void *) output, type, blockshape[0]);
201
0
      break;
202
0
    case 2:
203
0
      field = zfp_field_2d((void *) output, type, blockshape[1], blockshape[0]);
204
0
      break;
205
0
    case 3:
206
0
      field = zfp_field_3d((void *) output, type, blockshape[2], blockshape[1], blockshape[0]);
207
0
      break;
208
0
    case 4:
209
0
      field = zfp_field_4d((void *) output, type, blockshape[3], blockshape[2], blockshape[1], blockshape[0]);
210
0
      break;
211
0
    default:
212
0
      free(shape);
213
0
      free(chunkshape);
214
0
      free(blockshape);
215
0
      BLOSC_TRACE_ERROR("ZFP is not available for ndims: %d", ndim);
216
0
      return BLOSC2_ERROR_FAILURE;
217
0
  }
218
219
0
  zfpsize = zfp_decompress(zfp, field);
220
221
  /* clean up */
222
0
  zfp_field_free(field);
223
0
  zfp_stream_close(zfp);
224
0
  stream_close(stream);
225
0
  free(shape);
226
0
  free(chunkshape);
227
0
  free(blockshape);
228
229
0
  if (zfpsize == 0) {
230
0
    BLOSC_TRACE_ERROR("\n ZFP: Decompression failed\n");
231
0
    return (int) zfpsize;
232
0
  }
233
234
0
  return (int) output_len;
235
0
}
236
237
int zfp_prec_compress(const uint8_t *input, int32_t input_len, uint8_t *output,
238
0
                      int32_t output_len, uint8_t meta, blosc2_cparams *cparams, const void *chunk) {
239
0
  BLOSC_UNUSED_PARAM(chunk);
240
0
  ZFP_ERROR_NULL(input);
241
0
  ZFP_ERROR_NULL(output);
242
0
  ZFP_ERROR_NULL(cparams);
243
0
  ZFP_ERROR_NULL(cparams->schunk);
244
245
0
  int8_t ndim;
246
0
  int64_t *shape = malloc(8 * sizeof(int64_t));
247
0
  int32_t *chunkshape = malloc(8 * sizeof(int32_t));
248
0
  int32_t *blockshape = malloc(8 * sizeof(int32_t));
249
0
  uint8_t *smeta;
250
0
  int32_t smeta_len;
251
0
  if (blosc2_meta_get(cparams->schunk, "b2nd", &smeta, &smeta_len) < 0) {
252
0
    free(shape);
253
0
    free(chunkshape);
254
0
    free(blockshape);
255
0
    BLOSC_TRACE_ERROR("b2nd layer not found!");
256
0
    return BLOSC2_ERROR_FAILURE;
257
0
  }
258
0
  b2nd_deserialize_meta(smeta, smeta_len, &ndim, shape, chunkshape, blockshape, NULL, NULL);
259
0
  free(smeta);
260
261
0
  for(int i = 0; i < ndim; i++) {
262
0
    if (blockshape[i] < 4) {
263
0
      BLOSC_TRACE_ERROR("ZFP does not support blocks smaller than cells (4x...x4");
264
0
      return BLOSC2_ERROR_FAILURE;
265
0
    }
266
0
  }
267
268
0
  zfp_type type;     /* array scalar type */
269
0
  zfp_field *field;  /* array meta data */
270
0
  zfp_stream *zfp;   /* stream containing the real output buffer */
271
0
  zfp_stream *zfp_aux;   /* auxiliary compressed stream */
272
0
  bitstream *stream; /* bit stream to write to or read from */
273
0
  bitstream *stream_aux; /* auxiliary bit stream to write to or read from */
274
0
  size_t zfpsize;    /* byte size of compressed stream */
275
276
0
  uint prec;
277
0
  switch (ndim) {
278
0
    case 1:
279
0
      prec = meta + 5;
280
0
      break;
281
0
    case 2:
282
0
      prec = meta + 7;
283
0
      break;
284
0
    case 3:
285
0
      prec = meta + 9;
286
0
      break;
287
0
    case 4:
288
0
      prec = meta + 11;
289
0
      break;
290
0
    default:
291
0
      free(shape);
292
0
      free(chunkshape);
293
0
      free(blockshape);
294
0
      BLOSC_TRACE_ERROR("ZFP is not available for ndims: %d", ndim);
295
0
      return BLOSC2_ERROR_FAILURE;
296
0
  }
297
298
0
  if (prec > ZFP_MAX_PREC) {
299
0
    BLOSC_TRACE_ERROR("Max precision for this codecs is %d", ZFP_MAX_PREC);
300
0
    prec = ZFP_MAX_PREC;
301
0
  }
302
303
0
  int32_t typesize = cparams->typesize;
304
0
  switch (typesize) {
305
0
    case sizeof(float):
306
0
      type = zfp_type_float;
307
0
      break;
308
0
    case sizeof(double):
309
0
      type = zfp_type_double;
310
0
      break;
311
0
    default:
312
0
      free(shape);
313
0
      free(chunkshape);
314
0
      free(blockshape);
315
0
      BLOSC_TRACE_ERROR("ZFP is not available for typesize: %d", typesize);
316
0
      return BLOSC2_ERROR_FAILURE;
317
0
  }
318
319
0
  zfp = zfp_stream_open(NULL);
320
0
  zfp_stream_set_precision(zfp, prec);
321
0
  stream = stream_open(output, output_len);
322
0
  zfp_stream_set_bit_stream(zfp, stream);
323
0
  zfp_stream_rewind(zfp);
324
325
0
  switch (ndim) {
326
0
    case 1:
327
0
      field = zfp_field_1d((void *) input, type, blockshape[0]);
328
0
      break;
329
0
    case 2:
330
0
      field = zfp_field_2d((void *) input, type, blockshape[1], blockshape[0]);
331
0
      break;
332
0
    case 3:
333
0
      field = zfp_field_3d((void *) input, type, blockshape[2], blockshape[1], blockshape[0]);
334
0
      break;
335
0
    case 4:
336
0
      field = zfp_field_4d((void *) input, type, blockshape[3], blockshape[2], blockshape[1], blockshape[0]);
337
0
      break;
338
0
    default:
339
0
      free(shape);
340
0
      free(chunkshape);
341
0
      free(blockshape);
342
0
      BLOSC_TRACE_ERROR("ZFP is not available for ndims: %d", ndim);
343
0
      return BLOSC2_ERROR_FAILURE;
344
0
  }
345
346
0
  int zfp_maxout = (int) zfp_stream_maximum_size(zfp, field);
347
0
  zfp_stream_close(zfp);
348
0
  stream_close(stream);
349
0
  uint8_t *aux_out = malloc(zfp_maxout);
350
0
  zfp_aux = zfp_stream_open(NULL);
351
0
  zfp_stream_set_precision(zfp_aux, prec);
352
0
  stream_aux = stream_open(aux_out, zfp_maxout);
353
0
  zfp_stream_set_bit_stream(zfp_aux, stream_aux);
354
0
  zfp_stream_rewind(zfp_aux);
355
356
0
  zfpsize = zfp_compress(zfp_aux, field);
357
358
  /* clean up */
359
0
  zfp_field_free(field);
360
0
  zfp_stream_close(zfp_aux);
361
0
  stream_close(stream_aux);
362
0
  free(shape);
363
0
  free(chunkshape);
364
0
  free(blockshape);
365
366
0
  if (zfpsize == 0) {
367
0
    BLOSC_TRACE_ERROR("\n ZFP: Compression failed\n");
368
0
    free(aux_out);
369
0
    return (int) zfpsize;
370
0
  }
371
0
  if ((int32_t) zfpsize >= input_len) {
372
0
    BLOSC_TRACE_ERROR("\n ZFP: Compressed data is bigger than input! \n");
373
0
    free(aux_out);
374
0
    return 0;
375
0
  }
376
377
0
  memcpy(output, aux_out, zfpsize);
378
0
  free(aux_out);
379
380
0
  return (int) zfpsize;
381
0
}
382
383
int zfp_prec_decompress(const uint8_t *input, int32_t input_len, uint8_t *output,
384
0
                        int32_t output_len, uint8_t meta, blosc2_dparams *dparams, const void *chunk) {
385
0
  ZFP_ERROR_NULL(input);
386
0
  ZFP_ERROR_NULL(output);
387
0
  ZFP_ERROR_NULL(dparams);
388
0
  ZFP_ERROR_NULL(dparams->schunk);
389
0
  BLOSC_UNUSED_PARAM(chunk);
390
391
0
  blosc2_schunk *sc = dparams->schunk;
392
0
  int32_t typesize = sc->typesize;
393
0
  int8_t ndim;
394
0
  int64_t *shape = malloc(8 * sizeof(int64_t));
395
0
  int32_t *chunkshape = malloc(8 * sizeof(int32_t));
396
0
  int32_t *blockshape = malloc(8 * sizeof(int32_t));
397
0
  uint8_t *smeta;
398
0
  int32_t smeta_len;
399
0
  if (blosc2_meta_get(sc, "b2nd", &smeta, &smeta_len) < 0) {
400
0
    BLOSC_TRACE_ERROR("Cannot access b2nd meta info");
401
0
    free(shape);
402
0
    free(chunkshape);
403
0
    free(blockshape);
404
0
    return BLOSC2_ERROR_FAILURE;
405
0
  }
406
0
  b2nd_deserialize_meta(smeta, smeta_len, &ndim, shape, chunkshape, blockshape, NULL, NULL);
407
0
  free(smeta);
408
409
0
  zfp_type type;     /* array scalar type */
410
0
  zfp_field *field;  /* array meta data */
411
0
  zfp_stream *zfp;   /* compressed stream */
412
0
  bitstream *stream; /* bit stream to write to or read from */
413
0
  size_t zfpsize;    /* byte size of compressed stream */
414
415
0
  uint prec;
416
0
  switch (ndim) {
417
0
    case 1:
418
0
      prec = meta + 5;
419
0
      break;
420
0
    case 2:
421
0
      prec = meta + 7;
422
0
      break;
423
0
    case 3:
424
0
      prec = meta + 9;
425
0
      break;
426
0
    case 4:
427
0
      prec = meta + 11;
428
0
      break;
429
0
    default:
430
0
      free(shape);
431
0
      free(chunkshape);
432
0
      free(blockshape);
433
0
      BLOSC_TRACE_ERROR("ZFP is not available for ndims: %d", ndim);
434
0
      return BLOSC2_ERROR_FAILURE;
435
0
  }
436
437
0
  if (prec > ZFP_MAX_PREC) {
438
0
    BLOSC_TRACE_ERROR("Max precision for this codecs is %d", ZFP_MAX_PREC);
439
0
    prec = ZFP_MAX_PREC;
440
0
  }
441
442
0
  switch (typesize) {
443
0
    case sizeof(float):
444
0
      type = zfp_type_float;
445
0
      break;
446
0
    case sizeof(double):
447
0
      type = zfp_type_double;
448
0
      break;
449
0
    default:
450
0
      free(shape);
451
0
      free(chunkshape);
452
0
      free(blockshape);
453
0
      BLOSC_TRACE_ERROR("ZFP is not available for typesize: %d", typesize);
454
0
      return BLOSC2_ERROR_FAILURE;
455
0
  }
456
457
0
  zfp = zfp_stream_open(NULL);
458
0
  zfp_stream_set_precision(zfp, prec);
459
0
  stream = stream_open((void *) input, input_len);
460
0
  zfp_stream_set_bit_stream(zfp, stream);
461
0
  zfp_stream_rewind(zfp);
462
463
0
  switch (ndim) {
464
0
    case 1:
465
0
      field = zfp_field_1d((void *) output, type, blockshape[0]);
466
0
      break;
467
0
    case 2:
468
0
      field = zfp_field_2d((void *) output, type, blockshape[1], blockshape[0]);
469
0
      break;
470
0
    case 3:
471
0
      field = zfp_field_3d((void *) output, type, blockshape[2], blockshape[1], blockshape[0]);
472
0
      break;
473
0
    case 4:
474
0
      field = zfp_field_4d((void *) output, type, blockshape[3], blockshape[2], blockshape[1], blockshape[0]);
475
0
      break;
476
0
    default:
477
0
      free(shape);
478
0
      free(chunkshape);
479
0
      free(blockshape);
480
0
      BLOSC_TRACE_ERROR("ZFP is not available for ndims: %d", ndim);
481
0
      return BLOSC2_ERROR_FAILURE;
482
0
  }
483
484
0
  zfpsize = zfp_decompress(zfp, field);
485
486
  /* clean up */
487
0
  zfp_field_free(field);
488
0
  zfp_stream_close(zfp);
489
0
  stream_close(stream);
490
0
  free(shape);
491
0
  free(chunkshape);
492
0
  free(blockshape);
493
494
0
  if (zfpsize == 0) {
495
0
    BLOSC_TRACE_ERROR("\n ZFP: Decompression failed\n");
496
0
    return (int) zfpsize;
497
0
  }
498
499
0
  return (int) output_len;
500
0
}
501
502
int zfp_rate_compress(const uint8_t *input, int32_t input_len, uint8_t *output,
503
0
                      int32_t output_len, uint8_t meta, blosc2_cparams *cparams, const void *chunk) {
504
0
  BLOSC_UNUSED_PARAM(chunk);
505
0
  ZFP_ERROR_NULL(input);
506
0
  ZFP_ERROR_NULL(output);
507
0
  ZFP_ERROR_NULL(cparams);
508
0
  ZFP_ERROR_NULL(cparams->schunk);
509
510
0
  double ratio = (double) meta / 100.0;
511
0
  int8_t ndim;
512
0
  int64_t *shape = malloc(8 * sizeof(int64_t));
513
0
  int32_t *chunkshape = malloc(8 * sizeof(int32_t));
514
0
  int32_t *blockshape = malloc(8 * sizeof(int32_t));
515
0
  uint8_t *smeta;
516
0
  int32_t smeta_len;
517
0
  if (blosc2_meta_get(cparams->schunk, "b2nd", &smeta, &smeta_len) < 0) {
518
0
    free(shape);
519
0
    free(chunkshape);
520
0
    free(blockshape);
521
0
    BLOSC_TRACE_ERROR("b2nd layer not found!");
522
0
    return BLOSC2_ERROR_FAILURE;
523
0
  }
524
0
  b2nd_deserialize_meta(smeta, smeta_len, &ndim, shape, chunkshape, blockshape, NULL, NULL);
525
0
  free(smeta);
526
527
0
  for(int i = 0; i < ndim; i++) {
528
0
    if (blockshape[i] < 4) {
529
0
      BLOSC_TRACE_ERROR("ZFP does not support blocks smaller than cells (4x...x4");
530
0
      return BLOSC2_ERROR_FAILURE;
531
0
    }
532
0
  }
533
534
0
  zfp_type type;     /* array scalar type */
535
0
  zfp_field *field;  /* array meta data */
536
0
  zfp_stream *zfp;   /* stream containing the real output buffer */
537
0
  zfp_stream *zfp_aux;   /* auxiliary compressed stream */
538
0
  bitstream *stream; /* bit stream to write to or read from */
539
0
  bitstream *stream_aux; /* auxiliary bit stream to write to or read from */
540
0
  size_t zfpsize;    /* byte size of compressed stream */
541
542
0
  int32_t typesize = cparams->typesize;
543
544
0
  switch (typesize) {
545
0
    case sizeof(float):
546
0
      type = zfp_type_float;
547
0
      break;
548
0
    case sizeof(double):
549
0
      type = zfp_type_double;
550
0
      break;
551
0
    default:
552
0
      BLOSC_TRACE_ERROR("ZFP is not available for typesize: %d", typesize);
553
0
      return BLOSC2_ERROR_FAILURE;
554
0
  }
555
0
  double rate = ratio * typesize * 8;     // convert from output size / input size to output bits per input value
556
0
  uint cellsize = 1u << (2 * ndim);
557
0
  double min_rate;
558
0
  if (type == zfp_type_float) {
559
0
    min_rate = (double) (1 + 8u) / cellsize;
560
0
    if (rate < min_rate) {
561
0
      BLOSC_TRACE_ERROR("ZFP minimum rate for this item type is %f. Compression will be done using this one.\n",
562
0
                        min_rate);
563
0
    }
564
0
  }
565
0
  else {
566
0
    min_rate = (double) (1 + 11u) / cellsize;
567
0
    if (rate < min_rate) {
568
0
      BLOSC_TRACE_ERROR("ZFP minimum rate for this item type is %f. Compression will be done using this one.\n",
569
0
                        min_rate);
570
0
    }
571
0
  }
572
0
  zfp = zfp_stream_open(NULL);
573
0
  stream = stream_open(output, output_len);
574
0
  zfp_stream_set_bit_stream(zfp, stream);
575
0
  zfp_stream_rewind(zfp);
576
577
0
  switch (ndim) {
578
0
    case 1:
579
0
      field = zfp_field_1d((void *) input, type, blockshape[0]);
580
0
      break;
581
0
    case 2:
582
0
      field = zfp_field_2d((void *) input, type, blockshape[1], blockshape[0]);
583
0
      break;
584
0
    case 3:
585
0
      field = zfp_field_3d((void *) input, type, blockshape[2], blockshape[1], blockshape[0]);
586
0
      break;
587
0
    case 4:
588
0
      field = zfp_field_4d((void *) input, type, blockshape[3], blockshape[2], blockshape[1], blockshape[0]);
589
0
      break;
590
0
    default:
591
0
      free(shape);
592
0
      free(chunkshape);
593
0
      free(blockshape);
594
0
      BLOSC_TRACE_ERROR("ZFP is not available for ndims: %d", ndim);
595
0
      return BLOSC2_ERROR_FAILURE;
596
0
  }
597
598
0
  int zfp_maxout = (int) zfp_stream_maximum_size(zfp, field);
599
0
  zfp_stream_close(zfp);
600
0
  stream_close(stream);
601
0
  uint8_t *aux_out = malloc(zfp_maxout);
602
0
  zfp_aux = zfp_stream_open(NULL);
603
0
  stream_aux = stream_open(aux_out, zfp_maxout);
604
0
  zfp_stream_set_bit_stream(zfp_aux, stream_aux);
605
0
  zfp_stream_rewind(zfp_aux);
606
0
  zfp_stream_set_rate(zfp_aux, rate, type, ndim, zfp_false);
607
608
0
  zfpsize = zfp_compress(zfp_aux, field);
609
610
  /* clean up */
611
0
  zfp_field_free(field);
612
0
  zfp_stream_close(zfp_aux);
613
0
  stream_close(stream_aux);
614
0
  free(shape);
615
0
  free(chunkshape);
616
0
  free(blockshape);
617
618
0
  if (zfpsize == 0) {
619
0
    BLOSC_TRACE_ERROR("\n ZFP: Compression failed\n");
620
0
    free(aux_out);
621
0
    return (int) zfpsize;
622
0
  }
623
0
  if ((int32_t) zfpsize >= input_len) {
624
0
    BLOSC_TRACE_ERROR("\n ZFP: Compressed data is bigger than input! \n");
625
0
    free(aux_out);
626
0
    return 0;
627
0
  }
628
629
0
  memcpy(output, aux_out, zfpsize);
630
0
  free(aux_out);
631
632
0
  return (int) zfpsize;
633
0
}
634
635
int zfp_rate_decompress(const uint8_t *input, int32_t input_len, uint8_t *output,
636
0
                        int32_t output_len, uint8_t meta, blosc2_dparams *dparams, const void *chunk) {
637
0
  ZFP_ERROR_NULL(input);
638
0
  ZFP_ERROR_NULL(output);
639
0
  ZFP_ERROR_NULL(dparams);
640
0
  ZFP_ERROR_NULL(dparams->schunk);
641
0
  BLOSC_UNUSED_PARAM(chunk);
642
643
0
  blosc2_schunk *sc = dparams->schunk;
644
0
  int32_t typesize = sc->typesize;
645
646
0
  double ratio = (double) meta / 100.0;
647
0
  int8_t ndim;
648
0
  int64_t *shape = malloc(8 * sizeof(int64_t));
649
0
  int32_t *chunkshape = malloc(8 * sizeof(int32_t));
650
0
  int32_t *blockshape = malloc(8 * sizeof(int32_t));
651
0
  uint8_t *smeta;
652
0
  int32_t smeta_len;
653
0
  if (blosc2_meta_get(sc, "b2nd", &smeta, &smeta_len) < 0) {
654
0
    BLOSC_TRACE_ERROR("Cannot access b2nd meta info");
655
0
    free(shape);
656
0
    free(chunkshape);
657
0
    free(blockshape);
658
0
    return BLOSC2_ERROR_FAILURE;
659
0
  }
660
0
  b2nd_deserialize_meta(smeta, smeta_len, &ndim, shape, chunkshape, blockshape, NULL, NULL);
661
0
  free(smeta);
662
663
0
  zfp_type type;     /* array scalar type */
664
0
  zfp_field *field;  /* array meta data */
665
0
  zfp_stream *zfp;   /* compressed stream */
666
0
  bitstream *stream; /* bit stream to write to or read from */
667
0
  size_t zfpsize;    /* byte size of compressed stream */
668
669
0
  switch (typesize) {
670
0
    case sizeof(float):
671
0
      type = zfp_type_float;
672
0
      break;
673
0
    case sizeof(double):
674
0
      type = zfp_type_double;
675
0
      break;
676
0
    default:
677
0
      free(shape);
678
0
      free(chunkshape);
679
0
      free(blockshape);
680
0
      BLOSC_TRACE_ERROR("ZFP is not available for typesize: %d", typesize);
681
0
      return BLOSC2_ERROR_FAILURE;
682
0
  }
683
0
  double rate =
684
0
      ratio * (double) typesize * 8;     // convert from output size / input size to output bits per input value
685
0
  zfp = zfp_stream_open(NULL);
686
0
  zfp_stream_set_rate(zfp, rate, type, ndim, zfp_false);
687
688
0
  stream = stream_open((void *) input, input_len);
689
0
  zfp_stream_set_bit_stream(zfp, stream);
690
0
  zfp_stream_rewind(zfp);
691
692
0
  switch (ndim) {
693
0
    case 1:
694
0
      field = zfp_field_1d((void *) output, type, blockshape[0]);
695
0
      break;
696
0
    case 2:
697
0
      field = zfp_field_2d((void *) output, type, blockshape[1], blockshape[0]);
698
0
      break;
699
0
    case 3:
700
0
      field = zfp_field_3d((void *) output, type, blockshape[2], blockshape[1], blockshape[0]);
701
0
      break;
702
0
    case 4:
703
0
      field = zfp_field_4d((void *) output, type, blockshape[3], blockshape[2], blockshape[1], blockshape[0]);
704
0
      break;
705
0
    default:
706
0
      free(shape);
707
0
      free(chunkshape);
708
0
      free(blockshape);
709
0
      BLOSC_TRACE_ERROR("ZFP is not available for ndims: %d", ndim);
710
0
      return BLOSC2_ERROR_FAILURE;
711
0
  }
712
713
0
  zfpsize = zfp_decompress(zfp, field);
714
715
  /* clean up */
716
0
  zfp_field_free(field);
717
0
  zfp_stream_close(zfp);
718
0
  stream_close(stream);
719
0
  free(shape);
720
0
  free(chunkshape);
721
0
  free(blockshape);
722
723
0
  if (zfpsize == 0) {
724
0
    BLOSC_TRACE_ERROR("\n ZFP: Decompression failed\n");
725
0
    return (int) zfpsize;
726
0
  }
727
728
0
  return (int) output_len;
729
0
}
730
731
0
int zfp_getcell(void *thread_context, const uint8_t *block, int32_t cbytes, uint8_t *dest, int32_t destsize) {
732
0
  struct thread_context *thread_ctx = thread_context;
733
0
  blosc2_context *context = thread_ctx->parent_context;
734
0
  bool meta = false;
735
0
  int8_t ndim = ZFP_MAX_DIM + 1;
736
0
  int32_t blockmeta[ZFP_MAX_DIM];
737
0
  if (context->schunk->blockshape == NULL) {
738
    // blockshape is not filled yet.  Use the Blosc2 NDim layer to populate it.
739
0
    for (int nmetalayer = 0; nmetalayer < context->schunk->nmetalayers; nmetalayer++) {
740
0
      if (strcmp("b2nd", context->schunk->metalayers[nmetalayer]->name) == 0) {
741
0
        meta = true;
742
0
        uint8_t *pmeta = context->schunk->metalayers[nmetalayer]->content;
743
0
        ndim = (int8_t) pmeta[2];
744
0
        assert(ndim <= ZFP_MAX_DIM);
745
0
        pmeta += (6 + ndim * 9 + ndim * 5);
746
0
        for (int8_t i = 0; (uint8_t) i < ndim; i++) {
747
0
          pmeta += 1;
748
0
          swap_store(blockmeta + i, pmeta, sizeof(int32_t));
749
0
          pmeta += sizeof(int32_t);
750
0
        }
751
0
      }
752
0
    }
753
0
    if (!meta) {
754
0
      return -1;
755
0
    }
756
0
    context->schunk->ndim = ndim;
757
0
    context->schunk->blockshape = malloc(sizeof(int64_t) * ndim);
758
0
    for (int i = 0; i < ndim; ++i) {
759
0
      context->schunk->blockshape[i] = (int64_t) blockmeta[i];
760
0
    }
761
0
  }
762
0
  ndim = context->schunk->ndim;
763
0
  int64_t *blockshape = context->schunk->blockshape;
764
765
  // Compute the coordinates of the cell
766
0
  int64_t cell_start_ndim[ZFP_MAX_DIM];
767
0
  int64_t cell_ind_ndim[ZFP_MAX_DIM];
768
0
  int64_t ncell_ndim[ZFP_MAX_DIM];
769
0
  int64_t ind_strides[ZFP_MAX_DIM];
770
0
  int64_t cell_strides[ZFP_MAX_DIM];
771
0
  int64_t cell_ind, ncell;
772
0
  blosc2_unidim_to_multidim(ndim, blockshape, thread_ctx->zfp_cell_start, cell_start_ndim);
773
0
  for (int i = 0; i < ndim; ++i) {
774
0
    cell_ind_ndim[i] = cell_start_ndim[i] % ZFP_MAX_DIM;
775
0
    ncell_ndim[i] = cell_start_ndim[i] / ZFP_MAX_DIM;
776
0
  }
777
0
  ind_strides[ndim - 1] = cell_strides[ndim - 1] = 1;
778
0
  for (int i = ndim - 2; i >= 0; --i) {
779
0
    ind_strides[i] = ZFP_MAX_DIM * ind_strides[i + 1];
780
0
    cell_strides[i] = ((blockshape[i + 1] - 1) / ZFP_MAX_DIM + 1) * cell_strides[i + 1];
781
0
  }
782
0
  blosc2_multidim_to_unidim(cell_ind_ndim, (int8_t) ndim, ind_strides, &cell_ind);
783
0
  blosc2_multidim_to_unidim(ncell_ndim, (int8_t) ndim, cell_strides, &ncell);
784
0
  int cell_nitems = (int) (1u << (2 * ndim));
785
0
  if ((thread_ctx->zfp_cell_nitems > cell_nitems) ||
786
0
      ((cell_ind + thread_ctx->zfp_cell_nitems) > cell_nitems)) {
787
0
    return 0;
788
0
  }
789
790
  // Get the ZFP stream
791
0
  zfp_type type;     /* array scalar type */
792
0
  zfp_stream *zfp;   /* compressed stream */
793
0
  bitstream *stream; /* bit stream to write to or read from */
794
0
  int32_t typesize = context->typesize;
795
0
  zfp = zfp_stream_open(NULL);
796
797
0
  switch (typesize) {
798
0
    case sizeof(float):
799
0
      type = zfp_type_float;
800
0
      break;
801
0
    case sizeof(double):
802
0
      type = zfp_type_double;
803
0
      break;
804
0
    default:
805
0
      BLOSC_TRACE_ERROR("ZFP is not available for typesize: %d", typesize);
806
0
      return BLOSC2_ERROR_FAILURE;
807
0
  }
808
0
  uint8_t compmeta = context->compcode_meta;   // access to compressed chunk header
809
0
  double rate = (double) (compmeta * typesize * 8) /
810
0
                100.0;     // convert from output size / input size to output bits per input value
811
0
  zfp_stream_set_rate(zfp, rate, type, ndim, zfp_false);
812
813
0
  stream = stream_open((void *) block, cbytes);
814
0
  zfp_stream_set_bit_stream(zfp, stream);
815
0
  zfp_stream_rewind(zfp);
816
817
  // Check that ncell is a valid index
818
0
  int ncells = (int) ((cbytes * 8) / zfp->maxbits);
819
0
  if (ncell >= ncells) {
820
0
    BLOSC_TRACE_ERROR("Invalid cell index");
821
0
    return -1;
822
0
  }
823
824
  // Position the stream at the ncell bit offset for reading
825
0
  stream_rseek(zfp->stream, (size_t) (ncell * zfp->maxbits));
826
827
  // Get the cell
828
0
  size_t zfpsize;
829
0
  uint8_t *cell = malloc(cell_nitems * typesize);
830
0
  switch (ndim) {
831
0
    case 1:
832
0
      if (type == zfp_type_float) {
833
0
        zfpsize = zfp_decode_block_float_1(zfp, (float *) cell);
834
0
      }
835
0
      else {
836
0
        zfpsize = zfp_decode_block_double_1(zfp, (double *) cell);
837
0
      }
838
0
      break;
839
0
    case 2:
840
0
      if (type == zfp_type_float) {
841
0
        zfpsize = zfp_decode_block_float_2(zfp, (float *) cell);
842
0
      }
843
0
      else {
844
0
        zfpsize = zfp_decode_block_double_2(zfp, (double *) cell);
845
0
      }
846
0
      break;
847
0
    case 3:
848
0
      if (type == zfp_type_float) {
849
0
        zfpsize = zfp_decode_block_float_3(zfp, (float *) cell);
850
0
      }
851
0
      else {
852
0
        zfpsize = zfp_decode_block_double_3(zfp, (double *) cell);
853
0
      }
854
0
      break;
855
0
    case 4:
856
0
      if (type == zfp_type_float) {
857
0
        zfpsize = zfp_decode_block_float_4(zfp, (float *) cell);
858
0
      }
859
0
      else {
860
0
        zfpsize = zfp_decode_block_double_4(zfp, (double *) cell);
861
0
      }
862
0
      break;
863
0
    default:
864
0
      free(cell);
865
0
      BLOSC_TRACE_ERROR("ZFP is not available for ndims: %d", ndim);
866
0
      return BLOSC2_ERROR_FAILURE;
867
0
  }
868
0
  memcpy(dest, &cell[cell_ind * typesize], thread_ctx->zfp_cell_nitems * typesize);
869
0
  free(cell);
870
0
  zfp_stream_close(zfp);
871
0
  stream_close(stream);
872
873
0
  if ((zfpsize == 0) || ((int32_t) zfpsize > (destsize * 8)) ||
874
0
      ((int32_t) zfpsize > (cell_nitems * typesize * 8)) ||
875
0
      ((thread_ctx->zfp_cell_nitems * typesize * 8) > (int32_t) zfpsize)) {
876
0
    BLOSC_TRACE_ERROR("ZFP error or small destsize");
877
0
    return -1;
878
0
  }
879
880
0
  return (int) (thread_ctx->zfp_cell_nitems * typesize);
881
0
}