diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/generic/ylimits.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/generic/ylimits.h')
-rw-r--r-- | util/generic/ylimits.h | 92 |
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>()>(); +} |