aboutsummaryrefslogtreecommitdiffstats
path: root/util/generic/ylimits.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/generic/ylimits.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/generic/ylimits.h')
-rw-r--r--util/generic/ylimits.h92
1 files changed, 92 insertions, 0 deletions
diff --git a/util/generic/ylimits.h b/util/generic/ylimits.h
new file mode 100644
index 0000000000..fe42b4dfc0
--- /dev/null
+++ b/util/generic/ylimits.h
@@ -0,0 +1,92 @@
+#pragma once
+
+#include <limits>
+
+#if defined(max) || defined(min)
+ #error "stop defining 'min' and 'max' macros, evil people"
+#endif
+
+template <class T>
+static constexpr T Max() noexcept {
+ return std::numeric_limits<T>::max();
+}
+
+template <class T>
+static constexpr T Min() noexcept {
+ return std::numeric_limits<T>::min();
+}
+
+namespace NPrivate {
+ struct TMax {
+ template <class T>
+ constexpr operator T() const {
+ return Max<T>();
+ }
+ };
+
+ struct TMin {
+ template <class T>
+ constexpr operator T() const {
+ return Min<T>();
+ }
+ };
+}
+
+static constexpr ::NPrivate::TMax Max() noexcept {
+ return {};
+}
+
+static constexpr ::NPrivate::TMin Min() noexcept {
+ return {};
+}
+
+namespace NPrivate {
+ template <unsigned long long N>
+ static constexpr double MaxFloorValue() {
+ return N;
+ }
+ template <unsigned long long N>
+ static constexpr double MaxCeilValue() {
+ return N;
+ }
+ template <>
+ constexpr double MaxFloorValue<0x7FFF'FFFF'FFFF'FFFFull>() {
+ return 9223372036854774784.0; // 0x7FFFFFFFFFFFFC00p0
+ }
+ template <>
+ constexpr double MaxCeilValue<0x7FFF'FFFF'FFFF'FFFFull>() {
+ return 9223372036854775808.0; // 0x8000000000000000p0
+ }
+ template <>
+ constexpr double MaxFloorValue<0xFFFF'FFFF'FFFF'FFFFull>() {
+ return 18446744073709549568.0; // 0xFFFFFFFFFFFFF800p0
+ }
+ template <>
+ constexpr double MaxCeilValue<0xFFFF'FFFF'FFFF'FFFFull>() {
+ return 18446744073709551616.0; // 0x10000000000000000p0
+ }
+}
+
+// MaxFloor<T> is the greatest double within the range of T.
+//
+// 1. If Max<T> is an exact double, MaxFloor<T> = Max<T> = MaxCeil<T>.
+// In this case some doubles above MaxFloor<T> cast to T may round
+// to Max<T> depending on the rounding mode.
+//
+// 2. Otherwise Max<T> is between MaxFloor<T> and MaxCeil<T>, and
+// MaxFloor<T> is the largest double that does not overflow T.
+template <class T>
+static constexpr double MaxFloor() noexcept {
+ return ::NPrivate::MaxFloorValue<Max<T>()>();
+}
+
+// MaxCeil<T> is the smallest double not lesser than Max<T>.
+//
+// 1. If Max<T> is an exact double, MaxCeil<T> = Max<T> = MaxFloor<T>.
+//
+// 2. Otherwise Max<T> is between MaxFloor<T> and MaxCeil<T>, and
+// MaxCeil<T> is the smallest double that overflows T.
+template <class T>
+static constexpr double MaxCeil() noexcept {
+ return ::NPrivate::MaxCeilValue<Max<T>()>();
+}