]>
Commit | Line | Data |
---|---|---|
83ffe9cd | 1 | // Copyright (C) 2020-2023 Free Software Foundation, Inc. |
02e32295 MK |
2 | // |
3 | // This file is part of the GNU ISO C++ Library. This library is free | |
4 | // software; you can redistribute it and/or modify it under the | |
5 | // terms of the GNU General Public License as published by the | |
6 | // Free Software Foundation; either version 3, or (at your option) | |
7 | // any later version. | |
8 | // | |
9 | // This library is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | // | |
14 | // You should have received a copy of the GNU General Public License along | |
15 | // with this library; see the file COPYING3. If not see | |
16 | // <http://www.gnu.org/licenses/>. | |
17 | ||
18 | #include <array> | |
19 | ||
20 | // is_conversion_undefined | |
21 | /* implementation-defined | |
22 | * ====================== | |
23 | * §4.7 p3 (integral conversions) | |
24 | * If the destination type is signed, the value is unchanged if it can be | |
25 | * represented in the destination type (and bit-field width); otherwise, the | |
26 | * value is implementation-defined. | |
27 | * | |
28 | * undefined | |
29 | * ========= | |
30 | * §4.9/1 (floating-point conversions) | |
31 | * If the source value is neither exactly represented in the destination type | |
32 | * nor between two adjacent destination values the result is undefined. | |
33 | * | |
34 | * §4.10/1 (floating-integral conversions) | |
35 | * floating point type can be converted to integer type. | |
36 | * The behavior is undefined if the truncated value cannot be | |
37 | * represented in the destination type. | |
38 | * | |
39 | * §4.10/2 | |
40 | * integer can be converted to floating point type. | |
41 | * If the value being converted is outside the range of values that can be | |
42 | * represented, the behavior is undefined. | |
43 | */ | |
44 | template <typename To, typename From> | |
45 | constexpr bool | |
46 | is_conversion_undefined_impl(From x, std::true_type) | |
47 | { | |
48 | return x > static_cast<long double>(std::__finite_max_v<To>) | |
49 | || x < static_cast<long double>(std::__finite_min_v<To>); | |
50 | } | |
51 | ||
52 | template <typename To, typename From> | |
53 | constexpr bool | |
54 | is_conversion_undefined_impl(From, std::false_type) | |
55 | { return false; } | |
56 | ||
57 | template <typename To, typename From> | |
58 | constexpr bool | |
59 | is_conversion_undefined(From x) | |
60 | { | |
61 | static_assert(std::is_arithmetic<From>::value, | |
62 | "this overload is only meant for builtin arithmetic types"); | |
63 | return is_conversion_undefined_impl<To, From>( | |
64 | x, std::integral_constant< | |
65 | bool, std::is_floating_point<From>::value | |
66 | && (std::is_integral<To>::value | |
67 | || (std::is_floating_point<To>::value | |
68 | && sizeof(From) > sizeof(To)))>()); | |
69 | } | |
70 | ||
71 | static_assert(is_conversion_undefined<uint>(float(0x100000000LL)), | |
72 | "testing my expectations of is_conversion_undefined"); | |
73 | static_assert(!is_conversion_undefined<float>(0x100000000LL), | |
74 | "testing my expectations of is_conversion_undefined"); | |
75 | ||
76 | template <typename To, typename T, typename A> | |
77 | inline std::experimental::simd_mask<T, A> | |
78 | is_conversion_undefined(const std::experimental::simd<T, A>& x) | |
79 | { | |
80 | std::experimental::simd_mask<T, A> k = false; | |
81 | for (std::size_t i = 0; i < x.size(); ++i) | |
82 | k[i] = is_conversion_undefined(x[i]); | |
83 | return k; | |
84 | } | |
85 | ||
86 | template <class T> | |
87 | constexpr T | |
88 | genHalfBits() | |
89 | { return std::__finite_max_v<T> >> (std::__digits_v<T> / 2); } | |
90 | ||
91 | template <> | |
92 | constexpr long double | |
93 | genHalfBits<long double>() | |
94 | { return 0; } | |
95 | ||
96 | template <> | |
97 | constexpr double | |
98 | genHalfBits<double>() | |
99 | { return 0; } | |
100 | ||
101 | template <> | |
102 | constexpr float | |
103 | genHalfBits<float>() | |
104 | { return 0; } | |
105 | ||
106 | template <class U, class T, class UU> | |
107 | constexpr U | |
108 | avoid_ub(UU x) | |
109 | { return is_conversion_undefined<T>(U(x)) ? U(0) : U(x); } | |
110 | ||
111 | template <class U, class T, class UU> | |
112 | constexpr U | |
113 | avoid_ub2(UU x) | |
114 | { return is_conversion_undefined<U>(x) ? U(0) : avoid_ub<U, T>(x); } | |
115 | ||
116 | // conversion test input data | |
117 | template <class U, class T> | |
118 | static const std::array<U, 53> cvt_input_data = {{ | |
119 | avoid_ub<U, T>(0xc0000080U), | |
120 | avoid_ub<U, T>(0xc0000081U), | |
121 | avoid_ub<U, T>(0xc0000082U), | |
122 | avoid_ub<U, T>(0xc0000084U), | |
123 | avoid_ub<U, T>(0xc0000088U), | |
124 | avoid_ub<U, T>(0xc0000090U), | |
125 | avoid_ub<U, T>(0xc00000A0U), | |
126 | avoid_ub<U, T>(0xc00000C0U), | |
127 | avoid_ub<U, T>(0xc000017fU), | |
128 | avoid_ub<U, T>(0xc0000180U), | |
129 | avoid_ub<U, T>(0x100000001LL), | |
130 | avoid_ub<U, T>(0x100000011LL), | |
131 | avoid_ub<U, T>(0x100000111LL), | |
132 | avoid_ub<U, T>(0x100001111LL), | |
133 | avoid_ub<U, T>(0x100011111LL), | |
134 | avoid_ub<U, T>(0x100111111LL), | |
135 | avoid_ub<U, T>(0x101111111LL), | |
136 | avoid_ub<U, T>(-0x100000001LL), | |
137 | avoid_ub<U, T>(-0x100000011LL), | |
138 | avoid_ub<U, T>(-0x100000111LL), | |
139 | avoid_ub<U, T>(-0x100001111LL), | |
140 | avoid_ub<U, T>(-0x100011111LL), | |
141 | avoid_ub<U, T>(-0x100111111LL), | |
142 | avoid_ub<U, T>(-0x101111111LL), | |
143 | avoid_ub<U, T>(std::__norm_min_v<U>), | |
144 | avoid_ub<U, T>(std::__norm_min_v<U> + 1), | |
145 | avoid_ub<U, T>(std::__finite_min_v<U>), | |
146 | avoid_ub<U, T>(std::__finite_min_v<U> + 1), | |
147 | avoid_ub<U, T>(-1), | |
148 | avoid_ub<U, T>(-10), | |
149 | avoid_ub<U, T>(-100), | |
150 | avoid_ub<U, T>(-1000), | |
151 | avoid_ub<U, T>(-10000), | |
152 | avoid_ub<U, T>(0), | |
153 | avoid_ub<U, T>(1), | |
154 | avoid_ub<U, T>(genHalfBits<U>() - 1), | |
155 | avoid_ub<U, T>(genHalfBits<U>()), | |
156 | avoid_ub<U, T>(genHalfBits<U>() + 1), | |
157 | avoid_ub<U, T>(std::__finite_max_v<U> - 1), | |
158 | avoid_ub<U, T>(std::__finite_max_v<U>), | |
159 | avoid_ub<U, T>(std::__finite_max_v<U> - 0xff), | |
160 | avoid_ub<U, T>(std::__finite_max_v<U> - 0xff), | |
161 | avoid_ub<U, T>(std::__finite_max_v<U> - 0x55), | |
162 | avoid_ub<U, T>(-(std::__finite_min_v<U> + 1)), | |
163 | avoid_ub<U, T>(-std::__finite_max_v<U>), | |
164 | avoid_ub<U, T>(std::__finite_max_v<U> / std::pow(2., sizeof(T) * 6 - 1)), | |
165 | avoid_ub2<U, T>(-std::__finite_max_v<U> / std::pow(2., sizeof(T) * 6 - 1)), | |
166 | avoid_ub<U, T>(std::__finite_max_v<U> / std::pow(2., sizeof(T) * 4 - 1)), | |
167 | avoid_ub2<U, T>(-std::__finite_max_v<U> / std::pow(2., sizeof(T) * 4 - 1)), | |
168 | avoid_ub<U, T>(std::__finite_max_v<U> / std::pow(2., sizeof(T) * 2 - 1)), | |
169 | avoid_ub2<U, T>(-std::__finite_max_v<U> / std::pow(2., sizeof(T) * 2 - 1)), | |
170 | avoid_ub<U, T>(std::__finite_max_v<T> - 1), | |
171 | avoid_ub<U, T>(std::__finite_max_v<T> * 0.75), | |
172 | }}; | |
173 | ||
174 | template <class T, class U> | |
175 | struct cvt_inputs | |
176 | { | |
177 | static constexpr size_t | |
178 | size() | |
179 | { return cvt_input_data<U, T>.size(); } | |
180 | ||
181 | U | |
182 | operator[](size_t i) const | |
183 | { return cvt_input_data<U, T>[i]; } | |
184 | }; |