blob: cb92cf3e32a98e4616748a69040dc4a948a2d13f [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2013 The Chromium Authors
[email protected]c1c090d32013-01-16 23:34:042// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avi9b6f42932015-12-26 22:15:145#include <stddef.h>
[email protected]4efb2c32014-01-16 06:57:256#include <stdint.h>
7
8#include <limits>
vmpstr98a2fad2015-11-30 20:15:179#include <type_traits>
[email protected]4efb2c32014-01-16 06:57:2510
11#include "base/compiler_specific.h"
Peter Kastingfbb9e562021-06-27 02:57:3712#include "build/build_config.h"
Justin Schuhaeed1e42017-08-01 19:46:4313
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.
Xiaohan Wang38e4ebb2022-01-19 06:57:4317#if BUILDFLAG(IS_WIN)
Justin Schuhaeed1e42017-08-01 19:46:4318#pragma warning(disable : 4756) // Arithmetic overflow.
19#pragma warning(disable : 4293) // Invalid shift.
20#endif
21
Mostyn Bramley-Moore2c1339ee72018-03-28 21:10:0422// 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
jschuh224f1d72016-11-25 20:08:4829#include "base/logging.h"
[email protected]5bfecbc2014-02-27 13:49:0430#include "base/numerics/safe_conversions.h"
31#include "base/numerics/safe_math.h"
gab190f7542016-08-01 20:03:4132#include "base/test/gtest_util.h"
[email protected]4efb2c32014-01-16 06:57:2533#include "testing/gtest/include/gtest/gtest.h"
34
avi9b6f42932015-12-26 22:15:1435#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
36#include <mmintrin.h>
37#endif
38
Justin Schuha26da272017-07-13 23:04:3039namespace base {
40namespace internal {
41
[email protected]5bfecbc2014-02-27 13:49:0442using std::numeric_limits;
[email protected]5bfecbc2014-02-27 13:49:0443
jschuhfafe0712015-09-14 20:21:2444// This is a helper function for finding the maximum value in Src that can be
45// wholy represented as the destination floating-point type.
46template <typename Dst, typename Src>
47Dst GetMaxConvertibleToFloat() {
jschuh5030b002016-12-05 18:21:4848 using DstLimits = numeric_limits<Dst>;
49 using SrcLimits = numeric_limits<Src>;
jschuhfafe0712015-09-14 20:21:2450 static_assert(SrcLimits::is_specialized, "Source must be numeric.");
51 static_assert(DstLimits::is_specialized, "Destination must be numeric.");
52 CHECK(DstLimits::is_iec559);
53
54 if (SrcLimits::digits <= DstLimits::digits &&
55 MaxExponent<Src>::value <= MaxExponent<Dst>::value)
56 return SrcLimits::max();
57 Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
58 while (max != static_cast<Src>(static_cast<Dst>(max))) {
59 max /= 2;
60 }
61 return static_cast<Dst>(max);
62}
63
jschuh33232e02017-01-03 20:33:3664// Test corner case promotions used
65static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int8_t>::value, "");
66static_assert(IsIntegerArithmeticSafe<int32_t, int16_t, int8_t>::value, "");
67static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int16_t>::value, "");
68static_assert(!IsIntegerArithmeticSafe<int32_t, int32_t, int8_t>::value, "");
69static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
70static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
71static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
72static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
73static_assert(
74 std::is_same<BigEnoughPromotion<int16_t, int8_t>::type, int16_t>::value,
75 "");
76static_assert(
77 std::is_same<BigEnoughPromotion<int32_t, uint32_t>::type, int64_t>::value,
78 "");
79static_assert(
80 std::is_same<BigEnoughPromotion<intmax_t, int8_t>::type, intmax_t>::value,
81 "");
82static_assert(
83 std::is_same<BigEnoughPromotion<uintmax_t, int8_t>::type, uintmax_t>::value,
84 "");
85static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
86static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
87static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
88static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
89static_assert(
90 std::is_same<FastIntegerArithmeticPromotion<int16_t, int8_t>::type,
91 int32_t>::value,
92 "");
93static_assert(
94 std::is_same<FastIntegerArithmeticPromotion<int32_t, uint32_t>::type,
95 int64_t>::value,
96 "");
97static_assert(
98 std::is_same<FastIntegerArithmeticPromotion<intmax_t, int8_t>::type,
99 intmax_t>::value,
100 "");
101static_assert(
102 std::is_same<FastIntegerArithmeticPromotion<uintmax_t, int8_t>::type,
103 uintmax_t>::value,
104 "");
105static_assert(FastIntegerArithmeticPromotion<int16_t, int8_t>::is_contained,
106 "");
107static_assert(FastIntegerArithmeticPromotion<int32_t, uint32_t>::is_contained,
108 "");
109static_assert(!FastIntegerArithmeticPromotion<intmax_t, int8_t>::is_contained,
110 "");
111static_assert(!FastIntegerArithmeticPromotion<uintmax_t, int8_t>::is_contained,
112 "");
113
Justin Schuhe2eefe612022-01-13 22:48:50114// Test compile-time (constexpr) evaluation of checking and saturation.
115constexpr int32_t kIntOne = 1;
116static_assert(1 == checked_cast<uint8_t>(kIntOne), "");
117static_assert(1 == saturated_cast<uint8_t>(kIntOne), "");
118static_assert(2U == MakeClampedNum(kIntOne) + 1, "");
119static_assert(2U == (MakeCheckedNum(kIntOne) + 1).ValueOrDie(), "");
120static_assert(0U == MakeClampedNum(kIntOne) - 1, "");
121static_assert(0U == (MakeCheckedNum(kIntOne) - 1).ValueOrDie(), "");
122static_assert(-1 == -MakeClampedNum(kIntOne), "");
123static_assert(-1 == (-MakeCheckedNum(kIntOne)).ValueOrDie(), "");
124static_assert(1U == MakeClampedNum(kIntOne) * 1, "");
125static_assert(1U == (MakeCheckedNum(kIntOne) * 1).ValueOrDie(), "");
126static_assert(1U == MakeClampedNum(kIntOne) / 1, "");
127static_assert(1U == (MakeCheckedNum(kIntOne) / 1).ValueOrDie(), "");
128static_assert(1 == MakeClampedNum(-kIntOne).Abs(), "");
129static_assert(1 == MakeCheckedNum(-kIntOne).Abs().ValueOrDie(), "");
130static_assert(1U == MakeClampedNum(kIntOne) % 2, "");
131static_assert(1U == (MakeCheckedNum(kIntOne) % 2).ValueOrDie(), "");
132static_assert(0U == MakeClampedNum(kIntOne) >> 1U, "");
133static_assert(0U == (MakeCheckedNum(kIntOne) >> 1U).ValueOrDie(), "");
134static_assert(2U == MakeClampedNum(kIntOne) << 1U, "");
135static_assert(2U == (MakeCheckedNum(kIntOne) << 1U).ValueOrDie(), "");
136static_assert(1 == MakeClampedNum(kIntOne) & 1U, "");
137static_assert(1 == (MakeCheckedNum(kIntOne) & 1U).ValueOrDie(), "");
138static_assert(1 == MakeClampedNum(kIntOne) | 1U, "");
139static_assert(1 == (MakeCheckedNum(kIntOne) | 1U).ValueOrDie(), "");
140static_assert(0 == MakeClampedNum(kIntOne) ^ 1U, "");
141static_assert(0 == (MakeCheckedNum(kIntOne) ^ 1U).ValueOrDie(), "");
142constexpr float kFloatOne = 1.0;
143static_assert(1 == int{checked_cast<int8_t>(kFloatOne)}, "");
144static_assert(1 == int{saturated_cast<int8_t>(kFloatOne)}, "");
145static_assert(2U == unsigned{MakeClampedNum(kFloatOne) + 1}, "");
146static_assert(2U ==
147 (MakeCheckedNum(kFloatOne) + 1).Cast<unsigned>().ValueOrDie(),
148 "");
149static_assert(0U == unsigned{MakeClampedNum(kFloatOne) - 1}, "");
150static_assert(0U ==
151 (MakeCheckedNum(kFloatOne) - 1).Cast<unsigned>().ValueOrDie(),
152 "");
153static_assert(-1 == int{-MakeClampedNum(kFloatOne)}, "");
154static_assert(-1 == (-MakeCheckedNum(kFloatOne)).Cast<int>().ValueOrDie(), "");
155static_assert(1U == unsigned{MakeClampedNum(kFloatOne) * 1}, "");
156static_assert(1U ==
157 (MakeCheckedNum(kFloatOne) * 1).Cast<unsigned>().ValueOrDie(),
158 "");
159static_assert(1U == unsigned{MakeClampedNum(kFloatOne) / 1}, "");
160static_assert(1U ==
161 (MakeCheckedNum(kFloatOne) / 1).Cast<unsigned>().ValueOrDie(),
162 "");
163static_assert(1 == int{MakeClampedNum(-kFloatOne).Abs()}, "");
164static_assert(1 == MakeCheckedNum(-kFloatOne).Abs().Cast<int>().ValueOrDie(),
165 "");
166
jschuhd1c1f2e2016-11-21 21:45:48167template <typename U>
168U GetNumericValueForTest(const CheckedNumeric<U>& src) {
169 return src.state_.value();
170}
jschuhb180f392017-07-03 15:09:22171
172template <typename U>
173U GetNumericValueForTest(const ClampedNumeric<U>& src) {
174 return static_cast<U>(src);
175}
176
177template <typename U>
178U GetNumericValueForTest(const U& src) {
179 return src;
180}
181
jschuh224f1d72016-11-25 20:08:48182// Logs the ValueOrDie() failure instead of crashing.
183struct LogOnFailure {
184 template <typename T>
185 static T HandleFailure() {
186 LOG(WARNING) << "ValueOrDie() failed unexpectedly.";
187 return T();
188 }
189};
190
jschuhb180f392017-07-03 15:09:22191template <typename T>
192constexpr T GetValue(const T& src) {
193 return src;
194}
195
196template <typename T, typename U>
197constexpr T GetValueAsDest(const U& src) {
198 return static_cast<T>(src);
199}
200
201template <typename T>
202constexpr T GetValue(const CheckedNumeric<T>& src) {
203 return src.template ValueOrDie<T, LogOnFailure>();
204}
205
206template <typename T, typename U>
207constexpr T GetValueAsDest(const CheckedNumeric<U>& src) {
208 return src.template ValueOrDie<T, LogOnFailure>();
209}
210
211template <typename T>
212constexpr T GetValue(const ClampedNumeric<T>& src) {
213 return static_cast<T>(src);
214}
215
216template <typename T, typename U>
217constexpr T GetValueAsDest(const ClampedNumeric<U>& src) {
218 return static_cast<T>(src);
219}
220
[email protected]5bfecbc2014-02-27 13:49:04221// Helper macros to wrap displaying the conversion types and line numbers.
222#define TEST_EXPECTED_VALIDITY(expected, actual) \
jschuh4fcd6fa2016-11-24 11:58:39223 EXPECT_EQ(expected, (actual).template Cast<Dst>().IsValid()) \
jschuhd1c1f2e2016-11-21 21:45:48224 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
225 << dst << " on line " << line
[email protected]5bfecbc2014-02-27 13:49:04226
jschuh819c8262016-05-21 01:39:03227#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
228#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
229
jschuhba3c4f942016-12-10 14:03:55230// We have to handle promotions, so infer the underlying type below from actual.
231#define TEST_EXPECTED_VALUE(expected, actual) \
jschuhb180f392017-07-03 15:09:22232 EXPECT_EQ(GetValue(expected), GetValueAsDest<decltype(expected)>(actual)) \
jschuhba3c4f942016-12-10 14:03:55233 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
jschuhd1c1f2e2016-11-21 21:45:48234 << dst << " on line " << line
[email protected]5bfecbc2014-02-27 13:49:04235
jschuh23a4b062016-12-02 02:55:08236// Test the simple pointer arithmetic overrides.
237template <typename Dst>
238void TestStrictPointerMath() {
239 Dst dummy_value = 0;
240 Dst* dummy_ptr = &dummy_value;
241 static const Dst kDummyOffset = 2; // Don't want to go too far.
242 EXPECT_EQ(dummy_ptr + kDummyOffset,
243 dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
244 EXPECT_EQ(dummy_ptr - kDummyOffset,
245 dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
246 EXPECT_NE(dummy_ptr, dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
247 EXPECT_NE(dummy_ptr, dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
248 EXPECT_DEATH_IF_SUPPORTED(
249 dummy_ptr + StrictNumeric<size_t>(std::numeric_limits<size_t>::max()),
250 "");
251}
252
[email protected]5bfecbc2014-02-27 13:49:04253// Signed integer arithmetic.
254template <typename Dst>
255static void TestSpecializedArithmetic(
256 const char* dst,
257 int line,
vmpstr98a2fad2015-11-30 20:15:17258 typename std::enable_if<numeric_limits<Dst>::is_integer &&
259 numeric_limits<Dst>::is_signed,
260 int>::type = 0) {
jschuhb180f392017-07-03 15:09:22261 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:48262 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::lowest()));
263 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
[email protected]5bfecbc2014-02-27 13:49:04264 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
jschuhba3c4f942016-12-10 14:03:55265 TEST_EXPECTED_VALUE(DstLimits::max(),
266 MakeCheckedNum(-DstLimits::max()).Abs());
[email protected]5bfecbc2014-02-27 13:49:04267
jschuhb180f392017-07-03 15:09:22268 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
269 -ClampedNumeric<Dst>(DstLimits::lowest()));
270 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
271 ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
272 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).Abs());
273 TEST_EXPECTED_VALUE(DstLimits::max(),
274 MakeClampedNum(-DstLimits::max()).Abs());
275
jschuh819c8262016-05-21 01:39:03276 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
jschuh5030b002016-12-05 18:21:48277 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
278 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
279 DstLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:04280
jschuhb180f392017-07-03 15:09:22281 TEST_EXPECTED_VALUE(DstLimits::max() - 1,
282 ClampedNumeric<Dst>(DstLimits::max()) + -1);
283 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
284 ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
285 TEST_EXPECTED_VALUE(
286 DstLimits::Underflow(),
287 ClampedNumeric<Dst>(DstLimits::lowest()) + DstLimits::lowest());
288
jschuh5030b002016-12-05 18:21:48289 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
290 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) - -1);
jschuh819c8262016-05-21 01:39:03291 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
jschuh5030b002016-12-05 18:21:48292 DstLimits::lowest());
293 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
jschuh819c8262016-05-21 01:39:03294 DstLimits::max());
[email protected]5bfecbc2014-02-27 13:49:04295
jschuhb180f392017-07-03 15:09:22296 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
297 ClampedNumeric<Dst>(DstLimits::lowest()) - 1);
298 TEST_EXPECTED_VALUE(DstLimits::lowest() + 1,
299 ClampedNumeric<Dst>(DstLimits::lowest()) - -1);
300 TEST_EXPECTED_VALUE(
301 DstLimits::Overflow(),
302 ClampedNumeric<Dst>(DstLimits::max()) - DstLimits::lowest());
303 TEST_EXPECTED_VALUE(
304 DstLimits::Underflow(),
305 ClampedNumeric<Dst>(DstLimits::lowest()) - DstLimits::max());
306
jschuh5030b002016-12-05 18:21:48307 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
jschuhb180f392017-07-03 15:09:22308 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
309 ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
[email protected]5bfecbc2014-02-27 13:49:04310
jschuh5030b002016-12-05 18:21:48311 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) / -1);
[email protected]5bfecbc2014-02-27 13:49:04312 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
jschuh5030b002016-12-05 18:21:48313 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * -1);
jschuh33232e02017-01-03 20:33:36314 TEST_EXPECTED_VALUE(DstLimits::max(),
315 CheckedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
316 TEST_EXPECTED_VALUE(DstLimits::max(),
317 CheckedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
318 TEST_EXPECTED_VALUE(DstLimits::lowest(),
319 CheckedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
320 TEST_EXPECTED_VALUE(DstLimits::lowest(),
321 CheckedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
jschuhb180f392017-07-03 15:09:22322 TEST_EXPECTED_VALUE(
323 typename std::make_unsigned<Dst>::type(0) - DstLimits::lowest(),
324 MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
jschuhba3c4f942016-12-10 14:03:55325 TEST_EXPECTED_VALUE(DstLimits::max(),
326 MakeCheckedNum(DstLimits::max()).UnsignedAbs());
327 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
328 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
329 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).UnsignedAbs());
[email protected]5bfecbc2014-02-27 13:49:04330
jschuhb180f392017-07-03 15:09:22331 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
332 ClampedNumeric<Dst>(DstLimits::lowest()) / -1);
333 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) / 2);
334 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
335 ClampedNumeric<Dst>(DstLimits::lowest()) * -1);
336 TEST_EXPECTED_VALUE(DstLimits::max(),
337 ClampedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
338 TEST_EXPECTED_VALUE(DstLimits::max(),
339 ClampedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
340 TEST_EXPECTED_VALUE(DstLimits::lowest(),
341 ClampedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
342 TEST_EXPECTED_VALUE(DstLimits::lowest(),
343 ClampedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
344 TEST_EXPECTED_VALUE(
345 typename std::make_unsigned<Dst>::type(0) - DstLimits::lowest(),
346 MakeClampedNum(DstLimits::lowest()).UnsignedAbs());
347 TEST_EXPECTED_VALUE(DstLimits::max(),
348 MakeClampedNum(DstLimits::max()).UnsignedAbs());
349 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0).UnsignedAbs());
350 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).UnsignedAbs());
351 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).UnsignedAbs());
352
[email protected]5bfecbc2014-02-27 13:49:04353 // Modulus is legal only for integers.
Tom Sepezfe88d4192020-05-28 16:41:05354 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % 2);
355 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % 1);
356 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % -1);
357 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % -2);
358 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
[email protected]5bfecbc2014-02-27 13:49:04359 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
Tom Sepezfe88d4192020-05-28 16:41:05360 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % -1);
361 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % -2);
[email protected]5bfecbc2014-02-27 13:49:04362 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05363 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) % 1);
364 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) % -1);
jschuhb180f392017-07-03 15:09:22365 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % -2);
jschuh5030b002016-12-05 18:21:48366 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05367 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 1);
368 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % -1);
369 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % -2);
[email protected]5bfecbc2014-02-27 13:49:04370 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05371 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::max()) % 1);
372 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::max()) % -1);
373 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % -2);
[email protected]5bfecbc2014-02-27 13:49:04374 // Test all the different modulus combinations.
375 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
376 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
377 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
378 CheckedNumeric<Dst> checked_dst = 1;
379 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
tsepezdfd77a92016-11-02 20:18:06380 // Test that div by 0 is avoided but returns invalid result.
381 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
jschuh3ab54042016-11-17 06:58:44382 // Test bit shifts.
383 volatile Dst negative_one = -1;
384 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
jschuh5030b002016-12-05 18:21:48385 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
386 << (IntegerBitsPlusSign<Dst>::value - 1));
387 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
388 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44389 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
jschuh5030b002016-12-05 18:21:48390 TEST_EXPECTED_VALUE(
391 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2),
392 CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2));
jschuh3ab54042016-11-17 06:58:44393 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0)
jschuh5030b002016-12-05 18:21:48394 << (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44395 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
396 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
jschuh5030b002016-12-05 18:21:48397 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
398 IntegerBitsPlusSign<Dst>::value);
399 TEST_EXPECTED_VALUE(
400 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44401 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
jschuh23a4b062016-12-02 02:55:08402
jschuhb180f392017-07-03 15:09:22403 // Modulus is legal only for integers.
Tom Sepezfe88d4192020-05-28 16:41:05404 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % 2);
405 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % 1);
406 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % -1);
407 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % -2);
408 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % 2);
jschuhb180f392017-07-03 15:09:22409 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
Tom Sepezfe88d4192020-05-28 16:41:05410 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % -1);
411 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % -2);
jschuhb180f392017-07-03 15:09:22412 TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(-1) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05413 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) % 1);
414 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) % -1);
jschuhb180f392017-07-03 15:09:22415 TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(-1) % -2);
416 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05417 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 1);
418 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % -1);
419 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % -2);
jschuhb180f392017-07-03 15:09:22420 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05421 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) % 1);
422 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) % -1);
423 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % -2);
jschuhb180f392017-07-03 15:09:22424 // Test all the different modulus combinations.
425 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % ClampedNumeric<Dst>(1));
426 TEST_EXPECTED_VALUE(0, 1 % ClampedNumeric<Dst>(1));
427 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
428 ClampedNumeric<Dst> clamped_dst = 1;
429 TEST_EXPECTED_VALUE(0, clamped_dst %= 1);
430 TEST_EXPECTED_VALUE(Dst(1), ClampedNumeric<Dst>(1) % 0);
431 // Test bit shifts.
432 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
433 ClampedNumeric<Dst>(1)
434 << (IntegerBitsPlusSign<Dst>::value - 1U));
435 TEST_EXPECTED_VALUE(Dst(0), ClampedNumeric<Dst>(0)
436 << (IntegerBitsPlusSign<Dst>::value + 0U));
437 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
438 ClampedNumeric<Dst>(DstLimits::max()) << 1U);
439 TEST_EXPECTED_VALUE(
440 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2U),
441 ClampedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2U));
442 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0)
443 << (IntegerBitsPlusSign<Dst>::value - 1U));
444 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) << 0U);
445 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) << 1U);
446 TEST_EXPECTED_VALUE(
447 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value + 0U));
448 TEST_EXPECTED_VALUE(
449 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
450 TEST_EXPECTED_VALUE(
451 -1, ClampedNumeric<Dst>(-1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
452 TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(DstLimits::lowest()) >>
453 (IntegerBitsPlusSign<Dst>::value - 0U));
454
jschuh23a4b062016-12-02 02:55:08455 TestStrictPointerMath<Dst>();
[email protected]5bfecbc2014-02-27 13:49:04456}
457
458// Unsigned integer arithmetic.
459template <typename Dst>
460static void TestSpecializedArithmetic(
461 const char* dst,
462 int line,
vmpstr98a2fad2015-11-30 20:15:17463 typename std::enable_if<numeric_limits<Dst>::is_integer &&
464 !numeric_limits<Dst>::is_signed,
465 int>::type = 0) {
jschuhb180f392017-07-03 15:09:22466 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:48467 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
468 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
469 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
470 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
471 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
[email protected]5bfecbc2014-02-27 13:49:04472 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
jschuh5030b002016-12-05 18:21:48473 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
jschuh819c8262016-05-21 01:39:03474 TEST_EXPECTED_SUCCESS(
jschuh5030b002016-12-05 18:21:48475 CheckedNumeric<typename std::make_signed<Dst>::type>(
476 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
jschuheaf375f2015-09-17 01:04:28477 .UnsignedAbs());
jschuhba3c4f942016-12-10 14:03:55478 TEST_EXPECTED_VALUE(DstLimits::lowest(),
479 MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
480 TEST_EXPECTED_VALUE(DstLimits::max(),
481 MakeCheckedNum(DstLimits::max()).UnsignedAbs());
482 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
483 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
[email protected]5bfecbc2014-02-27 13:49:04484
jschuhb180f392017-07-03 15:09:22485 TEST_EXPECTED_VALUE(0, -ClampedNumeric<Dst>(DstLimits::lowest()));
486 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
487 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
488 ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
489 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
490 ClampedNumeric<Dst>(DstLimits::lowest()) - 1);
491 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
492 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) / 2);
493 TEST_EXPECTED_VALUE(0,
494 ClampedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
495 TEST_EXPECTED_VALUE(
496 as_unsigned(
497 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest()),
498 ClampedNumeric<typename std::make_signed<Dst>::type>(
499 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
500 .UnsignedAbs());
501 TEST_EXPECTED_VALUE(DstLimits::lowest(),
502 MakeClampedNum(DstLimits::lowest()).UnsignedAbs());
503 TEST_EXPECTED_VALUE(DstLimits::max(),
504 MakeClampedNum(DstLimits::max()).UnsignedAbs());
505 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0).UnsignedAbs());
506 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).UnsignedAbs());
507
[email protected]5bfecbc2014-02-27 13:49:04508 // Modulus is legal only for integers.
509 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
510 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
511 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
jschuh5030b002016-12-05 18:21:48512 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
[email protected]5bfecbc2014-02-27 13:49:04513 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
514 // Test all the different modulus combinations.
515 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
516 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
517 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
518 CheckedNumeric<Dst> checked_dst = 1;
519 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
tsepezdfd77a92016-11-02 20:18:06520 // Test that div by 0 is avoided but returns invalid result.
521 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
jschuh5030b002016-12-05 18:21:48522 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
523 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44524 // Test bit shifts.
525 volatile int negative_one = -1;
526 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
jschuh5030b002016-12-05 18:21:48527 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
528 << IntegerBitsPlusSign<Dst>::value);
529 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
530 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44531 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
jschuh5030b002016-12-05 18:21:48532 TEST_EXPECTED_VALUE(
533 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1),
534 CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44535 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
536 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
jschuh5030b002016-12-05 18:21:48537 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
538 IntegerBitsPlusSign<Dst>::value);
539 TEST_EXPECTED_VALUE(
540 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44541 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
jschuhb6737bb2016-11-29 03:06:59542 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) & 1);
543 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
544 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) & 1);
545 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
546 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
jschuh4bc919cb52016-12-04 15:08:27547 MakeCheckedNum(DstLimits::max()) & -1);
jschuhb6737bb2016-11-29 03:06:59548 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 1);
549 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 0);
550 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) | 1);
551 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0);
552 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
553 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1));
554 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1);
555 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0);
556 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1);
557 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0);
558 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
559 CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
jschuh970313c2016-11-24 21:40:58560 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0));
jschuh23a4b062016-12-02 02:55:08561
jschuhb180f392017-07-03 15:09:22562 // Modulus is legal only for integers.
563 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() % 1);
564 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
565 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % 2);
566 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 2);
567 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % 2);
568 // Test all the different modulus combinations.
569 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % ClampedNumeric<Dst>(1));
570 TEST_EXPECTED_VALUE(0, 1 % ClampedNumeric<Dst>(1));
571 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
572 ClampedNumeric<Dst> clamped_dst = 1;
573 TEST_EXPECTED_VALUE(0, clamped_dst %= 1);
574 // Test that div by 0 is avoided but returns invalid result.
575 TEST_EXPECTED_VALUE(Dst(1), ClampedNumeric<Dst>(1) % 0);
576 // Test bit shifts.
577 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
578 ClampedNumeric<Dst>(1)
579 << as_unsigned(IntegerBitsPlusSign<Dst>::value));
580 TEST_EXPECTED_VALUE(Dst(0), ClampedNumeric<Dst>(0) << as_unsigned(
581 IntegerBitsPlusSign<Dst>::value));
582 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
583 ClampedNumeric<Dst>(DstLimits::max()) << 1U);
584 TEST_EXPECTED_VALUE(
585 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1U),
586 ClampedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1U));
587 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) << 0U);
588 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) << 1U);
589 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) >>
590 as_unsigned(IntegerBitsPlusSign<Dst>::value));
591 TEST_EXPECTED_VALUE(
592 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
593 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) & 1);
594 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) & 0);
595 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) & 1);
596 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) & 0);
597 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
598 MakeClampedNum(DstLimits::max()) & -1);
599 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) | 1);
600 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) | 0);
601 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(0) | 1);
602 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) | 0);
603 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
604 ClampedNumeric<Dst>(0) | static_cast<Dst>(-1));
605 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) ^ 1);
606 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) ^ 0);
607 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(0) ^ 1);
608 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) ^ 0);
609 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
610 ClampedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
611 TEST_EXPECTED_VALUE(DstLimits::max(), ~ClampedNumeric<Dst>(0));
612
jschuh23a4b062016-12-02 02:55:08613 TestStrictPointerMath<Dst>();
[email protected]5bfecbc2014-02-27 13:49:04614}
615
616// Floating point arithmetic.
617template <typename Dst>
618void TestSpecializedArithmetic(
619 const char* dst,
620 int line,
vmpstr98a2fad2015-11-30 20:15:17621 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
jschuhb180f392017-07-03 15:09:22622 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:48623 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
[email protected]5bfecbc2014-02-27 13:49:04624
jschuh5030b002016-12-05 18:21:48625 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
[email protected]5bfecbc2014-02-27 13:49:04626 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
627
jschuh5030b002016-12-05 18:21:48628 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
jschuh819c8262016-05-21 01:39:03629 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
jschuh5030b002016-12-05 18:21:48630 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
631 DstLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:04632
jschuh819c8262016-05-21 01:39:03633 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
jschuh5030b002016-12-05 18:21:48634 DstLimits::lowest());
635 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
jschuh819c8262016-05-21 01:39:03636 DstLimits::max());
[email protected]5bfecbc2014-02-27 13:49:04637
jschuh5030b002016-12-05 18:21:48638 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
[email protected]5bfecbc2014-02-27 13:49:04639
640 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
jschuhb180f392017-07-03 15:09:22641
642 TEST_EXPECTED_VALUE(DstLimits::max(),
643 -ClampedNumeric<Dst>(DstLimits::lowest()));
644
645 TEST_EXPECTED_VALUE(DstLimits::max(),
646 ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
647 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).Abs());
648
649 TEST_EXPECTED_VALUE(DstLimits::lowest() - 1,
650 ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
651 TEST_EXPECTED_VALUE(DstLimits::max() + 1,
652 ClampedNumeric<Dst>(DstLimits::max()) + 1);
653 TEST_EXPECTED_VALUE(
654 DstLimits::Underflow(),
655 ClampedNumeric<Dst>(DstLimits::lowest()) + DstLimits::lowest());
656
657 TEST_EXPECTED_VALUE(
658 DstLimits::Overflow(),
659 ClampedNumeric<Dst>(DstLimits::max()) - DstLimits::lowest());
660 TEST_EXPECTED_VALUE(
661 DstLimits::Underflow(),
662 ClampedNumeric<Dst>(DstLimits::lowest()) - DstLimits::max());
663
664 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
665 ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
666
667 TEST_EXPECTED_VALUE(-0.5, ClampedNumeric<Dst>(-1.0) / 2);
[email protected]5bfecbc2014-02-27 13:49:04668}
669
670// Generic arithmetic tests.
671template <typename Dst>
672static void TestArithmetic(const char* dst, int line) {
jschuhb180f392017-07-03 15:09:22673 using DstLimits = SaturationDefaultLimits<Dst>;
[email protected]5bfecbc2014-02-27 13:49:04674
Daniel Chengef817202022-08-27 09:01:15675 // Test C++17 class template argument deduction
676 static_assert(
677 std::is_same_v<Dst, typename decltype(CheckedNumeric(Dst{0}))::type>);
678 static_assert(
679 std::is_same_v<Dst, typename decltype(ClampedNumeric(Dst{0}))::type>);
680 static_assert(
681 std::is_same_v<Dst, typename decltype(StrictNumeric(Dst{0}))::type>);
682
[email protected]5bfecbc2014-02-27 13:49:04683 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
Justin Schuh5cc331de2017-07-25 18:05:22684 EXPECT_EQ(false, CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
685 DstLimits::max())
686 .IsValid());
[email protected]5bfecbc2014-02-27 13:49:04687 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
688 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
689 EXPECT_EQ(static_cast<Dst>(1),
690 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
Justin Schuh5cc331de2017-07-25 18:05:22691 DstLimits::max())
692 .ValueOrDefault(1));
[email protected]5bfecbc2014-02-27 13:49:04693
694 // Test the operator combinations.
695 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
696 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
697 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
698 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
699 TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
700 TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
701 TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
702 TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
703 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
704 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
705 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
706 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
707 CheckedNumeric<Dst> checked_dst = 1;
708 TEST_EXPECTED_VALUE(2, checked_dst += 1);
709 checked_dst = 1;
710 TEST_EXPECTED_VALUE(0, checked_dst -= 1);
711 checked_dst = 1;
712 TEST_EXPECTED_VALUE(1, checked_dst *= 1);
713 checked_dst = 1;
714 TEST_EXPECTED_VALUE(1, checked_dst /= 1);
715
jschuhb180f392017-07-03 15:09:22716 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) + ClampedNumeric<Dst>(1));
717 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) - ClampedNumeric<Dst>(1));
718 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) * ClampedNumeric<Dst>(1));
719 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / ClampedNumeric<Dst>(1));
720 TEST_EXPECTED_VALUE(2, 1 + ClampedNumeric<Dst>(1));
721 TEST_EXPECTED_VALUE(0, 1 - ClampedNumeric<Dst>(1));
722 TEST_EXPECTED_VALUE(1, 1 * ClampedNumeric<Dst>(1));
723 TEST_EXPECTED_VALUE(1, 1 / ClampedNumeric<Dst>(1));
724 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) + 1);
725 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) - 1);
726 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) * 1);
727 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / 1);
728 ClampedNumeric<Dst> clamped_dst = 1;
729 TEST_EXPECTED_VALUE(2, clamped_dst += 1);
730 clamped_dst = 1;
731 TEST_EXPECTED_VALUE(0, clamped_dst -= 1);
732 clamped_dst = 1;
733 TEST_EXPECTED_VALUE(1, clamped_dst *= 1);
734 clamped_dst = 1;
735 TEST_EXPECTED_VALUE(1, clamped_dst /= 1);
736
[email protected]5bfecbc2014-02-27 13:49:04737 // Generic negation.
jschuh749c7f72016-09-07 16:22:26738 if (DstLimits::is_signed) {
739 TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
740 TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
741 TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
742 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
743 -CheckedNumeric<Dst>(DstLimits::max()));
jschuhb180f392017-07-03 15:09:22744
745 TEST_EXPECTED_VALUE(0, -ClampedNumeric<Dst>());
746 TEST_EXPECTED_VALUE(-1, -ClampedNumeric<Dst>(1));
747 TEST_EXPECTED_VALUE(1, -ClampedNumeric<Dst>(-1));
748 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
749 -ClampedNumeric<Dst>(DstLimits::max()));
Justin Schuha15cf3c2017-07-14 23:16:58750
751 // The runtime paths for saturated negation differ significantly from what
752 // gets evaluated at compile-time. Making this test volatile forces the
753 // compiler to generate code rather than fold constant expressions.
754 volatile Dst value = Dst(0);
755 TEST_EXPECTED_VALUE(0, -MakeClampedNum(value));
756 value = Dst(1);
757 TEST_EXPECTED_VALUE(-1, -MakeClampedNum(value));
758 value = Dst(2);
759 TEST_EXPECTED_VALUE(-2, -MakeClampedNum(value));
760 value = Dst(-1);
761 TEST_EXPECTED_VALUE(1, -MakeClampedNum(value));
762 value = Dst(-2);
763 TEST_EXPECTED_VALUE(2, -MakeClampedNum(value));
764 value = DstLimits::max();
765 TEST_EXPECTED_VALUE(Dst(DstLimits::max() * -1), -MakeClampedNum(value));
766 value = Dst(-1 * DstLimits::max());
767 TEST_EXPECTED_VALUE(DstLimits::max(), -MakeClampedNum(value));
768 value = DstLimits::lowest();
769 TEST_EXPECTED_VALUE(DstLimits::max(), -MakeClampedNum(value));
jschuh749c7f72016-09-07 16:22:26770 }
[email protected]5bfecbc2014-02-27 13:49:04771
772 // Generic absolute value.
773 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
774 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
775 TEST_EXPECTED_VALUE(DstLimits::max(),
776 CheckedNumeric<Dst>(DstLimits::max()).Abs());
777
jschuhb180f392017-07-03 15:09:22778 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>().Abs());
779 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).Abs());
780 TEST_EXPECTED_VALUE(DstLimits::max(),
781 ClampedNumeric<Dst>(DstLimits::max()).Abs());
782
[email protected]5bfecbc2014-02-27 13:49:04783 // Generic addition.
784 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
785 TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
jschuh216b62a92016-11-08 03:53:08786 if (numeric_limits<Dst>::is_signed)
787 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
jschuh5030b002016-12-05 18:21:48788 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + 1);
jschuh819c8262016-05-21 01:39:03789 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) +
790 DstLimits::max());
[email protected]5bfecbc2014-02-27 13:49:04791
jschuhb180f392017-07-03 15:09:22792 TEST_EXPECTED_VALUE(1, (ClampedNumeric<Dst>() + 1));
793 TEST_EXPECTED_VALUE(2, (ClampedNumeric<Dst>(1) + 1));
794 if (numeric_limits<Dst>::is_signed)
795 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(-1) + 1));
796 TEST_EXPECTED_VALUE(DstLimits::lowest() + 1,
797 ClampedNumeric<Dst>(DstLimits::lowest()) + 1);
798 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
799 ClampedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
800
[email protected]5bfecbc2014-02-27 13:49:04801 // Generic subtraction.
[email protected]5bfecbc2014-02-27 13:49:04802 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
jschuh819c8262016-05-21 01:39:03803 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
jschuh216b62a92016-11-08 03:53:08804 if (numeric_limits<Dst>::is_signed) {
805 TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
806 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
jschuh657a3d62016-11-15 18:23:45807 } else {
808 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -1);
jschuh216b62a92016-11-08 03:53:08809 }
[email protected]5bfecbc2014-02-27 13:49:04810
jschuhb180f392017-07-03 15:09:22811 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(1) - 1));
812 TEST_EXPECTED_VALUE(DstLimits::max() - 1,
813 ClampedNumeric<Dst>(DstLimits::max()) - 1);
814 if (numeric_limits<Dst>::is_signed) {
815 TEST_EXPECTED_VALUE(-1, (ClampedNumeric<Dst>() - 1));
816 TEST_EXPECTED_VALUE(-2, (ClampedNumeric<Dst>(-1) - 1));
817 } else {
818 TEST_EXPECTED_VALUE(DstLimits::max(),
819 ClampedNumeric<Dst>(DstLimits::max()) - -1);
820 }
821
[email protected]5bfecbc2014-02-27 13:49:04822 // Generic multiplication.
823 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
824 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
eroman0397125f2015-05-18 14:44:32825 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
jschuh216b62a92016-11-08 03:53:08826 if (numeric_limits<Dst>::is_signed) {
827 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
828 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
jschuh749c7f72016-09-07 16:22:26829 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
jschuh657a3d62016-11-15 18:23:45830 } else {
831 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * -2);
832 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
833 CheckedNumeric<uintmax_t>(-2));
jschuh749c7f72016-09-07 16:22:26834 }
jschuh216b62a92016-11-08 03:53:08835 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
836 DstLimits::max());
[email protected]5bfecbc2014-02-27 13:49:04837
jschuhb180f392017-07-03 15:09:22838 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>() * 1));
839 TEST_EXPECTED_VALUE(1, (ClampedNumeric<Dst>(1) * 1));
840 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(0) * 0));
841 if (numeric_limits<Dst>::is_signed) {
842 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(-1) * 0));
843 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(0) * -1));
844 TEST_EXPECTED_VALUE(-2, (ClampedNumeric<Dst>(-1) * 2));
845 } else {
846 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
847 ClampedNumeric<Dst>(DstLimits::max()) * -2);
848 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) *
849 ClampedNumeric<uintmax_t>(-2));
850 }
851 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
852 ClampedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
853
[email protected]5bfecbc2014-02-27 13:49:04854 // Generic division.
855 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
856 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
jschuh5030b002016-12-05 18:21:48857 TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
858 CheckedNumeric<Dst>(DstLimits::lowest()) / 2);
[email protected]5bfecbc2014-02-27 13:49:04859 TEST_EXPECTED_VALUE(DstLimits::max() / 2,
860 CheckedNumeric<Dst>(DstLimits::max()) / 2);
jschuhb180f392017-07-03 15:09:22861 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) / 0);
862
863 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() / 1);
864 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / 1);
865 TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
866 ClampedNumeric<Dst>(DstLimits::lowest()) / 2);
867 TEST_EXPECTED_VALUE(DstLimits::max() / 2,
868 ClampedNumeric<Dst>(DstLimits::max()) / 2);
869 TEST_EXPECTED_VALUE(DstLimits::Overflow(), ClampedNumeric<Dst>(1) / 0);
870 TEST_EXPECTED_VALUE(DstLimits::Underflow(), ClampedNumeric<Dst>(-1) / 0);
871 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) / 0);
[email protected]5bfecbc2014-02-27 13:49:04872
873 TestSpecializedArithmetic<Dst>(dst, line);
874}
875
876// Helper macro to wrap displaying the conversion types and line numbers.
877#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
878
879TEST(SafeNumerics, SignedIntegerMath) {
880 TEST_ARITHMETIC(int8_t);
Justin Schuha26da272017-07-13 23:04:30881 TEST_ARITHMETIC(int16_t);
[email protected]5bfecbc2014-02-27 13:49:04882 TEST_ARITHMETIC(int);
883 TEST_ARITHMETIC(intptr_t);
884 TEST_ARITHMETIC(intmax_t);
885}
886
887TEST(SafeNumerics, UnsignedIntegerMath) {
888 TEST_ARITHMETIC(uint8_t);
Justin Schuha26da272017-07-13 23:04:30889 TEST_ARITHMETIC(uint16_t);
[email protected]5bfecbc2014-02-27 13:49:04890 TEST_ARITHMETIC(unsigned int);
891 TEST_ARITHMETIC(uintptr_t);
892 TEST_ARITHMETIC(uintmax_t);
893}
894
895TEST(SafeNumerics, FloatingPointMath) {
896 TEST_ARITHMETIC(float);
897 TEST_ARITHMETIC(double);
898}
[email protected]c1c090d32013-01-16 23:34:04899
[email protected]4efb2c32014-01-16 06:57:25900// Enumerates the five different conversions types we need to test.
901enum NumericConversionType {
902 SIGN_PRESERVING_VALUE_PRESERVING,
903 SIGN_PRESERVING_NARROW,
904 SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
905 SIGN_TO_UNSIGN_NARROW,
906 UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
907};
[email protected]c1c090d32013-01-16 23:34:04908
[email protected]4efb2c32014-01-16 06:57:25909// Template covering the different conversion tests.
910template <typename Dst, typename Src, NumericConversionType conversion>
911struct TestNumericConversion {};
[email protected]c1c090d32013-01-16 23:34:04912
jschuh082b2ba2017-01-06 11:40:54913enum RangeConstraint {
914 RANGE_VALID = 0x0, // Value can be represented by the destination type.
915 RANGE_UNDERFLOW = 0x1, // Value would underflow.
916 RANGE_OVERFLOW = 0x2, // Value would overflow.
917 RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN).
918};
919
920// These are some wrappers to make the tests a bit cleaner.
921constexpr RangeConstraint RangeCheckToEnum(const RangeCheck constraint) {
922 return static_cast<RangeConstraint>(
923 static_cast<int>(constraint.IsOverflowFlagSet()) << 1 |
924 static_cast<int>(constraint.IsUnderflowFlagSet()));
925}
926
[email protected]5bfecbc2014-02-27 13:49:04927// EXPECT_EQ wrappers providing specific detail on test failures.
jschuh082b2ba2017-01-06 11:40:54928#define TEST_EXPECTED_RANGE(expected, actual) \
929 EXPECT_EQ(expected, \
Justin Schuha26da272017-07-13 23:04:30930 RangeCheckToEnum(DstRangeRelationToSrcRange<Dst>(actual))) \
jschuh082b2ba2017-01-06 11:40:54931 << "Conversion test: " << src << " value " << actual << " to " << dst \
jschuh657a3d62016-11-15 18:23:45932 << " on line " << line
[email protected]4efb2c32014-01-16 06:57:25933
934template <typename Dst, typename Src>
Justin Schuh5cc2abf2017-08-01 04:58:07935void TestStrictComparison(const char* dst, const char* src, int line) {
jschuh5030b002016-12-05 18:21:48936 using DstLimits = numeric_limits<Dst>;
937 using SrcLimits = numeric_limits<Src>;
jschuh711ac6a2016-12-04 07:17:48938 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < DstLimits::max(), "");
939 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < SrcLimits::max(), "");
940 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= DstLimits::max()),
jschuh23a4b062016-12-02 02:55:08941 "");
jschuh711ac6a2016-12-04 07:17:48942 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= SrcLimits::max()),
jschuh23a4b062016-12-02 02:55:08943 "");
jschuh711ac6a2016-12-04 07:17:48944 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= DstLimits::max(),
jschuh23a4b062016-12-02 02:55:08945 "");
jschuh711ac6a2016-12-04 07:17:48946 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= SrcLimits::max(),
jschuh23a4b062016-12-02 02:55:08947 "");
jschuh711ac6a2016-12-04 07:17:48948 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > DstLimits::max()),
949 "");
950 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > SrcLimits::max()),
951 "");
952 static_assert(StrictNumeric<Src>(SrcLimits::max()) > DstLimits::lowest(), "");
953 static_assert(StrictNumeric<Src>(SrcLimits::max()) > SrcLimits::lowest(), "");
954 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= DstLimits::lowest()),
955 "");
956 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= SrcLimits::lowest()),
957 "");
958 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= DstLimits::lowest(),
959 "");
960 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= SrcLimits::lowest(),
961 "");
962 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < DstLimits::lowest()),
963 "");
964 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < SrcLimits::lowest()),
965 "");
jschuh23a4b062016-12-02 02:55:08966 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(1),
967 "");
968 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(0),
969 "");
970 static_assert(StrictNumeric<Src>(SrcLimits::max()) != static_cast<Dst>(0),
971 "");
jschuh711ac6a2016-12-04 07:17:48972 static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::lowest(),
973 "");
jschuh23a4b062016-12-02 02:55:08974 static_assert(
975 !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), "");
976 static_assert(
977 !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), "");
jschuh711ac6a2016-12-04 07:17:48978
979 // Due to differences in float handling between compilers, these aren't
980 // compile-time constants everywhere. So, we use run-time tests.
jschuh4bc919cb52016-12-04 15:08:27981 EXPECT_EQ(
982 SrcLimits::max(),
983 MakeCheckedNum(SrcLimits::max()).Max(DstLimits::lowest()).ValueOrDie());
984 EXPECT_EQ(
985 DstLimits::max(),
986 MakeCheckedNum(SrcLimits::lowest()).Max(DstLimits::max()).ValueOrDie());
987 EXPECT_EQ(
988 DstLimits::lowest(),
989 MakeCheckedNum(SrcLimits::max()).Min(DstLimits::lowest()).ValueOrDie());
990 EXPECT_EQ(
991 SrcLimits::lowest(),
992 MakeCheckedNum(SrcLimits::lowest()).Min(DstLimits::max()).ValueOrDie());
993 EXPECT_EQ(SrcLimits::lowest(), CheckMin(MakeStrictNum(1), MakeCheckedNum(0),
jschuh711ac6a2016-12-04 07:17:48994 DstLimits::max(), SrcLimits::lowest())
995 .ValueOrDie());
jschuh4bc919cb52016-12-04 15:08:27996 EXPECT_EQ(DstLimits::max(), CheckMax(MakeStrictNum(1), MakeCheckedNum(0),
jschuh711ac6a2016-12-04 07:17:48997 DstLimits::max(), SrcLimits::lowest())
998 .ValueOrDie());
Justin Schuha81d2e52017-07-14 02:53:34999
1000 EXPECT_EQ(SrcLimits::max(),
1001 MakeClampedNum(SrcLimits::max()).Max(DstLimits::lowest()));
1002 EXPECT_EQ(DstLimits::max(),
1003 MakeClampedNum(SrcLimits::lowest()).Max(DstLimits::max()));
1004 EXPECT_EQ(DstLimits::lowest(),
1005 MakeClampedNum(SrcLimits::max()).Min(DstLimits::lowest()));
1006 EXPECT_EQ(SrcLimits::lowest(),
1007 MakeClampedNum(SrcLimits::lowest()).Min(DstLimits::max()));
1008 EXPECT_EQ(SrcLimits::lowest(),
1009 ClampMin(MakeStrictNum(1), MakeClampedNum(0), DstLimits::max(),
1010 SrcLimits::lowest()));
1011 EXPECT_EQ(DstLimits::max(), ClampMax(MakeStrictNum(1), MakeClampedNum(0),
1012 DstLimits::max(), SrcLimits::lowest()));
Justin Schuh5cc2abf2017-08-01 04:58:071013
1014 if (IsValueInRangeForNumericType<Dst>(SrcLimits::max())) {
1015 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()), (CommonMax<Dst, Src>()));
1016 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()),
1017 (CommonMaxOrMin<Dst, Src>(false)));
1018 } else {
1019 TEST_EXPECTED_VALUE(DstLimits::max(), (CommonMax<Dst, Src>()));
1020 TEST_EXPECTED_VALUE(DstLimits::max(), (CommonMaxOrMin<Dst, Src>(false)));
1021 }
1022
1023 if (IsValueInRangeForNumericType<Dst>(SrcLimits::lowest())) {
1024 TEST_EXPECTED_VALUE(Dst(SrcLimits::lowest()), (CommonMin<Dst, Src>()));
1025 TEST_EXPECTED_VALUE(Dst(SrcLimits::lowest()),
1026 (CommonMaxOrMin<Dst, Src>(true)));
1027 } else {
1028 TEST_EXPECTED_VALUE(DstLimits::lowest(), (CommonMin<Dst, Src>()));
1029 TEST_EXPECTED_VALUE(DstLimits::lowest(), (CommonMaxOrMin<Dst, Src>(true)));
1030 }
jschuh23a4b062016-12-02 02:55:081031}
1032
1033template <typename Dst, typename Src>
[email protected]4efb2c32014-01-16 06:57:251034struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
Justin Schuh5cc331de2017-07-25 18:05:221035 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221036 using SrcLimits = SaturationDefaultLimits<Src>;
1037 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:481038 // Integral to floating.
jschuhd2d9fe02014-10-14 14:31:371039 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
jschuh5030b002016-12-05 18:21:481040 // Not floating to integral and...
1041 (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
1042 // Same sign, same numeric, source is narrower or same.
1043 ((SrcLimits::is_signed == DstLimits::is_signed &&
1044 MaxExponent<Dst>::value >= MaxExponent<Src>::value) ||
1045 // Or signed destination and source is smaller
1046 (DstLimits::is_signed &&
1047 MaxExponent<Dst>::value >= MaxExponent<Src>::value))),
jschuhd2d9fe02014-10-14 14:31:371048 "Comparison must be sign preserving and value preserving");
[email protected]4efb2c32014-01-16 06:57:251049
Justin Schuh5cc2abf2017-08-01 04:58:071050 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081051
[email protected]5bfecbc2014-02-27 13:49:041052 const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
jschuhb180f392017-07-03 15:09:221053 const ClampedNumeric<Dst> clamped_dst = SrcLimits::max();
jschuh819c8262016-05-21 01:39:031054 TEST_EXPECTED_SUCCESS(checked_dst);
jschuhb180f392017-07-03 15:09:221055 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()), clamped_dst);
[email protected]5bfecbc2014-02-27 13:49:041056 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
1057 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
1058 // At least twice larger type.
jschuh819c8262016-05-21 01:39:031059 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
jschuhb180f392017-07-03 15:09:221060 TEST_EXPECTED_VALUE(SrcLimits::max() * clamped_dst,
Peter Kastingfbb9e562021-06-27 02:57:371061 Dst(SrcLimits::max()) * Dst(SrcLimits::max()));
[email protected]5bfecbc2014-02-27 13:49:041062 } else { // Larger, but not at least twice as large.
jschuh819c8262016-05-21 01:39:031063 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
1064 TEST_EXPECTED_SUCCESS(checked_dst + 1);
jschuhb180f392017-07-03 15:09:221065 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
1066 SrcLimits::max() * clamped_dst);
1067 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()) + Dst(1),
1068 clamped_dst + Dst(1));
[email protected]5bfecbc2014-02-27 13:49:041069 }
1070 } else { // Same width type.
jschuh819c8262016-05-21 01:39:031071 TEST_EXPECTED_FAILURE(checked_dst + 1);
jschuhb180f392017-07-03 15:09:221072 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + Dst(1));
[email protected]5bfecbc2014-02-27 13:49:041073 }
1074
1075 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
1076 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
[email protected]4efb2c32014-01-16 06:57:251077 if (SrcLimits::is_iec559) {
[email protected]5bfecbc2014-02-27 13:49:041078 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
1079 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
1080 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
1081 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
[email protected]5bfecbc2014-02-27 13:49:041082 } else if (numeric_limits<Src>::is_signed) {
Justin Schuh4ad909a2017-08-03 13:40:421083 // This block reverses the Src to Dst relationship so we don't have to
1084 // complicate the test macros.
1085 if (!std::is_same<Src, Dst>::value) {
1086 TEST_EXPECTED_SUCCESS(CheckDiv(SrcLimits::lowest(), Dst(-1)));
1087 }
[email protected]5bfecbc2014-02-27 13:49:041088 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:481089 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
[email protected]4efb2c32014-01-16 06:57:251090 }
[email protected]c1c090d32013-01-16 23:34:041091 }
[email protected]4efb2c32014-01-16 06:57:251092};
1093
1094template <typename Dst, typename Src>
1095struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
Justin Schuh5cc331de2017-07-25 18:05:221096 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221097 using SrcLimits = SaturationDefaultLimits<Src>;
1098 using DstLimits = SaturationDefaultLimits<Dst>;
jschuhd2d9fe02014-10-14 14:31:371099 static_assert(SrcLimits::is_signed == DstLimits::is_signed,
1100 "Destination and source sign must be the same");
jschuh5030b002016-12-05 18:21:481101 static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:371102 "Destination must be narrower than source");
[email protected]4efb2c32014-01-16 06:57:251103
Justin Schuh5cc2abf2017-08-01 04:58:071104 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081105
[email protected]5bfecbc2014-02-27 13:49:041106 const CheckedNumeric<Dst> checked_dst;
jschuh819c8262016-05-21 01:39:031107 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
jschuhb180f392017-07-03 15:09:221108 TEST_EXPECTED_VALUE(1, checked_dst + Src(1));
jschuh819c8262016-05-21 01:39:031109 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
[email protected]5bfecbc2014-02-27 13:49:041110
Justin Schuh3725ec32017-10-01 03:44:271111 ClampedNumeric<Dst> clamped_dst;
jschuhb180f392017-07-03 15:09:221112 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
1113 TEST_EXPECTED_VALUE(1, clamped_dst + Src(1));
1114 TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst - SrcLimits::max());
Justin Schuh3725ec32017-10-01 03:44:271115 clamped_dst += SrcLimits::max();
1116 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1117 clamped_dst = DstLimits::max();
1118 clamped_dst += SrcLimits::max();
1119 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1120 clamped_dst = DstLimits::max();
1121 clamped_dst -= SrcLimits::max();
1122 TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst);
1123 clamped_dst = 0;
jschuhb180f392017-07-03 15:09:221124
[email protected]5bfecbc2014-02-27 13:49:041125 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
1126 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
[email protected]4efb2c32014-01-16 06:57:251127 if (SrcLimits::is_iec559) {
[email protected]5bfecbc2014-02-27 13:49:041128 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
1129 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
1130 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
1131 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
1132 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuhfafe0712015-09-14 20:21:241133 if (DstLimits::is_integer) {
1134 if (SrcLimits::digits < DstLimits::digits) {
1135 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
1136 static_cast<Src>(DstLimits::max()));
1137 } else {
1138 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
1139 }
1140 TEST_EXPECTED_RANGE(
1141 RANGE_VALID,
1142 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
jschuh5030b002016-12-05 18:21:481143 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
jschuhfafe0712015-09-14 20:21:241144 }
[email protected]4efb2c32014-01-16 06:57:251145 } else if (SrcLimits::is_signed) {
[email protected]5bfecbc2014-02-27 13:49:041146 TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
jschuhb180f392017-07-03 15:09:221147 TEST_EXPECTED_VALUE(-1, clamped_dst - static_cast<Src>(1));
Justin Schuh4ad909a2017-08-03 13:40:421148 TEST_EXPECTED_VALUE(Src(Src(0) - DstLimits::lowest()),
1149 ClampDiv(DstLimits::lowest(), Src(-1)));
jschuh5030b002016-12-05 18:21:481150 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:041151 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
[email protected]4efb2c32014-01-16 06:57:251152 } else {
jschuh819c8262016-05-21 01:39:031153 TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
jschuhb180f392017-07-03 15:09:221154 TEST_EXPECTED_VALUE(Dst(0), clamped_dst - static_cast<Src>(1));
jschuh5030b002016-12-05 18:21:481155 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
[email protected]4efb2c32014-01-16 06:57:251156 }
1157 }
1158};
1159
1160template <typename Dst, typename Src>
1161struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
Justin Schuh5cc331de2017-07-25 18:05:221162 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221163 using SrcLimits = SaturationDefaultLimits<Src>;
1164 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:481165 static_assert(MaxExponent<Dst>::value >= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:371166 "Destination must be equal or wider than source.");
1167 static_assert(SrcLimits::is_signed, "Source must be signed");
1168 static_assert(!DstLimits::is_signed, "Destination must be unsigned");
[email protected]4efb2c32014-01-16 06:57:251169
Justin Schuh5cc2abf2017-08-01 04:58:071170 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081171
[email protected]5bfecbc2014-02-27 13:49:041172 const CheckedNumeric<Dst> checked_dst;
1173 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
jschuh819c8262016-05-21 01:39:031174 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
jschuhb180f392017-07-03 15:09:221175 TEST_EXPECTED_SUCCESS(checked_dst * static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:481176 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
Justin Schuh4ad909a2017-08-03 13:40:421177 TEST_EXPECTED_VALUE(Dst(0), CheckDiv(Dst(0), Src(-1)));
[email protected]5bfecbc2014-02-27 13:49:041178
jschuhb180f392017-07-03 15:09:221179 const ClampedNumeric<Dst> clamped_dst;
1180 TEST_EXPECTED_VALUE(SrcLimits::max(), clamped_dst + SrcLimits::max());
1181 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1182 clamped_dst + static_cast<Src>(-1));
1183 TEST_EXPECTED_VALUE(0, clamped_dst * static_cast<Src>(-1));
1184 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1185 clamped_dst + SrcLimits::lowest());
1186
jschuh5030b002016-12-05 18:21:481187 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:041188 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
1189 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
1190 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
[email protected]4efb2c32014-01-16 06:57:251191 }
1192};
1193
1194template <typename Dst, typename Src>
1195struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
Justin Schuh5cc331de2017-07-25 18:05:221196 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221197 using SrcLimits = SaturationDefaultLimits<Src>;
1198 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:481199 static_assert(MaxExponent<Dst>::value < MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:371200 "Destination must be narrower than source.");
1201 static_assert(SrcLimits::is_signed, "Source must be signed.");
1202 static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
[email protected]4efb2c32014-01-16 06:57:251203
Justin Schuh5cc2abf2017-08-01 04:58:071204 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081205
[email protected]5bfecbc2014-02-27 13:49:041206 const CheckedNumeric<Dst> checked_dst;
1207 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:031208 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
1209 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:481210 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:041211
Justin Schuh3725ec32017-10-01 03:44:271212 ClampedNumeric<Dst> clamped_dst;
jschuhb180f392017-07-03 15:09:221213 TEST_EXPECTED_VALUE(1, clamped_dst + static_cast<Src>(1));
1214 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
1215 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1216 clamped_dst + static_cast<Src>(-1));
1217 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1218 clamped_dst + SrcLimits::lowest());
Justin Schuh3725ec32017-10-01 03:44:271219 clamped_dst += SrcLimits::max();
1220 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1221 clamped_dst = DstLimits::max();
1222 clamped_dst += SrcLimits::max();
1223 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1224 clamped_dst = DstLimits::max();
1225 clamped_dst -= SrcLimits::max();
1226 TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst);
1227 clamped_dst = 0;
jschuhb180f392017-07-03 15:09:221228
[email protected]5bfecbc2014-02-27 13:49:041229 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
1230 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
1231 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
jschuhe3bd1f62016-12-20 05:11:301232
1233 // Additional saturation tests.
jschuhb180f392017-07-03 15:09:221234 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
jschuhe3bd1f62016-12-20 05:11:301235 EXPECT_EQ(DstLimits::lowest(), saturated_cast<Dst>(SrcLimits::lowest()));
1236
[email protected]4efb2c32014-01-16 06:57:251237 if (SrcLimits::is_iec559) {
jschuhe3bd1f62016-12-20 05:11:301238 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::quiet_NaN()));
1239
[email protected]5bfecbc2014-02-27 13:49:041240 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
1241 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
1242 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
1243 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuhfafe0712015-09-14 20:21:241244 if (DstLimits::is_integer) {
1245 if (SrcLimits::digits < DstLimits::digits) {
1246 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
1247 static_cast<Src>(DstLimits::max()));
1248 } else {
1249 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
1250 }
1251 TEST_EXPECTED_RANGE(
1252 RANGE_VALID,
1253 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
jschuh5030b002016-12-05 18:21:481254 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
jschuhfafe0712015-09-14 20:21:241255 }
[email protected]4efb2c32014-01-16 06:57:251256 } else {
jschuh5030b002016-12-05 18:21:481257 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
[email protected]4efb2c32014-01-16 06:57:251258 }
1259 }
1260};
1261
1262template <typename Dst, typename Src>
1263struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
Justin Schuh5cc331de2017-07-25 18:05:221264 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221265 using SrcLimits = SaturationDefaultLimits<Src>;
1266 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:481267 static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:371268 "Destination must be narrower or equal to source.");
1269 static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
1270 static_assert(DstLimits::is_signed, "Destination must be signed.");
[email protected]4efb2c32014-01-16 06:57:251271
Justin Schuh5cc2abf2017-08-01 04:58:071272 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081273
[email protected]5bfecbc2014-02-27 13:49:041274 const CheckedNumeric<Dst> checked_dst;
1275 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:031276 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
jschuh5030b002016-12-05 18:21:481277 TEST_EXPECTED_VALUE(SrcLimits::lowest(), checked_dst + SrcLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:041278
jschuhb180f392017-07-03 15:09:221279 const ClampedNumeric<Dst> clamped_dst;
1280 TEST_EXPECTED_VALUE(1, clamped_dst + static_cast<Src>(1));
1281 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
1282 TEST_EXPECTED_VALUE(SrcLimits::lowest(), clamped_dst + SrcLimits::lowest());
1283
jschuh5030b002016-12-05 18:21:481284 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
[email protected]5bfecbc2014-02-27 13:49:041285 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
1286 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuhe3bd1f62016-12-20 05:11:301287
1288 // Additional saturation tests.
1289 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
1290 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::lowest()));
[email protected]4efb2c32014-01-16 06:57:251291 }
1292};
1293
1294// Helper macro to wrap displaying the conversion types and line numbers
1295#define TEST_NUMERIC_CONVERSION(d, s, t) \
1296 TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
1297
[email protected]5bfecbc2014-02-27 13:49:041298TEST(SafeNumerics, IntMinOperations) {
[email protected]4efb2c32014-01-16 06:57:251299 TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1300 TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1301
Justin Schuha26da272017-07-13 23:04:301302 TEST_NUMERIC_CONVERSION(int8_t, int16_t, SIGN_PRESERVING_NARROW);
[email protected]4efb2c32014-01-16 06:57:251303 TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
Justin Schuha26da272017-07-13 23:04:301304 TEST_NUMERIC_CONVERSION(uint8_t, uint16_t, SIGN_PRESERVING_NARROW);
[email protected]4efb2c32014-01-16 06:57:251305 TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
1306 TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
1307
1308 TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1309
Justin Schuha26da272017-07-13 23:04:301310 TEST_NUMERIC_CONVERSION(uint8_t, int16_t, SIGN_TO_UNSIGN_NARROW);
[email protected]4efb2c32014-01-16 06:57:251311 TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
1312 TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
1313 TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
1314
Justin Schuha26da272017-07-13 23:04:301315 TEST_NUMERIC_CONVERSION(int8_t, uint16_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
[email protected]4efb2c32014-01-16 06:57:251316 TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1317 TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
[email protected]c1c090d32013-01-16 23:34:041318}
1319
Justin Schuha26da272017-07-13 23:04:301320TEST(SafeNumerics, Int16Operations) {
1321 TEST_NUMERIC_CONVERSION(int16_t, int16_t, SIGN_PRESERVING_VALUE_PRESERVING);
1322 TEST_NUMERIC_CONVERSION(uint16_t, uint16_t, SIGN_PRESERVING_VALUE_PRESERVING);
1323
1324 TEST_NUMERIC_CONVERSION(int16_t, int, SIGN_PRESERVING_NARROW);
1325 TEST_NUMERIC_CONVERSION(uint16_t, unsigned int, SIGN_PRESERVING_NARROW);
1326 TEST_NUMERIC_CONVERSION(int16_t, float, SIGN_PRESERVING_NARROW);
1327
1328 TEST_NUMERIC_CONVERSION(uint16_t, int16_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1329
1330 TEST_NUMERIC_CONVERSION(uint16_t, int, SIGN_TO_UNSIGN_NARROW);
1331 TEST_NUMERIC_CONVERSION(uint16_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
1332 TEST_NUMERIC_CONVERSION(uint16_t, float, SIGN_TO_UNSIGN_NARROW);
1333
1334 TEST_NUMERIC_CONVERSION(int16_t, unsigned int,
1335 UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1336 TEST_NUMERIC_CONVERSION(int16_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1337}
1338
[email protected]5bfecbc2014-02-27 13:49:041339TEST(SafeNumerics, IntOperations) {
[email protected]4efb2c32014-01-16 06:57:251340 TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
1341 TEST_NUMERIC_CONVERSION(unsigned int, unsigned int,
1342 SIGN_PRESERVING_VALUE_PRESERVING);
1343 TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1344 TEST_NUMERIC_CONVERSION(unsigned int, uint8_t,
1345 SIGN_PRESERVING_VALUE_PRESERVING);
1346 TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1347
1348 TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
1349 TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
1350 TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
1351 TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
1352
1353 TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1354 TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1355
1356 TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
1357 TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
1358 TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
1359
1360 TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1361 TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
[email protected]c1c090d32013-01-16 23:34:041362}
1363
[email protected]5bfecbc2014-02-27 13:49:041364TEST(SafeNumerics, IntMaxOperations) {
[email protected]4efb2c32014-01-16 06:57:251365 TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
1366 TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t,
1367 SIGN_PRESERVING_VALUE_PRESERVING);
1368 TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
1369 TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int,
1370 SIGN_PRESERVING_VALUE_PRESERVING);
1371 TEST_NUMERIC_CONVERSION(intmax_t, unsigned int,
1372 SIGN_PRESERVING_VALUE_PRESERVING);
1373 TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1374
1375 TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
1376 TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
1377
1378 TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1379 TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1380
1381 TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
1382 TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
1383
1384 TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1385}
1386
[email protected]5bfecbc2014-02-27 13:49:041387TEST(SafeNumerics, FloatOperations) {
[email protected]4efb2c32014-01-16 06:57:251388 TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
Justin Schuh5cc331de2017-07-25 18:05:221389 TEST_NUMERIC_CONVERSION(float, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
[email protected]4efb2c32014-01-16 06:57:251390 TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
1391 TEST_NUMERIC_CONVERSION(float, unsigned int,
1392 SIGN_PRESERVING_VALUE_PRESERVING);
1393
1394 TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
1395}
1396
[email protected]5bfecbc2014-02-27 13:49:041397TEST(SafeNumerics, DoubleOperations) {
[email protected]4efb2c32014-01-16 06:57:251398 TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
Justin Schuh5cc331de2017-07-25 18:05:221399 TEST_NUMERIC_CONVERSION(double, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
[email protected]4efb2c32014-01-16 06:57:251400 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
1401 TEST_NUMERIC_CONVERSION(double, unsigned int,
1402 SIGN_PRESERVING_VALUE_PRESERVING);
1403}
1404
[email protected]5bfecbc2014-02-27 13:49:041405TEST(SafeNumerics, SizeTOperations) {
[email protected]4efb2c32014-01-16 06:57:251406 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1407 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1408}
1409
jschuh23a4b062016-12-02 02:55:081410// A one-off test to ensure StrictNumeric won't resolve to an incorrect type.
1411// If this fails we'll just get a compiler error on an ambiguous overload.
1412int TestOverload(int) { // Overload fails.
1413 return 0;
1414}
1415uint8_t TestOverload(uint8_t) { // Overload fails.
1416 return 0;
1417}
1418size_t TestOverload(size_t) { // Overload succeeds.
1419 return 0;
1420}
1421
1422static_assert(
1423 std::is_same<decltype(TestOverload(StrictNumeric<int>())), int>::value,
1424 "");
1425static_assert(std::is_same<decltype(TestOverload(StrictNumeric<size_t>())),
1426 size_t>::value,
1427 "");
1428
jschuh71b669a2016-12-17 01:13:311429template <typename T>
1430struct CastTest1 {
jschuhc8f03cd2017-01-05 03:40:511431 static constexpr T NaN() { return -1; }
jschuh71b669a2016-12-17 01:13:311432 static constexpr T max() { return numeric_limits<T>::max() - 1; }
jschuhc8f03cd2017-01-05 03:40:511433 static constexpr T Overflow() { return max(); }
jschuh71b669a2016-12-17 01:13:311434 static constexpr T lowest() { return numeric_limits<T>::lowest() + 1; }
jschuhc8f03cd2017-01-05 03:40:511435 static constexpr T Underflow() { return lowest(); }
jschuh71b669a2016-12-17 01:13:311436};
1437
1438template <typename T>
1439struct CastTest2 {
jschuhc8f03cd2017-01-05 03:40:511440 static constexpr T NaN() { return 11; }
jschuh71b669a2016-12-17 01:13:311441 static constexpr T max() { return 10; }
jschuhc8f03cd2017-01-05 03:40:511442 static constexpr T Overflow() { return max(); }
jschuh71b669a2016-12-17 01:13:311443 static constexpr T lowest() { return 1; }
jschuhc8f03cd2017-01-05 03:40:511444 static constexpr T Underflow() { return lowest(); }
jschuh71b669a2016-12-17 01:13:311445};
1446
agrieve7772a0502016-12-16 18:18:481447TEST(SafeNumerics, CastTests) {
[email protected]4efb2c32014-01-16 06:57:251448// 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)
[email protected]c1c090d32013-01-16 23:34:041452#endif
1453
[email protected]c1c090d32013-01-16 23:34:041454 int small_positive = 1;
1455 int small_negative = -1;
[email protected]4efb2c32014-01-16 06:57:251456 double double_small = 1.0;
[email protected]5bfecbc2014-02-27 13:49:041457 double double_large = numeric_limits<double>::max();
1458 double double_infinity = numeric_limits<float>::infinity();
danakj3193742f2015-06-05 18:15:101459 double double_large_int = numeric_limits<int>::max();
jschuh5030b002016-12-05 18:21:481460 double double_small_int = numeric_limits<int>::lowest();
[email protected]c1c090d32013-01-16 23:34:041461
jschuh4bf22c6d2015-05-28 02:29:251462 // Just test that the casts compile, since the other tests cover logic.
[email protected]5bfecbc2014-02-27 13:49:041463 EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
jschuh4bf22c6d2015-05-28 02:29:251464 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
jschuh07345e62015-09-22 22:13:361475 EXPECT_TRUE(IsValueNegative(-1));
jschuh5030b002016-12-05 18:21:481476 EXPECT_TRUE(IsValueNegative(numeric_limits<int>::lowest()));
1477 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::lowest()));
1478 EXPECT_TRUE(IsValueNegative(numeric_limits<double>::lowest()));
jschuh07345e62015-09-22 22:13:361479 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
jschuh4bf22c6d2015-05-28 02:29:251487 // 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));
[email protected]c1c090d32013-01-16 23:34:041492
[email protected]4efb2c32014-01-16 06:57:251493 // 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));
Justin Schuh5cc331de2017-07-25 18:05:221498 EXPECT_EQ(saturated_cast<unsigned>(small_negative), static_cast<unsigned>(0));
1499 EXPECT_EQ(saturated_cast<int>(double_small), static_cast<int>(double_small));
[email protected]5bfecbc2014-02-27 13:49:041500 EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
[email protected]4efb2c32014-01-16 06:57:251501 EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
1502 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
jschuh5030b002016-12-05 18:21:481503 EXPECT_EQ(numeric_limits<int>::lowest(),
1504 saturated_cast<int>(double_small_int));
danakj3193742f2015-06-05 18:15:101505 EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
vmpstredf1e182015-12-14 20:09:421506
jschuh71b669a2016-12-17 01:13:311507 // 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
vmpstredf1e182015-12-14 20:09:421536 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));
jschuh224f1d72016-11-25 20:08:481540
1541 // Test the CheckedNumeric value extractions functions.
jschuh5030b002016-12-05 18:21:481542 auto int8_min = MakeCheckedNum(numeric_limits<int8_t>::lowest());
jschuh4bc919cb52016-12-04 15:08:271543 auto int8_max = MakeCheckedNum(numeric_limits<int8_t>::max());
1544 auto double_max = MakeCheckedNum(numeric_limits<double>::max());
jschuh224f1d72016-11-25 20:08:481545 static_assert(
jschuh23a4b062016-12-02 02:55:081546 std::is_same<int16_t,
1547 decltype(int8_min.ValueOrDie<int16_t>())::type>::value,
jschuh224f1d72016-11-25 20:08:481548 "ValueOrDie returning incorrect type.");
1549 static_assert(
1550 std::is_same<int16_t,
jschuh23a4b062016-12-02 02:55:081551 decltype(int8_min.ValueOrDefault<int16_t>(0))::type>::value,
jschuh224f1d72016-11-25 20:08:481552 "ValueOrDefault returning incorrect type.");
jschuh23a4b062016-12-02 02:55:081553 EXPECT_FALSE(IsValidForType<uint8_t>(int8_min));
1554 EXPECT_TRUE(IsValidForType<uint8_t>(int8_max));
jschuh5030b002016-12-05 18:21:481555 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::lowest()),
jschuh23a4b062016-12-02 02:55:081556 ValueOrDieForType<int>(int8_min));
1557 EXPECT_TRUE(IsValidForType<uint32_t>(int8_max));
jschuh224f1d72016-11-25 20:08:481558 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()),
jschuh23a4b062016-12-02 02:55:081559 ValueOrDieForType<int>(int8_max));
1560 EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0));
jschuhe17e0f12016-11-26 03:00:081561 uint8_t uint8_dest = 0;
1562 int16_t int16_dest = 0;
1563 double double_dest = 0;
1564 EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest));
1565 EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest);
1566 EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest));
1567 EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest));
1568 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest);
1569 EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest));
jschuh5030b002016-12-05 18:21:481570 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::lowest()), int16_dest);
jschuhe17e0f12016-11-26 03:00:081571 EXPECT_FALSE(double_max.AssignIfValid(&uint8_dest));
1572 EXPECT_FALSE(double_max.AssignIfValid(&int16_dest));
1573 EXPECT_TRUE(double_max.AssignIfValid(&double_dest));
1574 EXPECT_EQ(numeric_limits<double>::max(), double_dest);
jschuh23a4b062016-12-02 02:55:081575 EXPECT_EQ(1, checked_cast<int>(StrictNumeric<int>(1)));
1576 EXPECT_EQ(1, saturated_cast<int>(StrictNumeric<int>(1)));
1577 EXPECT_EQ(1, strict_cast<int>(StrictNumeric<int>(1)));
Justin Schuh4d93ee32017-08-14 20:06:281578
1579 enum class EnumTest { kOne = 1 };
1580 EXPECT_EQ(1, checked_cast<int>(EnumTest::kOne));
1581 EXPECT_EQ(1, saturated_cast<int>(EnumTest::kOne));
1582 EXPECT_EQ(1, strict_cast<int>(EnumTest::kOne));
[email protected]c1c090d32013-01-16 23:34:041583}
1584
jschuhfafe0712015-09-14 20:21:241585TEST(SafeNumerics, IsValueInRangeForNumericType) {
1586 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
1587 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
1588 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
1589 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
1590 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
1591 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
1592 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
1593 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
1594 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
jschuh5030b002016-12-05 18:21:481595 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241596 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
jschuh5030b002016-12-05 18:21:481597 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241598
Ng Zhi An280ed262020-10-22 00:10:121599 // Converting to integer types will discard the fractional part first, so -0.9
1600 // will be truncated to -0.0.
1601 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(-0.9));
1602 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1.0));
1603
jschuhfafe0712015-09-14 20:21:241604 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
1605 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
1606 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
1607 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
1608 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
1609 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
1610 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
1611 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
1612 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
1613 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
1614 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
1615 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481616 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241617 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481618 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
jschuhfafe0712015-09-14 20:21:241619 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481620 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest()) - 1));
jschuhfafe0712015-09-14 20:21:241621 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481622 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241623
1624 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
1625 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
1626 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
1627 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
1628 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
1629 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
1630 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
1631 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
1632 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
jschuh5030b002016-12-05 18:21:481633 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241634 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
1635 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
jschuh5030b002016-12-05 18:21:481636 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241637
Ng Zhi An280ed262020-10-22 00:10:121638 // Converting to integer types will discard the fractional part first, so -0.9
1639 // will be truncated to -0.0.
1640 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(-0.9));
1641 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1.0));
1642
jschuhfafe0712015-09-14 20:21:241643 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
1644 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
1645 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
1646 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
1647 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
1648 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
1649 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
1650 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
1651 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
1652 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
1653 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
1654 EXPECT_TRUE(
1655 IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
1656 EXPECT_TRUE(
1657 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
1658 EXPECT_FALSE(
1659 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
1660 EXPECT_FALSE(
1661 IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
1662 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481663 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241664 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481665 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
jschuhfafe0712015-09-14 20:21:241666 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481667 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241668}
vmpstr19477492015-09-29 22:34:491669
1670TEST(SafeNumerics, CompoundNumericOperations) {
1671 CheckedNumeric<int> a = 1;
1672 CheckedNumeric<int> b = 2;
1673 CheckedNumeric<int> c = 3;
1674 CheckedNumeric<int> d = 4;
1675 a += b;
1676 EXPECT_EQ(3, a.ValueOrDie());
1677 a -= c;
1678 EXPECT_EQ(0, a.ValueOrDie());
1679 d /= b;
1680 EXPECT_EQ(2, d.ValueOrDie());
1681 d *= d;
1682 EXPECT_EQ(4, d.ValueOrDie());
Peter Kasting0559fb62020-08-12 00:02:051683 d *= 0.5;
1684 EXPECT_EQ(2, d.ValueOrDie());
vmpstr19477492015-09-29 22:34:491685
1686 CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
1687 EXPECT_TRUE(too_large.IsValid());
1688 too_large += d;
1689 EXPECT_FALSE(too_large.IsValid());
1690 too_large -= d;
1691 EXPECT_FALSE(too_large.IsValid());
1692 too_large /= d;
1693 EXPECT_FALSE(too_large.IsValid());
1694}
jschuh4fcd6fa2016-11-24 11:58:391695
Will Harris128da002023-02-07 23:47:491696TEST(SafeNumerics, TemplatedSafeMath) {
1697 // CheckMul and friends can be confusing, as they change behavior depending on
1698 // where the template is specified.
1699 uint64_t result;
1700 short short_one_thousand = 1000;
1701 // In this case, CheckMul uses template deduction to use the <short> variant,
1702 // and this will overflow even if assigned to a uint64_t.
1703 EXPECT_FALSE(CheckMul(short_one_thousand, short_one_thousand)
1704 .AssignIfValid<uint64_t>(&result));
1705 EXPECT_FALSE(CheckMul(short_one_thousand, short_one_thousand).IsValid());
1706 // In both cases, CheckMul is forced to use the uint64_t template and will not
1707 // overflow.
1708 EXPECT_TRUE(CheckMul<uint64_t>(short_one_thousand, short_one_thousand)
1709 .AssignIfValid(&result));
1710 EXPECT_TRUE(CheckMul<uint64_t>(short_one_thousand, short_one_thousand)
1711 .AssignIfValid<uint64_t>(&result));
1712
1713 uint64_t big_one_thousand = 1000u;
1714 // Order doesn't matter here: if one of the parameters is uint64_t then the
1715 // operation is done on a uint64_t.
1716 EXPECT_TRUE(
1717 CheckMul(big_one_thousand, short_one_thousand).AssignIfValid(&result));
1718 EXPECT_TRUE(
1719 CheckMul(short_one_thousand, big_one_thousand).AssignIfValid(&result));
1720
1721 // Checked math functions can also take two template type parameters. Here are
1722 // the results of all four combinations.
1723 EXPECT_TRUE((CheckMul<short, uint64_t>(1000, 1000).AssignIfValid(&result)));
1724
1725 // Note: Order here does not matter.
1726 EXPECT_TRUE((CheckMul<uint64_t, short>(1000, 1000).AssignIfValid(&result)));
1727
1728 // Only if both are short will the operation be invalid.
1729 EXPECT_FALSE((CheckMul<short, short>(1000, 1000).AssignIfValid(&result)));
1730
1731 // Same as above.
1732 EXPECT_TRUE(
1733 (CheckMul<uint64_t, uint64_t>(1000, 1000).AssignIfValid(&result)));
1734}
1735
jschuh4fcd6fa2016-11-24 11:58:391736TEST(SafeNumerics, VariadicNumericOperations) {
jschuhb180f392017-07-03 15:09:221737 { // Synthetic scope to avoid variable naming collisions.
1738 auto a = CheckAdd(1, 2UL, MakeCheckedNum(3LL), 4).ValueOrDie();
1739 EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
1740 auto b = CheckSub(MakeCheckedNum(20.0), 2UL, 4).ValueOrDie();
1741 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
1742 auto c = CheckMul(20.0, MakeCheckedNum(1), 5, 3UL).ValueOrDie();
1743 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
1744 auto d = CheckDiv(20.0, 2.0, MakeCheckedNum(5LL), -4).ValueOrDie();
1745 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
1746 auto e = CheckMod(MakeCheckedNum(20), 3).ValueOrDie();
1747 EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
1748 auto f = CheckLsh(1, MakeCheckedNum(2)).ValueOrDie();
1749 EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
1750 auto g = CheckRsh(4, MakeCheckedNum(2)).ValueOrDie();
1751 EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
1752 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
1753 EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
1754 }
1755
1756 {
1757 auto a = ClampAdd(1, 2UL, MakeClampedNum(3LL), 4);
1758 EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
1759 auto b = ClampSub(MakeClampedNum(20.0), 2UL, 4);
1760 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
1761 auto c = ClampMul(20.0, MakeClampedNum(1), 5, 3UL);
1762 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
1763 auto d = ClampDiv(20.0, 2.0, MakeClampedNum(5LL), -4);
1764 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
1765 auto e = ClampMod(MakeClampedNum(20), 3);
1766 EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
1767 auto f = ClampLsh(1, MakeClampedNum(2U));
1768 EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
1769 auto g = ClampRsh(4, MakeClampedNum(2U));
1770 EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
1771 auto h = ClampRsh(ClampAdd(1, 1, 1, 1), ClampSub(4U, 2));
1772 EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
1773 }
jschuh4fcd6fa2016-11-24 11:58:391774}
Justin Schuha26da272017-07-13 23:04:301775
Peter Kastingfc5d8f32020-06-30 02:38:171776TEST(SafeNumerics, CeilInt) {
Peter Kastingfbb9e562021-06-27 02:57:371777 constexpr float kMax = static_cast<float>(std::numeric_limits<int>::max());
Peter Kastingfc5d8f32020-06-30 02:38:171778 constexpr float kMin = std::numeric_limits<int>::min();
1779 constexpr float kInfinity = std::numeric_limits<float>::infinity();
1780 constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();
1781
1782 constexpr int kIntMax = std::numeric_limits<int>::max();
1783 constexpr int kIntMin = std::numeric_limits<int>::min();
1784
Peter Kasting24e973d2020-07-20 06:13:091785 EXPECT_EQ(kIntMax, ClampCeil(kInfinity));
1786 EXPECT_EQ(kIntMax, ClampCeil(kMax));
1787 EXPECT_EQ(kIntMax, ClampCeil(kMax + 100.0f));
1788 EXPECT_EQ(0, ClampCeil(kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171789
Peter Kasting24e973d2020-07-20 06:13:091790 EXPECT_EQ(-100, ClampCeil(-100.5f));
1791 EXPECT_EQ(0, ClampCeil(0.0f));
1792 EXPECT_EQ(101, ClampCeil(100.5f));
Peter Kastingfc5d8f32020-06-30 02:38:171793
Peter Kasting24e973d2020-07-20 06:13:091794 EXPECT_EQ(kIntMin, ClampCeil(-kInfinity));
1795 EXPECT_EQ(kIntMin, ClampCeil(kMin));
1796 EXPECT_EQ(kIntMin, ClampCeil(kMin - 100.0f));
1797 EXPECT_EQ(0, ClampCeil(-kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171798}
1799
1800TEST(SafeNumerics, FloorInt) {
Peter Kastingfbb9e562021-06-27 02:57:371801 constexpr float kMax = static_cast<float>(std::numeric_limits<int>::max());
Peter Kastingfc5d8f32020-06-30 02:38:171802 constexpr float kMin = std::numeric_limits<int>::min();
1803 constexpr float kInfinity = std::numeric_limits<float>::infinity();
1804 constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();
1805
1806 constexpr int kIntMax = std::numeric_limits<int>::max();
1807 constexpr int kIntMin = std::numeric_limits<int>::min();
1808
Peter Kasting24e973d2020-07-20 06:13:091809 EXPECT_EQ(kIntMax, ClampFloor(kInfinity));
1810 EXPECT_EQ(kIntMax, ClampFloor(kMax));
1811 EXPECT_EQ(kIntMax, ClampFloor(kMax + 100.0f));
1812 EXPECT_EQ(0, ClampFloor(kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171813
Peter Kasting24e973d2020-07-20 06:13:091814 EXPECT_EQ(-101, ClampFloor(-100.5f));
1815 EXPECT_EQ(0, ClampFloor(0.0f));
1816 EXPECT_EQ(100, ClampFloor(100.5f));
Peter Kastingfc5d8f32020-06-30 02:38:171817
Peter Kasting24e973d2020-07-20 06:13:091818 EXPECT_EQ(kIntMin, ClampFloor(-kInfinity));
1819 EXPECT_EQ(kIntMin, ClampFloor(kMin));
1820 EXPECT_EQ(kIntMin, ClampFloor(kMin - 100.0f));
1821 EXPECT_EQ(0, ClampFloor(-kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171822}
1823
1824TEST(SafeNumerics, RoundInt) {
Peter Kastingfbb9e562021-06-27 02:57:371825 constexpr float kMax = static_cast<float>(std::numeric_limits<int>::max());
Peter Kastingfc5d8f32020-06-30 02:38:171826 constexpr float kMin = std::numeric_limits<int>::min();
1827 constexpr float kInfinity = std::numeric_limits<float>::infinity();
1828 constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();
1829
1830 constexpr int kIntMax = std::numeric_limits<int>::max();
1831 constexpr int kIntMin = std::numeric_limits<int>::min();
1832
Peter Kasting24e973d2020-07-20 06:13:091833 EXPECT_EQ(kIntMax, ClampRound(kInfinity));
1834 EXPECT_EQ(kIntMax, ClampRound(kMax));
1835 EXPECT_EQ(kIntMax, ClampRound(kMax + 100.0f));
1836 EXPECT_EQ(0, ClampRound(kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171837
Peter Kasting24e973d2020-07-20 06:13:091838 EXPECT_EQ(-100, ClampRound(-100.1f));
1839 EXPECT_EQ(-101, ClampRound(-100.5f));
1840 EXPECT_EQ(-101, ClampRound(-100.9f));
1841 EXPECT_EQ(0, ClampRound(0.0f));
1842 EXPECT_EQ(100, ClampRound(100.1f));
1843 EXPECT_EQ(101, ClampRound(100.5f));
1844 EXPECT_EQ(101, ClampRound(100.9f));
Peter Kastingfc5d8f32020-06-30 02:38:171845
Peter Kasting24e973d2020-07-20 06:13:091846 EXPECT_EQ(kIntMin, ClampRound(-kInfinity));
1847 EXPECT_EQ(kIntMin, ClampRound(kMin));
1848 EXPECT_EQ(kIntMin, ClampRound(kMin - 100.0f));
1849 EXPECT_EQ(0, ClampRound(-kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171850}
1851
1852TEST(SafeNumerics, Int64) {
Peter Kastingfbb9e562021-06-27 02:57:371853 constexpr double kMax =
1854 static_cast<double>(std::numeric_limits<int64_t>::max());
Peter Kastingfc5d8f32020-06-30 02:38:171855 constexpr double kMin = std::numeric_limits<int64_t>::min();
1856 constexpr double kInfinity = std::numeric_limits<double>::infinity();
1857 constexpr double kNaN = std::numeric_limits<double>::quiet_NaN();
1858
1859 constexpr int64_t kInt64Max = std::numeric_limits<int64_t>::max();
1860 constexpr int64_t kInt64Min = std::numeric_limits<int64_t>::min();
1861
Peter Kasting24e973d2020-07-20 06:13:091862 EXPECT_EQ(kInt64Max, ClampFloor<int64_t>(kInfinity));
1863 EXPECT_EQ(kInt64Max, ClampCeil<int64_t>(kInfinity));
1864 EXPECT_EQ(kInt64Max, ClampRound<int64_t>(kInfinity));
1865 EXPECT_EQ(kInt64Max, ClampFloor<int64_t>(kMax));
1866 EXPECT_EQ(kInt64Max, ClampCeil<int64_t>(kMax));
1867 EXPECT_EQ(kInt64Max, ClampRound<int64_t>(kMax));
1868 EXPECT_EQ(kInt64Max, ClampFloor<int64_t>(kMax + 100.0));
1869 EXPECT_EQ(kInt64Max, ClampCeil<int64_t>(kMax + 100.0));
1870 EXPECT_EQ(kInt64Max, ClampRound<int64_t>(kMax + 100.0));
1871 EXPECT_EQ(0, ClampFloor<int64_t>(kNaN));
1872 EXPECT_EQ(0, ClampCeil<int64_t>(kNaN));
1873 EXPECT_EQ(0, ClampRound<int64_t>(kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171874
Peter Kasting24e973d2020-07-20 06:13:091875 EXPECT_EQ(kInt64Min, ClampFloor<int64_t>(-kInfinity));
1876 EXPECT_EQ(kInt64Min, ClampCeil<int64_t>(-kInfinity));
1877 EXPECT_EQ(kInt64Min, ClampRound<int64_t>(-kInfinity));
1878 EXPECT_EQ(kInt64Min, ClampFloor<int64_t>(kMin));
1879 EXPECT_EQ(kInt64Min, ClampCeil<int64_t>(kMin));
1880 EXPECT_EQ(kInt64Min, ClampRound<int64_t>(kMin));
1881 EXPECT_EQ(kInt64Min, ClampFloor<int64_t>(kMin - 100.0));
1882 EXPECT_EQ(kInt64Min, ClampCeil<int64_t>(kMin - 100.0));
1883 EXPECT_EQ(kInt64Min, ClampRound<int64_t>(kMin - 100.0));
1884 EXPECT_EQ(0, ClampFloor<int64_t>(-kNaN));
1885 EXPECT_EQ(0, ClampCeil<int64_t>(-kNaN));
1886 EXPECT_EQ(0, ClampRound<int64_t>(-kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171887}
1888
Mostyn Bramley-Moore2c1339ee72018-03-28 21:10:041889#if defined(__clang__)
1890#pragma clang diagnostic pop // -Winteger-overflow
1891#endif
1892
Justin Schuha26da272017-07-13 23:04:301893} // namespace internal
1894} // namespace base