/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 | } |