xref: /freebsd/contrib/llvm-project/libc/src/__support/CPP/limits.h (revision bb722a7d0f1642bff6487f943ad0427799a6e5bf)
1*bb722a7dSDimitry Andric //===-- A self contained equivalent of std::limits --------------*- C++ -*-===//
2*bb722a7dSDimitry Andric //
3*bb722a7dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*bb722a7dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*bb722a7dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*bb722a7dSDimitry Andric //
7*bb722a7dSDimitry Andric //===----------------------------------------------------------------------===//
8*bb722a7dSDimitry Andric 
9*bb722a7dSDimitry Andric #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_LIMITS_H
10*bb722a7dSDimitry Andric #define LLVM_LIBC_SRC___SUPPORT_CPP_LIMITS_H
11*bb722a7dSDimitry Andric 
12*bb722a7dSDimitry Andric #include "hdr/limits_macros.h" // CHAR_BIT
13*bb722a7dSDimitry Andric #include "src/__support/CPP/type_traits/is_integral.h"
14*bb722a7dSDimitry Andric #include "src/__support/CPP/type_traits/is_signed.h"
15*bb722a7dSDimitry Andric #include "src/__support/macros/attributes.h" // LIBC_INLINE
16*bb722a7dSDimitry Andric #include "src/__support/macros/config.h"
17*bb722a7dSDimitry Andric #include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128
18*bb722a7dSDimitry Andric 
19*bb722a7dSDimitry Andric namespace LIBC_NAMESPACE_DECL {
20*bb722a7dSDimitry Andric namespace cpp {
21*bb722a7dSDimitry Andric 
22*bb722a7dSDimitry Andric namespace internal {
23*bb722a7dSDimitry Andric 
24*bb722a7dSDimitry Andric template <typename T, T min_value, T max_value> struct integer_impl {
25*bb722a7dSDimitry Andric   static_assert(cpp::is_integral_v<T>);
maxinteger_impl26*bb722a7dSDimitry Andric   LIBC_INLINE static constexpr T max() { return max_value; }
mininteger_impl27*bb722a7dSDimitry Andric   LIBC_INLINE static constexpr T min() { return min_value; }
28*bb722a7dSDimitry Andric   LIBC_INLINE_VAR static constexpr int digits =
29*bb722a7dSDimitry Andric       CHAR_BIT * sizeof(T) - cpp::is_signed_v<T>;
30*bb722a7dSDimitry Andric };
31*bb722a7dSDimitry Andric 
32*bb722a7dSDimitry Andric } // namespace internal
33*bb722a7dSDimitry Andric 
34*bb722a7dSDimitry Andric template <class T> struct numeric_limits {};
35*bb722a7dSDimitry Andric 
36*bb722a7dSDimitry Andric // TODO: Add numeric_limits specializations as needed for new types.
37*bb722a7dSDimitry Andric template <>
38*bb722a7dSDimitry Andric struct numeric_limits<short>
39*bb722a7dSDimitry Andric     : public internal::integer_impl<short, SHRT_MIN, SHRT_MAX> {};
40*bb722a7dSDimitry Andric 
41*bb722a7dSDimitry Andric template <>
42*bb722a7dSDimitry Andric struct numeric_limits<unsigned short>
43*bb722a7dSDimitry Andric     : public internal::integer_impl<unsigned short, 0, USHRT_MAX> {};
44*bb722a7dSDimitry Andric 
45*bb722a7dSDimitry Andric template <>
46*bb722a7dSDimitry Andric struct numeric_limits<int>
47*bb722a7dSDimitry Andric     : public internal::integer_impl<int, INT_MIN, INT_MAX> {};
48*bb722a7dSDimitry Andric 
49*bb722a7dSDimitry Andric template <>
50*bb722a7dSDimitry Andric struct numeric_limits<unsigned int>
51*bb722a7dSDimitry Andric     : public internal::integer_impl<unsigned int, 0, UINT_MAX> {};
52*bb722a7dSDimitry Andric 
53*bb722a7dSDimitry Andric template <>
54*bb722a7dSDimitry Andric struct numeric_limits<long>
55*bb722a7dSDimitry Andric     : public internal::integer_impl<long, LONG_MIN, LONG_MAX> {};
56*bb722a7dSDimitry Andric 
57*bb722a7dSDimitry Andric template <>
58*bb722a7dSDimitry Andric struct numeric_limits<unsigned long>
59*bb722a7dSDimitry Andric     : public internal::integer_impl<unsigned long, 0, ULONG_MAX> {};
60*bb722a7dSDimitry Andric 
61*bb722a7dSDimitry Andric template <>
62*bb722a7dSDimitry Andric struct numeric_limits<long long>
63*bb722a7dSDimitry Andric     : public internal::integer_impl<long long, LLONG_MIN, LLONG_MAX> {};
64*bb722a7dSDimitry Andric 
65*bb722a7dSDimitry Andric template <>
66*bb722a7dSDimitry Andric struct numeric_limits<unsigned long long>
67*bb722a7dSDimitry Andric     : public internal::integer_impl<unsigned long long, 0, ULLONG_MAX> {};
68*bb722a7dSDimitry Andric 
69*bb722a7dSDimitry Andric template <>
70*bb722a7dSDimitry Andric struct numeric_limits<char>
71*bb722a7dSDimitry Andric     : public internal::integer_impl<char, CHAR_MIN, CHAR_MAX> {};
72*bb722a7dSDimitry Andric 
73*bb722a7dSDimitry Andric template <>
74*bb722a7dSDimitry Andric struct numeric_limits<signed char>
75*bb722a7dSDimitry Andric     : public internal::integer_impl<signed char, SCHAR_MIN, SCHAR_MAX> {};
76*bb722a7dSDimitry Andric 
77*bb722a7dSDimitry Andric template <>
78*bb722a7dSDimitry Andric struct numeric_limits<unsigned char>
79*bb722a7dSDimitry Andric     : public internal::integer_impl<unsigned char, 0, UCHAR_MAX> {};
80*bb722a7dSDimitry Andric 
81*bb722a7dSDimitry Andric #ifdef LIBC_TYPES_HAS_INT128
82*bb722a7dSDimitry Andric // On platform where UInt128 resolves to __uint128_t, this specialization
83*bb722a7dSDimitry Andric // provides the limits of UInt128.
84*bb722a7dSDimitry Andric template <>
85*bb722a7dSDimitry Andric struct numeric_limits<__uint128_t>
86*bb722a7dSDimitry Andric     : public internal::integer_impl<__uint128_t, 0, ~__uint128_t(0)> {};
87*bb722a7dSDimitry Andric #endif
88*bb722a7dSDimitry Andric 
89*bb722a7dSDimitry Andric } // namespace cpp
90*bb722a7dSDimitry Andric } // namespace LIBC_NAMESPACE_DECL
91*bb722a7dSDimitry Andric 
92*bb722a7dSDimitry Andric #endif // LLVM_LIBC_SRC___SUPPORT_CPP_LIMITS_H
93