FLANG
numeric-limits.h
1//===-- include/flang/Common/numeric-limits.h -------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef FORTRAN_COMMON_NUMERIC_LIMITS_H_
10#define FORTRAN_COMMON_NUMERIC_LIMITS_H_
11
12#include <limits>
13#include <type_traits>
14
15namespace Fortran::common {
16
17namespace detail {
18
19template <typename T> class numeric_limits_impl {
20public:
21 static constexpr bool is_specialized{false};
22};
23
24template <typename T> class make_unsigned_impl;
25
26#if defined(__SIZEOF_INT128__)
27// Handle discrepancy of support of 128-bit integers by compiler and
28// standard library. The compiler may treat __int128 as a builtin type, but the
29// standard library does not define std::numeric_limits for it. Two cases are
30// known:
31//
32// 1. clang-cl supports __int128, but MSVC, and therefore its STL used by
33// clang-cl, does not.
34//
35// 2. Some versions of libstdc++ in strict mode (-std=c++NN)
36// intentionally remove any use of __int128, even though gcc does not make
37// such a distinction.
38//
39// Using __int128_t/__uint128_t typedefs; spelling out the __int128
40// keyword is a warning "ISO C++ does not support ‘__int128’ for ‘type name’"
41// under -Wpedantic
42
43template <> class numeric_limits_impl<__uint128_t> {
44public:
45 using T = __uint128_t;
46
47 static constexpr bool is_specialized{true};
48 static constexpr bool is_signed{false};
49 static constexpr bool is_integer{true};
50
51 static constexpr T min() { return static_cast<T>(0); }
52 static constexpr T max() { return ~static_cast<T>(0); }
53 static constexpr T lowest() { return min(); }
54};
55
56template <> class numeric_limits_impl<__int128_t> {
57public:
58 using T = __int128_t;
59
60 static constexpr bool is_specialized{true};
61 static constexpr bool is_signed{true};
62 static constexpr bool is_integer{true};
63
64 static constexpr T min() {
65 return static_cast<T>(static_cast<__uint128_t>(1) << 127u);
66 }
67 static constexpr T max() {
68 return static_cast<T>(~(static_cast<__uint128_t>(1) << 127u));
69 }
70 static constexpr T lowest() { return min(); }
71};
72
73template <> class make_unsigned_impl<__int128_t> {
74public:
75 using type = __uint128_t;
76};
77template <> class make_unsigned_impl<__uint128_t> {
78public:
79 using type = __uint128_t;
80};
81
82#endif // defined(__SIZEOF_INT128__)
83
84template <typename T>
85using numeric_limits = numeric_limits_impl<std::remove_cv_t<T>>;
86
87// Like std::make_unsigned: preserves the cv-qualifiers of T.
88template <typename T> class make_unsigned {
89 using Base = typename make_unsigned_impl<std::remove_cv_t<T>>::type;
90 using C =
91 std::conditional_t<std::is_const_v<T>, std::add_const_t<Base>, Base>;
92
93public:
94 using type =
95 std::conditional_t<std::is_volatile_v<T>, std::add_volatile_t<C>, C>;
96};
97
98// True if make_unsigned_impl has been defined for T (ignoring cv-qualifiers).
99template <typename T, typename = void>
100inline constexpr bool has_make_unsigned_impl{false};
101template <typename T>
102inline constexpr bool has_make_unsigned_impl<T,
103 std::void_t<typename make_unsigned_impl<std::remove_cv_t<T>>::type>>{true};
104
105} // namespace detail
106
117template <typename T>
119 typename std::conditional_t<detail::numeric_limits<T>::is_specialized &&
120 !std::numeric_limits<T>::is_specialized,
121 detail::numeric_limits<T>, std::numeric_limits<T>>;
122
126template <typename T>
128template <typename T>
129inline constexpr bool is_integral_v{
130 numeric_limits<T>::is_specialized && numeric_limits<T>::is_integer};
131template <typename T>
132inline constexpr bool is_signed_v{
133 numeric_limits<T>::is_specialized && numeric_limits<T>::is_signed};
134template <typename T>
135inline constexpr bool is_unsigned_v{
137
141template <typename T>
143 typename std::conditional_t<detail::has_make_unsigned_impl<T>,
144 detail::make_unsigned<T>, std::make_unsigned<T>>;
145
146template <typename T> using make_unsigned_t = typename make_unsigned<T>::type;
147
148} // namespace Fortran::common
149#endif // FORTRAN_COMMON_NUMERIC_LIMITS_H_
Definition numeric-limits.h:24
Definition numeric-limits.h:88
Definition numeric-limits.h:19
Definition bit-population-count.h:20
typename std::conditional_t< detail::numeric_limits< T >::is_specialized && !std::numeric_limits< T >::is_specialized, detail::numeric_limits< T >, std::numeric_limits< T > > numeric_limits
Definition numeric-limits.h:118
constexpr bool is_arithmetic_v
Definition numeric-limits.h:127
typename std::conditional_t< detail::has_make_unsigned_impl< T >, detail::make_unsigned< T >, std::make_unsigned< T > > make_unsigned
Definition numeric-limits.h:142