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