/Users/eugenesiegel/btc/bitcoin/src/util/serfloat.cpp
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | // Copyright (c) 2021 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 | 0 | double DecodeDouble(uint64_t v) noexcept { | 
| 11 | 0 |     static constexpr double NANVAL = std::numeric_limits<double>::quiet_NaN(); | 
| 12 | 0 |     static constexpr double INFVAL = std::numeric_limits<double>::infinity(); | 
| 13 | 0 |     double sign = 1.0; | 
| 14 | 0 |     if (v & 0x8000000000000000) { | 
| 15 | 0 |         sign = -1.0; | 
| 16 | 0 |         v ^= 0x8000000000000000; | 
| 17 | 0 |     } | 
| 18 |  |     // Zero | 
| 19 | 0 |     if (v == 0) return copysign(0.0, sign); | 
| 20 |  |     // Infinity | 
| 21 | 0 |     if (v == 0x7ff0000000000000) return copysign(INFVAL, sign); | 
| 22 |  |     // Other numbers | 
| 23 | 0 |     int exp = (v & 0x7FF0000000000000) >> 52; | 
| 24 | 0 |     uint64_t man = v & 0xFFFFFFFFFFFFF; | 
| 25 | 0 |     if (exp == 2047) { | 
| 26 |  |         // NaN | 
| 27 | 0 |         return NANVAL; | 
| 28 | 0 |     } else if (exp == 0) { | 
| 29 |  |         // Subnormal | 
| 30 | 0 |         return copysign(ldexp((double)man, -1074), sign); | 
| 31 | 0 |     } else { | 
| 32 |  |         // Normal | 
| 33 | 0 |         return copysign(ldexp((double)(man + 0x10000000000000), -1075 + exp), sign); | 
| 34 | 0 |     } | 
| 35 | 0 | } | 
| 36 |  |  | 
| 37 | 0 | uint64_t EncodeDouble(double f) noexcept { | 
| 38 | 0 |     int cls = std::fpclassify(f); | 
| 39 | 0 |     uint64_t sign = 0; | 
| 40 | 0 |     if (copysign(1.0, f) == -1.0) { | 
| 41 | 0 |         f = -f; | 
| 42 | 0 |         sign = 0x8000000000000000; | 
| 43 | 0 |     } | 
| 44 |  |     // Zero | 
| 45 | 0 |     if (cls == FP_ZERO) return sign; | 
| 46 |  |     // Infinity | 
| 47 | 0 |     if (cls == FP_INFINITE) return sign | 0x7ff0000000000000; | 
| 48 |  |     // NaN | 
| 49 | 0 |     if (cls == FP_NAN) return 0x7ff8000000000000; | 
| 50 |  |     // Other numbers | 
| 51 | 0 |     int exp; | 
| 52 | 0 |     uint64_t man = std::round(std::frexp(f, &exp) * 9007199254740992.0); | 
| 53 | 0 |     if (exp < -1021) { | 
| 54 |  |         // Too small to represent, encode 0 | 
| 55 | 0 |         if (exp < -1084) return sign; | 
| 56 |  |         // Subnormal numbers | 
| 57 | 0 |         return sign | (man >> (-1021 - exp)); | 
| 58 | 0 |     } else { | 
| 59 |  |         // Too big to represent, encode infinity | 
| 60 | 0 |         if (exp > 1024) return sign | 0x7ff0000000000000; | 
| 61 |  |         // Normal numbers | 
| 62 | 0 |         return sign | (((uint64_t)(1022 + exp)) << 52) | (man & 0xFFFFFFFFFFFFF); | 
| 63 | 0 |     } | 
| 64 | 0 | } |