aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/serfloat.cpp64
-rw-r--r--src/util/serfloat.h16
-rw-r--r--src/util/time.cpp2
-rw-r--r--src/util/time.h4
4 files changed, 83 insertions, 3 deletions
diff --git a/src/util/serfloat.cpp b/src/util/serfloat.cpp
new file mode 100644
index 0000000000..8edca924cd
--- /dev/null
+++ b/src/util/serfloat.cpp
@@ -0,0 +1,64 @@
+// Copyright (c) 2021 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/serfloat.h>
+
+#include <cmath>
+#include <limits>
+
+double DecodeDouble(uint64_t v) noexcept {
+ static constexpr double NANVAL = std::numeric_limits<double>::quiet_NaN();
+ static constexpr double INFVAL = std::numeric_limits<double>::infinity();
+ double sign = 1.0;
+ if (v & 0x8000000000000000) {
+ sign = -1.0;
+ v ^= 0x8000000000000000;
+ }
+ // Zero
+ if (v == 0) return copysign(0.0, sign);
+ // Infinity
+ if (v == 0x7ff0000000000000) return copysign(INFVAL, sign);
+ // Other numbers
+ int exp = (v & 0x7FF0000000000000) >> 52;
+ uint64_t man = v & 0xFFFFFFFFFFFFF;
+ if (exp == 2047) {
+ // NaN
+ return NANVAL;
+ } else if (exp == 0) {
+ // Subnormal
+ return copysign(ldexp((double)man, -1074), sign);
+ } else {
+ // Normal
+ return copysign(ldexp((double)(man + 0x10000000000000), -1075 + exp), sign);
+ }
+}
+
+uint64_t EncodeDouble(double f) noexcept {
+ int cls = std::fpclassify(f);
+ uint64_t sign = 0;
+ if (copysign(1.0, f) == -1.0) {
+ f = -f;
+ sign = 0x8000000000000000;
+ }
+ // Zero
+ if (cls == FP_ZERO) return sign;
+ // Infinity
+ if (cls == FP_INFINITE) return sign | 0x7ff0000000000000;
+ // NaN
+ if (cls == FP_NAN) return 0x7ff8000000000000;
+ // Other numbers
+ int exp;
+ uint64_t man = std::round(std::frexp(f, &exp) * 9007199254740992.0);
+ if (exp < -1021) {
+ // Too small to represent, encode 0
+ if (exp < -1084) return sign;
+ // Subnormal numbers
+ return sign | (man >> (-1021 - exp));
+ } else {
+ // Too big to represent, encode infinity
+ if (exp > 1024) return sign | 0x7ff0000000000000;
+ // Normal numbers
+ return sign | (((uint64_t)(1022 + exp)) << 52) | (man & 0xFFFFFFFFFFFFF);
+ }
+}
diff --git a/src/util/serfloat.h b/src/util/serfloat.h
new file mode 100644
index 0000000000..4d912b0176
--- /dev/null
+++ b/src/util/serfloat.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2021 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_SERFLOAT_H
+#define BITCOIN_UTIL_SERFLOAT_H
+
+#include <stdint.h>
+
+/* Encode a double using the IEEE 754 binary64 format. All NaNs are encoded as x86/ARM's
+ * positive quiet NaN with payload 0. */
+uint64_t EncodeDouble(double f) noexcept;
+/* Reverse operation of DecodeDouble. DecodeDouble(EncodeDouble(f))==f unless isnan(f). */
+double DecodeDouble(uint64_t v) noexcept;
+
+#endif // BITCOIN_UTIL_SERFLOAT_H
diff --git a/src/util/time.cpp b/src/util/time.cpp
index e6f0986a39..eda710b12c 100644
--- a/src/util/time.cpp
+++ b/src/util/time.cpp
@@ -124,7 +124,7 @@ int64_t GetTimeMicros()
return int64_t{GetSystemTime<std::chrono::microseconds>().count()};
}
-int64_t GetSystemTimeInSeconds()
+int64_t GetTimeSeconds()
{
return int64_t{GetSystemTime<std::chrono::seconds>().count()};
}
diff --git a/src/util/time.h b/src/util/time.h
index 7ebcaaa339..4aee01967d 100644
--- a/src/util/time.h
+++ b/src/util/time.h
@@ -39,7 +39,7 @@ inline double CountSecondsDouble(SecondsDouble t) { return t.count(); }
/**
* DEPRECATED
- * Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
+ * Use either GetTimeSeconds (not mockable) or GetTime<T> (mockable)
*/
int64_t GetTime();
@@ -48,7 +48,7 @@ int64_t GetTimeMillis();
/** Returns the system time (not mockable) */
int64_t GetTimeMicros();
/** Returns the system time (not mockable) */
-int64_t GetSystemTimeInSeconds(); // Like GetTime(), but not mockable
+int64_t GetTimeSeconds(); // Like GetTime(), but not mockable
/**
* DEPRECATED