Coverage Report

Created: 2026-04-29 19:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/util/serfloat.cpp
Line
Count
Source
1
// Copyright (c) 2021-present The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#include <util/serfloat.h>
6
7
#include <cmath>
8
#include <limits>
9
10
22.0M
double DecodeDouble(uint64_t v) noexcept {
11
22.0M
    static constexpr double NANVAL = std::numeric_limits<double>::quiet_NaN();
12
22.0M
    static constexpr double INFVAL = std::numeric_limits<double>::infinity();
13
22.0M
    double sign = 1.0;
14
22.0M
    if (v & 0x8000000000000000) {
15
255k
        sign = -1.0;
16
255k
        v ^= 0x8000000000000000;
17
255k
    }
18
    // Zero
19
22.0M
    if (v == 0) return copysign(0.0, sign);
20
    // Infinity
21
721k
    if (v == 0x7ff0000000000000) return copysign(INFVAL, sign);
22
    // Other numbers
23
721k
    int exp = (v & 0x7FF0000000000000) >> 52;
24
721k
    uint64_t man = v & 0xFFFFFFFFFFFFF;
25
721k
    if (exp == 2047) {
26
        // NaN
27
269
        return NANVAL;
28
720k
    } else if (exp == 0) {
29
        // Subnormal
30
254
        return copysign(ldexp((double)man, -1074), sign);
31
720k
    } else {
32
        // Normal
33
720k
        return copysign(ldexp((double)(man + 0x10000000000000), -1075 + exp), sign);
34
720k
    }
35
721k
}
36
37
41.3M
uint64_t EncodeDouble(double f) noexcept {
38
41.3M
    int cls = std::fpclassify(f);
39
41.3M
    uint64_t sign = 0;
40
41.3M
    if (copysign(1.0, f) == -1.0) {
41
511k
        f = -f;
42
511k
        sign = 0x8000000000000000;
43
511k
    }
44
    // Zero
45
41.3M
    if (cls == FP_ZERO) return sign;
46
    // Infinity
47
1.42M
    if (cls == FP_INFINITE) return sign | 0x7ff0000000000000;
48
    // NaN
49
1.42M
    if (cls == FP_NAN) return 0x7ff8000000000000;
50
    // Other numbers
51
1.42M
    int exp;
52
1.42M
    uint64_t man = std::round(std::frexp(f, &exp) * 9007199254740992.0);
53
1.42M
    if (exp < -1021) {
54
        // Too small to represent, encode 0
55
508
        if (exp < -1084) return sign;
56
        // Subnormal numbers
57
508
        return sign | (man >> (-1021 - exp));
58
1.42M
    } else {
59
        // Too big to represent, encode infinity
60
1.42M
        if (exp > 1024) return sign | 0x7ff0000000000000;
61
        // Normal numbers
62
1.42M
        return sign | (((uint64_t)(1022 + exp)) << 52) | (man & 0xFFFFFFFFFFFFF);
63
1.42M
    }
64
1.42M
}