зеркало из https://github.com/microsoft/STL.git
1183 строки
33 KiB
C++
1183 строки
33 KiB
C++
// limits standard header (core)
|
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#pragma once
|
|
#ifndef _LIMITS_
|
|
#define _LIMITS_
|
|
#include <yvals_core.h>
|
|
#if _STL_COMPILER_PREPROCESSOR
|
|
#include <cfloat>
|
|
#include <climits>
|
|
#include <cwchar>
|
|
#include <intrin0.h>
|
|
#include <isa_availability.h>
|
|
#include <xstddef>
|
|
|
|
#pragma pack(push, _CRT_PACKING)
|
|
#pragma warning(push, _STL_WARNING_LEVEL)
|
|
#pragma warning(disable : _STL_DISABLED_WARNINGS)
|
|
_STL_DISABLE_CLANG_WARNINGS
|
|
#pragma push_macro("new")
|
|
#undef new
|
|
|
|
_STD_BEGIN
|
|
// ENUM float_denorm_style
|
|
enum float_denorm_style { // constants for different IEEE float denormalization styles
|
|
denorm_indeterminate = -1,
|
|
denorm_absent = 0,
|
|
denorm_present = 1
|
|
};
|
|
|
|
// ENUM float_round_style
|
|
enum float_round_style { // constants for different IEEE rounding styles
|
|
round_indeterminate = -1,
|
|
round_toward_zero = 0,
|
|
round_to_nearest = 1,
|
|
round_toward_infinity = 2,
|
|
round_toward_neg_infinity = 3
|
|
};
|
|
|
|
// STRUCT _Num_base
|
|
struct _Num_base { // base for all types, with common defaults
|
|
static constexpr float_denorm_style has_denorm = denorm_absent;
|
|
static constexpr bool has_denorm_loss = false;
|
|
static constexpr bool has_infinity = false;
|
|
static constexpr bool has_quiet_NaN = false;
|
|
static constexpr bool has_signaling_NaN = false;
|
|
static constexpr bool is_bounded = false;
|
|
static constexpr bool is_exact = false;
|
|
static constexpr bool is_iec559 = false;
|
|
static constexpr bool is_integer = false;
|
|
static constexpr bool is_modulo = false;
|
|
static constexpr bool is_signed = false;
|
|
static constexpr bool is_specialized = false;
|
|
static constexpr bool tinyness_before = false;
|
|
static constexpr bool traps = false;
|
|
static constexpr float_round_style round_style = round_toward_zero;
|
|
static constexpr int digits = 0;
|
|
static constexpr int digits10 = 0;
|
|
static constexpr int max_digits10 = 0;
|
|
static constexpr int max_exponent = 0;
|
|
static constexpr int max_exponent10 = 0;
|
|
static constexpr int min_exponent = 0;
|
|
static constexpr int min_exponent10 = 0;
|
|
static constexpr int radix = 0;
|
|
};
|
|
|
|
// CLASS TEMPLATE numeric_limits
|
|
template <class _Ty>
|
|
class numeric_limits : public _Num_base { // numeric limits for arbitrary type _Ty (say little or nothing)
|
|
public:
|
|
_NODISCARD static constexpr _Ty(min)() noexcept {
|
|
return _Ty();
|
|
}
|
|
|
|
_NODISCARD static constexpr _Ty(max)() noexcept {
|
|
return _Ty();
|
|
}
|
|
|
|
_NODISCARD static constexpr _Ty lowest() noexcept {
|
|
return _Ty();
|
|
}
|
|
|
|
_NODISCARD static constexpr _Ty epsilon() noexcept {
|
|
return _Ty();
|
|
}
|
|
|
|
_NODISCARD static constexpr _Ty round_error() noexcept {
|
|
return _Ty();
|
|
}
|
|
|
|
_NODISCARD static constexpr _Ty denorm_min() noexcept {
|
|
return _Ty();
|
|
}
|
|
|
|
_NODISCARD static constexpr _Ty infinity() noexcept {
|
|
return _Ty();
|
|
}
|
|
|
|
_NODISCARD static constexpr _Ty quiet_NaN() noexcept {
|
|
return _Ty();
|
|
}
|
|
|
|
_NODISCARD static constexpr _Ty signaling_NaN() noexcept {
|
|
return _Ty();
|
|
}
|
|
};
|
|
|
|
template <class _Ty>
|
|
class numeric_limits<const _Ty> : public numeric_limits<_Ty> {}; // numeric limits for const types
|
|
|
|
template <class _Ty>
|
|
class numeric_limits<volatile _Ty> : public numeric_limits<_Ty> {}; // numeric limits for volatile types
|
|
|
|
template <class _Ty>
|
|
class numeric_limits<const volatile _Ty> : public numeric_limits<_Ty> {}; // numeric limits for const volatile types
|
|
|
|
// STRUCT _Num_int_base
|
|
struct _Num_int_base : _Num_base { // base for integer types
|
|
static constexpr bool is_bounded = true;
|
|
static constexpr bool is_exact = true;
|
|
static constexpr bool is_integer = true;
|
|
static constexpr bool is_specialized = true;
|
|
static constexpr int radix = 2;
|
|
};
|
|
|
|
// STRUCT _Num_float_base
|
|
struct _Num_float_base : _Num_base { // base for floating-point types
|
|
static constexpr float_denorm_style has_denorm = denorm_present;
|
|
static constexpr bool has_infinity = true;
|
|
static constexpr bool has_quiet_NaN = true;
|
|
static constexpr bool has_signaling_NaN = true;
|
|
static constexpr bool is_bounded = true;
|
|
static constexpr bool is_iec559 = true;
|
|
static constexpr bool is_signed = true;
|
|
static constexpr bool is_specialized = true;
|
|
static constexpr float_round_style round_style = round_to_nearest;
|
|
static constexpr int radix = FLT_RADIX;
|
|
};
|
|
|
|
// CLASS numeric_limits<bool>
|
|
template <>
|
|
class numeric_limits<bool> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr bool(min)() noexcept {
|
|
return false;
|
|
}
|
|
|
|
_NODISCARD static constexpr bool(max)() noexcept {
|
|
return true;
|
|
}
|
|
|
|
_NODISCARD static constexpr bool lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr bool epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr bool round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr bool denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr bool infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr bool quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr bool signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr int digits = 1;
|
|
};
|
|
|
|
// CLASS numeric_limits<char>
|
|
template <>
|
|
class numeric_limits<char> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr char(min)() noexcept {
|
|
return CHAR_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr char(max)() noexcept {
|
|
return CHAR_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr char lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr char epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_signed = CHAR_MIN != 0;
|
|
static constexpr bool is_modulo = CHAR_MIN == 0;
|
|
static constexpr int digits = 8 - (CHAR_MIN != 0);
|
|
static constexpr int digits10 = 2;
|
|
};
|
|
|
|
// CLASS numeric_limits<signed char>
|
|
template <>
|
|
class numeric_limits<signed char> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr signed char(min)() noexcept {
|
|
return SCHAR_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr signed char(max)() noexcept {
|
|
return SCHAR_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr signed char lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr signed char epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr signed char round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr signed char denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr signed char infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr signed char quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr signed char signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_signed = true;
|
|
static constexpr int digits = 7;
|
|
static constexpr int digits10 = 2;
|
|
};
|
|
|
|
// CLASS numeric_limits<unsigned char>
|
|
template <>
|
|
class numeric_limits<unsigned char> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr unsigned char(min)() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned char(max)() noexcept {
|
|
return UCHAR_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned char lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned char epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned char round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned char denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned char infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned char quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned char signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_modulo = true;
|
|
static constexpr int digits = 8;
|
|
static constexpr int digits10 = 2;
|
|
};
|
|
|
|
#ifdef __cpp_char8_t
|
|
// CLASS numeric_limits<char8_t>
|
|
template <>
|
|
class numeric_limits<char8_t> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr char8_t(min)() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char8_t(max)() noexcept {
|
|
return UCHAR_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr char8_t lowest() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char8_t epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char8_t round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char8_t denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char8_t infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char8_t quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char8_t signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_modulo = true;
|
|
static constexpr int digits = 8;
|
|
static constexpr int digits10 = 2;
|
|
};
|
|
#endif // __cpp_char8_t
|
|
|
|
// CLASS numeric_limits<char16_t>
|
|
template <>
|
|
class numeric_limits<char16_t> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr char16_t(min)() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char16_t(max)() noexcept {
|
|
return USHRT_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr char16_t lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr char16_t epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char16_t round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char16_t denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char16_t infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char16_t quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char16_t signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_modulo = true;
|
|
static constexpr int digits = 16;
|
|
static constexpr int digits10 = 4;
|
|
};
|
|
|
|
// CLASS numeric_limits<char32_t>
|
|
template <>
|
|
class numeric_limits<char32_t> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr char32_t(min)() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char32_t(max)() noexcept {
|
|
return UINT_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr char32_t lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr char32_t epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char32_t round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char32_t denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char32_t infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char32_t quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr char32_t signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_modulo = true;
|
|
static constexpr int digits = 32;
|
|
static constexpr int digits10 = 9;
|
|
};
|
|
|
|
// CLASS numeric_limits<wchar_t>
|
|
template <>
|
|
class numeric_limits<wchar_t> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr wchar_t(min)() noexcept {
|
|
return WCHAR_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr wchar_t(max)() noexcept {
|
|
return WCHAR_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr wchar_t lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr wchar_t epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr wchar_t round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr wchar_t denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr wchar_t infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr wchar_t quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr wchar_t signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_modulo = true;
|
|
static constexpr int digits = 16;
|
|
static constexpr int digits10 = 4;
|
|
};
|
|
|
|
// CLASS numeric_limits<short>
|
|
template <>
|
|
class numeric_limits<short> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr short(min)() noexcept {
|
|
return SHRT_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr short(max)() noexcept {
|
|
return SHRT_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr short lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr short epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr short round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr short denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr short infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr short quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr short signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_signed = true;
|
|
static constexpr int digits = 15;
|
|
static constexpr int digits10 = 4;
|
|
};
|
|
|
|
// CLASS numeric_limits<int>
|
|
template <>
|
|
class numeric_limits<int> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr int(min)() noexcept {
|
|
return INT_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr int(max)() noexcept {
|
|
return INT_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr int lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr int epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr int round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr int denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr int infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr int quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr int signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_signed = true;
|
|
static constexpr int digits = 31;
|
|
static constexpr int digits10 = 9;
|
|
};
|
|
|
|
// CLASS numeric_limits<long>
|
|
template <>
|
|
class numeric_limits<long> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr long(min)() noexcept {
|
|
return LONG_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr long(max)() noexcept {
|
|
return LONG_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr long lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr long epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr long round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr long denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr long infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr long quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr long signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static_assert(sizeof(int) == sizeof(long), "LLP64 assumption");
|
|
static constexpr bool is_signed = true;
|
|
static constexpr int digits = 31;
|
|
static constexpr int digits10 = 9;
|
|
};
|
|
|
|
// CLASS numeric_limits<long long>
|
|
template <>
|
|
class numeric_limits<long long> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr long long(min)() noexcept {
|
|
return LLONG_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr long long(max)() noexcept {
|
|
return LLONG_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr long long lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr long long epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr long long round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr long long denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr long long infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr long long quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr long long signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_signed = true;
|
|
static constexpr int digits = 63;
|
|
static constexpr int digits10 = 18;
|
|
};
|
|
|
|
#ifdef _NATIVE_WCHAR_T_DEFINED
|
|
// CLASS numeric_limits<unsigned short>
|
|
template <>
|
|
class numeric_limits<unsigned short> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr unsigned short(min)() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned short(max)() noexcept {
|
|
return USHRT_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned short lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned short epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned short round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned short denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned short infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned short quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned short signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_modulo = true;
|
|
static constexpr int digits = 16;
|
|
static constexpr int digits10 = 4;
|
|
};
|
|
#endif // _NATIVE_WCHAR_T_DEFINED
|
|
|
|
// CLASS numeric_limits<unsigned int>
|
|
template <>
|
|
class numeric_limits<unsigned int> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr unsigned int(min)() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned int(max)() noexcept {
|
|
return UINT_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned int lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned int epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned int round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned int denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned int infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned int quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned int signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_modulo = true;
|
|
static constexpr int digits = 32;
|
|
static constexpr int digits10 = 9;
|
|
};
|
|
|
|
// CLASS numeric_limits<unsigned long>
|
|
template <>
|
|
class numeric_limits<unsigned long> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr unsigned long(min)() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long(max)() noexcept {
|
|
return ULONG_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static_assert(sizeof(unsigned int) == sizeof(unsigned long), "LLP64 assumption");
|
|
static constexpr bool is_modulo = true;
|
|
static constexpr int digits = 32;
|
|
static constexpr int digits10 = 9;
|
|
};
|
|
|
|
// CLASS numeric_limits<unsigned long long>
|
|
template <>
|
|
class numeric_limits<unsigned long long> : public _Num_int_base {
|
|
public:
|
|
_NODISCARD static constexpr unsigned long long(min)() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long long(max)() noexcept {
|
|
return ULLONG_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long long lowest() noexcept {
|
|
return (min) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long long epsilon() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long long round_error() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long long denorm_min() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long long infinity() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long long quiet_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
_NODISCARD static constexpr unsigned long long signaling_NaN() noexcept {
|
|
return 0;
|
|
}
|
|
|
|
static constexpr bool is_modulo = true;
|
|
static constexpr int digits = 64;
|
|
static constexpr int digits10 = 19;
|
|
};
|
|
|
|
// CLASS numeric_limits<float>
|
|
template <>
|
|
class numeric_limits<float> : public _Num_float_base {
|
|
public:
|
|
_NODISCARD static constexpr float(min)() noexcept {
|
|
return FLT_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr float(max)() noexcept {
|
|
return FLT_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr float lowest() noexcept {
|
|
return -(max) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr float epsilon() noexcept {
|
|
return FLT_EPSILON;
|
|
}
|
|
|
|
_NODISCARD static constexpr float round_error() noexcept {
|
|
return 0.5F;
|
|
}
|
|
|
|
_NODISCARD static constexpr float denorm_min() noexcept {
|
|
return FLT_TRUE_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr float infinity() noexcept {
|
|
return __builtin_huge_valf();
|
|
}
|
|
|
|
_NODISCARD static constexpr float quiet_NaN() noexcept {
|
|
return __builtin_nanf("0");
|
|
}
|
|
|
|
_NODISCARD static constexpr float signaling_NaN() noexcept {
|
|
return __builtin_nansf("1");
|
|
}
|
|
|
|
static constexpr int digits = FLT_MANT_DIG;
|
|
static constexpr int digits10 = FLT_DIG;
|
|
static constexpr int max_digits10 = 9;
|
|
static constexpr int max_exponent = FLT_MAX_EXP;
|
|
static constexpr int max_exponent10 = FLT_MAX_10_EXP;
|
|
static constexpr int min_exponent = FLT_MIN_EXP;
|
|
static constexpr int min_exponent10 = FLT_MIN_10_EXP;
|
|
};
|
|
|
|
// CLASS numeric_limits<double>
|
|
template <>
|
|
class numeric_limits<double> : public _Num_float_base {
|
|
public:
|
|
_NODISCARD static constexpr double(min)() noexcept {
|
|
return DBL_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr double(max)() noexcept {
|
|
return DBL_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr double lowest() noexcept {
|
|
return -(max) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr double epsilon() noexcept {
|
|
return DBL_EPSILON;
|
|
}
|
|
|
|
_NODISCARD static constexpr double round_error() noexcept {
|
|
return 0.5;
|
|
}
|
|
|
|
_NODISCARD static constexpr double denorm_min() noexcept {
|
|
return DBL_TRUE_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr double infinity() noexcept {
|
|
return __builtin_huge_val();
|
|
}
|
|
|
|
_NODISCARD static constexpr double quiet_NaN() noexcept {
|
|
return __builtin_nan("0");
|
|
}
|
|
|
|
_NODISCARD static constexpr double signaling_NaN() noexcept {
|
|
return __builtin_nans("1");
|
|
}
|
|
|
|
static constexpr int digits = DBL_MANT_DIG;
|
|
static constexpr int digits10 = DBL_DIG;
|
|
static constexpr int max_digits10 = 17;
|
|
static constexpr int max_exponent = DBL_MAX_EXP;
|
|
static constexpr int max_exponent10 = DBL_MAX_10_EXP;
|
|
static constexpr int min_exponent = DBL_MIN_EXP;
|
|
static constexpr int min_exponent10 = DBL_MIN_10_EXP;
|
|
};
|
|
|
|
// CLASS numeric_limits<long double>
|
|
template <>
|
|
class numeric_limits<long double> : public _Num_float_base {
|
|
public:
|
|
_NODISCARD static constexpr long double(min)() noexcept {
|
|
return LDBL_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr long double(max)() noexcept {
|
|
return LDBL_MAX;
|
|
}
|
|
|
|
_NODISCARD static constexpr long double lowest() noexcept {
|
|
return -(max) ();
|
|
}
|
|
|
|
_NODISCARD static constexpr long double epsilon() noexcept {
|
|
return LDBL_EPSILON;
|
|
}
|
|
|
|
_NODISCARD static constexpr long double round_error() noexcept {
|
|
return 0.5L;
|
|
}
|
|
|
|
_NODISCARD static constexpr long double denorm_min() noexcept {
|
|
return LDBL_TRUE_MIN;
|
|
}
|
|
|
|
_NODISCARD static constexpr long double infinity() noexcept {
|
|
return __builtin_huge_val();
|
|
}
|
|
|
|
_NODISCARD static constexpr long double quiet_NaN() noexcept {
|
|
return __builtin_nan("0");
|
|
}
|
|
|
|
_NODISCARD static constexpr long double signaling_NaN() noexcept {
|
|
return __builtin_nans("1");
|
|
}
|
|
|
|
static constexpr int digits = LDBL_MANT_DIG;
|
|
static constexpr int digits10 = LDBL_DIG;
|
|
static constexpr int max_digits10 = 17;
|
|
static constexpr int max_exponent = LDBL_MAX_EXP;
|
|
static constexpr int max_exponent10 = LDBL_MAX_10_EXP;
|
|
static constexpr int min_exponent = LDBL_MIN_EXP;
|
|
static constexpr int min_exponent10 = LDBL_MIN_10_EXP;
|
|
};
|
|
|
|
// Implementation of countl_zero without using specialized CPU instructions.
|
|
// Used at compile time and when said instructions are not supported.
|
|
// see "Hacker's Delight" section 5-3
|
|
template <class _Ty>
|
|
_NODISCARD constexpr int _Countl_zero_fallback(_Ty _Val) noexcept {
|
|
_Ty _Yy = 0;
|
|
|
|
unsigned int _Nn = numeric_limits<_Ty>::digits;
|
|
unsigned int _Cc = numeric_limits<_Ty>::digits / 2;
|
|
do {
|
|
_Yy = static_cast<_Ty>(_Val >> _Cc);
|
|
if (_Yy != 0) {
|
|
_Nn -= _Cc;
|
|
_Val = _Yy;
|
|
}
|
|
_Cc >>= 1;
|
|
} while (_Cc != 0);
|
|
return static_cast<int>(_Nn) - static_cast<int>(_Val);
|
|
}
|
|
|
|
// Implementation of countr_zero without using specialized CPU instructions.
|
|
// Used at compile time and when said instructions are not supported.
|
|
// see "Hacker's Delight" section 5-4
|
|
template <class _Ty>
|
|
_NODISCARD constexpr int _Countr_zero_fallback(const _Ty _Val) noexcept {
|
|
constexpr int _Digits = std::numeric_limits<_Ty>::digits;
|
|
return _Digits - _Countl_zero_fallback(static_cast<_Ty>(static_cast<_Ty>(~_Val) & static_cast<_Ty>(_Val - 1)));
|
|
}
|
|
|
|
// Implementation of popcount without using specialized CPU instructions.
|
|
// Used at compile time and when said instructions are not supported.
|
|
template <class _Ty>
|
|
_NODISCARD constexpr int _Popcount_fallback(_Ty _Val) noexcept {
|
|
constexpr int _Digits = numeric_limits<_Ty>::digits;
|
|
// we static_cast these bit patterns in order to truncate them to the correct size
|
|
_Val = static_cast<_Ty>(_Val - ((_Val >> 1) & static_cast<_Ty>(0x5555'5555'5555'5555ull)));
|
|
_Val = static_cast<_Ty>((_Val & static_cast<_Ty>(0x3333'3333'3333'3333ull))
|
|
+ ((_Val >> 2) & static_cast<_Ty>(0x3333'3333'3333'3333ull)));
|
|
_Val = static_cast<_Ty>((_Val + (_Val >> 4)) & static_cast<_Ty>(0x0F0F'0F0F'0F0F'0F0Full));
|
|
for (int _Shift_digits = 8; _Shift_digits < _Digits; _Shift_digits <<= 1) {
|
|
_Val = static_cast<_Ty>(_Val + static_cast<_Ty>(_Val >> _Shift_digits));
|
|
}
|
|
// we want the bottom "slot" that's big enough to store _Digits
|
|
return static_cast<int>(_Val & static_cast<_Ty>(_Digits + _Digits - 1));
|
|
}
|
|
|
|
#if defined(_M_IX86) || defined(_M_X64)
|
|
extern "C" {
|
|
extern int __isa_available;
|
|
#ifdef __clang__
|
|
#define _TZCNT_U32 __builtin_ia32_tzcnt_u32
|
|
#define _TZCNT_U64 __builtin_ia32_tzcnt_u64
|
|
#else // ^^^ __clang__ / !__clang__ vvv
|
|
#define _TZCNT_U32 _tzcnt_u32
|
|
#define _TZCNT_U64 _tzcnt_u64
|
|
#endif // __clang__
|
|
}
|
|
|
|
template <class _Ty>
|
|
_NODISCARD int _Checked_x86_x64_countr_zero(const _Ty _Val) noexcept {
|
|
constexpr int _Digits = numeric_limits<_Ty>::digits;
|
|
constexpr _Ty _Max = (numeric_limits<_Ty>::max) ();
|
|
|
|
#ifndef __AVX2__
|
|
// Because the widening done below will always give a non-0 value, checking for tzcnt
|
|
// is not required for 8-bit and 16-bit since the only difference in behavior between
|
|
// bsf and tzcnt is when the value is 0.
|
|
if constexpr (_Digits > 16) {
|
|
const bool _Definitely_have_tzcnt = __isa_available >= __ISA_AVAILABLE_AVX2;
|
|
if (!_Definitely_have_tzcnt && _Val == 0) {
|
|
return _Digits;
|
|
}
|
|
}
|
|
#endif // __AVX2__
|
|
|
|
if constexpr (_Digits <= 32) {
|
|
// Intended widening to int. This operation means that a narrow 0 will widen
|
|
// to 0xFFFF....FFFF0... instead of 0. We need this to avoid counting all the zeros
|
|
// of the wider type.
|
|
return static_cast<int>(_TZCNT_U32(static_cast<unsigned int>(~_Max | _Val)));
|
|
} else {
|
|
#ifdef _M_IX86
|
|
const unsigned int _High = _Val >> 32;
|
|
const unsigned int _Low = static_cast<unsigned int>(_Val);
|
|
if (_Low == 0) {
|
|
return 32 + _Checked_x86_x64_countr_zero(_High);
|
|
} else {
|
|
return _Checked_x86_x64_countr_zero(_Low);
|
|
}
|
|
#else // ^^^ _M_IX86 / !_M_IX86 vvv
|
|
return static_cast<int>(_TZCNT_U64(_Val));
|
|
#endif // _M_IX86
|
|
}
|
|
}
|
|
#undef _TZCNT_U32
|
|
#undef _TZCNT_U64
|
|
#endif // defined(_M_IX86) || defined(_M_X64)
|
|
|
|
#if (defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))) && !defined(_M_CEE_PURE) && !defined(__CUDACC__) \
|
|
&& !defined(__INTEL_COMPILER)
|
|
#define _HAS_POPCNT_INTRINSICS 1
|
|
#else // ^^^ intrinsics available ^^^ / vvv intrinsics unavailable vvv
|
|
#define _HAS_POPCNT_INTRINSICS 0
|
|
#endif // ^^^ intrinsics unavailable ^^^
|
|
|
|
#if _HAS_POPCNT_INTRINSICS
|
|
template <class _Ty>
|
|
_NODISCARD int _Checked_x86_x64_popcount(const _Ty _Val) noexcept {
|
|
constexpr int _Digits = numeric_limits<_Ty>::digits;
|
|
#ifndef __AVX__
|
|
const bool _Definitely_have_popcnt = __isa_available >= __ISA_AVAILABLE_SSE42;
|
|
if (!_Definitely_have_popcnt) {
|
|
return _Popcount_fallback(_Val);
|
|
}
|
|
#endif // !defined(__AVX__)
|
|
|
|
if constexpr (_Digits <= 16) {
|
|
return static_cast<int>(__popcnt16(_Val));
|
|
} else if constexpr (_Digits == 32) {
|
|
return static_cast<int>(__popcnt(_Val));
|
|
} else {
|
|
#ifdef _M_IX86
|
|
return static_cast<int>(__popcnt(_Val >> 32) + __popcnt(static_cast<unsigned int>(_Val)));
|
|
#else // ^^^ _M_IX86 / !_M_IX86 vvv
|
|
return static_cast<int>(__popcnt64(_Val));
|
|
#endif // _M_IX86
|
|
}
|
|
}
|
|
#endif // _HAS_POPCNT_INTRINSICS
|
|
|
|
template <class _Ty>
|
|
constexpr bool _Is_standard_unsigned_integer =
|
|
_Is_any_of_v<remove_cv_t<_Ty>, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long>;
|
|
|
|
template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
|
|
_NODISCARD constexpr int _Countr_zero(const _Ty _Val) noexcept {
|
|
#if defined(_M_IX86) || defined(_M_X64)
|
|
#if _HAS_CXX20
|
|
if (!_STD is_constant_evaluated()) {
|
|
return _Checked_x86_x64_countr_zero(_Val);
|
|
}
|
|
#endif // _HAS_CXX20
|
|
#endif // defined(_M_IX86) || defined(_M_X64)
|
|
// C++17 constexpr gcd() calls this function, so it should be constexpr unless we detect runtime evaluation.
|
|
return _Countr_zero_fallback(_Val);
|
|
}
|
|
|
|
template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> _Enabled = 0>
|
|
_NODISCARD _CONSTEXPR20 int _Popcount(const _Ty _Val) noexcept {
|
|
#if _HAS_POPCNT_INTRINSICS
|
|
#if _HAS_CXX20
|
|
if (!_STD is_constant_evaluated())
|
|
#endif // _HAS_CXX20
|
|
{
|
|
return _Checked_x86_x64_popcount(_Val);
|
|
}
|
|
#endif // _HAS_POPCNT_INTRINSICS
|
|
return _Popcount_fallback(_Val);
|
|
}
|
|
|
|
#undef _HAS_POPCNT_INTRINSICS
|
|
|
|
_STD_END
|
|
#pragma pop_macro("new")
|
|
_STL_RESTORE_CLANG_WARNINGS
|
|
#pragma warning(pop)
|
|
#pragma pack(pop)
|
|
#endif // _STL_COMPILER_PREPROCESSOR
|
|
#endif // _LIMITS_
|