1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6 #include <stdint.h>
7
8 #include <limits>
9 #include <type_traits>
10
11 #include "base/compiler_specific.h"
12 #include "build/build_config.h"
13
14 // WARNING: This block must come before the base/numerics headers are included.
15 // These tests deliberately cause arithmetic boundary errors. If the compiler is
16 // aggressive enough, it can const detect these errors, so we disable warnings.
17 #if BUILDFLAG(IS_WIN)
18 #pragma warning(disable : 4756) // Arithmetic overflow.
19 #pragma warning(disable : 4293) // Invalid shift.
20 #endif
21
22 // This may not need to come before the base/numerics headers, but let's keep
23 // it close to the MSVC equivalent.
24 #if defined(__clang__)
25 #pragma clang diagnostic push
26 #pragma clang diagnostic ignored "-Winteger-overflow"
27 #endif
28
29 #include "base/logging.h"
30 #include "base/numerics/safe_conversions.h"
31 #include "base/numerics/safe_math.h"
32 #include "base/numerics/wrapping_math.h"
33 #include "base/test/gtest_util.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35
36 #if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
37 #include <mmintrin.h>
38 #endif
39
40 namespace base {
41 namespace internal {
42
43 using std::numeric_limits;
44
45 // This is a helper function for finding the maximum value in Src that can be
46 // wholy represented as the destination floating-point type.
47 template <typename Dst, typename Src>
GetMaxConvertibleToFloat()48 Dst GetMaxConvertibleToFloat() {
49 using DstLimits = numeric_limits<Dst>;
50 using SrcLimits = numeric_limits<Src>;
51 static_assert(SrcLimits::is_specialized, "Source must be numeric.");
52 static_assert(DstLimits::is_specialized, "Destination must be numeric.");
53 CHECK(DstLimits::is_iec559);
54
55 if (SrcLimits::digits <= DstLimits::digits &&
56 MaxExponent<Src>::value <= MaxExponent<Dst>::value)
57 return SrcLimits::max();
58 Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
59 while (max != static_cast<Src>(static_cast<Dst>(max))) {
60 max /= 2;
61 }
62 return static_cast<Dst>(max);
63 }
64
65 // Test corner case promotions used
66 static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int8_t>::value, "");
67 static_assert(IsIntegerArithmeticSafe<int32_t, int16_t, int8_t>::value, "");
68 static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int16_t>::value, "");
69 static_assert(!IsIntegerArithmeticSafe<int32_t, int32_t, int8_t>::value, "");
70 static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
71 static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
72 static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
73 static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
74 static_assert(
75 std::is_same_v<BigEnoughPromotion<int16_t, int8_t>::type, int16_t>,
76 "");
77 static_assert(
78 std::is_same_v<BigEnoughPromotion<int32_t, uint32_t>::type, int64_t>,
79 "");
80 static_assert(
81 std::is_same_v<BigEnoughPromotion<intmax_t, int8_t>::type, intmax_t>,
82 "");
83 static_assert(
84 std::is_same_v<BigEnoughPromotion<uintmax_t, int8_t>::type, uintmax_t>,
85 "");
86 static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
87 static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
88 static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
89 static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
90 static_assert(
91 std::is_same_v<FastIntegerArithmeticPromotion<int16_t, int8_t>::type,
92 int32_t>,
93 "");
94 static_assert(
95 std::is_same_v<FastIntegerArithmeticPromotion<int32_t, uint32_t>::type,
96 int64_t>,
97 "");
98 static_assert(
99 std::is_same_v<FastIntegerArithmeticPromotion<intmax_t, int8_t>::type,
100 intmax_t>,
101 "");
102 static_assert(
103 std::is_same_v<FastIntegerArithmeticPromotion<uintmax_t, int8_t>::type,
104 uintmax_t>,
105 "");
106 static_assert(FastIntegerArithmeticPromotion<int16_t, int8_t>::is_contained,
107 "");
108 static_assert(FastIntegerArithmeticPromotion<int32_t, uint32_t>::is_contained,
109 "");
110 static_assert(!FastIntegerArithmeticPromotion<intmax_t, int8_t>::is_contained,
111 "");
112 static_assert(!FastIntegerArithmeticPromotion<uintmax_t, int8_t>::is_contained,
113 "");
114
115 // Test compile-time (constexpr) evaluation of checking and saturation.
116 constexpr int32_t kIntOne = 1;
117 static_assert(1 == checked_cast<uint8_t>(kIntOne), "");
118 static_assert(1 == saturated_cast<uint8_t>(kIntOne), "");
119 static_assert(2U == MakeClampedNum(kIntOne) + 1, "");
120 static_assert(2U == (MakeCheckedNum(kIntOne) + 1).ValueOrDie(), "");
121 static_assert(0U == MakeClampedNum(kIntOne) - 1, "");
122 static_assert(0U == (MakeCheckedNum(kIntOne) - 1).ValueOrDie(), "");
123 static_assert(-1 == -MakeClampedNum(kIntOne), "");
124 static_assert(-1 == (-MakeCheckedNum(kIntOne)).ValueOrDie(), "");
125 static_assert(1U == MakeClampedNum(kIntOne) * 1, "");
126 static_assert(1U == (MakeCheckedNum(kIntOne) * 1).ValueOrDie(), "");
127 static_assert(1U == MakeClampedNum(kIntOne) / 1, "");
128 static_assert(1U == (MakeCheckedNum(kIntOne) / 1).ValueOrDie(), "");
129 static_assert(1 == MakeClampedNum(-kIntOne).Abs(), "");
130 static_assert(1 == MakeCheckedNum(-kIntOne).Abs().ValueOrDie(), "");
131 static_assert(1U == MakeClampedNum(kIntOne) % 2, "");
132 static_assert(1U == (MakeCheckedNum(kIntOne) % 2).ValueOrDie(), "");
133 static_assert(0U == MakeClampedNum(kIntOne) >> 1U, "");
134 static_assert(0U == (MakeCheckedNum(kIntOne) >> 1U).ValueOrDie(), "");
135 static_assert(2U == MakeClampedNum(kIntOne) << 1U, "");
136 static_assert(2U == (MakeCheckedNum(kIntOne) << 1U).ValueOrDie(), "");
137 static_assert(1 == MakeClampedNum(kIntOne) & 1U, "");
138 static_assert(1 == (MakeCheckedNum(kIntOne) & 1U).ValueOrDie(), "");
139 static_assert(1 == MakeClampedNum(kIntOne) | 1U, "");
140 static_assert(1 == (MakeCheckedNum(kIntOne) | 1U).ValueOrDie(), "");
141 static_assert(0 == MakeClampedNum(kIntOne) ^ 1U, "");
142 static_assert(0 == (MakeCheckedNum(kIntOne) ^ 1U).ValueOrDie(), "");
143 constexpr float kFloatOne = 1.0;
144 static_assert(1 == int{checked_cast<int8_t>(kFloatOne)}, "");
145 static_assert(1 == int{saturated_cast<int8_t>(kFloatOne)}, "");
146 static_assert(2U == unsigned{MakeClampedNum(kFloatOne) + 1}, "");
147 static_assert(2U ==
148 (MakeCheckedNum(kFloatOne) + 1).Cast<unsigned>().ValueOrDie(),
149 "");
150 static_assert(0U == unsigned{MakeClampedNum(kFloatOne) - 1}, "");
151 static_assert(0U ==
152 (MakeCheckedNum(kFloatOne) - 1).Cast<unsigned>().ValueOrDie(),
153 "");
154 static_assert(-1 == int{-MakeClampedNum(kFloatOne)}, "");
155 static_assert(-1 == (-MakeCheckedNum(kFloatOne)).Cast<int>().ValueOrDie(), "");
156 static_assert(1U == unsigned{MakeClampedNum(kFloatOne) * 1}, "");
157 static_assert(1U ==
158 (MakeCheckedNum(kFloatOne) * 1).Cast<unsigned>().ValueOrDie(),
159 "");
160 static_assert(1U == unsigned{MakeClampedNum(kFloatOne) / 1}, "");
161 static_assert(1U ==
162 (MakeCheckedNum(kFloatOne) / 1).Cast<unsigned>().ValueOrDie(),
163 "");
164 static_assert(1 == int{MakeClampedNum(-kFloatOne).Abs()}, "");
165 static_assert(1 == MakeCheckedNum(-kFloatOne).Abs().Cast<int>().ValueOrDie(),
166 "");
167
168 template <typename U>
GetNumericValueForTest(const CheckedNumeric<U> & src)169 U GetNumericValueForTest(const CheckedNumeric<U>& src) {
170 return src.state_.value();
171 }
172
173 template <typename U>
GetNumericValueForTest(const ClampedNumeric<U> & src)174 U GetNumericValueForTest(const ClampedNumeric<U>& src) {
175 return static_cast<U>(src);
176 }
177
178 template <typename U>
GetNumericValueForTest(const U & src)179 U GetNumericValueForTest(const U& src) {
180 return src;
181 }
182
183 // Logs the ValueOrDie() failure instead of crashing.
184 struct LogOnFailure {
185 template <typename T>
HandleFailurebase::internal::LogOnFailure186 static T HandleFailure() {
187 LOG(WARNING) << "ValueOrDie() failed unexpectedly.";
188 return T();
189 }
190 };
191
192 template <typename T>
GetValue(const T & src)193 constexpr T GetValue(const T& src) {
194 return src;
195 }
196
197 template <typename T, typename U>
GetValueAsDest(const U & src)198 constexpr T GetValueAsDest(const U& src) {
199 return static_cast<T>(src);
200 }
201
202 template <typename T>
GetValue(const CheckedNumeric<T> & src)203 constexpr T GetValue(const CheckedNumeric<T>& src) {
204 return src.template ValueOrDie<T, LogOnFailure>();
205 }
206
207 template <typename T, typename U>
GetValueAsDest(const CheckedNumeric<U> & src)208 constexpr T GetValueAsDest(const CheckedNumeric<U>& src) {
209 return src.template ValueOrDie<T, LogOnFailure>();
210 }
211
212 template <typename T>
GetValue(const ClampedNumeric<T> & src)213 constexpr T GetValue(const ClampedNumeric<T>& src) {
214 return static_cast<T>(src);
215 }
216
217 template <typename T, typename U>
GetValueAsDest(const ClampedNumeric<U> & src)218 constexpr T GetValueAsDest(const ClampedNumeric<U>& src) {
219 return static_cast<T>(src);
220 }
221
222 // Helper macros to wrap displaying the conversion types and line numbers.
223 #define TEST_EXPECTED_VALIDITY(expected, actual) \
224 EXPECT_EQ(expected, (actual).template Cast<Dst>().IsValid()) \
225 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
226 << dst << " on line " << line
227
228 #define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
229 #define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
230
231 // We have to handle promotions, so infer the underlying type below from actual.
232 #define TEST_EXPECTED_VALUE(expected, actual) \
233 EXPECT_EQ(GetValue(expected), GetValueAsDest<decltype(expected)>(actual)) \
234 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
235 << dst << " on line " << line
236
237 // Test the simple pointer arithmetic overrides.
238 template <typename Dst>
TestStrictPointerMath()239 void TestStrictPointerMath() {
240 Dst dummy_value = 0;
241 Dst* dummy_ptr = &dummy_value;
242 static const Dst kDummyOffset = 2; // Don't want to go too far.
243 EXPECT_EQ(dummy_ptr + kDummyOffset,
244 dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
245 EXPECT_EQ(dummy_ptr - kDummyOffset,
246 dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
247 EXPECT_NE(dummy_ptr, dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
248 EXPECT_NE(dummy_ptr, dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
249 EXPECT_DEATH_IF_SUPPORTED(
250 dummy_ptr + StrictNumeric<size_t>(std::numeric_limits<size_t>::max()),
251 "");
252 }
253
254 // Signed integer arithmetic.
255 template <typename Dst>
TestSpecializedArithmetic(const char * dst,int line,std::enable_if_t<numeric_limits<Dst>::is_integer && numeric_limits<Dst>::is_signed,int>=0)256 static void TestSpecializedArithmetic(
257 const char* dst,
258 int line,
259 std::enable_if_t<numeric_limits<Dst>::is_integer &&
260 numeric_limits<Dst>::is_signed,
261 int> = 0) {
262 using DstLimits = SaturationDefaultLimits<Dst>;
263 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::lowest()));
264 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
265 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
266 TEST_EXPECTED_VALUE(DstLimits::max(),
267 MakeCheckedNum(-DstLimits::max()).Abs());
268
269 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
270 -ClampedNumeric<Dst>(DstLimits::lowest()));
271 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
272 ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
273 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).Abs());
274 TEST_EXPECTED_VALUE(DstLimits::max(),
275 MakeClampedNum(-DstLimits::max()).Abs());
276
277 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
278 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
279 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
280 DstLimits::lowest());
281
282 TEST_EXPECTED_VALUE(DstLimits::max() - 1,
283 ClampedNumeric<Dst>(DstLimits::max()) + -1);
284 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
285 ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
286 TEST_EXPECTED_VALUE(
287 DstLimits::Underflow(),
288 ClampedNumeric<Dst>(DstLimits::lowest()) + DstLimits::lowest());
289
290 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
291 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) - -1);
292 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
293 DstLimits::lowest());
294 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
295 DstLimits::max());
296
297 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
298 ClampedNumeric<Dst>(DstLimits::lowest()) - 1);
299 TEST_EXPECTED_VALUE(DstLimits::lowest() + 1,
300 ClampedNumeric<Dst>(DstLimits::lowest()) - -1);
301 TEST_EXPECTED_VALUE(
302 DstLimits::Overflow(),
303 ClampedNumeric<Dst>(DstLimits::max()) - DstLimits::lowest());
304 TEST_EXPECTED_VALUE(
305 DstLimits::Underflow(),
306 ClampedNumeric<Dst>(DstLimits::lowest()) - DstLimits::max());
307
308 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
309 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
310 ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
311
312 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) / -1);
313 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
314 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * -1);
315 TEST_EXPECTED_VALUE(DstLimits::max(),
316 CheckedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
317 TEST_EXPECTED_VALUE(DstLimits::max(),
318 CheckedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
319 TEST_EXPECTED_VALUE(DstLimits::lowest(),
320 CheckedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
321 TEST_EXPECTED_VALUE(DstLimits::lowest(),
322 CheckedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
323 TEST_EXPECTED_VALUE(
324 typename std::make_unsigned<Dst>::type(0) - DstLimits::lowest(),
325 MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
326 TEST_EXPECTED_VALUE(DstLimits::max(),
327 MakeCheckedNum(DstLimits::max()).UnsignedAbs());
328 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
329 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
330 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).UnsignedAbs());
331
332 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
333 ClampedNumeric<Dst>(DstLimits::lowest()) / -1);
334 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) / 2);
335 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
336 ClampedNumeric<Dst>(DstLimits::lowest()) * -1);
337 TEST_EXPECTED_VALUE(DstLimits::max(),
338 ClampedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
339 TEST_EXPECTED_VALUE(DstLimits::max(),
340 ClampedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
341 TEST_EXPECTED_VALUE(DstLimits::lowest(),
342 ClampedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
343 TEST_EXPECTED_VALUE(DstLimits::lowest(),
344 ClampedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
345 TEST_EXPECTED_VALUE(
346 typename std::make_unsigned<Dst>::type(0) - DstLimits::lowest(),
347 MakeClampedNum(DstLimits::lowest()).UnsignedAbs());
348 TEST_EXPECTED_VALUE(DstLimits::max(),
349 MakeClampedNum(DstLimits::max()).UnsignedAbs());
350 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0).UnsignedAbs());
351 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).UnsignedAbs());
352 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).UnsignedAbs());
353
354 // Modulus is legal only for integers.
355 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % 2);
356 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % 1);
357 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % -1);
358 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % -2);
359 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
360 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
361 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % -1);
362 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % -2);
363 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
364 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) % 1);
365 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) % -1);
366 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % -2);
367 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
368 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 1);
369 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % -1);
370 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % -2);
371 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
372 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::max()) % 1);
373 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::max()) % -1);
374 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % -2);
375 // Test all the different modulus combinations.
376 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
377 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
378 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
379 CheckedNumeric<Dst> checked_dst = 1;
380 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
381 // Test that div by 0 is avoided but returns invalid result.
382 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
383 // Test bit shifts.
384 volatile Dst negative_one = -1;
385 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
386 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
387 << (IntegerBitsPlusSign<Dst>::value - 1));
388 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
389 << IntegerBitsPlusSign<Dst>::value);
390 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
391 TEST_EXPECTED_VALUE(
392 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2),
393 CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2));
394 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0)
395 << (IntegerBitsPlusSign<Dst>::value - 1));
396 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
397 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
398 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
399 IntegerBitsPlusSign<Dst>::value);
400 TEST_EXPECTED_VALUE(
401 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
402 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
403
404 // Modulus is legal only for integers.
405 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % 2);
406 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % 1);
407 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % -1);
408 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % -2);
409 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % 2);
410 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
411 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % -1);
412 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % -2);
413 TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(-1) % 2);
414 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) % 1);
415 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) % -1);
416 TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(-1) % -2);
417 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 2);
418 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 1);
419 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % -1);
420 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % -2);
421 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % 2);
422 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) % 1);
423 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) % -1);
424 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % -2);
425 // Test all the different modulus combinations.
426 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % ClampedNumeric<Dst>(1));
427 TEST_EXPECTED_VALUE(0, 1 % ClampedNumeric<Dst>(1));
428 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
429 ClampedNumeric<Dst> clamped_dst = 1;
430 TEST_EXPECTED_VALUE(0, clamped_dst %= 1);
431 TEST_EXPECTED_VALUE(Dst(1), ClampedNumeric<Dst>(1) % 0);
432 // Test bit shifts.
433 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
434 ClampedNumeric<Dst>(1)
435 << (IntegerBitsPlusSign<Dst>::value - 1U));
436 TEST_EXPECTED_VALUE(Dst(0), ClampedNumeric<Dst>(0)
437 << (IntegerBitsPlusSign<Dst>::value + 0U));
438 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
439 ClampedNumeric<Dst>(DstLimits::max()) << 1U);
440 TEST_EXPECTED_VALUE(
441 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2U),
442 ClampedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2U));
443 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0)
444 << (IntegerBitsPlusSign<Dst>::value - 1U));
445 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) << 0U);
446 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) << 1U);
447 TEST_EXPECTED_VALUE(
448 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value + 0U));
449 TEST_EXPECTED_VALUE(
450 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
451 TEST_EXPECTED_VALUE(
452 -1, ClampedNumeric<Dst>(-1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
453 TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(DstLimits::lowest()) >>
454 (IntegerBitsPlusSign<Dst>::value - 0U));
455
456 TestStrictPointerMath<Dst>();
457 }
458
459 // Unsigned integer arithmetic.
460 template <typename Dst>
TestSpecializedArithmetic(const char * dst,int line,std::enable_if_t<numeric_limits<Dst>::is_integer &&!numeric_limits<Dst>::is_signed,int>=0)461 static void TestSpecializedArithmetic(
462 const char* dst,
463 int line,
464 std::enable_if_t<numeric_limits<Dst>::is_integer &&
465 !numeric_limits<Dst>::is_signed,
466 int> = 0) {
467 using DstLimits = SaturationDefaultLimits<Dst>;
468 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
469 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
470 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
471 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
472 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
473 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
474 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
475 TEST_EXPECTED_SUCCESS(
476 CheckedNumeric<typename std::make_signed<Dst>::type>(
477 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
478 .UnsignedAbs());
479 TEST_EXPECTED_VALUE(DstLimits::lowest(),
480 MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
481 TEST_EXPECTED_VALUE(DstLimits::max(),
482 MakeCheckedNum(DstLimits::max()).UnsignedAbs());
483 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
484 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
485
486 TEST_EXPECTED_VALUE(0, -ClampedNumeric<Dst>(DstLimits::lowest()));
487 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
488 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
489 ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
490 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
491 ClampedNumeric<Dst>(DstLimits::lowest()) - 1);
492 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
493 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) / 2);
494 TEST_EXPECTED_VALUE(0,
495 ClampedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
496 TEST_EXPECTED_VALUE(
497 as_unsigned(
498 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest()),
499 ClampedNumeric<typename std::make_signed<Dst>::type>(
500 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
501 .UnsignedAbs());
502 TEST_EXPECTED_VALUE(DstLimits::lowest(),
503 MakeClampedNum(DstLimits::lowest()).UnsignedAbs());
504 TEST_EXPECTED_VALUE(DstLimits::max(),
505 MakeClampedNum(DstLimits::max()).UnsignedAbs());
506 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0).UnsignedAbs());
507 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).UnsignedAbs());
508
509 // Modulus is legal only for integers.
510 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
511 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
512 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
513 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
514 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
515 // Test all the different modulus combinations.
516 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
517 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
518 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
519 CheckedNumeric<Dst> checked_dst = 1;
520 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
521 // Test that div by 0 is avoided but returns invalid result.
522 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
523 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
524 << IntegerBitsPlusSign<Dst>::value);
525 // Test bit shifts.
526 volatile int negative_one = -1;
527 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
528 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
529 << IntegerBitsPlusSign<Dst>::value);
530 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
531 << IntegerBitsPlusSign<Dst>::value);
532 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
533 TEST_EXPECTED_VALUE(
534 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1),
535 CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1));
536 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
537 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
538 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
539 IntegerBitsPlusSign<Dst>::value);
540 TEST_EXPECTED_VALUE(
541 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
542 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
543 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) & 1);
544 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
545 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) & 1);
546 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
547 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
548 MakeCheckedNum(DstLimits::max()) & -1);
549 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 1);
550 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 0);
551 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) | 1);
552 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0);
553 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
554 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1));
555 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1);
556 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0);
557 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1);
558 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0);
559 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
560 CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
561 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0));
562
563 // Modulus is legal only for integers.
564 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() % 1);
565 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
566 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % 2);
567 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 2);
568 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % 2);
569 // Test all the different modulus combinations.
570 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % ClampedNumeric<Dst>(1));
571 TEST_EXPECTED_VALUE(0, 1 % ClampedNumeric<Dst>(1));
572 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
573 ClampedNumeric<Dst> clamped_dst = 1;
574 TEST_EXPECTED_VALUE(0, clamped_dst %= 1);
575 // Test that div by 0 is avoided but returns invalid result.
576 TEST_EXPECTED_VALUE(Dst(1), ClampedNumeric<Dst>(1) % 0);
577 // Test bit shifts.
578 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
579 ClampedNumeric<Dst>(1)
580 << as_unsigned(IntegerBitsPlusSign<Dst>::value));
581 TEST_EXPECTED_VALUE(Dst(0), ClampedNumeric<Dst>(0) << as_unsigned(
582 IntegerBitsPlusSign<Dst>::value));
583 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
584 ClampedNumeric<Dst>(DstLimits::max()) << 1U);
585 TEST_EXPECTED_VALUE(
586 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1U),
587 ClampedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1U));
588 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) << 0U);
589 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) << 1U);
590 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) >>
591 as_unsigned(IntegerBitsPlusSign<Dst>::value));
592 TEST_EXPECTED_VALUE(
593 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
594 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) & 1);
595 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) & 0);
596 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) & 1);
597 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) & 0);
598 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
599 MakeClampedNum(DstLimits::max()) & -1);
600 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) | 1);
601 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) | 0);
602 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(0) | 1);
603 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) | 0);
604 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
605 ClampedNumeric<Dst>(0) | static_cast<Dst>(-1));
606 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) ^ 1);
607 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) ^ 0);
608 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(0) ^ 1);
609 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) ^ 0);
610 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
611 ClampedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
612 TEST_EXPECTED_VALUE(DstLimits::max(), ~ClampedNumeric<Dst>(0));
613
614 TestStrictPointerMath<Dst>();
615 }
616
617 // Floating point arithmetic.
618 template <typename Dst>
TestSpecializedArithmetic(const char * dst,int line,std::enable_if_t<numeric_limits<Dst>::is_iec559,int>=0)619 void TestSpecializedArithmetic(
620 const char* dst,
621 int line,
622 std::enable_if_t<numeric_limits<Dst>::is_iec559, int> = 0) {
623 using DstLimits = SaturationDefaultLimits<Dst>;
624 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
625
626 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
627 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
628
629 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
630 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
631 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
632 DstLimits::lowest());
633
634 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
635 DstLimits::lowest());
636 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
637 DstLimits::max());
638
639 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
640
641 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
642
643 TEST_EXPECTED_VALUE(DstLimits::max(),
644 -ClampedNumeric<Dst>(DstLimits::lowest()));
645
646 TEST_EXPECTED_VALUE(DstLimits::max(),
647 ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
648 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).Abs());
649
650 TEST_EXPECTED_VALUE(DstLimits::lowest() - 1,
651 ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
652 TEST_EXPECTED_VALUE(DstLimits::max() + 1,
653 ClampedNumeric<Dst>(DstLimits::max()) + 1);
654 TEST_EXPECTED_VALUE(
655 DstLimits::Underflow(),
656 ClampedNumeric<Dst>(DstLimits::lowest()) + DstLimits::lowest());
657
658 TEST_EXPECTED_VALUE(
659 DstLimits::Overflow(),
660 ClampedNumeric<Dst>(DstLimits::max()) - DstLimits::lowest());
661 TEST_EXPECTED_VALUE(
662 DstLimits::Underflow(),
663 ClampedNumeric<Dst>(DstLimits::lowest()) - DstLimits::max());
664
665 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
666 ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
667
668 TEST_EXPECTED_VALUE(-0.5, ClampedNumeric<Dst>(-1.0) / 2);
669 }
670
671 // Generic arithmetic tests.
672 template <typename Dst>
TestArithmetic(const char * dst,int line)673 static void TestArithmetic(const char* dst, int line) {
674 using DstLimits = SaturationDefaultLimits<Dst>;
675
676 // Test C++17 class template argument deduction
677 static_assert(
678 std::is_same_v<Dst, typename decltype(CheckedNumeric(Dst{0}))::type>);
679 static_assert(
680 std::is_same_v<Dst, typename decltype(ClampedNumeric(Dst{0}))::type>);
681 static_assert(
682 std::is_same_v<Dst, typename decltype(StrictNumeric(Dst{0}))::type>);
683
684 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
685 EXPECT_EQ(false, CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
686 DstLimits::max())
687 .IsValid());
688 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
689 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
690 EXPECT_EQ(static_cast<Dst>(1),
691 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
692 DstLimits::max())
693 .ValueOrDefault(1));
694
695 // Test the operator combinations.
696 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
697 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
698 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
699 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
700 TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
701 TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
702 TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
703 TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
704 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
705 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
706 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
707 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
708 CheckedNumeric<Dst> checked_dst = 1;
709 TEST_EXPECTED_VALUE(2, checked_dst += 1);
710 checked_dst = 1;
711 TEST_EXPECTED_VALUE(0, checked_dst -= 1);
712 checked_dst = 1;
713 TEST_EXPECTED_VALUE(1, checked_dst *= 1);
714 checked_dst = 1;
715 TEST_EXPECTED_VALUE(1, checked_dst /= 1);
716
717 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) + ClampedNumeric<Dst>(1));
718 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) - ClampedNumeric<Dst>(1));
719 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) * ClampedNumeric<Dst>(1));
720 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / ClampedNumeric<Dst>(1));
721 TEST_EXPECTED_VALUE(2, 1 + ClampedNumeric<Dst>(1));
722 TEST_EXPECTED_VALUE(0, 1 - ClampedNumeric<Dst>(1));
723 TEST_EXPECTED_VALUE(1, 1 * ClampedNumeric<Dst>(1));
724 TEST_EXPECTED_VALUE(1, 1 / ClampedNumeric<Dst>(1));
725 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) + 1);
726 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) - 1);
727 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) * 1);
728 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / 1);
729 ClampedNumeric<Dst> clamped_dst = 1;
730 TEST_EXPECTED_VALUE(2, clamped_dst += 1);
731 clamped_dst = 1;
732 TEST_EXPECTED_VALUE(0, clamped_dst -= 1);
733 clamped_dst = 1;
734 TEST_EXPECTED_VALUE(1, clamped_dst *= 1);
735 clamped_dst = 1;
736 TEST_EXPECTED_VALUE(1, clamped_dst /= 1);
737
738 // Generic negation.
739 if (DstLimits::is_signed) {
740 TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
741 TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
742 TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
743 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
744 -CheckedNumeric<Dst>(DstLimits::max()));
745
746 TEST_EXPECTED_VALUE(0, -ClampedNumeric<Dst>());
747 TEST_EXPECTED_VALUE(-1, -ClampedNumeric<Dst>(1));
748 TEST_EXPECTED_VALUE(1, -ClampedNumeric<Dst>(-1));
749 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
750 -ClampedNumeric<Dst>(DstLimits::max()));
751
752 // The runtime paths for saturated negation differ significantly from what
753 // gets evaluated at compile-time. Making this test volatile forces the
754 // compiler to generate code rather than fold constant expressions.
755 volatile Dst value = Dst(0);
756 TEST_EXPECTED_VALUE(0, -MakeClampedNum(value));
757 value = Dst(1);
758 TEST_EXPECTED_VALUE(-1, -MakeClampedNum(value));
759 value = Dst(2);
760 TEST_EXPECTED_VALUE(-2, -MakeClampedNum(value));
761 value = Dst(-1);
762 TEST_EXPECTED_VALUE(1, -MakeClampedNum(value));
763 value = Dst(-2);
764 TEST_EXPECTED_VALUE(2, -MakeClampedNum(value));
765 value = DstLimits::max();
766 TEST_EXPECTED_VALUE(Dst(DstLimits::max() * -1), -MakeClampedNum(value));
767 value = Dst(-1 * DstLimits::max());
768 TEST_EXPECTED_VALUE(DstLimits::max(), -MakeClampedNum(value));
769 value = DstLimits::lowest();
770 TEST_EXPECTED_VALUE(DstLimits::max(), -MakeClampedNum(value));
771 }
772
773 // Generic absolute value.
774 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
775 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
776 TEST_EXPECTED_VALUE(DstLimits::max(),
777 CheckedNumeric<Dst>(DstLimits::max()).Abs());
778
779 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>().Abs());
780 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).Abs());
781 TEST_EXPECTED_VALUE(DstLimits::max(),
782 ClampedNumeric<Dst>(DstLimits::max()).Abs());
783
784 // Generic addition.
785 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
786 TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
787 if (numeric_limits<Dst>::is_signed)
788 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
789 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + 1);
790 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) +
791 DstLimits::max());
792
793 TEST_EXPECTED_VALUE(1, (ClampedNumeric<Dst>() + 1));
794 TEST_EXPECTED_VALUE(2, (ClampedNumeric<Dst>(1) + 1));
795 if (numeric_limits<Dst>::is_signed)
796 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(-1) + 1));
797 TEST_EXPECTED_VALUE(DstLimits::lowest() + 1,
798 ClampedNumeric<Dst>(DstLimits::lowest()) + 1);
799 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
800 ClampedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
801
802 // Generic subtraction.
803 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
804 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
805 if (numeric_limits<Dst>::is_signed) {
806 TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
807 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
808 } else {
809 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -1);
810 }
811
812 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(1) - 1));
813 TEST_EXPECTED_VALUE(DstLimits::max() - 1,
814 ClampedNumeric<Dst>(DstLimits::max()) - 1);
815 if (numeric_limits<Dst>::is_signed) {
816 TEST_EXPECTED_VALUE(-1, (ClampedNumeric<Dst>() - 1));
817 TEST_EXPECTED_VALUE(-2, (ClampedNumeric<Dst>(-1) - 1));
818 } else {
819 TEST_EXPECTED_VALUE(DstLimits::max(),
820 ClampedNumeric<Dst>(DstLimits::max()) - -1);
821 }
822
823 // Generic multiplication.
824 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
825 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
826 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
827 if (numeric_limits<Dst>::is_signed) {
828 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
829 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
830 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
831 } else {
832 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * -2);
833 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
834 CheckedNumeric<uintmax_t>(-2));
835 }
836 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
837 DstLimits::max());
838
839 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>() * 1));
840 TEST_EXPECTED_VALUE(1, (ClampedNumeric<Dst>(1) * 1));
841 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(0) * 0));
842 if (numeric_limits<Dst>::is_signed) {
843 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(-1) * 0));
844 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(0) * -1));
845 TEST_EXPECTED_VALUE(-2, (ClampedNumeric<Dst>(-1) * 2));
846 } else {
847 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
848 ClampedNumeric<Dst>(DstLimits::max()) * -2);
849 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) *
850 ClampedNumeric<uintmax_t>(-2));
851 }
852 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
853 ClampedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
854
855 // Generic division.
856 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
857 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
858 TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
859 CheckedNumeric<Dst>(DstLimits::lowest()) / 2);
860 TEST_EXPECTED_VALUE(DstLimits::max() / 2,
861 CheckedNumeric<Dst>(DstLimits::max()) / 2);
862 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) / 0);
863
864 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() / 1);
865 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / 1);
866 TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
867 ClampedNumeric<Dst>(DstLimits::lowest()) / 2);
868 TEST_EXPECTED_VALUE(DstLimits::max() / 2,
869 ClampedNumeric<Dst>(DstLimits::max()) / 2);
870 TEST_EXPECTED_VALUE(DstLimits::Overflow(), ClampedNumeric<Dst>(1) / 0);
871 TEST_EXPECTED_VALUE(DstLimits::Underflow(), ClampedNumeric<Dst>(-1) / 0);
872 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) / 0);
873
874 TestSpecializedArithmetic<Dst>(dst, line);
875 }
876
877 // Helper macro to wrap displaying the conversion types and line numbers.
878 #define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
879
TEST(SafeNumerics,SignedIntegerMath)880 TEST(SafeNumerics, SignedIntegerMath) {
881 TEST_ARITHMETIC(int8_t);
882 TEST_ARITHMETIC(int16_t);
883 TEST_ARITHMETIC(int);
884 TEST_ARITHMETIC(intptr_t);
885 TEST_ARITHMETIC(intmax_t);
886 }
887
TEST(SafeNumerics,UnsignedIntegerMath)888 TEST(SafeNumerics, UnsignedIntegerMath) {
889 TEST_ARITHMETIC(uint8_t);
890 TEST_ARITHMETIC(uint16_t);
891 TEST_ARITHMETIC(unsigned int);
892 TEST_ARITHMETIC(uintptr_t);
893 TEST_ARITHMETIC(uintmax_t);
894 }
895
TEST(SafeNumerics,FloatingPointMath)896 TEST(SafeNumerics, FloatingPointMath) {
897 TEST_ARITHMETIC(float);
898 TEST_ARITHMETIC(double);
899 }
900
901 // Enumerates the five different conversions types we need to test.
902 enum NumericConversionType {
903 SIGN_PRESERVING_VALUE_PRESERVING,
904 SIGN_PRESERVING_NARROW,
905 SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
906 SIGN_TO_UNSIGN_NARROW,
907 UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
908 };
909
910 // Template covering the different conversion tests.
911 template <typename Dst, typename Src, NumericConversionType conversion>
912 struct TestNumericConversion {};
913
914 enum RangeConstraint {
915 RANGE_VALID = 0x0, // Value can be represented by the destination type.
916 RANGE_UNDERFLOW = 0x1, // Value would underflow.
917 RANGE_OVERFLOW = 0x2, // Value would overflow.
918 RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN).
919 };
920
921 // These are some wrappers to make the tests a bit cleaner.
RangeCheckToEnum(const RangeCheck constraint)922 constexpr RangeConstraint RangeCheckToEnum(const RangeCheck constraint) {
923 return static_cast<RangeConstraint>(
924 static_cast<int>(constraint.IsOverflowFlagSet()) << 1 |
925 static_cast<int>(constraint.IsUnderflowFlagSet()));
926 }
927
928 // EXPECT_EQ wrappers providing specific detail on test failures.
929 #define TEST_EXPECTED_RANGE(expected, actual) \
930 EXPECT_EQ(expected, \
931 RangeCheckToEnum(DstRangeRelationToSrcRange<Dst>(actual))) \
932 << "Conversion test: " << src << " value " << actual << " to " << dst \
933 << " on line " << line
934
935 template <typename Dst, typename Src>
TestStrictComparison(const char * dst,const char * src,int line)936 void TestStrictComparison(const char* dst, const char* src, int line) {
937 using DstLimits = numeric_limits<Dst>;
938 using SrcLimits = numeric_limits<Src>;
939 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < DstLimits::max(), "");
940 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < SrcLimits::max(), "");
941 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= DstLimits::max()),
942 "");
943 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= SrcLimits::max()),
944 "");
945 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= DstLimits::max(),
946 "");
947 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= SrcLimits::max(),
948 "");
949 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > DstLimits::max()),
950 "");
951 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > SrcLimits::max()),
952 "");
953 static_assert(StrictNumeric<Src>(SrcLimits::max()) > DstLimits::lowest(), "");
954 static_assert(StrictNumeric<Src>(SrcLimits::max()) > SrcLimits::lowest(), "");
955 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= DstLimits::lowest()),
956 "");
957 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= SrcLimits::lowest()),
958 "");
959 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= DstLimits::lowest(),
960 "");
961 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= SrcLimits::lowest(),
962 "");
963 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < DstLimits::lowest()),
964 "");
965 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < SrcLimits::lowest()),
966 "");
967 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(1),
968 "");
969 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(0),
970 "");
971 static_assert(StrictNumeric<Src>(SrcLimits::max()) != static_cast<Dst>(0),
972 "");
973 static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::lowest(),
974 "");
975 static_assert(
976 !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), "");
977 static_assert(
978 !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), "");
979
980 // Due to differences in float handling between compilers, these aren't
981 // compile-time constants everywhere. So, we use run-time tests.
982 EXPECT_EQ(
983 SrcLimits::max(),
984 MakeCheckedNum(SrcLimits::max()).Max(DstLimits::lowest()).ValueOrDie());
985 EXPECT_EQ(
986 DstLimits::max(),
987 MakeCheckedNum(SrcLimits::lowest()).Max(DstLimits::max()).ValueOrDie());
988 EXPECT_EQ(
989 DstLimits::lowest(),
990 MakeCheckedNum(SrcLimits::max()).Min(DstLimits::lowest()).ValueOrDie());
991 EXPECT_EQ(
992 SrcLimits::lowest(),
993 MakeCheckedNum(SrcLimits::lowest()).Min(DstLimits::max()).ValueOrDie());
994 EXPECT_EQ(SrcLimits::lowest(), CheckMin(MakeStrictNum(1), MakeCheckedNum(0),
995 DstLimits::max(), SrcLimits::lowest())
996 .ValueOrDie());
997 EXPECT_EQ(DstLimits::max(), CheckMax(MakeStrictNum(1), MakeCheckedNum(0),
998 DstLimits::max(), SrcLimits::lowest())
999 .ValueOrDie());
1000
1001 EXPECT_EQ(SrcLimits::max(),
1002 MakeClampedNum(SrcLimits::max()).Max(DstLimits::lowest()));
1003 EXPECT_EQ(DstLimits::max(),
1004 MakeClampedNum(SrcLimits::lowest()).Max(DstLimits::max()));
1005 EXPECT_EQ(DstLimits::lowest(),
1006 MakeClampedNum(SrcLimits::max()).Min(DstLimits::lowest()));
1007 EXPECT_EQ(SrcLimits::lowest(),
1008 MakeClampedNum(SrcLimits::lowest()).Min(DstLimits::max()));
1009 EXPECT_EQ(SrcLimits::lowest(),
1010 ClampMin(MakeStrictNum(1), MakeClampedNum(0), DstLimits::max(),
1011 SrcLimits::lowest()));
1012 EXPECT_EQ(DstLimits::max(), ClampMax(MakeStrictNum(1), MakeClampedNum(0),
1013 DstLimits::max(), SrcLimits::lowest()));
1014
1015 if (IsValueInRangeForNumericType<Dst>(SrcLimits::max())) {
1016 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()), (CommonMax<Dst, Src>()));
1017 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()),
1018 (CommonMaxOrMin<Dst, Src>(false)));
1019 } else {
1020 TEST_EXPECTED_VALUE(DstLimits::max(), (CommonMax<Dst, Src>()));
1021 TEST_EXPECTED_VALUE(DstLimits::max(), (CommonMaxOrMin<Dst, Src>(false)));
1022 }
1023
1024 if (IsValueInRangeForNumericType<Dst>(SrcLimits::lowest())) {
1025 TEST_EXPECTED_VALUE(Dst(SrcLimits::lowest()), (CommonMin<Dst, Src>()));
1026 TEST_EXPECTED_VALUE(Dst(SrcLimits::lowest()),
1027 (CommonMaxOrMin<Dst, Src>(true)));
1028 } else {
1029 TEST_EXPECTED_VALUE(DstLimits::lowest(), (CommonMin<Dst, Src>()));
1030 TEST_EXPECTED_VALUE(DstLimits::lowest(), (CommonMaxOrMin<Dst, Src>(true)));
1031 }
1032 }
1033
1034 template <typename Dst, typename Src>
1035 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
Testbase::internal::TestNumericConversion1036 static void Test(const char* dst, const char* src, int line) {
1037 using SrcLimits = SaturationDefaultLimits<Src>;
1038 using DstLimits = SaturationDefaultLimits<Dst>;
1039 // Integral to floating.
1040 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
1041 // Not floating to integral and...
1042 (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
1043 // Same sign, same numeric, source is narrower or same.
1044 ((SrcLimits::is_signed == DstLimits::is_signed &&
1045 MaxExponent<Dst>::value >= MaxExponent<Src>::value) ||
1046 // Or signed destination and source is smaller
1047 (DstLimits::is_signed &&
1048 MaxExponent<Dst>::value >= MaxExponent<Src>::value))),
1049 "Comparison must be sign preserving and value preserving");
1050
1051 TestStrictComparison<Dst, Src>(dst, src, line);
1052
1053 const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
1054 const ClampedNumeric<Dst> clamped_dst = SrcLimits::max();
1055 TEST_EXPECTED_SUCCESS(checked_dst);
1056 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()), clamped_dst);
1057 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
1058 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
1059 // At least twice larger type.
1060 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
1061 TEST_EXPECTED_VALUE(SrcLimits::max() * clamped_dst,
1062 Dst(SrcLimits::max()) * Dst(SrcLimits::max()));
1063 } else { // Larger, but not at least twice as large.
1064 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
1065 TEST_EXPECTED_SUCCESS(checked_dst + 1);
1066 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
1067 SrcLimits::max() * clamped_dst);
1068 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()) + Dst(1),
1069 clamped_dst + Dst(1));
1070 }
1071 } else { // Same width type.
1072 TEST_EXPECTED_FAILURE(checked_dst + 1);
1073 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + Dst(1));
1074 }
1075
1076 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
1077 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
1078 if (SrcLimits::is_iec559) {
1079 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
1080 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
1081 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
1082 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
1083 } else if (numeric_limits<Src>::is_signed) {
1084 // This block reverses the Src to Dst relationship so we don't have to
1085 // complicate the test macros.
1086 if (!std::is_same_v<Src, Dst>) {
1087 TEST_EXPECTED_SUCCESS(CheckDiv(SrcLimits::lowest(), Dst(-1)));
1088 }
1089 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
1090 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
1091 }
1092 }
1093 };
1094
1095 template <typename Dst, typename Src>
1096 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
Testbase::internal::TestNumericConversion1097 static void Test(const char* dst, const char* src, int line) {
1098 using SrcLimits = SaturationDefaultLimits<Src>;
1099 using DstLimits = SaturationDefaultLimits<Dst>;
1100 static_assert(SrcLimits::is_signed == DstLimits::is_signed,
1101 "Destination and source sign must be the same");
1102 static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
1103 "Destination must be narrower than source");
1104
1105 TestStrictComparison<Dst, Src>(dst, src, line);
1106
1107 const CheckedNumeric<Dst> checked_dst;
1108 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
1109 TEST_EXPECTED_VALUE(1, checked_dst + Src(1));
1110 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
1111
1112 ClampedNumeric<Dst> clamped_dst;
1113 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
1114 TEST_EXPECTED_VALUE(1, clamped_dst + Src(1));
1115 TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst - SrcLimits::max());
1116 clamped_dst += SrcLimits::max();
1117 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1118 clamped_dst = DstLimits::max();
1119 clamped_dst += SrcLimits::max();
1120 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1121 clamped_dst = DstLimits::max();
1122 clamped_dst -= SrcLimits::max();
1123 TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst);
1124 clamped_dst = 0;
1125
1126 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
1127 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
1128 if (SrcLimits::is_iec559) {
1129 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
1130 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
1131 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
1132 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
1133 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
1134 if (DstLimits::is_integer) {
1135 if (SrcLimits::digits < DstLimits::digits) {
1136 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
1137 static_cast<Src>(DstLimits::max()));
1138 } else {
1139 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
1140 }
1141 TEST_EXPECTED_RANGE(
1142 RANGE_VALID,
1143 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
1144 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
1145 }
1146 } else if (SrcLimits::is_signed) {
1147 TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
1148 TEST_EXPECTED_VALUE(-1, clamped_dst - static_cast<Src>(1));
1149 TEST_EXPECTED_VALUE(Src(Src(0) - DstLimits::lowest()),
1150 ClampDiv(DstLimits::lowest(), Src(-1)));
1151 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
1152 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
1153 } else {
1154 TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
1155 TEST_EXPECTED_VALUE(Dst(0), clamped_dst - static_cast<Src>(1));
1156 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
1157 }
1158 }
1159 };
1160
1161 template <typename Dst, typename Src>
1162 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
Testbase::internal::TestNumericConversion1163 static void Test(const char* dst, const char* src, int line) {
1164 using SrcLimits = SaturationDefaultLimits<Src>;
1165 using DstLimits = SaturationDefaultLimits<Dst>;
1166 static_assert(MaxExponent<Dst>::value >= MaxExponent<Src>::value,
1167 "Destination must be equal or wider than source.");
1168 static_assert(SrcLimits::is_signed, "Source must be signed");
1169 static_assert(!DstLimits::is_signed, "Destination must be unsigned");
1170
1171 TestStrictComparison<Dst, Src>(dst, src, line);
1172
1173 const CheckedNumeric<Dst> checked_dst;
1174 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
1175 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
1176 TEST_EXPECTED_SUCCESS(checked_dst * static_cast<Src>(-1));
1177 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
1178 TEST_EXPECTED_VALUE(Dst(0), CheckDiv(Dst(0), Src(-1)));
1179
1180 const ClampedNumeric<Dst> clamped_dst;
1181 TEST_EXPECTED_VALUE(SrcLimits::max(), clamped_dst + SrcLimits::max());
1182 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1183 clamped_dst + static_cast<Src>(-1));
1184 TEST_EXPECTED_VALUE(0, clamped_dst * static_cast<Src>(-1));
1185 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1186 clamped_dst + SrcLimits::lowest());
1187
1188 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
1189 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
1190 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
1191 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
1192 }
1193 };
1194
1195 template <typename Dst, typename Src>
1196 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
Testbase::internal::TestNumericConversion1197 static void Test(const char* dst, const char* src, int line) {
1198 using SrcLimits = SaturationDefaultLimits<Src>;
1199 using DstLimits = SaturationDefaultLimits<Dst>;
1200 static_assert(MaxExponent<Dst>::value < MaxExponent<Src>::value,
1201 "Destination must be narrower than source.");
1202 static_assert(SrcLimits::is_signed, "Source must be signed.");
1203 static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
1204
1205 TestStrictComparison<Dst, Src>(dst, src, line);
1206
1207 const CheckedNumeric<Dst> checked_dst;
1208 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
1209 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
1210 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
1211 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
1212
1213 ClampedNumeric<Dst> clamped_dst;
1214 TEST_EXPECTED_VALUE(1, clamped_dst + static_cast<Src>(1));
1215 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
1216 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1217 clamped_dst + static_cast<Src>(-1));
1218 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1219 clamped_dst + SrcLimits::lowest());
1220 clamped_dst += SrcLimits::max();
1221 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1222 clamped_dst = DstLimits::max();
1223 clamped_dst += SrcLimits::max();
1224 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1225 clamped_dst = DstLimits::max();
1226 clamped_dst -= SrcLimits::max();
1227 TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst);
1228 clamped_dst = 0;
1229
1230 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
1231 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
1232 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
1233
1234 // Additional saturation tests.
1235 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
1236 EXPECT_EQ(DstLimits::lowest(), saturated_cast<Dst>(SrcLimits::lowest()));
1237
1238 if (SrcLimits::is_iec559) {
1239 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::quiet_NaN()));
1240
1241 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
1242 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
1243 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
1244 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
1245 if (DstLimits::is_integer) {
1246 if (SrcLimits::digits < DstLimits::digits) {
1247 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
1248 static_cast<Src>(DstLimits::max()));
1249 } else {
1250 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
1251 }
1252 TEST_EXPECTED_RANGE(
1253 RANGE_VALID,
1254 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
1255 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
1256 }
1257 } else {
1258 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
1259 }
1260 }
1261 };
1262
1263 template <typename Dst, typename Src>
1264 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
Testbase::internal::TestNumericConversion1265 static void Test(const char* dst, const char* src, int line) {
1266 using SrcLimits = SaturationDefaultLimits<Src>;
1267 using DstLimits = SaturationDefaultLimits<Dst>;
1268 static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
1269 "Destination must be narrower or equal to source.");
1270 static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
1271 static_assert(DstLimits::is_signed, "Destination must be signed.");
1272
1273 TestStrictComparison<Dst, Src>(dst, src, line);
1274
1275 const CheckedNumeric<Dst> checked_dst;
1276 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
1277 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
1278 TEST_EXPECTED_VALUE(SrcLimits::lowest(), checked_dst + SrcLimits::lowest());
1279
1280 const ClampedNumeric<Dst> clamped_dst;
1281 TEST_EXPECTED_VALUE(1, clamped_dst + static_cast<Src>(1));
1282 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
1283 TEST_EXPECTED_VALUE(SrcLimits::lowest(), clamped_dst + SrcLimits::lowest());
1284
1285 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
1286 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
1287 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
1288
1289 // Additional saturation tests.
1290 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
1291 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::lowest()));
1292 }
1293 };
1294
1295 // Helper macro to wrap displaying the conversion types and line numbers
1296 #define TEST_NUMERIC_CONVERSION(d, s, t) \
1297 TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
1298
TEST(SafeNumerics,IntMinOperations)1299 TEST(SafeNumerics, IntMinOperations) {
1300 TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1301 TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1302
1303 TEST_NUMERIC_CONVERSION(int8_t, int16_t, SIGN_PRESERVING_NARROW);
1304 TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
1305 TEST_NUMERIC_CONVERSION(uint8_t, uint16_t, SIGN_PRESERVING_NARROW);
1306 TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
1307 TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
1308
1309 TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1310
1311 TEST_NUMERIC_CONVERSION(uint8_t, int16_t, SIGN_TO_UNSIGN_NARROW);
1312 TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
1313 TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
1314 TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
1315
1316 TEST_NUMERIC_CONVERSION(int8_t, uint16_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1317 TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1318 TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1319 }
1320
TEST(SafeNumerics,Int16Operations)1321 TEST(SafeNumerics, Int16Operations) {
1322 TEST_NUMERIC_CONVERSION(int16_t, int16_t, SIGN_PRESERVING_VALUE_PRESERVING);
1323 TEST_NUMERIC_CONVERSION(uint16_t, uint16_t, SIGN_PRESERVING_VALUE_PRESERVING);
1324
1325 TEST_NUMERIC_CONVERSION(int16_t, int, SIGN_PRESERVING_NARROW);
1326 TEST_NUMERIC_CONVERSION(uint16_t, unsigned int, SIGN_PRESERVING_NARROW);
1327 TEST_NUMERIC_CONVERSION(int16_t, float, SIGN_PRESERVING_NARROW);
1328
1329 TEST_NUMERIC_CONVERSION(uint16_t, int16_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1330
1331 TEST_NUMERIC_CONVERSION(uint16_t, int, SIGN_TO_UNSIGN_NARROW);
1332 TEST_NUMERIC_CONVERSION(uint16_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
1333 TEST_NUMERIC_CONVERSION(uint16_t, float, SIGN_TO_UNSIGN_NARROW);
1334
1335 TEST_NUMERIC_CONVERSION(int16_t, unsigned int,
1336 UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1337 TEST_NUMERIC_CONVERSION(int16_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1338 }
1339
TEST(SafeNumerics,IntOperations)1340 TEST(SafeNumerics, IntOperations) {
1341 TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
1342 TEST_NUMERIC_CONVERSION(unsigned int, unsigned int,
1343 SIGN_PRESERVING_VALUE_PRESERVING);
1344 TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1345 TEST_NUMERIC_CONVERSION(unsigned int, uint8_t,
1346 SIGN_PRESERVING_VALUE_PRESERVING);
1347 TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1348
1349 TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
1350 TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
1351 TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
1352 TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
1353
1354 TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1355 TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1356
1357 TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
1358 TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
1359 TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
1360
1361 TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1362 TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1363 }
1364
TEST(SafeNumerics,IntMaxOperations)1365 TEST(SafeNumerics, IntMaxOperations) {
1366 TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
1367 TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t,
1368 SIGN_PRESERVING_VALUE_PRESERVING);
1369 TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
1370 TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int,
1371 SIGN_PRESERVING_VALUE_PRESERVING);
1372 TEST_NUMERIC_CONVERSION(intmax_t, unsigned int,
1373 SIGN_PRESERVING_VALUE_PRESERVING);
1374 TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1375
1376 TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
1377 TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
1378
1379 TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1380 TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1381
1382 TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
1383 TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
1384
1385 TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1386 }
1387
TEST(SafeNumerics,FloatOperations)1388 TEST(SafeNumerics, FloatOperations) {
1389 TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
1390 TEST_NUMERIC_CONVERSION(float, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
1391 TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
1392 TEST_NUMERIC_CONVERSION(float, unsigned int,
1393 SIGN_PRESERVING_VALUE_PRESERVING);
1394
1395 TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
1396 }
1397
TEST(SafeNumerics,DoubleOperations)1398 TEST(SafeNumerics, DoubleOperations) {
1399 TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
1400 TEST_NUMERIC_CONVERSION(double, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
1401 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
1402 TEST_NUMERIC_CONVERSION(double, unsigned int,
1403 SIGN_PRESERVING_VALUE_PRESERVING);
1404 }
1405
TEST(SafeNumerics,SizeTOperations)1406 TEST(SafeNumerics, SizeTOperations) {
1407 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1408 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1409 }
1410
1411 // A one-off test to ensure StrictNumeric won't resolve to an incorrect type.
1412 // If this fails we'll just get a compiler error on an ambiguous overload.
TestOverload(int)1413 int TestOverload(int) { // Overload fails.
1414 return 0;
1415 }
TestOverload(uint8_t)1416 uint8_t TestOverload(uint8_t) { // Overload fails.
1417 return 0;
1418 }
TestOverload(size_t)1419 size_t TestOverload(size_t) { // Overload succeeds.
1420 return 0;
1421 }
1422
1423 static_assert(std::is_same_v<decltype(TestOverload(StrictNumeric<int>())), int>,
1424 "");
1425 static_assert(
1426 std::is_same_v<decltype(TestOverload(StrictNumeric<size_t>())), size_t>,
1427 "");
1428
1429 template <typename T>
1430 struct CastTest1 {
NaNbase::internal::CastTest11431 static constexpr T NaN() { return -1; }
maxbase::internal::CastTest11432 static constexpr T max() { return numeric_limits<T>::max() - 1; }
Overflowbase::internal::CastTest11433 static constexpr T Overflow() { return max(); }
lowestbase::internal::CastTest11434 static constexpr T lowest() { return numeric_limits<T>::lowest() + 1; }
Underflowbase::internal::CastTest11435 static constexpr T Underflow() { return lowest(); }
1436 };
1437
1438 template <typename T>
1439 struct CastTest2 {
NaNbase::internal::CastTest21440 static constexpr T NaN() { return 11; }
maxbase::internal::CastTest21441 static constexpr T max() { return 10; }
Overflowbase::internal::CastTest21442 static constexpr T Overflow() { return max(); }
lowestbase::internal::CastTest21443 static constexpr T lowest() { return 1; }
Underflowbase::internal::CastTest21444 static constexpr T Underflow() { return lowest(); }
1445 };
1446
TEST(SafeNumerics,CastTests)1447 TEST(SafeNumerics, CastTests) {
1448 // MSVC catches and warns that we're forcing saturation in these tests.
1449 // Since that's intentional, we need to shut this warning off.
1450 #if defined(COMPILER_MSVC)
1451 #pragma warning(disable : 4756)
1452 #endif
1453
1454 int small_positive = 1;
1455 int small_negative = -1;
1456 double double_small = 1.0;
1457 double double_large = numeric_limits<double>::max();
1458 double double_infinity = numeric_limits<float>::infinity();
1459 double double_large_int = numeric_limits<int>::max();
1460 double double_small_int = numeric_limits<int>::lowest();
1461
1462 // Just test that the casts compile, since the other tests cover logic.
1463 EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
1464 EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
1465 EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
1466 EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
1467 EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
1468 EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
1469 EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
1470
1471 EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
1472 EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
1473 EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
1474
1475 EXPECT_TRUE(IsValueNegative(-1));
1476 EXPECT_TRUE(IsValueNegative(numeric_limits<int>::lowest()));
1477 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::lowest()));
1478 EXPECT_TRUE(IsValueNegative(numeric_limits<double>::lowest()));
1479 EXPECT_FALSE(IsValueNegative(0));
1480 EXPECT_FALSE(IsValueNegative(1));
1481 EXPECT_FALSE(IsValueNegative(0u));
1482 EXPECT_FALSE(IsValueNegative(1u));
1483 EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
1484 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
1485 EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
1486
1487 // These casts and coercions will fail to compile:
1488 // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0)));
1489 // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0)));
1490 // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1));
1491 // EXPECT_EQ(1, StrictNumeric<size_t>(1U));
1492
1493 // Test various saturation corner cases.
1494 EXPECT_EQ(saturated_cast<int>(small_negative),
1495 static_cast<int>(small_negative));
1496 EXPECT_EQ(saturated_cast<int>(small_positive),
1497 static_cast<int>(small_positive));
1498 EXPECT_EQ(saturated_cast<unsigned>(small_negative), static_cast<unsigned>(0));
1499 EXPECT_EQ(saturated_cast<int>(double_small), static_cast<int>(double_small));
1500 EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
1501 EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
1502 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
1503 EXPECT_EQ(numeric_limits<int>::lowest(),
1504 saturated_cast<int>(double_small_int));
1505 EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
1506
1507 // Test the saturated cast overrides.
1508 using FloatLimits = numeric_limits<float>;
1509 using IntLimits = numeric_limits<int>;
1510 EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(FloatLimits::quiet_NaN())));
1511 EXPECT_EQ(CastTest1<int>::max(),
1512 (saturated_cast<int, CastTest1>(FloatLimits::infinity())));
1513 EXPECT_EQ(CastTest1<int>::max(),
1514 (saturated_cast<int, CastTest1>(FloatLimits::max())));
1515 EXPECT_EQ(CastTest1<int>::max(),
1516 (saturated_cast<int, CastTest1>(float(IntLimits::max()))));
1517 EXPECT_EQ(CastTest1<int>::lowest(),
1518 (saturated_cast<int, CastTest1>(-FloatLimits::infinity())));
1519 EXPECT_EQ(CastTest1<int>::lowest(),
1520 (saturated_cast<int, CastTest1>(FloatLimits::lowest())));
1521 EXPECT_EQ(0, (saturated_cast<int, CastTest1>(0.0)));
1522 EXPECT_EQ(1, (saturated_cast<int, CastTest1>(1.0)));
1523 EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(-1.0)));
1524 EXPECT_EQ(0, (saturated_cast<int, CastTest1>(0)));
1525 EXPECT_EQ(1, (saturated_cast<int, CastTest1>(1)));
1526 EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(-1)));
1527 EXPECT_EQ(CastTest1<int>::lowest(),
1528 (saturated_cast<int, CastTest1>(float(IntLimits::lowest()))));
1529 EXPECT_EQ(11, (saturated_cast<int, CastTest2>(FloatLimits::quiet_NaN())));
1530 EXPECT_EQ(10, (saturated_cast<int, CastTest2>(FloatLimits::infinity())));
1531 EXPECT_EQ(10, (saturated_cast<int, CastTest2>(FloatLimits::max())));
1532 EXPECT_EQ(1, (saturated_cast<int, CastTest2>(-FloatLimits::infinity())));
1533 EXPECT_EQ(1, (saturated_cast<int, CastTest2>(FloatLimits::lowest())));
1534 EXPECT_EQ(1, (saturated_cast<int, CastTest2>(0U)));
1535
1536 float not_a_number = std::numeric_limits<float>::infinity() -
1537 std::numeric_limits<float>::infinity();
1538 EXPECT_TRUE(std::isnan(not_a_number));
1539 EXPECT_EQ(0, saturated_cast<int>(not_a_number));
1540
1541 // Test the CheckedNumeric value extractions functions.
1542 auto int8_min = MakeCheckedNum(numeric_limits<int8_t>::lowest());
1543 auto int8_max = MakeCheckedNum(numeric_limits<int8_t>::max());
1544 auto double_max = MakeCheckedNum(numeric_limits<double>::max());
1545 static_assert(
1546 std::is_same_v<int16_t, decltype(int8_min.ValueOrDie<int16_t>())::type>,
1547 "ValueOrDie returning incorrect type.");
1548 static_assert(
1549 std::is_same_v<int16_t,
1550 decltype(int8_min.ValueOrDefault<int16_t>(0))::type>,
1551 "ValueOrDefault returning incorrect type.");
1552 EXPECT_FALSE(IsValidForType<uint8_t>(int8_min));
1553 EXPECT_TRUE(IsValidForType<uint8_t>(int8_max));
1554 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::lowest()),
1555 ValueOrDieForType<int>(int8_min));
1556 EXPECT_TRUE(IsValidForType<uint32_t>(int8_max));
1557 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()),
1558 ValueOrDieForType<int>(int8_max));
1559 EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0));
1560 uint8_t uint8_dest = 0;
1561 int16_t int16_dest = 0;
1562 double double_dest = 0;
1563 EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest));
1564 EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest);
1565 EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest));
1566 EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest));
1567 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest);
1568 EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest));
1569 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::lowest()), int16_dest);
1570 EXPECT_FALSE(double_max.AssignIfValid(&uint8_dest));
1571 EXPECT_FALSE(double_max.AssignIfValid(&int16_dest));
1572 EXPECT_TRUE(double_max.AssignIfValid(&double_dest));
1573 EXPECT_EQ(numeric_limits<double>::max(), double_dest);
1574 EXPECT_EQ(1, checked_cast<int>(StrictNumeric<int>(1)));
1575 EXPECT_EQ(1, saturated_cast<int>(StrictNumeric<int>(1)));
1576 EXPECT_EQ(1, strict_cast<int>(StrictNumeric<int>(1)));
1577
1578 enum class EnumTest { kOne = 1 };
1579 EXPECT_EQ(1, checked_cast<int>(EnumTest::kOne));
1580 EXPECT_EQ(1, saturated_cast<int>(EnumTest::kOne));
1581 EXPECT_EQ(1, strict_cast<int>(EnumTest::kOne));
1582 }
1583
TEST(SafeNumerics,IsValueInRangeForNumericType)1584 TEST(SafeNumerics, IsValueInRangeForNumericType) {
1585 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
1586 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
1587 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
1588 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
1589 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
1590 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
1591 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
1592 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
1593 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
1594 std::numeric_limits<int32_t>::lowest()));
1595 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
1596 std::numeric_limits<int64_t>::lowest()));
1597
1598 // Converting to integer types will discard the fractional part first, so -0.9
1599 // will be truncated to -0.0.
1600 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(-0.9));
1601 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1.0));
1602
1603 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
1604 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
1605 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
1606 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
1607 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
1608 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
1609 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
1610 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
1611 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
1612 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
1613 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
1614 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
1615 std::numeric_limits<int32_t>::lowest()));
1616 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
1617 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
1618 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
1619 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest()) - 1));
1620 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
1621 std::numeric_limits<int64_t>::lowest()));
1622
1623 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
1624 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
1625 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
1626 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
1627 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
1628 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
1629 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
1630 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
1631 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
1632 std::numeric_limits<int32_t>::lowest()));
1633 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
1634 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
1635 std::numeric_limits<int64_t>::lowest()));
1636
1637 // Converting to integer types will discard the fractional part first, so -0.9
1638 // will be truncated to -0.0.
1639 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(-0.9));
1640 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1.0));
1641
1642 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
1643 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
1644 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
1645 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
1646 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
1647 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
1648 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
1649 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
1650 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
1651 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
1652 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
1653 EXPECT_TRUE(
1654 IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
1655 EXPECT_TRUE(
1656 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
1657 EXPECT_FALSE(
1658 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
1659 EXPECT_FALSE(
1660 IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
1661 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
1662 std::numeric_limits<int32_t>::lowest()));
1663 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
1664 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
1665 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
1666 std::numeric_limits<int64_t>::lowest()));
1667 }
1668
TEST(SafeNumerics,CompoundNumericOperations)1669 TEST(SafeNumerics, CompoundNumericOperations) {
1670 CheckedNumeric<int> a = 1;
1671 CheckedNumeric<int> b = 2;
1672 CheckedNumeric<int> c = 3;
1673 CheckedNumeric<int> d = 4;
1674 a += b;
1675 EXPECT_EQ(3, a.ValueOrDie());
1676 a -= c;
1677 EXPECT_EQ(0, a.ValueOrDie());
1678 d /= b;
1679 EXPECT_EQ(2, d.ValueOrDie());
1680 d *= d;
1681 EXPECT_EQ(4, d.ValueOrDie());
1682 d *= 0.5;
1683 EXPECT_EQ(2, d.ValueOrDie());
1684
1685 CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
1686 EXPECT_TRUE(too_large.IsValid());
1687 too_large += d;
1688 EXPECT_FALSE(too_large.IsValid());
1689 too_large -= d;
1690 EXPECT_FALSE(too_large.IsValid());
1691 too_large /= d;
1692 EXPECT_FALSE(too_large.IsValid());
1693 }
1694
TEST(SafeNumerics,TemplatedSafeMath)1695 TEST(SafeNumerics, TemplatedSafeMath) {
1696 // CheckMul and friends can be confusing, as they change behavior depending on
1697 // where the template is specified.
1698 uint64_t result;
1699 short short_one_thousand = 1000;
1700 // In this case, CheckMul uses template deduction to use the <short> variant,
1701 // and this will overflow even if assigned to a uint64_t.
1702 EXPECT_FALSE(CheckMul(short_one_thousand, short_one_thousand)
1703 .AssignIfValid<uint64_t>(&result));
1704 EXPECT_FALSE(CheckMul(short_one_thousand, short_one_thousand).IsValid());
1705 // In both cases, CheckMul is forced to use the uint64_t template and will not
1706 // overflow.
1707 EXPECT_TRUE(CheckMul<uint64_t>(short_one_thousand, short_one_thousand)
1708 .AssignIfValid(&result));
1709 EXPECT_TRUE(CheckMul<uint64_t>(short_one_thousand, short_one_thousand)
1710 .AssignIfValid<uint64_t>(&result));
1711
1712 uint64_t big_one_thousand = 1000u;
1713 // Order doesn't matter here: if one of the parameters is uint64_t then the
1714 // operation is done on a uint64_t.
1715 EXPECT_TRUE(
1716 CheckMul(big_one_thousand, short_one_thousand).AssignIfValid(&result));
1717 EXPECT_TRUE(
1718 CheckMul(short_one_thousand, big_one_thousand).AssignIfValid(&result));
1719
1720 // Checked math functions can also take two template type parameters. Here are
1721 // the results of all four combinations.
1722 EXPECT_TRUE((CheckMul<short, uint64_t>(1000, 1000).AssignIfValid(&result)));
1723
1724 // Note: Order here does not matter.
1725 EXPECT_TRUE((CheckMul<uint64_t, short>(1000, 1000).AssignIfValid(&result)));
1726
1727 // Only if both are short will the operation be invalid.
1728 EXPECT_FALSE((CheckMul<short, short>(1000, 1000).AssignIfValid(&result)));
1729
1730 // Same as above.
1731 EXPECT_TRUE(
1732 (CheckMul<uint64_t, uint64_t>(1000, 1000).AssignIfValid(&result)));
1733 }
1734
TEST(SafeNumerics,VariadicNumericOperations)1735 TEST(SafeNumerics, VariadicNumericOperations) {
1736 { // Synthetic scope to avoid variable naming collisions.
1737 auto a = CheckAdd(1, 2UL, MakeCheckedNum(3LL), 4).ValueOrDie();
1738 EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
1739 auto b = CheckSub(MakeCheckedNum(20.0), 2UL, 4).ValueOrDie();
1740 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
1741 auto c = CheckMul(20.0, MakeCheckedNum(1), 5, 3UL).ValueOrDie();
1742 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
1743 auto d = CheckDiv(20.0, 2.0, MakeCheckedNum(5LL), -4).ValueOrDie();
1744 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
1745 auto e = CheckMod(MakeCheckedNum(20), 3).ValueOrDie();
1746 EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
1747 auto f = CheckLsh(1, MakeCheckedNum(2)).ValueOrDie();
1748 EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
1749 auto g = CheckRsh(4, MakeCheckedNum(2)).ValueOrDie();
1750 EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
1751 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
1752 EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
1753 }
1754
1755 {
1756 auto a = ClampAdd(1, 2UL, MakeClampedNum(3LL), 4);
1757 EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
1758 auto b = ClampSub(MakeClampedNum(20.0), 2UL, 4);
1759 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
1760 auto c = ClampMul(20.0, MakeClampedNum(1), 5, 3UL);
1761 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
1762 auto d = ClampDiv(20.0, 2.0, MakeClampedNum(5LL), -4);
1763 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
1764 auto e = ClampMod(MakeClampedNum(20), 3);
1765 EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
1766 auto f = ClampLsh(1, MakeClampedNum(2U));
1767 EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
1768 auto g = ClampRsh(4, MakeClampedNum(2U));
1769 EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
1770 auto h = ClampRsh(ClampAdd(1, 1, 1, 1), ClampSub(4U, 2));
1771 EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
1772 }
1773 }
1774
TEST(SafeNumerics,CeilInt)1775 TEST(SafeNumerics, CeilInt) {
1776 constexpr float kMax = static_cast<float>(std::numeric_limits<int>::max());
1777 constexpr float kMin = std::numeric_limits<int>::min();
1778 constexpr float kInfinity = std::numeric_limits<float>::infinity();
1779 constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();
1780
1781 constexpr int kIntMax = std::numeric_limits<int>::max();
1782 constexpr int kIntMin = std::numeric_limits<int>::min();
1783
1784 EXPECT_EQ(kIntMax, ClampCeil(kInfinity));
1785 EXPECT_EQ(kIntMax, ClampCeil(kMax));
1786 EXPECT_EQ(kIntMax, ClampCeil(kMax + 100.0f));
1787 EXPECT_EQ(0, ClampCeil(kNaN));
1788
1789 EXPECT_EQ(-100, ClampCeil(-100.5f));
1790 EXPECT_EQ(0, ClampCeil(0.0f));
1791 EXPECT_EQ(101, ClampCeil(100.5f));
1792
1793 EXPECT_EQ(kIntMin, ClampCeil(-kInfinity));
1794 EXPECT_EQ(kIntMin, ClampCeil(kMin));
1795 EXPECT_EQ(kIntMin, ClampCeil(kMin - 100.0f));
1796 EXPECT_EQ(0, ClampCeil(-kNaN));
1797 }
1798
TEST(SafeNumerics,FloorInt)1799 TEST(SafeNumerics, FloorInt) {
1800 constexpr float kMax = static_cast<float>(std::numeric_limits<int>::max());
1801 constexpr float kMin = std::numeric_limits<int>::min();
1802 constexpr float kInfinity = std::numeric_limits<float>::infinity();
1803 constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();
1804
1805 constexpr int kIntMax = std::numeric_limits<int>::max();
1806 constexpr int kIntMin = std::numeric_limits<int>::min();
1807
1808 EXPECT_EQ(kIntMax, ClampFloor(kInfinity));
1809 EXPECT_EQ(kIntMax, ClampFloor(kMax));
1810 EXPECT_EQ(kIntMax, ClampFloor(kMax + 100.0f));
1811 EXPECT_EQ(0, ClampFloor(kNaN));
1812
1813 EXPECT_EQ(-101, ClampFloor(-100.5f));
1814 EXPECT_EQ(0, ClampFloor(0.0f));
1815 EXPECT_EQ(100, ClampFloor(100.5f));
1816
1817 EXPECT_EQ(kIntMin, ClampFloor(-kInfinity));
1818 EXPECT_EQ(kIntMin, ClampFloor(kMin));
1819 EXPECT_EQ(kIntMin, ClampFloor(kMin - 100.0f));
1820 EXPECT_EQ(0, ClampFloor(-kNaN));
1821 }
1822
TEST(SafeNumerics,RoundInt)1823 TEST(SafeNumerics, RoundInt) {
1824 constexpr float kMax = static_cast<float>(std::numeric_limits<int>::max());
1825 constexpr float kMin = std::numeric_limits<int>::min();
1826 constexpr float kInfinity = std::numeric_limits<float>::infinity();
1827 constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();
1828
1829 constexpr int kIntMax = std::numeric_limits<int>::max();
1830 constexpr int kIntMin = std::numeric_limits<int>::min();
1831
1832 EXPECT_EQ(kIntMax, ClampRound(kInfinity));
1833 EXPECT_EQ(kIntMax, ClampRound(kMax));
1834 EXPECT_EQ(kIntMax, ClampRound(kMax + 100.0f));
1835 EXPECT_EQ(0, ClampRound(kNaN));
1836
1837 EXPECT_EQ(-100, ClampRound(-100.1f));
1838 EXPECT_EQ(-101, ClampRound(-100.5f));
1839 EXPECT_EQ(-101, ClampRound(-100.9f));
1840 EXPECT_EQ(0, ClampRound(std::nextafter(-0.5f, 0.0f)));
1841 EXPECT_EQ(0, ClampRound(0.0f));
1842 EXPECT_EQ(0, ClampRound(std::nextafter(0.5f, 0.0f)));
1843 EXPECT_EQ(100, ClampRound(100.1f));
1844 EXPECT_EQ(101, ClampRound(100.5f));
1845 EXPECT_EQ(101, ClampRound(100.9f));
1846
1847 EXPECT_EQ(kIntMin, ClampRound(-kInfinity));
1848 EXPECT_EQ(kIntMin, ClampRound(kMin));
1849 EXPECT_EQ(kIntMin, ClampRound(kMin - 100.0f));
1850 EXPECT_EQ(0, ClampRound(-kNaN));
1851 }
1852
TEST(SafeNumerics,Int64)1853 TEST(SafeNumerics, Int64) {
1854 constexpr double kMax =
1855 static_cast<double>(std::numeric_limits<int64_t>::max());
1856 constexpr double kMin = std::numeric_limits<int64_t>::min();
1857 constexpr double kInfinity = std::numeric_limits<double>::infinity();
1858 constexpr double kNaN = std::numeric_limits<double>::quiet_NaN();
1859
1860 constexpr int64_t kInt64Max = std::numeric_limits<int64_t>::max();
1861 constexpr int64_t kInt64Min = std::numeric_limits<int64_t>::min();
1862
1863 EXPECT_EQ(kInt64Max, ClampFloor<int64_t>(kInfinity));
1864 EXPECT_EQ(kInt64Max, ClampCeil<int64_t>(kInfinity));
1865 EXPECT_EQ(kInt64Max, ClampRound<int64_t>(kInfinity));
1866 EXPECT_EQ(kInt64Max, ClampFloor<int64_t>(kMax));
1867 EXPECT_EQ(kInt64Max, ClampCeil<int64_t>(kMax));
1868 EXPECT_EQ(kInt64Max, ClampRound<int64_t>(kMax));
1869 EXPECT_EQ(kInt64Max, ClampFloor<int64_t>(kMax + 100.0));
1870 EXPECT_EQ(kInt64Max, ClampCeil<int64_t>(kMax + 100.0));
1871 EXPECT_EQ(kInt64Max, ClampRound<int64_t>(kMax + 100.0));
1872 EXPECT_EQ(0, ClampFloor<int64_t>(kNaN));
1873 EXPECT_EQ(0, ClampCeil<int64_t>(kNaN));
1874 EXPECT_EQ(0, ClampRound<int64_t>(kNaN));
1875
1876 EXPECT_EQ(kInt64Min, ClampFloor<int64_t>(-kInfinity));
1877 EXPECT_EQ(kInt64Min, ClampCeil<int64_t>(-kInfinity));
1878 EXPECT_EQ(kInt64Min, ClampRound<int64_t>(-kInfinity));
1879 EXPECT_EQ(kInt64Min, ClampFloor<int64_t>(kMin));
1880 EXPECT_EQ(kInt64Min, ClampCeil<int64_t>(kMin));
1881 EXPECT_EQ(kInt64Min, ClampRound<int64_t>(kMin));
1882 EXPECT_EQ(kInt64Min, ClampFloor<int64_t>(kMin - 100.0));
1883 EXPECT_EQ(kInt64Min, ClampCeil<int64_t>(kMin - 100.0));
1884 EXPECT_EQ(kInt64Min, ClampRound<int64_t>(kMin - 100.0));
1885 EXPECT_EQ(0, ClampFloor<int64_t>(-kNaN));
1886 EXPECT_EQ(0, ClampCeil<int64_t>(-kNaN));
1887 EXPECT_EQ(0, ClampRound<int64_t>(-kNaN));
1888 }
1889
1890 template <typename T>
TestWrappingMathSigned()1891 void TestWrappingMathSigned() {
1892 static_assert(std::is_signed_v<T>);
1893 constexpr T kMinusTwo = -2;
1894 constexpr T kMinusOne = -1;
1895 constexpr T kZero = 0;
1896 constexpr T kOne = 1;
1897 constexpr T kTwo = 2;
1898 constexpr T kThree = 3;
1899 constexpr T kMax = std::numeric_limits<T>::max();
1900 constexpr T kMin = std::numeric_limits<T>::min();
1901
1902 EXPECT_EQ(base::WrappingAdd(kOne, kTwo), kThree);
1903 static_assert(base::WrappingAdd(kOne, kTwo) == kThree);
1904 EXPECT_EQ(base::WrappingAdd(kMax, kOne), kMin);
1905 static_assert(base::WrappingAdd(kMax, kOne) == kMin);
1906 EXPECT_EQ(base::WrappingAdd(kMax, kTwo), kMin + 1);
1907 static_assert(base::WrappingAdd(kMax, kTwo) == kMin + 1);
1908 EXPECT_EQ(base::WrappingAdd(kMax, kMax), kMinusTwo);
1909 static_assert(base::WrappingAdd(kMax, kMax) == kMinusTwo);
1910 EXPECT_EQ(base::WrappingAdd(kMin, kMin), kZero);
1911 static_assert(base::WrappingAdd(kMin, kMin) == kZero);
1912
1913 EXPECT_EQ(base::WrappingSub(kTwo, kOne), kOne);
1914 static_assert(base::WrappingSub(kTwo, kOne) == kOne);
1915 EXPECT_EQ(base::WrappingSub(kOne, kTwo), kMinusOne);
1916 static_assert(base::WrappingSub(kOne, kTwo) == kMinusOne);
1917 EXPECT_EQ(base::WrappingSub(kMin, kOne), kMax);
1918 static_assert(base::WrappingSub(kMin, kOne) == kMax);
1919 EXPECT_EQ(base::WrappingSub(kMin, kTwo), kMax - 1);
1920 static_assert(base::WrappingSub(kMin, kTwo) == kMax - 1);
1921 EXPECT_EQ(base::WrappingSub(kMax, kMin), kMinusOne);
1922 static_assert(base::WrappingSub(kMax, kMin) == kMinusOne);
1923 EXPECT_EQ(base::WrappingSub(kMin, kMax), kOne);
1924 static_assert(base::WrappingSub(kMin, kMax) == kOne);
1925 }
1926
1927 template <typename T>
TestWrappingMathUnsigned()1928 void TestWrappingMathUnsigned() {
1929 static_assert(std::is_unsigned_v<T>);
1930 constexpr T kZero = 0;
1931 constexpr T kOne = 1;
1932 constexpr T kTwo = 2;
1933 constexpr T kThree = 3;
1934 constexpr T kMax = std::numeric_limits<T>::max();
1935
1936 EXPECT_EQ(base::WrappingAdd(kOne, kTwo), kThree);
1937 static_assert(base::WrappingAdd(kOne, kTwo) == kThree);
1938 EXPECT_EQ(base::WrappingAdd(kMax, kOne), kZero);
1939 static_assert(base::WrappingAdd(kMax, kOne) == kZero);
1940 EXPECT_EQ(base::WrappingAdd(kMax, kTwo), kOne);
1941 static_assert(base::WrappingAdd(kMax, kTwo) == kOne);
1942 EXPECT_EQ(base::WrappingAdd(kMax, kMax), kMax - 1);
1943 static_assert(base::WrappingAdd(kMax, kMax) == kMax - 1);
1944
1945 EXPECT_EQ(base::WrappingSub(kTwo, kOne), kOne);
1946 static_assert(base::WrappingSub(kTwo, kOne) == kOne);
1947 EXPECT_EQ(base::WrappingSub(kOne, kTwo), kMax);
1948 static_assert(base::WrappingSub(kOne, kTwo) == kMax);
1949 EXPECT_EQ(base::WrappingSub(kZero, kOne), kMax);
1950 static_assert(base::WrappingSub(kZero, kOne) == kMax);
1951 EXPECT_EQ(base::WrappingSub(kZero, kTwo), kMax - 1);
1952 static_assert(base::WrappingSub(kZero, kTwo) == kMax - 1);
1953 }
1954
TEST(SafeNumerics,WrappingMath)1955 TEST(SafeNumerics, WrappingMath) {
1956 TestWrappingMathSigned<int8_t>();
1957 TestWrappingMathUnsigned<uint8_t>();
1958 TestWrappingMathSigned<int16_t>();
1959 TestWrappingMathUnsigned<uint16_t>();
1960 TestWrappingMathSigned<int32_t>();
1961 TestWrappingMathUnsigned<uint32_t>();
1962 TestWrappingMathSigned<int64_t>();
1963 TestWrappingMathUnsigned<uint64_t>();
1964 }
1965
1966 #if defined(__clang__)
1967 #pragma clang diagnostic pop // -Winteger-overflow
1968 #endif
1969
1970 } // namespace internal
1971 } // namespace base
1972