Coverage Report

Created: 2025-07-11 06:49

/src/c-blosc2/blosc/trunc-prec.c
Line
Count
Source (jump to first uncovered line)
1
/*********************************************************************
2
  Blosc - Blocked Shuffling and Compression Library
3
4
  Copyright (c) 2021  Blosc Development Team <blosc@blosc.org>
5
  https://blosc.org
6
  License: BSD 3-Clause (see LICENSE.txt)
7
8
  See LICENSE.txt for details about copyright and rights to use.
9
**********************************************************************/
10
11
#include "trunc-prec.h"
12
#include "blosc2.h"
13
14
#include <assert.h>
15
#include <stdio.h>
16
#include <stdint.h>
17
#include <stdlib.h>
18
19
0
#define BITS_MANTISSA_FLOAT 23
20
0
#define BITS_MANTISSA_DOUBLE 52
21
22
23
int truncate_precision32(int8_t prec_bits, int32_t nelems,
24
0
                         const int32_t* src, int32_t* dest) {
25
  // Make sure that we don't remove all the bits in mantissa so that we
26
  // don't mess with NaNs or Infinite representation in IEEE 754:
27
  // https://en.wikipedia.org/wiki/NaN
28
0
  if ((abs(prec_bits) > BITS_MANTISSA_FLOAT)) {
29
0
    BLOSC_TRACE_ERROR("The precision cannot be larger than %d bits for floats (asking for %d bits)",
30
0
                      BITS_MANTISSA_FLOAT, prec_bits);
31
0
    return -1;
32
0
  }
33
0
  int zeroed_bits = (prec_bits >= 0) ? BITS_MANTISSA_FLOAT - prec_bits : -prec_bits;
34
0
  if (zeroed_bits >= BITS_MANTISSA_FLOAT) {
35
0
    BLOSC_TRACE_ERROR("The reduction in precision cannot be larger or equal than %d bits for floats (asking for %d bits)",
36
0
                      BITS_MANTISSA_FLOAT, zeroed_bits);
37
0
    return -1;
38
0
  }
39
0
  int32_t mask = ~((1 << zeroed_bits) - 1);
40
0
  for (int i = 0; i < nelems; i++) {
41
0
    dest[i] = src[i] & mask;
42
0
  }
43
0
  return 0;
44
0
}
45
46
int truncate_precision64(int8_t prec_bits, int32_t nelems,
47
0
                          const int64_t* src, int64_t* dest) {
48
  // Make sure that we don't remove all the bits in mantissa so that we
49
  // don't mess with NaNs or Infinite representation in IEEE 754:
50
  // https://en.wikipedia.org/wiki/NaN
51
0
  if ((abs(prec_bits) > BITS_MANTISSA_DOUBLE)) {
52
0
    BLOSC_TRACE_ERROR("The precision cannot be larger than %d bits for floats (asking for %d bits)",
53
0
                      BITS_MANTISSA_DOUBLE, prec_bits);
54
0
    return -1;
55
0
  }
56
0
  int zeroed_bits = (prec_bits >= 0) ? BITS_MANTISSA_DOUBLE - prec_bits : -prec_bits;
57
0
  if (zeroed_bits >= BITS_MANTISSA_DOUBLE) {
58
0
    BLOSC_TRACE_ERROR("The reduction in precision cannot be larger or equal than %d bits for floats (asking for %d bits)",
59
0
                      BITS_MANTISSA_DOUBLE, zeroed_bits);
60
0
    return -1;
61
0
  }
62
0
  uint64_t mask = ~((1ULL << zeroed_bits) - 1ULL);
63
0
  for (int i = 0; i < nelems; i++) {
64
0
    dest[i] = (int64_t)(src[i] & mask);
65
0
  }
66
0
  return 0;
67
0
}
68
69
/* Apply the truncate precision to src.  This can never fail. */
70
int truncate_precision(int8_t prec_bits, int32_t typesize, int32_t nbytes,
71
0
                       const uint8_t* src, uint8_t* dest) {
72
  // Positive values of prec_bits will set absolute precision bits, whereas negative
73
  // values will reduce the precision bits (similar to Python slicing convention).
74
0
  switch (typesize) {
75
0
    case 4:
76
0
      return truncate_precision32(prec_bits, nbytes / typesize,
77
0
                              (int32_t *)src, (int32_t *)dest);
78
0
    case 8:
79
0
      return truncate_precision64(prec_bits, nbytes / typesize,
80
0
                              (int64_t *)src, (int64_t *)dest);
81
0
    default:
82
0
      BLOSC_TRACE_ERROR("Error in trunc-prec filter: Precision for typesize %d not handled",
83
0
                        (int)typesize);
84
0
      return -1;
85
0
  }
86
0
}