]>
Commit | Line | Data |
---|---|---|
83ffe9cd | 1 | // Copyright (C) 2020-2023 Free Software Foundation, Inc. |
e6c76f0d PP |
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 | // { dg-options "-std=gnu++2a" } | |
19 | // { dg-do run { target c++2a } } | |
e9b639c4 | 20 | // { dg-timeout-factor 4 } |
e6c76f0d PP |
21 | |
22 | #include <limits> | |
23 | #include <ranges> | |
24 | #include <testsuite_hooks.h> | |
25 | ||
26 | using max_size_t = std::ranges::__detail::__max_size_type; | |
27 | using max_diff_t = std::ranges::__detail::__max_diff_type; | |
28 | using rep_t = max_size_t::__rep; | |
29 | ||
30 | static_assert(sizeof(max_size_t) == sizeof(max_diff_t)); | |
31 | ||
32 | static_assert(std::regular<max_size_t>); | |
33 | static_assert(std::totally_ordered<max_size_t>); | |
34 | ||
35 | static_assert(std::regular<max_diff_t>); | |
36 | static_assert(std::totally_ordered<max_diff_t>); | |
37 | ||
38 | // We can't use numeric_limits<rep_t>::max() here because __int128 is an | |
39 | // integral type only in GNU mode. | |
40 | constexpr max_size_t mu = max_size_t(~rep_t(0)); | |
41 | constexpr max_size_t ou = 1; | |
42 | constexpr max_diff_t ns = -1; | |
43 | ||
44 | void | |
45 | test01() | |
46 | { | |
47 | static_assert(max_size_t(7) % 3 == 1); | |
48 | static_assert(max_size_t(7) % 4 == 3); | |
49 | ||
50 | static_assert(-max_diff_t(1) == max_diff_t(-1)); | |
51 | static_assert(max_diff_t(3) % 2 == 1); | |
52 | static_assert(max_diff_t(-3) / 2 == -1); | |
53 | static_assert(max_diff_t(-3) % 2 == -1); | |
54 | static_assert(max_diff_t(3) % -2 == 1); | |
55 | static_assert(max_diff_t(-3) << 1 == -6); | |
56 | static_assert(max_diff_t(-3) >> 1 == -2); | |
57 | static_assert(max_diff_t(3) >> 1 == 1); | |
58 | static_assert(max_diff_t(3) >> 2 == 0); | |
59 | ||
60 | static_assert(max_diff_t(-5) / 3 == -1); | |
61 | static_assert(max_diff_t(5) / -3 == -1); | |
62 | static_assert(max_diff_t(-5) / -3 == 1); | |
63 | static_assert(max_diff_t(5) / 3 == 1); | |
64 | ||
65 | static_assert(max_diff_t(-6) / 3 == -2); | |
66 | static_assert(max_diff_t(6) / -3 == -2); | |
67 | static_assert(max_diff_t(-6) / -3 == 2); | |
68 | static_assert(max_diff_t(6) / 3 == 2); | |
69 | ||
70 | static_assert(~max_size_t(-3) == 2); | |
71 | static_assert(~max_diff_t(-3) == 2); | |
72 | ||
73 | static_assert(max_diff_t(1) < max_diff_t(3)); | |
74 | static_assert(max_diff_t(-1) < max_diff_t(3)); | |
75 | static_assert(max_diff_t(1) > max_diff_t(-3)); | |
76 | static_assert(max_diff_t(-1) > max_diff_t(-3)); | |
77 | ||
78 | static_assert(max_diff_t(mu)/-1 == -max_diff_t(mu)); | |
79 | static_assert(-max_diff_t(mu)/1 == -max_diff_t(mu)); | |
80 | static_assert(max_diff_t(mu)>>1 == max_diff_t(mu)/2); | |
81 | static_assert(-max_diff_t(mu+1) == max_diff_t(mu+1)); | |
82 | static_assert(-(mu+1) == mu+1); | |
83 | static_assert((mu+1)<<1 == 0); | |
84 | static_assert(max_diff_t(mu+1)<<1 == 0); | |
85 | static_assert(max_diff_t(mu+1)>>1 < 0); | |
86 | ||
87 | static_assert(int(max_diff_t(mu+1)) == 0); | |
88 | static_assert(rep_t(max_diff_t(mu+1)) == 0); | |
89 | static_assert(int(max_diff_t(mu)) == -1); | |
90 | static_assert(rep_t(max_diff_t(mu)) == rep_t(-1)); | |
91 | ||
92 | static_assert(2*mu+1 > 2*mu); | |
93 | static_assert(~(2*mu+1) == 0); | |
94 | static_assert(mu/mu == 1); | |
95 | static_assert(2*mu > mu); | |
96 | static_assert(2*mu-mu == mu); | |
97 | static_assert((2*mu)/mu == 2); | |
98 | static_assert((2*mu+1)/mu == 2); | |
99 | static_assert((2*mu-1)/(mu-1) == 2); | |
100 | static_assert((2*mu-1)/mu == 1); | |
101 | static_assert((2*mu+-1)/mu == 1); | |
102 | static_assert(2*mu-1 < 2*mu); | |
103 | static_assert(2*mu-1 <= 2*mu); | |
104 | static_assert(2*mu+1 > 2*mu); | |
105 | static_assert(2*mu+1 >= 2*mu); | |
106 | static_assert((2*mu)/1 == 2*mu); | |
107 | static_assert(mu/mu-1 == 0); | |
108 | static_assert(mu*0 == 0); | |
109 | static_assert((2*mu-1)*0 == 0); | |
110 | static_assert((2*mu-1)>>1 == mu-1); | |
111 | static_assert(mu+-1+1 == mu); | |
112 | static_assert(mu+1+-1 == mu); | |
113 | static_assert(mu+1); | |
114 | static_assert((2*mu)/2 == mu); | |
115 | static_assert((2*mu)>>1 == mu); | |
116 | static_assert((mu<<1)>>1 == mu); | |
117 | static_assert(1/mu == 0); | |
118 | static_assert(mu/1 == mu); | |
119 | static_assert(((mu+1)|mu) == -1); | |
120 | static_assert((mu+1)+(mu+1) < mu+1); | |
121 | ||
122 | static_assert(max_size_t(ns) == -1); | |
123 | static_assert(-max_diff_t(ou) == -1); | |
124 | static_assert(-max_diff_t(-ou) == 1); | |
125 | static_assert(max_size_t(-max_diff_t(-ou)) == 1); | |
126 | static_assert(ns*ns == max_diff_t(ou)); | |
127 | static_assert(max_size_t(ns)*max_size_t(ns) == ou); | |
128 | static_assert(-max_diff_t(0) == max_diff_t(0)); | |
129 | static_assert(-ou-ou == -2*ou); | |
130 | ||
131 | static_assert(int(ns) == -1); | |
132 | static_assert(rep_t(ns) == rep_t(-1)); | |
133 | ||
134 | static_assert(max_size_t() == 0); | |
135 | static_assert(max_diff_t() == 0); | |
136 | ||
137 | auto f = [] (auto a) { a /= a; return a; }; | |
138 | static_assert(f(max_size_t(5)) == 1); | |
139 | static_assert(f(max_size_t(-5)) == 1); | |
140 | static_assert(f(max_diff_t(5)) == 1); | |
141 | ||
142 | auto g = [] (auto a) { a >>= a; return a; }; | |
143 | static_assert(g(max_size_t(5)) == 0); | |
144 | static_assert(g(max_diff_t(5)) == 0); | |
145 | ||
146 | auto h = [] (auto a) { a <<= a; return a; }; | |
147 | static_assert(h(max_size_t(3)) == 24); | |
148 | static_assert(h(max_diff_t(3)) == 24); | |
dce586ff PP |
149 | |
150 | auto w = [] (auto a) { | |
151 | const auto b = a; | |
152 | VERIFY( a++ == b && a == b+1 ); | |
153 | VERIFY( a-- == b+1 && a == b ); | |
154 | ||
155 | VERIFY( ++(++a) == b+2 ); | |
156 | VERIFY( --(--a) == b ); | |
157 | return true; | |
158 | }; | |
159 | static_assert(w(max_size_t(10))); | |
160 | static_assert(w(-max_diff_t(10))); | |
161 | ||
162 | #if __cpp_lib_three_way_comparison | |
163 | static_assert(max_size_t{1} <=> max_size_t{9} == std::strong_ordering::less); | |
164 | static_assert(max_size_t{3} <=> max_size_t{2} == std::strong_ordering::greater); | |
165 | static_assert(max_size_t{5} <=> max_size_t{5} == std::strong_ordering::equal); | |
166 | static_assert(~max_size_t{1} <=> ~max_size_t{9} == std::strong_ordering::greater); | |
167 | static_assert(~max_size_t{3} <=> ~max_size_t{2} == std::strong_ordering::less); | |
168 | static_assert(~max_size_t{5} <=> ~max_size_t{5} == std::strong_ordering::equal); | |
169 | static_assert(~max_size_t{5} <=> max_size_t{9} == std::strong_ordering::greater); | |
170 | static_assert(~max_size_t{9} <=> max_size_t{5} == std::strong_ordering::greater); | |
171 | static_assert(max_size_t{5} <=> ~max_size_t{9} == std::strong_ordering::less); | |
172 | static_assert(max_size_t{9} <=> ~max_size_t{5} == std::strong_ordering::less); | |
173 | ||
174 | static_assert(max_diff_t{1} <=> max_diff_t{9} == std::strong_ordering::less); | |
175 | static_assert(max_diff_t{3} <=> max_diff_t{2} == std::strong_ordering::greater); | |
176 | static_assert(max_diff_t{5} <=> max_diff_t{5} == std::strong_ordering::equal); | |
177 | static_assert(max_diff_t{-1} <=> max_diff_t{-9} == std::strong_ordering::greater); | |
178 | static_assert(max_diff_t{-3} <=> max_diff_t{-2} == std::strong_ordering::less); | |
179 | static_assert(max_diff_t{-5} <=> max_diff_t{-5} == std::strong_ordering::equal); | |
180 | static_assert(max_diff_t{-5} <=> max_diff_t{9} == std::strong_ordering::less); | |
181 | static_assert(max_diff_t{-9} <=> max_diff_t{5} == std::strong_ordering::less); | |
182 | static_assert(max_diff_t{5} <=> max_diff_t{-9} == std::strong_ordering::greater); | |
183 | static_assert(max_diff_t{9} <=> max_diff_t{-5} == std::strong_ordering::greater); | |
184 | #endif | |
e6c76f0d PP |
185 | } |
186 | ||
187 | template<bool signed_p, bool shorten_p> | |
188 | void | |
189 | test02() | |
190 | { | |
191 | using hw_type = std::conditional_t<signed_p, signed rep_t, rep_t>; | |
192 | using max_type = std::conditional_t<signed_p, max_diff_t, max_size_t>; | |
193 | using shorten_type = std::conditional_t<shorten_p, hw_type, max_type>; | |
194 | const int hw_type_bit_size = sizeof(hw_type) * __CHAR_BIT__; | |
195 | const int limit = 1000; | |
196 | const int log2_limit = 10; | |
197 | static_assert((1 << log2_limit) >= limit); | |
198 | const int min = (signed_p ? -limit : 0); | |
199 | const int max = limit; | |
200 | for (hw_type i = min; i <= max; i++) | |
201 | { | |
202 | bool ok = true; | |
203 | if (signed_p || shorten_p) | |
204 | { | |
205 | ok &= (~i == shorten_type(~max_type(i))); | |
206 | ok &= (-i == shorten_type(-max_type(i))); | |
207 | } | |
208 | for (hw_type j = min; j <= max; j++) | |
209 | { | |
210 | ok &= (i*j == shorten_type(max_type(i)*j)); | |
211 | ok &= (i+j == shorten_type(max_type(i)+j)); | |
212 | if (j != 0) | |
213 | { | |
214 | ok &= (i/j == shorten_type(max_type(i)/j)); | |
215 | ok &= (i%j == shorten_type(max_type(i)%j)); | |
216 | } | |
217 | if (signed_p || shorten_p) | |
218 | ok &= (i-j == shorten_type(max_type(i)-j)); | |
219 | ok &= ((i&j) == shorten_type(max_type(i)&j)); | |
220 | ok &= ((i|j) == shorten_type(max_type(i)|j)); | |
221 | ok &= ((i^j) == shorten_type(max_type(i)^j)); | |
222 | if (j >= 0 && j < hw_type(hw_type_bit_size) | |
223 | && (shorten_p || j < hw_type(hw_type_bit_size) - log2_limit)) | |
224 | { | |
225 | ok &= ((i>>j) == shorten_type(max_type(i)>>j)); | |
226 | ok &= ((i<<j) == shorten_type(max_type(i)<<j)); | |
227 | } | |
228 | ok &= (i>j) == (max_type(i) > j); | |
229 | ok &= (i<j) == (max_type(i) < j); | |
230 | ok &= (i>=j) == (max_type(i) >= j); | |
231 | ok &= (i<=j) == (max_type(i) <= j); | |
232 | ok &= (i==j) == (max_type(i) == j); | |
233 | ok &= (i!=j) == (max_type(i) != j); | |
234 | if (!ok) | |
235 | { | |
236 | fprintf(stderr, | |
237 | "Inconsistency found: %d %d %lld %lld\n", | |
238 | signed_p, shorten_p, (long long)i, (long long)j) ; | |
239 | VERIFY(0); | |
240 | } | |
241 | } | |
242 | } | |
243 | } | |
244 | ||
245 | template<bool signed_p, bool toggle_base_p> | |
246 | void | |
247 | test03() | |
248 | { | |
249 | using hw_type = std::conditional_t<signed_p, signed rep_t, rep_t>; | |
250 | using max_type = std::conditional_t<signed_p, max_diff_t, max_size_t>; | |
251 | using base_type = std::conditional_t<toggle_base_p, hw_type, max_type>; | |
252 | constexpr int hw_type_bit_size = sizeof(hw_type) * __CHAR_BIT__; | |
253 | constexpr int limit = 1000; | |
254 | constexpr int log2_limit = 10; | |
255 | static_assert((1 << log2_limit) >= limit); | |
256 | const int min = (signed_p ? -limit : 0); | |
257 | const int max = limit; | |
258 | for (hw_type i = min; i <= max; i++) | |
259 | { | |
260 | bool ok = true; | |
261 | base_type k; | |
262 | for (hw_type j = min; j <= max; j++) | |
263 | { | |
264 | k = i; k *= j; | |
265 | ok &= (k == (max_type(i)*j)); | |
266 | k = i; k += j; | |
267 | ok &= (k == (max_type(i)+j)); | |
268 | if (j != 0) | |
269 | { | |
270 | k = i; k /= j; | |
271 | ok &= (k == (max_type(i)/j)); | |
272 | k = i; k %= j; | |
273 | ok &= (k == (max_type(i)%j)); | |
274 | } | |
275 | if (signed_p) | |
276 | { | |
277 | k = i; k -= j; | |
278 | ok &= (k == (max_type(i)-j)); | |
279 | } | |
280 | k = i; k &= j; | |
281 | ok &= (k == (max_type(i)&j)); | |
282 | k = i; k |= j; | |
283 | ok &= (k == (max_type(i)|j)); | |
284 | k = i; k ^= j; | |
285 | ok &= (k == (max_type(i)^j)); | |
286 | if (j >= 0 && j < hw_type(hw_type_bit_size) | |
287 | && (!toggle_base_p || j < hw_type(hw_type_bit_size) - log2_limit)) | |
288 | { | |
289 | k = i; k >>= j; | |
290 | ok &= (k == (max_type(i)>>j)); | |
291 | k = i; k <<= j; | |
292 | ok &= (k == (max_type(i)<<j)); | |
293 | } | |
294 | if (!ok) | |
295 | { | |
296 | fprintf(stderr, | |
297 | "Inconsistency found: %d %d %lld %lld\n", | |
298 | signed_p, toggle_base_p, (long long)i, (long long)j) ; | |
299 | VERIFY(0); | |
300 | } | |
301 | } | |
302 | } | |
303 | } | |
304 | ||
305 | void | |
306 | test04() | |
307 | { | |
308 | constexpr int limit = 1000; | |
309 | for (int i = -limit; i <= limit; i++) | |
310 | { | |
311 | VERIFY( -max_size_t(-i) == i ); | |
312 | for (int j = i; j <= limit; j++) | |
313 | { | |
314 | VERIFY( max_size_t(-i) * max_size_t(-j) == i*j ); | |
315 | VERIFY( max_size_t(-j) * max_size_t(-i) == j*i ); | |
316 | VERIFY( rep_t(((mu+1)+i)*((mu+1)+j)) == rep_t(i*j) ); | |
317 | VERIFY( rep_t(((mu+1)+j)*((mu+1)+i)) == rep_t(j*i) ); | |
318 | if (i >= 0 && j > 0) | |
319 | { | |
320 | auto r = (mu+i)-((mu+i)/j)*j; | |
321 | VERIFY( r >= 0 && r < j ); | |
322 | VERIFY( r == (mu+i)%j ); | |
323 | } | |
324 | } | |
325 | } | |
326 | } | |
327 | ||
328 | void | |
329 | test05() | |
330 | { | |
331 | #if __SIZEOF_INT128__ | |
332 | max_size_t x = 0; | |
333 | x = static_cast<__int128>(0); | |
334 | x = static_cast<unsigned __int128>(0); | |
335 | ||
336 | max_diff_t y = 0; | |
337 | y = static_cast<__int128>(0);; | |
338 | y = static_cast<unsigned __int128>(0); | |
339 | #endif | |
340 | } | |
341 | ||
342 | using std::numeric_limits; | |
343 | ||
344 | static_assert(numeric_limits<max_size_t>::is_specialized); | |
345 | static_assert(!numeric_limits<max_size_t>::is_signed); | |
346 | static_assert(numeric_limits<max_size_t>::is_integer); | |
347 | static_assert(numeric_limits<max_size_t>::is_exact); | |
348 | // We can't unconditionally use numeric_limits here because __int128 is an | |
349 | // integral type only in GNU mode. | |
350 | #if __SIZEOF_INT128__ | |
351 | static_assert(numeric_limits<max_size_t>::digits == 129); | |
352 | static_assert(numeric_limits<max_size_t>::digits10 == 38); | |
353 | static_assert(numeric_limits<max_size_t>::max() | |
354 | == 2*max_size_t(~rep_t(0)) + 1); | |
355 | #else | |
356 | static_assert(numeric_limits<max_size_t>::digits | |
357 | == numeric_limits<rep_t>::digits + 1); | |
358 | static_assert(numeric_limits<max_size_t>::digits10 | |
359 | == numeric_limits<rep_t>::digits10); | |
360 | static_assert(numeric_limits<max_size_t>::max() | |
361 | == 2*max_size_t(numeric_limits<rep_t>::max())+1); | |
362 | #endif | |
363 | static_assert(numeric_limits<max_size_t>::min() == 0); | |
364 | static_assert(numeric_limits<max_size_t>::max() | |
365 | == max_size_t(-1)); | |
366 | static_assert((numeric_limits<max_size_t>::max() | |
367 | >> (numeric_limits<max_size_t>::digits-1)) == 1); | |
368 | static_assert(numeric_limits<max_size_t>::lowest() | |
369 | == numeric_limits<max_size_t>::min()); | |
370 | ||
371 | static_assert(numeric_limits<max_diff_t>::is_specialized); | |
372 | static_assert(numeric_limits<max_diff_t>::is_signed); | |
373 | static_assert(numeric_limits<max_diff_t>::is_integer); | |
374 | static_assert(numeric_limits<max_diff_t>::is_exact); | |
375 | static_assert(numeric_limits<max_diff_t>::digits | |
376 | == numeric_limits<max_size_t>::digits - 1); | |
377 | static_assert(numeric_limits<max_diff_t>::digits10 | |
378 | == numeric_limits<max_size_t>::digits10); | |
379 | // We can't unconditionally use numeric_limits here because __int128 is an | |
380 | // integral type only in GNU mode. | |
381 | #if __SIZEOF_INT128__ | |
382 | static_assert(numeric_limits<max_diff_t>::min() == -max_diff_t(~rep_t(0))-1); | |
383 | static_assert(numeric_limits<max_diff_t>::max() == ~rep_t(0)); | |
384 | #else | |
385 | static_assert(numeric_limits<max_diff_t>::min() | |
386 | == -max_diff_t(numeric_limits<rep_t>::max())-1); | |
387 | static_assert(numeric_limits<max_diff_t>::max() | |
388 | == numeric_limits<rep_t>::max()); | |
389 | #endif | |
390 | static_assert(numeric_limits<max_diff_t>::lowest() | |
391 | == numeric_limits<max_diff_t>::min()); | |
392 | static_assert(max_diff_t(max_size_t(1) | |
393 | << (numeric_limits<max_size_t>::digits-1)) | |
394 | == numeric_limits<max_diff_t>::min()); | |
395 | ||
396 | int | |
397 | main() | |
398 | { | |
399 | test01(); | |
400 | ||
401 | test02<false,false>(); | |
402 | test02<false,true>(); | |
403 | test02<true,false>(); | |
404 | test02<true,true>(); | |
405 | ||
406 | test03<false,false>(); | |
407 | test03<false,true>(); | |
408 | test03<true,false>(); | |
409 | test03<true,true>(); | |
410 | ||
411 | test04(); | |
412 | test05(); | |
413 | } |