[go: nahoru, domu]

blob: daadf6537430e80da0e35a146a4b6a1895a27ef1 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2013 The Chromium Authors
scottmg@chromium.orgc1c090d32013-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>
jschuh@chromium.org4efb2c32014-01-16 06:57:256#include <stdint.h>
7
8#include <limits>
vmpstr98a2fad2015-11-30 20:15:179#include <type_traits>
jschuh@chromium.org4efb2c32014-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"
jschuh@chromium.org5bfecbc2014-02-27 13:49:0430#include "base/numerics/safe_conversions.h"
31#include "base/numerics/safe_math.h"
David Benjamin954152b2023-10-24 17:46:2032#include "base/numerics/wrapping_math.h"
gab190f7542016-08-01 20:03:4133#include "base/test/gtest_util.h"
jschuh@chromium.org4efb2c32014-01-16 06:57:2534#include "testing/gtest/include/gtest/gtest.h"
35
avi9b6f42932015-12-26 22:15:1436#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
37#include <mmintrin.h>
38#endif
39
Justin Schuha26da272017-07-13 23:04:3040namespace base {
41namespace internal {
42
jschuh@chromium.org5bfecbc2014-02-27 13:49:0443using std::numeric_limits;
jschuh@chromium.org5bfecbc2014-02-27 13:49:0444
jschuhfafe0712015-09-14 20:21:2445// This is a helper function for finding the maximum value in Src that can be
46// wholy represented as the destination floating-point type.
47template <typename Dst, typename Src>
48Dst GetMaxConvertibleToFloat() {
jschuh5030b002016-12-05 18:21:4849 using DstLimits = numeric_limits<Dst>;
50 using SrcLimits = numeric_limits<Src>;
jschuhfafe0712015-09-14 20:21:2451 static_assert(SrcLimits::is_specialized, "Source must be numeric.");
52 static_assert(DstLimits::is_specialized, "Destination must be numeric.");
53 CHECK(DstLimits::is_iec559);
54
55 if (SrcLimits::digits <= DstLimits::digits &&
56 MaxExponent<Src>::value <= MaxExponent<Dst>::value)
57 return SrcLimits::max();
58 Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
59 while (max != static_cast<Src>(static_cast<Dst>(max))) {
60 max /= 2;
61 }
62 return static_cast<Dst>(max);
63}
64
jschuh33232e02017-01-03 20:33:3665// Test corner case promotions used
66static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int8_t>::value, "");
67static_assert(IsIntegerArithmeticSafe<int32_t, int16_t, int8_t>::value, "");
68static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int16_t>::value, "");
69static_assert(!IsIntegerArithmeticSafe<int32_t, int32_t, int8_t>::value, "");
70static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
71static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
72static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
73static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
74static_assert(
Andrew Rayskiy629912382023-10-18 22:58:4275 std::is_same_v<BigEnoughPromotion<int16_t, int8_t>::type, int16_t>,
jschuh33232e02017-01-03 20:33:3676 "");
77static_assert(
Andrew Rayskiy629912382023-10-18 22:58:4278 std::is_same_v<BigEnoughPromotion<int32_t, uint32_t>::type, int64_t>,
jschuh33232e02017-01-03 20:33:3679 "");
80static_assert(
Andrew Rayskiy629912382023-10-18 22:58:4281 std::is_same_v<BigEnoughPromotion<intmax_t, int8_t>::type, intmax_t>,
jschuh33232e02017-01-03 20:33:3682 "");
83static_assert(
Andrew Rayskiy629912382023-10-18 22:58:4284 std::is_same_v<BigEnoughPromotion<uintmax_t, int8_t>::type, uintmax_t>,
jschuh33232e02017-01-03 20:33:3685 "");
86static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
87static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
88static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
89static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
90static_assert(
Andrew Rayskiy6f021362023-10-19 19:55:0691 std::is_same_v<FastIntegerArithmeticPromotion<int16_t, int8_t>::type,
92 int32_t>,
jschuh33232e02017-01-03 20:33:3693 "");
94static_assert(
Andrew Rayskiy6f021362023-10-19 19:55:0695 std::is_same_v<FastIntegerArithmeticPromotion<int32_t, uint32_t>::type,
96 int64_t>,
jschuh33232e02017-01-03 20:33:3697 "");
98static_assert(
Andrew Rayskiy6f021362023-10-19 19:55:0699 std::is_same_v<FastIntegerArithmeticPromotion<intmax_t, int8_t>::type,
100 intmax_t>,
jschuh33232e02017-01-03 20:33:36101 "");
102static_assert(
Andrew Rayskiy6f021362023-10-19 19:55:06103 std::is_same_v<FastIntegerArithmeticPromotion<uintmax_t, int8_t>::type,
104 uintmax_t>,
jschuh33232e02017-01-03 20:33:36105 "");
106static_assert(FastIntegerArithmeticPromotion<int16_t, int8_t>::is_contained,
107 "");
108static_assert(FastIntegerArithmeticPromotion<int32_t, uint32_t>::is_contained,
109 "");
110static_assert(!FastIntegerArithmeticPromotion<intmax_t, int8_t>::is_contained,
111 "");
112static_assert(!FastIntegerArithmeticPromotion<uintmax_t, int8_t>::is_contained,
113 "");
114
Justin Schuhe2eefe612022-01-13 22:48:50115// Test compile-time (constexpr) evaluation of checking and saturation.
116constexpr int32_t kIntOne = 1;
117static_assert(1 == checked_cast<uint8_t>(kIntOne), "");
118static_assert(1 == saturated_cast<uint8_t>(kIntOne), "");
119static_assert(2U == MakeClampedNum(kIntOne) + 1, "");
120static_assert(2U == (MakeCheckedNum(kIntOne) + 1).ValueOrDie(), "");
121static_assert(0U == MakeClampedNum(kIntOne) - 1, "");
122static_assert(0U == (MakeCheckedNum(kIntOne) - 1).ValueOrDie(), "");
123static_assert(-1 == -MakeClampedNum(kIntOne), "");
124static_assert(-1 == (-MakeCheckedNum(kIntOne)).ValueOrDie(), "");
125static_assert(1U == MakeClampedNum(kIntOne) * 1, "");
126static_assert(1U == (MakeCheckedNum(kIntOne) * 1).ValueOrDie(), "");
127static_assert(1U == MakeClampedNum(kIntOne) / 1, "");
128static_assert(1U == (MakeCheckedNum(kIntOne) / 1).ValueOrDie(), "");
129static_assert(1 == MakeClampedNum(-kIntOne).Abs(), "");
130static_assert(1 == MakeCheckedNum(-kIntOne).Abs().ValueOrDie(), "");
131static_assert(1U == MakeClampedNum(kIntOne) % 2, "");
132static_assert(1U == (MakeCheckedNum(kIntOne) % 2).ValueOrDie(), "");
133static_assert(0U == MakeClampedNum(kIntOne) >> 1U, "");
134static_assert(0U == (MakeCheckedNum(kIntOne) >> 1U).ValueOrDie(), "");
135static_assert(2U == MakeClampedNum(kIntOne) << 1U, "");
136static_assert(2U == (MakeCheckedNum(kIntOne) << 1U).ValueOrDie(), "");
137static_assert(1 == MakeClampedNum(kIntOne) & 1U, "");
138static_assert(1 == (MakeCheckedNum(kIntOne) & 1U).ValueOrDie(), "");
139static_assert(1 == MakeClampedNum(kIntOne) | 1U, "");
140static_assert(1 == (MakeCheckedNum(kIntOne) | 1U).ValueOrDie(), "");
141static_assert(0 == MakeClampedNum(kIntOne) ^ 1U, "");
142static_assert(0 == (MakeCheckedNum(kIntOne) ^ 1U).ValueOrDie(), "");
143constexpr float kFloatOne = 1.0;
144static_assert(1 == int{checked_cast<int8_t>(kFloatOne)}, "");
145static_assert(1 == int{saturated_cast<int8_t>(kFloatOne)}, "");
146static_assert(2U == unsigned{MakeClampedNum(kFloatOne) + 1}, "");
147static_assert(2U ==
148 (MakeCheckedNum(kFloatOne) + 1).Cast<unsigned>().ValueOrDie(),
149 "");
150static_assert(0U == unsigned{MakeClampedNum(kFloatOne) - 1}, "");
151static_assert(0U ==
152 (MakeCheckedNum(kFloatOne) - 1).Cast<unsigned>().ValueOrDie(),
153 "");
154static_assert(-1 == int{-MakeClampedNum(kFloatOne)}, "");
155static_assert(-1 == (-MakeCheckedNum(kFloatOne)).Cast<int>().ValueOrDie(), "");
156static_assert(1U == unsigned{MakeClampedNum(kFloatOne) * 1}, "");
157static_assert(1U ==
158 (MakeCheckedNum(kFloatOne) * 1).Cast<unsigned>().ValueOrDie(),
159 "");
160static_assert(1U == unsigned{MakeClampedNum(kFloatOne) / 1}, "");
161static_assert(1U ==
162 (MakeCheckedNum(kFloatOne) / 1).Cast<unsigned>().ValueOrDie(),
163 "");
164static_assert(1 == int{MakeClampedNum(-kFloatOne).Abs()}, "");
165static_assert(1 == MakeCheckedNum(-kFloatOne).Abs().Cast<int>().ValueOrDie(),
166 "");
167
jschuhd1c1f2e2016-11-21 21:45:48168template <typename U>
169U GetNumericValueForTest(const CheckedNumeric<U>& src) {
170 return src.state_.value();
171}
jschuhb180f392017-07-03 15:09:22172
173template <typename U>
174U GetNumericValueForTest(const ClampedNumeric<U>& src) {
175 return static_cast<U>(src);
176}
177
178template <typename U>
179U GetNumericValueForTest(const U& src) {
180 return src;
181}
182
jschuh224f1d72016-11-25 20:08:48183// Logs the ValueOrDie() failure instead of crashing.
184struct LogOnFailure {
185 template <typename T>
186 static T HandleFailure() {
187 LOG(WARNING) << "ValueOrDie() failed unexpectedly.";
188 return T();
189 }
190};
191
jschuhb180f392017-07-03 15:09:22192template <typename T>
193constexpr T GetValue(const T& src) {
194 return src;
195}
196
197template <typename T, typename U>
198constexpr T GetValueAsDest(const U& src) {
199 return static_cast<T>(src);
200}
201
202template <typename T>
203constexpr T GetValue(const CheckedNumeric<T>& src) {
204 return src.template ValueOrDie<T, LogOnFailure>();
205}
206
207template <typename T, typename U>
208constexpr T GetValueAsDest(const CheckedNumeric<U>& src) {
209 return src.template ValueOrDie<T, LogOnFailure>();
210}
211
212template <typename T>
213constexpr T GetValue(const ClampedNumeric<T>& src) {
214 return static_cast<T>(src);
215}
216
217template <typename T, typename U>
218constexpr T GetValueAsDest(const ClampedNumeric<U>& src) {
219 return static_cast<T>(src);
220}
221
jschuh@chromium.org5bfecbc2014-02-27 13:49:04222// Helper macros to wrap displaying the conversion types and line numbers.
223#define TEST_EXPECTED_VALIDITY(expected, actual) \
jschuh4fcd6fa2016-11-24 11:58:39224 EXPECT_EQ(expected, (actual).template Cast<Dst>().IsValid()) \
jschuhd1c1f2e2016-11-21 21:45:48225 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
226 << dst << " on line " << line
jschuh@chromium.org5bfecbc2014-02-27 13:49:04227
jschuh819c8262016-05-21 01:39:03228#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
229#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
230
jschuhba3c4f942016-12-10 14:03:55231// We have to handle promotions, so infer the underlying type below from actual.
232#define TEST_EXPECTED_VALUE(expected, actual) \
jschuhb180f392017-07-03 15:09:22233 EXPECT_EQ(GetValue(expected), GetValueAsDest<decltype(expected)>(actual)) \
jschuhba3c4f942016-12-10 14:03:55234 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
jschuhd1c1f2e2016-11-21 21:45:48235 << dst << " on line " << line
jschuh@chromium.org5bfecbc2014-02-27 13:49:04236
jschuh23a4b062016-12-02 02:55:08237// Test the simple pointer arithmetic overrides.
238template <typename Dst>
239void TestStrictPointerMath() {
240 Dst dummy_value = 0;
241 Dst* dummy_ptr = &dummy_value;
242 static const Dst kDummyOffset = 2; // Don't want to go too far.
243 EXPECT_EQ(dummy_ptr + kDummyOffset,
244 dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
245 EXPECT_EQ(dummy_ptr - kDummyOffset,
246 dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
247 EXPECT_NE(dummy_ptr, dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
248 EXPECT_NE(dummy_ptr, dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
249 EXPECT_DEATH_IF_SUPPORTED(
250 dummy_ptr + StrictNumeric<size_t>(std::numeric_limits<size_t>::max()),
251 "");
252}
253
jschuh@chromium.org5bfecbc2014-02-27 13:49:04254// Signed integer arithmetic.
255template <typename Dst>
256static void TestSpecializedArithmetic(
257 const char* dst,
258 int line,
Andrew Rayskiy26072e12023-10-19 20:08:09259 std::enable_if_t<numeric_limits<Dst>::is_integer &&
260 numeric_limits<Dst>::is_signed,
261 int> = 0) {
jschuhb180f392017-07-03 15:09:22262 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:48263 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::lowest()));
264 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04265 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
jschuhba3c4f942016-12-10 14:03:55266 TEST_EXPECTED_VALUE(DstLimits::max(),
267 MakeCheckedNum(-DstLimits::max()).Abs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04268
jschuhb180f392017-07-03 15:09:22269 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
270 -ClampedNumeric<Dst>(DstLimits::lowest()));
271 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
272 ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
273 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).Abs());
274 TEST_EXPECTED_VALUE(DstLimits::max(),
275 MakeClampedNum(-DstLimits::max()).Abs());
276
jschuh819c8262016-05-21 01:39:03277 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
jschuh5030b002016-12-05 18:21:48278 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
279 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
280 DstLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04281
jschuhb180f392017-07-03 15:09:22282 TEST_EXPECTED_VALUE(DstLimits::max() - 1,
283 ClampedNumeric<Dst>(DstLimits::max()) + -1);
284 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
285 ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
286 TEST_EXPECTED_VALUE(
287 DstLimits::Underflow(),
288 ClampedNumeric<Dst>(DstLimits::lowest()) + DstLimits::lowest());
289
jschuh5030b002016-12-05 18:21:48290 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
291 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) - -1);
jschuh819c8262016-05-21 01:39:03292 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
jschuh5030b002016-12-05 18:21:48293 DstLimits::lowest());
294 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
jschuh819c8262016-05-21 01:39:03295 DstLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04296
jschuhb180f392017-07-03 15:09:22297 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
298 ClampedNumeric<Dst>(DstLimits::lowest()) - 1);
299 TEST_EXPECTED_VALUE(DstLimits::lowest() + 1,
300 ClampedNumeric<Dst>(DstLimits::lowest()) - -1);
301 TEST_EXPECTED_VALUE(
302 DstLimits::Overflow(),
303 ClampedNumeric<Dst>(DstLimits::max()) - DstLimits::lowest());
304 TEST_EXPECTED_VALUE(
305 DstLimits::Underflow(),
306 ClampedNumeric<Dst>(DstLimits::lowest()) - DstLimits::max());
307
jschuh5030b002016-12-05 18:21:48308 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
jschuhb180f392017-07-03 15:09:22309 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
310 ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04311
jschuh5030b002016-12-05 18:21:48312 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) / -1);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04313 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
jschuh5030b002016-12-05 18:21:48314 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * -1);
jschuh33232e02017-01-03 20:33:36315 TEST_EXPECTED_VALUE(DstLimits::max(),
316 CheckedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
317 TEST_EXPECTED_VALUE(DstLimits::max(),
318 CheckedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
319 TEST_EXPECTED_VALUE(DstLimits::lowest(),
320 CheckedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
321 TEST_EXPECTED_VALUE(DstLimits::lowest(),
322 CheckedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
jschuhb180f392017-07-03 15:09:22323 TEST_EXPECTED_VALUE(
324 typename std::make_unsigned<Dst>::type(0) - DstLimits::lowest(),
325 MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
jschuhba3c4f942016-12-10 14:03:55326 TEST_EXPECTED_VALUE(DstLimits::max(),
327 MakeCheckedNum(DstLimits::max()).UnsignedAbs());
328 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
329 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
330 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).UnsignedAbs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04331
jschuhb180f392017-07-03 15:09:22332 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
333 ClampedNumeric<Dst>(DstLimits::lowest()) / -1);
334 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) / 2);
335 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
336 ClampedNumeric<Dst>(DstLimits::lowest()) * -1);
337 TEST_EXPECTED_VALUE(DstLimits::max(),
338 ClampedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
339 TEST_EXPECTED_VALUE(DstLimits::max(),
340 ClampedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
341 TEST_EXPECTED_VALUE(DstLimits::lowest(),
342 ClampedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
343 TEST_EXPECTED_VALUE(DstLimits::lowest(),
344 ClampedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
345 TEST_EXPECTED_VALUE(
346 typename std::make_unsigned<Dst>::type(0) - DstLimits::lowest(),
347 MakeClampedNum(DstLimits::lowest()).UnsignedAbs());
348 TEST_EXPECTED_VALUE(DstLimits::max(),
349 MakeClampedNum(DstLimits::max()).UnsignedAbs());
350 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0).UnsignedAbs());
351 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).UnsignedAbs());
352 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).UnsignedAbs());
353
jschuh@chromium.org5bfecbc2014-02-27 13:49:04354 // Modulus is legal only for integers.
Tom Sepezfe88d4192020-05-28 16:41:05355 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % 2);
356 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % 1);
357 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % -1);
358 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % -2);
359 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04360 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
Tom Sepezfe88d4192020-05-28 16:41:05361 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % -1);
362 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % -2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04363 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05364 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) % 1);
365 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) % -1);
jschuhb180f392017-07-03 15:09:22366 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % -2);
jschuh5030b002016-12-05 18:21:48367 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05368 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 1);
369 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % -1);
370 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % -2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04371 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05372 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::max()) % 1);
373 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::max()) % -1);
374 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % -2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04375 // Test all the different modulus combinations.
376 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
377 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
378 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
379 CheckedNumeric<Dst> checked_dst = 1;
380 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
tsepezdfd77a92016-11-02 20:18:06381 // Test that div by 0 is avoided but returns invalid result.
382 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
jschuh3ab54042016-11-17 06:58:44383 // Test bit shifts.
384 volatile Dst negative_one = -1;
385 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
jschuh5030b002016-12-05 18:21:48386 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
387 << (IntegerBitsPlusSign<Dst>::value - 1));
388 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
389 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44390 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
jschuh5030b002016-12-05 18:21:48391 TEST_EXPECTED_VALUE(
392 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2),
393 CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2));
jschuh3ab54042016-11-17 06:58:44394 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0)
jschuh5030b002016-12-05 18:21:48395 << (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44396 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
397 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
jschuh5030b002016-12-05 18:21:48398 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
399 IntegerBitsPlusSign<Dst>::value);
400 TEST_EXPECTED_VALUE(
401 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44402 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
jschuh23a4b062016-12-02 02:55:08403
jschuhb180f392017-07-03 15:09:22404 // Modulus is legal only for integers.
Tom Sepezfe88d4192020-05-28 16:41:05405 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % 2);
406 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % 1);
407 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % -1);
408 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % -2);
409 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % 2);
jschuhb180f392017-07-03 15:09:22410 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
Tom Sepezfe88d4192020-05-28 16:41:05411 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % -1);
412 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % -2);
jschuhb180f392017-07-03 15:09:22413 TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(-1) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05414 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) % 1);
415 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) % -1);
jschuhb180f392017-07-03 15:09:22416 TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(-1) % -2);
417 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05418 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 1);
419 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % -1);
420 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % -2);
jschuhb180f392017-07-03 15:09:22421 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05422 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) % 1);
423 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) % -1);
424 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % -2);
jschuhb180f392017-07-03 15:09:22425 // Test all the different modulus combinations.
426 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % ClampedNumeric<Dst>(1));
427 TEST_EXPECTED_VALUE(0, 1 % ClampedNumeric<Dst>(1));
428 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
429 ClampedNumeric<Dst> clamped_dst = 1;
430 TEST_EXPECTED_VALUE(0, clamped_dst %= 1);
431 TEST_EXPECTED_VALUE(Dst(1), ClampedNumeric<Dst>(1) % 0);
432 // Test bit shifts.
433 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
434 ClampedNumeric<Dst>(1)
435 << (IntegerBitsPlusSign<Dst>::value - 1U));
436 TEST_EXPECTED_VALUE(Dst(0), ClampedNumeric<Dst>(0)
437 << (IntegerBitsPlusSign<Dst>::value + 0U));
438 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
439 ClampedNumeric<Dst>(DstLimits::max()) << 1U);
440 TEST_EXPECTED_VALUE(
441 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2U),
442 ClampedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2U));
443 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0)
444 << (IntegerBitsPlusSign<Dst>::value - 1U));
445 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) << 0U);
446 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) << 1U);
447 TEST_EXPECTED_VALUE(
448 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value + 0U));
449 TEST_EXPECTED_VALUE(
450 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
451 TEST_EXPECTED_VALUE(
452 -1, ClampedNumeric<Dst>(-1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
453 TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(DstLimits::lowest()) >>
454 (IntegerBitsPlusSign<Dst>::value - 0U));
455
jschuh23a4b062016-12-02 02:55:08456 TestStrictPointerMath<Dst>();
jschuh@chromium.org5bfecbc2014-02-27 13:49:04457}
458
459// Unsigned integer arithmetic.
460template <typename Dst>
461static void TestSpecializedArithmetic(
462 const char* dst,
463 int line,
Andrew Rayskiy26072e12023-10-19 20:08:09464 std::enable_if_t<numeric_limits<Dst>::is_integer &&
465 !numeric_limits<Dst>::is_signed,
466 int> = 0) {
jschuhb180f392017-07-03 15:09:22467 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:48468 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
469 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
470 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
471 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
472 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04473 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
jschuh5030b002016-12-05 18:21:48474 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
jschuh819c8262016-05-21 01:39:03475 TEST_EXPECTED_SUCCESS(
jschuh5030b002016-12-05 18:21:48476 CheckedNumeric<typename std::make_signed<Dst>::type>(
477 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
jschuheaf375f2015-09-17 01:04:28478 .UnsignedAbs());
jschuhba3c4f942016-12-10 14:03:55479 TEST_EXPECTED_VALUE(DstLimits::lowest(),
480 MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
481 TEST_EXPECTED_VALUE(DstLimits::max(),
482 MakeCheckedNum(DstLimits::max()).UnsignedAbs());
483 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
484 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04485
jschuhb180f392017-07-03 15:09:22486 TEST_EXPECTED_VALUE(0, -ClampedNumeric<Dst>(DstLimits::lowest()));
487 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
488 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
489 ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
490 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
491 ClampedNumeric<Dst>(DstLimits::lowest()) - 1);
492 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
493 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) / 2);
494 TEST_EXPECTED_VALUE(0,
495 ClampedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
496 TEST_EXPECTED_VALUE(
497 as_unsigned(
498 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest()),
499 ClampedNumeric<typename std::make_signed<Dst>::type>(
500 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
501 .UnsignedAbs());
502 TEST_EXPECTED_VALUE(DstLimits::lowest(),
503 MakeClampedNum(DstLimits::lowest()).UnsignedAbs());
504 TEST_EXPECTED_VALUE(DstLimits::max(),
505 MakeClampedNum(DstLimits::max()).UnsignedAbs());
506 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0).UnsignedAbs());
507 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).UnsignedAbs());
508
jschuh@chromium.org5bfecbc2014-02-27 13:49:04509 // Modulus is legal only for integers.
510 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
511 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
512 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
jschuh5030b002016-12-05 18:21:48513 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04514 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
515 // Test all the different modulus combinations.
516 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
517 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
518 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
519 CheckedNumeric<Dst> checked_dst = 1;
520 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
tsepezdfd77a92016-11-02 20:18:06521 // Test that div by 0 is avoided but returns invalid result.
522 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
jschuh5030b002016-12-05 18:21:48523 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
524 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44525 // Test bit shifts.
526 volatile int negative_one = -1;
527 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
jschuh5030b002016-12-05 18:21:48528 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
529 << IntegerBitsPlusSign<Dst>::value);
530 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
531 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44532 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
jschuh5030b002016-12-05 18:21:48533 TEST_EXPECTED_VALUE(
534 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1),
535 CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44536 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
537 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
jschuh5030b002016-12-05 18:21:48538 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
539 IntegerBitsPlusSign<Dst>::value);
540 TEST_EXPECTED_VALUE(
541 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44542 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
jschuhb6737bb2016-11-29 03:06:59543 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) & 1);
544 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
545 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) & 1);
546 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
547 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
jschuh4bc919c2016-12-04 15:08:27548 MakeCheckedNum(DstLimits::max()) & -1);
jschuhb6737bb2016-11-29 03:06:59549 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 1);
550 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 0);
551 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) | 1);
552 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0);
553 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
554 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1));
555 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1);
556 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0);
557 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1);
558 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0);
559 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
560 CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
jschuh970313c2016-11-24 21:40:58561 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0));
jschuh23a4b062016-12-02 02:55:08562
jschuhb180f392017-07-03 15:09:22563 // Modulus is legal only for integers.
564 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() % 1);
565 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
566 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % 2);
567 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 2);
568 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % 2);
569 // Test all the different modulus combinations.
570 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % ClampedNumeric<Dst>(1));
571 TEST_EXPECTED_VALUE(0, 1 % ClampedNumeric<Dst>(1));
572 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
573 ClampedNumeric<Dst> clamped_dst = 1;
574 TEST_EXPECTED_VALUE(0, clamped_dst %= 1);
575 // Test that div by 0 is avoided but returns invalid result.
576 TEST_EXPECTED_VALUE(Dst(1), ClampedNumeric<Dst>(1) % 0);
577 // Test bit shifts.
578 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
579 ClampedNumeric<Dst>(1)
580 << as_unsigned(IntegerBitsPlusSign<Dst>::value));
581 TEST_EXPECTED_VALUE(Dst(0), ClampedNumeric<Dst>(0) << as_unsigned(
582 IntegerBitsPlusSign<Dst>::value));
583 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
584 ClampedNumeric<Dst>(DstLimits::max()) << 1U);
585 TEST_EXPECTED_VALUE(
586 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1U),
587 ClampedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1U));
588 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) << 0U);
589 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) << 1U);
590 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) >>
591 as_unsigned(IntegerBitsPlusSign<Dst>::value));
592 TEST_EXPECTED_VALUE(
593 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
594 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) & 1);
595 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) & 0);
596 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) & 1);
597 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) & 0);
598 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
599 MakeClampedNum(DstLimits::max()) & -1);
600 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) | 1);
601 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) | 0);
602 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(0) | 1);
603 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) | 0);
604 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
605 ClampedNumeric<Dst>(0) | static_cast<Dst>(-1));
606 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) ^ 1);
607 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) ^ 0);
608 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(0) ^ 1);
609 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) ^ 0);
610 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
611 ClampedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
612 TEST_EXPECTED_VALUE(DstLimits::max(), ~ClampedNumeric<Dst>(0));
613
jschuh23a4b062016-12-02 02:55:08614 TestStrictPointerMath<Dst>();
jschuh@chromium.org5bfecbc2014-02-27 13:49:04615}
616
617// Floating point arithmetic.
618template <typename Dst>
619void TestSpecializedArithmetic(
620 const char* dst,
621 int line,
Andrew Rayskiy26072e12023-10-19 20:08:09622 std::enable_if_t<numeric_limits<Dst>::is_iec559, int> = 0) {
jschuhb180f392017-07-03 15:09:22623 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:48624 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
jschuh@chromium.org5bfecbc2014-02-27 13:49:04625
jschuh5030b002016-12-05 18:21:48626 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04627 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
628
jschuh5030b002016-12-05 18:21:48629 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
jschuh819c8262016-05-21 01:39:03630 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
jschuh5030b002016-12-05 18:21:48631 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
632 DstLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04633
jschuh819c8262016-05-21 01:39:03634 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
jschuh5030b002016-12-05 18:21:48635 DstLimits::lowest());
636 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
jschuh819c8262016-05-21 01:39:03637 DstLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04638
jschuh5030b002016-12-05 18:21:48639 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04640
641 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
jschuhb180f392017-07-03 15:09:22642
643 TEST_EXPECTED_VALUE(DstLimits::max(),
644 -ClampedNumeric<Dst>(DstLimits::lowest()));
645
646 TEST_EXPECTED_VALUE(DstLimits::max(),
647 ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
648 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).Abs());
649
650 TEST_EXPECTED_VALUE(DstLimits::lowest() - 1,
651 ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
652 TEST_EXPECTED_VALUE(DstLimits::max() + 1,
653 ClampedNumeric<Dst>(DstLimits::max()) + 1);
654 TEST_EXPECTED_VALUE(
655 DstLimits::Underflow(),
656 ClampedNumeric<Dst>(DstLimits::lowest()) + DstLimits::lowest());
657
658 TEST_EXPECTED_VALUE(
659 DstLimits::Overflow(),
660 ClampedNumeric<Dst>(DstLimits::max()) - DstLimits::lowest());
661 TEST_EXPECTED_VALUE(
662 DstLimits::Underflow(),
663 ClampedNumeric<Dst>(DstLimits::lowest()) - DstLimits::max());
664
665 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
666 ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
667
668 TEST_EXPECTED_VALUE(-0.5, ClampedNumeric<Dst>(-1.0) / 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04669}
670
671// Generic arithmetic tests.
672template <typename Dst>
673static void TestArithmetic(const char* dst, int line) {
jschuhb180f392017-07-03 15:09:22674 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh@chromium.org5bfecbc2014-02-27 13:49:04675
Daniel Chengef817202022-08-27 09:01:15676 // Test C++17 class template argument deduction
677 static_assert(
678 std::is_same_v<Dst, typename decltype(CheckedNumeric(Dst{0}))::type>);
679 static_assert(
680 std::is_same_v<Dst, typename decltype(ClampedNumeric(Dst{0}))::type>);
681 static_assert(
682 std::is_same_v<Dst, typename decltype(StrictNumeric(Dst{0}))::type>);
683
jschuh@chromium.org5bfecbc2014-02-27 13:49:04684 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
Justin Schuh5cc331de2017-07-25 18:05:22685 EXPECT_EQ(false, CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
686 DstLimits::max())
687 .IsValid());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04688 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
689 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
690 EXPECT_EQ(static_cast<Dst>(1),
691 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
Justin Schuh5cc331de2017-07-25 18:05:22692 DstLimits::max())
693 .ValueOrDefault(1));
jschuh@chromium.org5bfecbc2014-02-27 13:49:04694
695 // Test the operator combinations.
696 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
697 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
698 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
699 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
700 TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
701 TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
702 TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
703 TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
704 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
705 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
706 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
707 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
708 CheckedNumeric<Dst> checked_dst = 1;
709 TEST_EXPECTED_VALUE(2, checked_dst += 1);
710 checked_dst = 1;
711 TEST_EXPECTED_VALUE(0, checked_dst -= 1);
712 checked_dst = 1;
713 TEST_EXPECTED_VALUE(1, checked_dst *= 1);
714 checked_dst = 1;
715 TEST_EXPECTED_VALUE(1, checked_dst /= 1);
716
jschuhb180f392017-07-03 15:09:22717 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) + ClampedNumeric<Dst>(1));
718 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) - ClampedNumeric<Dst>(1));
719 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) * ClampedNumeric<Dst>(1));
720 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / ClampedNumeric<Dst>(1));
721 TEST_EXPECTED_VALUE(2, 1 + ClampedNumeric<Dst>(1));
722 TEST_EXPECTED_VALUE(0, 1 - ClampedNumeric<Dst>(1));
723 TEST_EXPECTED_VALUE(1, 1 * ClampedNumeric<Dst>(1));
724 TEST_EXPECTED_VALUE(1, 1 / ClampedNumeric<Dst>(1));
725 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) + 1);
726 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) - 1);
727 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) * 1);
728 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / 1);
729 ClampedNumeric<Dst> clamped_dst = 1;
730 TEST_EXPECTED_VALUE(2, clamped_dst += 1);
731 clamped_dst = 1;
732 TEST_EXPECTED_VALUE(0, clamped_dst -= 1);
733 clamped_dst = 1;
734 TEST_EXPECTED_VALUE(1, clamped_dst *= 1);
735 clamped_dst = 1;
736 TEST_EXPECTED_VALUE(1, clamped_dst /= 1);
737
jschuh@chromium.org5bfecbc2014-02-27 13:49:04738 // Generic negation.
jschuh749c7f72016-09-07 16:22:26739 if (DstLimits::is_signed) {
740 TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
741 TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
742 TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
743 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
744 -CheckedNumeric<Dst>(DstLimits::max()));
jschuhb180f392017-07-03 15:09:22745
746 TEST_EXPECTED_VALUE(0, -ClampedNumeric<Dst>());
747 TEST_EXPECTED_VALUE(-1, -ClampedNumeric<Dst>(1));
748 TEST_EXPECTED_VALUE(1, -ClampedNumeric<Dst>(-1));
749 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
750 -ClampedNumeric<Dst>(DstLimits::max()));
Justin Schuha15cf3c2017-07-14 23:16:58751
752 // The runtime paths for saturated negation differ significantly from what
753 // gets evaluated at compile-time. Making this test volatile forces the
754 // compiler to generate code rather than fold constant expressions.
755 volatile Dst value = Dst(0);
756 TEST_EXPECTED_VALUE(0, -MakeClampedNum(value));
757 value = Dst(1);
758 TEST_EXPECTED_VALUE(-1, -MakeClampedNum(value));
759 value = Dst(2);
760 TEST_EXPECTED_VALUE(-2, -MakeClampedNum(value));
761 value = Dst(-1);
762 TEST_EXPECTED_VALUE(1, -MakeClampedNum(value));
763 value = Dst(-2);
764 TEST_EXPECTED_VALUE(2, -MakeClampedNum(value));
765 value = DstLimits::max();
766 TEST_EXPECTED_VALUE(Dst(DstLimits::max() * -1), -MakeClampedNum(value));
767 value = Dst(-1 * DstLimits::max());
768 TEST_EXPECTED_VALUE(DstLimits::max(), -MakeClampedNum(value));
769 value = DstLimits::lowest();
770 TEST_EXPECTED_VALUE(DstLimits::max(), -MakeClampedNum(value));
jschuh749c7f72016-09-07 16:22:26771 }
jschuh@chromium.org5bfecbc2014-02-27 13:49:04772
773 // Generic absolute value.
774 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
775 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
776 TEST_EXPECTED_VALUE(DstLimits::max(),
777 CheckedNumeric<Dst>(DstLimits::max()).Abs());
778
jschuhb180f392017-07-03 15:09:22779 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>().Abs());
780 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).Abs());
781 TEST_EXPECTED_VALUE(DstLimits::max(),
782 ClampedNumeric<Dst>(DstLimits::max()).Abs());
783
jschuh@chromium.org5bfecbc2014-02-27 13:49:04784 // Generic addition.
785 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
786 TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
jschuh216b62a2016-11-08 03:53:08787 if (numeric_limits<Dst>::is_signed)
788 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
jschuh5030b002016-12-05 18:21:48789 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + 1);
jschuh819c8262016-05-21 01:39:03790 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) +
791 DstLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04792
jschuhb180f392017-07-03 15:09:22793 TEST_EXPECTED_VALUE(1, (ClampedNumeric<Dst>() + 1));
794 TEST_EXPECTED_VALUE(2, (ClampedNumeric<Dst>(1) + 1));
795 if (numeric_limits<Dst>::is_signed)
796 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(-1) + 1));
797 TEST_EXPECTED_VALUE(DstLimits::lowest() + 1,
798 ClampedNumeric<Dst>(DstLimits::lowest()) + 1);
799 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
800 ClampedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
801
jschuh@chromium.org5bfecbc2014-02-27 13:49:04802 // Generic subtraction.
jschuh@chromium.org5bfecbc2014-02-27 13:49:04803 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
jschuh819c8262016-05-21 01:39:03804 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
jschuh216b62a2016-11-08 03:53:08805 if (numeric_limits<Dst>::is_signed) {
806 TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
807 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
jschuh657a3d62016-11-15 18:23:45808 } else {
809 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -1);
jschuh216b62a2016-11-08 03:53:08810 }
jschuh@chromium.org5bfecbc2014-02-27 13:49:04811
jschuhb180f392017-07-03 15:09:22812 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(1) - 1));
813 TEST_EXPECTED_VALUE(DstLimits::max() - 1,
814 ClampedNumeric<Dst>(DstLimits::max()) - 1);
815 if (numeric_limits<Dst>::is_signed) {
816 TEST_EXPECTED_VALUE(-1, (ClampedNumeric<Dst>() - 1));
817 TEST_EXPECTED_VALUE(-2, (ClampedNumeric<Dst>(-1) - 1));
818 } else {
819 TEST_EXPECTED_VALUE(DstLimits::max(),
820 ClampedNumeric<Dst>(DstLimits::max()) - -1);
821 }
822
jschuh@chromium.org5bfecbc2014-02-27 13:49:04823 // Generic multiplication.
824 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
825 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
eroman0397125f2015-05-18 14:44:32826 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
jschuh216b62a2016-11-08 03:53:08827 if (numeric_limits<Dst>::is_signed) {
828 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
829 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
jschuh749c7f72016-09-07 16:22:26830 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
jschuh657a3d62016-11-15 18:23:45831 } else {
832 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * -2);
833 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
834 CheckedNumeric<uintmax_t>(-2));
jschuh749c7f72016-09-07 16:22:26835 }
jschuh216b62a2016-11-08 03:53:08836 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
837 DstLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04838
jschuhb180f392017-07-03 15:09:22839 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>() * 1));
840 TEST_EXPECTED_VALUE(1, (ClampedNumeric<Dst>(1) * 1));
841 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(0) * 0));
842 if (numeric_limits<Dst>::is_signed) {
843 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(-1) * 0));
844 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(0) * -1));
845 TEST_EXPECTED_VALUE(-2, (ClampedNumeric<Dst>(-1) * 2));
846 } else {
847 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
848 ClampedNumeric<Dst>(DstLimits::max()) * -2);
849 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) *
850 ClampedNumeric<uintmax_t>(-2));
851 }
852 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
853 ClampedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
854
jschuh@chromium.org5bfecbc2014-02-27 13:49:04855 // Generic division.
856 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
857 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
jschuh5030b002016-12-05 18:21:48858 TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
859 CheckedNumeric<Dst>(DstLimits::lowest()) / 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04860 TEST_EXPECTED_VALUE(DstLimits::max() / 2,
861 CheckedNumeric<Dst>(DstLimits::max()) / 2);
jschuhb180f392017-07-03 15:09:22862 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) / 0);
863
864 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() / 1);
865 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / 1);
866 TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
867 ClampedNumeric<Dst>(DstLimits::lowest()) / 2);
868 TEST_EXPECTED_VALUE(DstLimits::max() / 2,
869 ClampedNumeric<Dst>(DstLimits::max()) / 2);
870 TEST_EXPECTED_VALUE(DstLimits::Overflow(), ClampedNumeric<Dst>(1) / 0);
871 TEST_EXPECTED_VALUE(DstLimits::Underflow(), ClampedNumeric<Dst>(-1) / 0);
872 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) / 0);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04873
874 TestSpecializedArithmetic<Dst>(dst, line);
875}
876
877// Helper macro to wrap displaying the conversion types and line numbers.
878#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
879
880TEST(SafeNumerics, SignedIntegerMath) {
881 TEST_ARITHMETIC(int8_t);
Justin Schuha26da272017-07-13 23:04:30882 TEST_ARITHMETIC(int16_t);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04883 TEST_ARITHMETIC(int);
884 TEST_ARITHMETIC(intptr_t);
885 TEST_ARITHMETIC(intmax_t);
886}
887
888TEST(SafeNumerics, UnsignedIntegerMath) {
889 TEST_ARITHMETIC(uint8_t);
Justin Schuha26da272017-07-13 23:04:30890 TEST_ARITHMETIC(uint16_t);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04891 TEST_ARITHMETIC(unsigned int);
892 TEST_ARITHMETIC(uintptr_t);
893 TEST_ARITHMETIC(uintmax_t);
894}
895
896TEST(SafeNumerics, FloatingPointMath) {
897 TEST_ARITHMETIC(float);
898 TEST_ARITHMETIC(double);
899}
scottmg@chromium.orgc1c090d32013-01-16 23:34:04900
jschuh@chromium.org4efb2c32014-01-16 06:57:25901// Enumerates the five different conversions types we need to test.
902enum NumericConversionType {
903 SIGN_PRESERVING_VALUE_PRESERVING,
904 SIGN_PRESERVING_NARROW,
905 SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
906 SIGN_TO_UNSIGN_NARROW,
907 UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
908};
scottmg@chromium.orgc1c090d32013-01-16 23:34:04909
jschuh@chromium.org4efb2c32014-01-16 06:57:25910// Template covering the different conversion tests.
911template <typename Dst, typename Src, NumericConversionType conversion>
912struct TestNumericConversion {};
scottmg@chromium.orgc1c090d32013-01-16 23:34:04913
jschuh082b2ba2017-01-06 11:40:54914enum RangeConstraint {
915 RANGE_VALID = 0x0, // Value can be represented by the destination type.
916 RANGE_UNDERFLOW = 0x1, // Value would underflow.
917 RANGE_OVERFLOW = 0x2, // Value would overflow.
918 RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN).
919};
920
921// These are some wrappers to make the tests a bit cleaner.
922constexpr RangeConstraint RangeCheckToEnum(const RangeCheck constraint) {
923 return static_cast<RangeConstraint>(
924 static_cast<int>(constraint.IsOverflowFlagSet()) << 1 |
925 static_cast<int>(constraint.IsUnderflowFlagSet()));
926}
927
jschuh@chromium.org5bfecbc2014-02-27 13:49:04928// EXPECT_EQ wrappers providing specific detail on test failures.
jschuh082b2ba2017-01-06 11:40:54929#define TEST_EXPECTED_RANGE(expected, actual) \
930 EXPECT_EQ(expected, \
Justin Schuha26da272017-07-13 23:04:30931 RangeCheckToEnum(DstRangeRelationToSrcRange<Dst>(actual))) \
jschuh082b2ba2017-01-06 11:40:54932 << "Conversion test: " << src << " value " << actual << " to " << dst \
jschuh657a3d62016-11-15 18:23:45933 << " on line " << line
jschuh@chromium.org4efb2c32014-01-16 06:57:25934
935template <typename Dst, typename Src>
Justin Schuh5cc2abf2017-08-01 04:58:07936void TestStrictComparison(const char* dst, const char* src, int line) {
jschuh5030b002016-12-05 18:21:48937 using DstLimits = numeric_limits<Dst>;
938 using SrcLimits = numeric_limits<Src>;
jschuh711ac6a2016-12-04 07:17:48939 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < DstLimits::max(), "");
940 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < SrcLimits::max(), "");
941 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= DstLimits::max()),
jschuh23a4b062016-12-02 02:55:08942 "");
jschuh711ac6a2016-12-04 07:17:48943 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= SrcLimits::max()),
jschuh23a4b062016-12-02 02:55:08944 "");
jschuh711ac6a2016-12-04 07:17:48945 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= DstLimits::max(),
jschuh23a4b062016-12-02 02:55:08946 "");
jschuh711ac6a2016-12-04 07:17:48947 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= SrcLimits::max(),
jschuh23a4b062016-12-02 02:55:08948 "");
jschuh711ac6a2016-12-04 07:17:48949 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > DstLimits::max()),
950 "");
951 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > SrcLimits::max()),
952 "");
953 static_assert(StrictNumeric<Src>(SrcLimits::max()) > DstLimits::lowest(), "");
954 static_assert(StrictNumeric<Src>(SrcLimits::max()) > SrcLimits::lowest(), "");
955 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= DstLimits::lowest()),
956 "");
957 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= SrcLimits::lowest()),
958 "");
959 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= DstLimits::lowest(),
960 "");
961 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= SrcLimits::lowest(),
962 "");
963 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < DstLimits::lowest()),
964 "");
965 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < SrcLimits::lowest()),
966 "");
jschuh23a4b062016-12-02 02:55:08967 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(1),
968 "");
969 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(0),
970 "");
971 static_assert(StrictNumeric<Src>(SrcLimits::max()) != static_cast<Dst>(0),
972 "");
jschuh711ac6a2016-12-04 07:17:48973 static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::lowest(),
974 "");
jschuh23a4b062016-12-02 02:55:08975 static_assert(
976 !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), "");
977 static_assert(
978 !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), "");
jschuh711ac6a2016-12-04 07:17:48979
980 // Due to differences in float handling between compilers, these aren't
981 // compile-time constants everywhere. So, we use run-time tests.
jschuh4bc919c2016-12-04 15:08:27982 EXPECT_EQ(
983 SrcLimits::max(),
984 MakeCheckedNum(SrcLimits::max()).Max(DstLimits::lowest()).ValueOrDie());
985 EXPECT_EQ(
986 DstLimits::max(),
987 MakeCheckedNum(SrcLimits::lowest()).Max(DstLimits::max()).ValueOrDie());
988 EXPECT_EQ(
989 DstLimits::lowest(),
990 MakeCheckedNum(SrcLimits::max()).Min(DstLimits::lowest()).ValueOrDie());
991 EXPECT_EQ(
992 SrcLimits::lowest(),
993 MakeCheckedNum(SrcLimits::lowest()).Min(DstLimits::max()).ValueOrDie());
994 EXPECT_EQ(SrcLimits::lowest(), CheckMin(MakeStrictNum(1), MakeCheckedNum(0),
jschuh711ac6a2016-12-04 07:17:48995 DstLimits::max(), SrcLimits::lowest())
996 .ValueOrDie());
jschuh4bc919c2016-12-04 15:08:27997 EXPECT_EQ(DstLimits::max(), CheckMax(MakeStrictNum(1), MakeCheckedNum(0),
jschuh711ac6a2016-12-04 07:17:48998 DstLimits::max(), SrcLimits::lowest())
999 .ValueOrDie());
Justin Schuha81d2e52017-07-14 02:53:341000
1001 EXPECT_EQ(SrcLimits::max(),
1002 MakeClampedNum(SrcLimits::max()).Max(DstLimits::lowest()));
1003 EXPECT_EQ(DstLimits::max(),
1004 MakeClampedNum(SrcLimits::lowest()).Max(DstLimits::max()));
1005 EXPECT_EQ(DstLimits::lowest(),
1006 MakeClampedNum(SrcLimits::max()).Min(DstLimits::lowest()));
1007 EXPECT_EQ(SrcLimits::lowest(),
1008 MakeClampedNum(SrcLimits::lowest()).Min(DstLimits::max()));
1009 EXPECT_EQ(SrcLimits::lowest(),
1010 ClampMin(MakeStrictNum(1), MakeClampedNum(0), DstLimits::max(),
1011 SrcLimits::lowest()));
1012 EXPECT_EQ(DstLimits::max(), ClampMax(MakeStrictNum(1), MakeClampedNum(0),
1013 DstLimits::max(), SrcLimits::lowest()));
Justin Schuh5cc2abf2017-08-01 04:58:071014
1015 if (IsValueInRangeForNumericType<Dst>(SrcLimits::max())) {
1016 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()), (CommonMax<Dst, Src>()));
1017 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()),
1018 (CommonMaxOrMin<Dst, Src>(false)));
1019 } else {
1020 TEST_EXPECTED_VALUE(DstLimits::max(), (CommonMax<Dst, Src>()));
1021 TEST_EXPECTED_VALUE(DstLimits::max(), (CommonMaxOrMin<Dst, Src>(false)));
1022 }
1023
1024 if (IsValueInRangeForNumericType<Dst>(SrcLimits::lowest())) {
1025 TEST_EXPECTED_VALUE(Dst(SrcLimits::lowest()), (CommonMin<Dst, Src>()));
1026 TEST_EXPECTED_VALUE(Dst(SrcLimits::lowest()),
1027 (CommonMaxOrMin<Dst, Src>(true)));
1028 } else {
1029 TEST_EXPECTED_VALUE(DstLimits::lowest(), (CommonMin<Dst, Src>()));
1030 TEST_EXPECTED_VALUE(DstLimits::lowest(), (CommonMaxOrMin<Dst, Src>(true)));
1031 }
jschuh23a4b062016-12-02 02:55:081032}
1033
1034template <typename Dst, typename Src>
jschuh@chromium.org4efb2c32014-01-16 06:57:251035struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
Justin Schuh5cc331de2017-07-25 18:05:221036 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221037 using SrcLimits = SaturationDefaultLimits<Src>;
1038 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:481039 // Integral to floating.
jschuhd2d9fe02014-10-14 14:31:371040 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
jschuh5030b002016-12-05 18:21:481041 // Not floating to integral and...
1042 (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
1043 // Same sign, same numeric, source is narrower or same.
1044 ((SrcLimits::is_signed == DstLimits::is_signed &&
1045 MaxExponent<Dst>::value >= MaxExponent<Src>::value) ||
1046 // Or signed destination and source is smaller
1047 (DstLimits::is_signed &&
1048 MaxExponent<Dst>::value >= MaxExponent<Src>::value))),
jschuhd2d9fe02014-10-14 14:31:371049 "Comparison must be sign preserving and value preserving");
jschuh@chromium.org4efb2c32014-01-16 06:57:251050
Justin Schuh5cc2abf2017-08-01 04:58:071051 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081052
jschuh@chromium.org5bfecbc2014-02-27 13:49:041053 const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
jschuhb180f392017-07-03 15:09:221054 const ClampedNumeric<Dst> clamped_dst = SrcLimits::max();
jschuh819c8262016-05-21 01:39:031055 TEST_EXPECTED_SUCCESS(checked_dst);
jschuhb180f392017-07-03 15:09:221056 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()), clamped_dst);
jschuh@chromium.org5bfecbc2014-02-27 13:49:041057 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
1058 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
1059 // At least twice larger type.
jschuh819c8262016-05-21 01:39:031060 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
jschuhb180f392017-07-03 15:09:221061 TEST_EXPECTED_VALUE(SrcLimits::max() * clamped_dst,
Peter Kastingfbb9e562021-06-27 02:57:371062 Dst(SrcLimits::max()) * Dst(SrcLimits::max()));
jschuh@chromium.org5bfecbc2014-02-27 13:49:041063 } else { // Larger, but not at least twice as large.
jschuh819c8262016-05-21 01:39:031064 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
1065 TEST_EXPECTED_SUCCESS(checked_dst + 1);
jschuhb180f392017-07-03 15:09:221066 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
1067 SrcLimits::max() * clamped_dst);
1068 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()) + Dst(1),
1069 clamped_dst + Dst(1));
jschuh@chromium.org5bfecbc2014-02-27 13:49:041070 }
1071 } else { // Same width type.
jschuh819c8262016-05-21 01:39:031072 TEST_EXPECTED_FAILURE(checked_dst + 1);
jschuhb180f392017-07-03 15:09:221073 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + Dst(1));
jschuh@chromium.org5bfecbc2014-02-27 13:49:041074 }
1075
1076 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
1077 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuh@chromium.org4efb2c32014-01-16 06:57:251078 if (SrcLimits::is_iec559) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:041079 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
1080 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
1081 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
1082 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuh@chromium.org5bfecbc2014-02-27 13:49:041083 } else if (numeric_limits<Src>::is_signed) {
Justin Schuh4ad909a2017-08-03 13:40:421084 // This block reverses the Src to Dst relationship so we don't have to
1085 // complicate the test macros.
Andrew Rayskiy629912382023-10-18 22:58:421086 if (!std::is_same_v<Src, Dst>) {
Justin Schuh4ad909a2017-08-03 13:40:421087 TEST_EXPECTED_SUCCESS(CheckDiv(SrcLimits::lowest(), Dst(-1)));
1088 }
jschuh@chromium.org5bfecbc2014-02-27 13:49:041089 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:481090 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
jschuh@chromium.org4efb2c32014-01-16 06:57:251091 }
scottmg@chromium.orgc1c090d32013-01-16 23:34:041092 }
jschuh@chromium.org4efb2c32014-01-16 06:57:251093};
1094
1095template <typename Dst, typename Src>
1096struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
Justin Schuh5cc331de2017-07-25 18:05:221097 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221098 using SrcLimits = SaturationDefaultLimits<Src>;
1099 using DstLimits = SaturationDefaultLimits<Dst>;
jschuhd2d9fe02014-10-14 14:31:371100 static_assert(SrcLimits::is_signed == DstLimits::is_signed,
1101 "Destination and source sign must be the same");
jschuh5030b002016-12-05 18:21:481102 static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:371103 "Destination must be narrower than source");
jschuh@chromium.org4efb2c32014-01-16 06:57:251104
Justin Schuh5cc2abf2017-08-01 04:58:071105 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081106
jschuh@chromium.org5bfecbc2014-02-27 13:49:041107 const CheckedNumeric<Dst> checked_dst;
jschuh819c8262016-05-21 01:39:031108 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
jschuhb180f392017-07-03 15:09:221109 TEST_EXPECTED_VALUE(1, checked_dst + Src(1));
jschuh819c8262016-05-21 01:39:031110 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:041111
Justin Schuh3725ec32017-10-01 03:44:271112 ClampedNumeric<Dst> clamped_dst;
jschuhb180f392017-07-03 15:09:221113 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
1114 TEST_EXPECTED_VALUE(1, clamped_dst + Src(1));
1115 TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst - SrcLimits::max());
Justin Schuh3725ec32017-10-01 03:44:271116 clamped_dst += SrcLimits::max();
1117 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1118 clamped_dst = DstLimits::max();
1119 clamped_dst += SrcLimits::max();
1120 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1121 clamped_dst = DstLimits::max();
1122 clamped_dst -= SrcLimits::max();
1123 TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst);
1124 clamped_dst = 0;
jschuhb180f392017-07-03 15:09:221125
jschuh@chromium.org5bfecbc2014-02-27 13:49:041126 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
1127 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuh@chromium.org4efb2c32014-01-16 06:57:251128 if (SrcLimits::is_iec559) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:041129 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
1130 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
1131 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
1132 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
1133 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuhfafe0712015-09-14 20:21:241134 if (DstLimits::is_integer) {
1135 if (SrcLimits::digits < DstLimits::digits) {
1136 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
1137 static_cast<Src>(DstLimits::max()));
1138 } else {
1139 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
1140 }
1141 TEST_EXPECTED_RANGE(
1142 RANGE_VALID,
1143 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
jschuh5030b002016-12-05 18:21:481144 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
jschuhfafe0712015-09-14 20:21:241145 }
jschuh@chromium.org4efb2c32014-01-16 06:57:251146 } else if (SrcLimits::is_signed) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:041147 TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
jschuhb180f392017-07-03 15:09:221148 TEST_EXPECTED_VALUE(-1, clamped_dst - static_cast<Src>(1));
Justin Schuh4ad909a2017-08-03 13:40:421149 TEST_EXPECTED_VALUE(Src(Src(0) - DstLimits::lowest()),
1150 ClampDiv(DstLimits::lowest(), Src(-1)));
jschuh5030b002016-12-05 18:21:481151 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:041152 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
jschuh@chromium.org4efb2c32014-01-16 06:57:251153 } else {
jschuh819c8262016-05-21 01:39:031154 TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
jschuhb180f392017-07-03 15:09:221155 TEST_EXPECTED_VALUE(Dst(0), clamped_dst - static_cast<Src>(1));
jschuh5030b002016-12-05 18:21:481156 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
jschuh@chromium.org4efb2c32014-01-16 06:57:251157 }
1158 }
1159};
1160
1161template <typename Dst, typename Src>
1162struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
Justin Schuh5cc331de2017-07-25 18:05:221163 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221164 using SrcLimits = SaturationDefaultLimits<Src>;
1165 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:481166 static_assert(MaxExponent<Dst>::value >= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:371167 "Destination must be equal or wider than source.");
1168 static_assert(SrcLimits::is_signed, "Source must be signed");
1169 static_assert(!DstLimits::is_signed, "Destination must be unsigned");
jschuh@chromium.org4efb2c32014-01-16 06:57:251170
Justin Schuh5cc2abf2017-08-01 04:58:071171 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081172
jschuh@chromium.org5bfecbc2014-02-27 13:49:041173 const CheckedNumeric<Dst> checked_dst;
1174 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
jschuh819c8262016-05-21 01:39:031175 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
jschuhb180f392017-07-03 15:09:221176 TEST_EXPECTED_SUCCESS(checked_dst * static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:481177 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
Justin Schuh4ad909a2017-08-03 13:40:421178 TEST_EXPECTED_VALUE(Dst(0), CheckDiv(Dst(0), Src(-1)));
jschuh@chromium.org5bfecbc2014-02-27 13:49:041179
jschuhb180f392017-07-03 15:09:221180 const ClampedNumeric<Dst> clamped_dst;
1181 TEST_EXPECTED_VALUE(SrcLimits::max(), clamped_dst + SrcLimits::max());
1182 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1183 clamped_dst + static_cast<Src>(-1));
1184 TEST_EXPECTED_VALUE(0, clamped_dst * static_cast<Src>(-1));
1185 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1186 clamped_dst + SrcLimits::lowest());
1187
jschuh5030b002016-12-05 18:21:481188 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:041189 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
1190 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
1191 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
jschuh@chromium.org4efb2c32014-01-16 06:57:251192 }
1193};
1194
1195template <typename Dst, typename Src>
1196struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
Justin Schuh5cc331de2017-07-25 18:05:221197 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221198 using SrcLimits = SaturationDefaultLimits<Src>;
1199 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:481200 static_assert(MaxExponent<Dst>::value < MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:371201 "Destination must be narrower than source.");
1202 static_assert(SrcLimits::is_signed, "Source must be signed.");
1203 static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
jschuh@chromium.org4efb2c32014-01-16 06:57:251204
Justin Schuh5cc2abf2017-08-01 04:58:071205 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081206
jschuh@chromium.org5bfecbc2014-02-27 13:49:041207 const CheckedNumeric<Dst> checked_dst;
1208 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:031209 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
1210 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:481211 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:041212
Justin Schuh3725ec32017-10-01 03:44:271213 ClampedNumeric<Dst> clamped_dst;
jschuhb180f392017-07-03 15:09:221214 TEST_EXPECTED_VALUE(1, clamped_dst + static_cast<Src>(1));
1215 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
1216 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1217 clamped_dst + static_cast<Src>(-1));
1218 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1219 clamped_dst + SrcLimits::lowest());
Justin Schuh3725ec32017-10-01 03:44:271220 clamped_dst += SrcLimits::max();
1221 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1222 clamped_dst = DstLimits::max();
1223 clamped_dst += SrcLimits::max();
1224 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1225 clamped_dst = DstLimits::max();
1226 clamped_dst -= SrcLimits::max();
1227 TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst);
1228 clamped_dst = 0;
jschuhb180f392017-07-03 15:09:221229
jschuh@chromium.org5bfecbc2014-02-27 13:49:041230 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
1231 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
1232 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
jschuhe3bd1f62016-12-20 05:11:301233
1234 // Additional saturation tests.
jschuhb180f392017-07-03 15:09:221235 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
jschuhe3bd1f62016-12-20 05:11:301236 EXPECT_EQ(DstLimits::lowest(), saturated_cast<Dst>(SrcLimits::lowest()));
1237
jschuh@chromium.org4efb2c32014-01-16 06:57:251238 if (SrcLimits::is_iec559) {
jschuhe3bd1f62016-12-20 05:11:301239 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::quiet_NaN()));
1240
jschuh@chromium.org5bfecbc2014-02-27 13:49:041241 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
1242 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
1243 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
1244 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
jschuhfafe0712015-09-14 20:21:241245 if (DstLimits::is_integer) {
1246 if (SrcLimits::digits < DstLimits::digits) {
1247 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
1248 static_cast<Src>(DstLimits::max()));
1249 } else {
1250 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
1251 }
1252 TEST_EXPECTED_RANGE(
1253 RANGE_VALID,
1254 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
jschuh5030b002016-12-05 18:21:481255 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
jschuhfafe0712015-09-14 20:21:241256 }
jschuh@chromium.org4efb2c32014-01-16 06:57:251257 } else {
jschuh5030b002016-12-05 18:21:481258 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
jschuh@chromium.org4efb2c32014-01-16 06:57:251259 }
1260 }
1261};
1262
1263template <typename Dst, typename Src>
1264struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
Justin Schuh5cc331de2017-07-25 18:05:221265 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221266 using SrcLimits = SaturationDefaultLimits<Src>;
1267 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b002016-12-05 18:21:481268 static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:371269 "Destination must be narrower or equal to source.");
1270 static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
1271 static_assert(DstLimits::is_signed, "Destination must be signed.");
jschuh@chromium.org4efb2c32014-01-16 06:57:251272
Justin Schuh5cc2abf2017-08-01 04:58:071273 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081274
jschuh@chromium.org5bfecbc2014-02-27 13:49:041275 const CheckedNumeric<Dst> checked_dst;
1276 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:031277 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
jschuh5030b002016-12-05 18:21:481278 TEST_EXPECTED_VALUE(SrcLimits::lowest(), checked_dst + SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:041279
jschuhb180f392017-07-03 15:09:221280 const ClampedNumeric<Dst> clamped_dst;
1281 TEST_EXPECTED_VALUE(1, clamped_dst + static_cast<Src>(1));
1282 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
1283 TEST_EXPECTED_VALUE(SrcLimits::lowest(), clamped_dst + SrcLimits::lowest());
1284
jschuh5030b002016-12-05 18:21:481285 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:041286 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
1287 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuhe3bd1f62016-12-20 05:11:301288
1289 // Additional saturation tests.
1290 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
1291 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::lowest()));
jschuh@chromium.org4efb2c32014-01-16 06:57:251292 }
1293};
1294
1295// Helper macro to wrap displaying the conversion types and line numbers
1296#define TEST_NUMERIC_CONVERSION(d, s, t) \
1297 TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
1298
jschuh@chromium.org5bfecbc2014-02-27 13:49:041299TEST(SafeNumerics, IntMinOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:251300 TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1301 TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1302
Justin Schuha26da272017-07-13 23:04:301303 TEST_NUMERIC_CONVERSION(int8_t, int16_t, SIGN_PRESERVING_NARROW);
jschuh@chromium.org4efb2c32014-01-16 06:57:251304 TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
Justin Schuha26da272017-07-13 23:04:301305 TEST_NUMERIC_CONVERSION(uint8_t, uint16_t, SIGN_PRESERVING_NARROW);
jschuh@chromium.org4efb2c32014-01-16 06:57:251306 TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
1307 TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
1308
1309 TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1310
Justin Schuha26da272017-07-13 23:04:301311 TEST_NUMERIC_CONVERSION(uint8_t, int16_t, SIGN_TO_UNSIGN_NARROW);
jschuh@chromium.org4efb2c32014-01-16 06:57:251312 TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
1313 TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
1314 TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
1315
Justin Schuha26da272017-07-13 23:04:301316 TEST_NUMERIC_CONVERSION(int8_t, uint16_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
jschuh@chromium.org4efb2c32014-01-16 06:57:251317 TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1318 TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
scottmg@chromium.orgc1c090d32013-01-16 23:34:041319}
1320
Justin Schuha26da272017-07-13 23:04:301321TEST(SafeNumerics, Int16Operations) {
1322 TEST_NUMERIC_CONVERSION(int16_t, int16_t, SIGN_PRESERVING_VALUE_PRESERVING);
1323 TEST_NUMERIC_CONVERSION(uint16_t, uint16_t, SIGN_PRESERVING_VALUE_PRESERVING);
1324
1325 TEST_NUMERIC_CONVERSION(int16_t, int, SIGN_PRESERVING_NARROW);
1326 TEST_NUMERIC_CONVERSION(uint16_t, unsigned int, SIGN_PRESERVING_NARROW);
1327 TEST_NUMERIC_CONVERSION(int16_t, float, SIGN_PRESERVING_NARROW);
1328
1329 TEST_NUMERIC_CONVERSION(uint16_t, int16_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1330
1331 TEST_NUMERIC_CONVERSION(uint16_t, int, SIGN_TO_UNSIGN_NARROW);
1332 TEST_NUMERIC_CONVERSION(uint16_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
1333 TEST_NUMERIC_CONVERSION(uint16_t, float, SIGN_TO_UNSIGN_NARROW);
1334
1335 TEST_NUMERIC_CONVERSION(int16_t, unsigned int,
1336 UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1337 TEST_NUMERIC_CONVERSION(int16_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1338}
1339
jschuh@chromium.org5bfecbc2014-02-27 13:49:041340TEST(SafeNumerics, IntOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:251341 TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
1342 TEST_NUMERIC_CONVERSION(unsigned int, unsigned int,
1343 SIGN_PRESERVING_VALUE_PRESERVING);
1344 TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1345 TEST_NUMERIC_CONVERSION(unsigned int, uint8_t,
1346 SIGN_PRESERVING_VALUE_PRESERVING);
1347 TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1348
1349 TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
1350 TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
1351 TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
1352 TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
1353
1354 TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1355 TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1356
1357 TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
1358 TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
1359 TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
1360
1361 TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1362 TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
scottmg@chromium.orgc1c090d32013-01-16 23:34:041363}
1364
jschuh@chromium.org5bfecbc2014-02-27 13:49:041365TEST(SafeNumerics, IntMaxOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:251366 TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
1367 TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t,
1368 SIGN_PRESERVING_VALUE_PRESERVING);
1369 TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
1370 TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int,
1371 SIGN_PRESERVING_VALUE_PRESERVING);
1372 TEST_NUMERIC_CONVERSION(intmax_t, unsigned int,
1373 SIGN_PRESERVING_VALUE_PRESERVING);
1374 TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1375
1376 TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
1377 TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
1378
1379 TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1380 TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1381
1382 TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
1383 TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
1384
1385 TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1386}
1387
jschuh@chromium.org5bfecbc2014-02-27 13:49:041388TEST(SafeNumerics, FloatOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:251389 TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
Justin Schuh5cc331de2017-07-25 18:05:221390 TEST_NUMERIC_CONVERSION(float, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
jschuh@chromium.org4efb2c32014-01-16 06:57:251391 TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
1392 TEST_NUMERIC_CONVERSION(float, unsigned int,
1393 SIGN_PRESERVING_VALUE_PRESERVING);
1394
1395 TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
1396}
1397
jschuh@chromium.org5bfecbc2014-02-27 13:49:041398TEST(SafeNumerics, DoubleOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:251399 TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
Justin Schuh5cc331de2017-07-25 18:05:221400 TEST_NUMERIC_CONVERSION(double, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
jschuh@chromium.org4efb2c32014-01-16 06:57:251401 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
1402 TEST_NUMERIC_CONVERSION(double, unsigned int,
1403 SIGN_PRESERVING_VALUE_PRESERVING);
1404}
1405
jschuh@chromium.org5bfecbc2014-02-27 13:49:041406TEST(SafeNumerics, SizeTOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:251407 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1408 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1409}
1410
jschuh23a4b062016-12-02 02:55:081411// A one-off test to ensure StrictNumeric won't resolve to an incorrect type.
1412// If this fails we'll just get a compiler error on an ambiguous overload.
1413int TestOverload(int) { // Overload fails.
1414 return 0;
1415}
1416uint8_t TestOverload(uint8_t) { // Overload fails.
1417 return 0;
1418}
1419size_t TestOverload(size_t) { // Overload succeeds.
1420 return 0;
1421}
1422
Andrew Rayskiy629912382023-10-18 22:58:421423static_assert(std::is_same_v<decltype(TestOverload(StrictNumeric<int>())), int>,
1424 "");
Andrew Rayskiy6f021362023-10-19 19:55:061425static_assert(
1426 std::is_same_v<decltype(TestOverload(StrictNumeric<size_t>())), size_t>,
1427 "");
jschuh23a4b062016-12-02 02:55:081428
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) {
jschuh@chromium.org4efb2c32014-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)
scottmg@chromium.orgc1c090d32013-01-16 23:34:041452#endif
1453
scottmg@chromium.orgc1c090d32013-01-16 23:34:041454 int small_positive = 1;
1455 int small_negative = -1;
jschuh@chromium.org4efb2c32014-01-16 06:57:251456 double double_small = 1.0;
jschuh@chromium.org5bfecbc2014-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();
scottmg@chromium.orgc1c090d32013-01-16 23:34:041461
jschuh4bf22c6d2015-05-28 02:29:251462 // Just test that the casts compile, since the other tests cover logic.
jschuh@chromium.org5bfecbc2014-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));
scottmg@chromium.orgc1c090d32013-01-16 23:34:041492
jschuh@chromium.org4efb2c32014-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));
jschuh@chromium.org5bfecbc2014-02-27 13:49:041500 EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
jschuh@chromium.org4efb2c32014-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());
jschuh4bc919c2016-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(
Andrew Rayskiy6f021362023-10-19 19:55:061546 std::is_same_v<int16_t, decltype(int8_min.ValueOrDie<int16_t>())::type>,
jschuh224f1d72016-11-25 20:08:481547 "ValueOrDie returning incorrect type.");
1548 static_assert(
Andrew Rayskiy6f021362023-10-19 19:55:061549 std::is_same_v<int16_t,
1550 decltype(int8_min.ValueOrDefault<int16_t>(0))::type>,
jschuh224f1d72016-11-25 20:08:481551 "ValueOrDefault returning incorrect type.");
jschuh23a4b062016-12-02 02:55:081552 EXPECT_FALSE(IsValidForType<uint8_t>(int8_min));
1553 EXPECT_TRUE(IsValidForType<uint8_t>(int8_max));
jschuh5030b002016-12-05 18:21:481554 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::lowest()),
jschuh23a4b062016-12-02 02:55:081555 ValueOrDieForType<int>(int8_min));
1556 EXPECT_TRUE(IsValidForType<uint32_t>(int8_max));
jschuh224f1d72016-11-25 20:08:481557 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()),
jschuh23a4b062016-12-02 02:55:081558 ValueOrDieForType<int>(int8_max));
1559 EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0));
jschuhe17e0f12016-11-26 03:00:081560 uint8_t uint8_dest = 0;
1561 int16_t int16_dest = 0;
1562 double double_dest = 0;
1563 EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest));
1564 EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest);
1565 EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest));
1566 EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest));
1567 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest);
1568 EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest));
jschuh5030b002016-12-05 18:21:481569 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::lowest()), int16_dest);
jschuhe17e0f12016-11-26 03:00:081570 EXPECT_FALSE(double_max.AssignIfValid(&uint8_dest));
1571 EXPECT_FALSE(double_max.AssignIfValid(&int16_dest));
1572 EXPECT_TRUE(double_max.AssignIfValid(&double_dest));
1573 EXPECT_EQ(numeric_limits<double>::max(), double_dest);
jschuh23a4b062016-12-02 02:55:081574 EXPECT_EQ(1, checked_cast<int>(StrictNumeric<int>(1)));
1575 EXPECT_EQ(1, saturated_cast<int>(StrictNumeric<int>(1)));
1576 EXPECT_EQ(1, strict_cast<int>(StrictNumeric<int>(1)));
Justin Schuh4d93ee32017-08-14 20:06:281577
1578 enum class EnumTest { kOne = 1 };
1579 EXPECT_EQ(1, checked_cast<int>(EnumTest::kOne));
1580 EXPECT_EQ(1, saturated_cast<int>(EnumTest::kOne));
1581 EXPECT_EQ(1, strict_cast<int>(EnumTest::kOne));
scottmg@chromium.orgc1c090d32013-01-16 23:34:041582}
1583
jschuhfafe0712015-09-14 20:21:241584TEST(SafeNumerics, IsValueInRangeForNumericType) {
1585 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
1586 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
1587 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
1588 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
1589 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
1590 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
1591 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
1592 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
1593 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
jschuh5030b002016-12-05 18:21:481594 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241595 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
jschuh5030b002016-12-05 18:21:481596 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241597
Ng Zhi An280ed262020-10-22 00:10:121598 // Converting to integer types will discard the fractional part first, so -0.9
1599 // will be truncated to -0.0.
1600 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(-0.9));
1601 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1.0));
1602
jschuhfafe0712015-09-14 20:21:241603 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
1604 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
1605 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
1606 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
1607 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
1608 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
1609 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
1610 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
1611 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
1612 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
1613 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
1614 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481615 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241616 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481617 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
jschuhfafe0712015-09-14 20:21:241618 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481619 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest()) - 1));
jschuhfafe0712015-09-14 20:21:241620 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481621 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241622
1623 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
1624 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
1625 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
1626 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
1627 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
1628 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
1629 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
1630 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
1631 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
jschuh5030b002016-12-05 18:21:481632 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241633 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
1634 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
jschuh5030b002016-12-05 18:21:481635 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241636
Ng Zhi An280ed262020-10-22 00:10:121637 // Converting to integer types will discard the fractional part first, so -0.9
1638 // will be truncated to -0.0.
1639 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(-0.9));
1640 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1.0));
1641
jschuhfafe0712015-09-14 20:21:241642 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
1643 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
1644 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
1645 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
1646 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
1647 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
1648 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
1649 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
1650 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
1651 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
1652 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
1653 EXPECT_TRUE(
1654 IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
1655 EXPECT_TRUE(
1656 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
1657 EXPECT_FALSE(
1658 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
1659 EXPECT_FALSE(
1660 IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
1661 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481662 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241663 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481664 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
jschuhfafe0712015-09-14 20:21:241665 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481666 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241667}
vmpstr19477492015-09-29 22:34:491668
1669TEST(SafeNumerics, CompoundNumericOperations) {
1670 CheckedNumeric<int> a = 1;
1671 CheckedNumeric<int> b = 2;
1672 CheckedNumeric<int> c = 3;
1673 CheckedNumeric<int> d = 4;
1674 a += b;
1675 EXPECT_EQ(3, a.ValueOrDie());
1676 a -= c;
1677 EXPECT_EQ(0, a.ValueOrDie());
1678 d /= b;
1679 EXPECT_EQ(2, d.ValueOrDie());
1680 d *= d;
1681 EXPECT_EQ(4, d.ValueOrDie());
Peter Kasting0559fb62020-08-12 00:02:051682 d *= 0.5;
1683 EXPECT_EQ(2, d.ValueOrDie());
vmpstr19477492015-09-29 22:34:491684
1685 CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
1686 EXPECT_TRUE(too_large.IsValid());
1687 too_large += d;
1688 EXPECT_FALSE(too_large.IsValid());
1689 too_large -= d;
1690 EXPECT_FALSE(too_large.IsValid());
1691 too_large /= d;
1692 EXPECT_FALSE(too_large.IsValid());
1693}
jschuh4fcd6fa2016-11-24 11:58:391694
Will Harris128da002023-02-07 23:47:491695TEST(SafeNumerics, TemplatedSafeMath) {
1696 // CheckMul and friends can be confusing, as they change behavior depending on
1697 // where the template is specified.
1698 uint64_t result;
1699 short short_one_thousand = 1000;
1700 // In this case, CheckMul uses template deduction to use the <short> variant,
1701 // and this will overflow even if assigned to a uint64_t.
1702 EXPECT_FALSE(CheckMul(short_one_thousand, short_one_thousand)
1703 .AssignIfValid<uint64_t>(&result));
1704 EXPECT_FALSE(CheckMul(short_one_thousand, short_one_thousand).IsValid());
1705 // In both cases, CheckMul is forced to use the uint64_t template and will not
1706 // overflow.
1707 EXPECT_TRUE(CheckMul<uint64_t>(short_one_thousand, short_one_thousand)
1708 .AssignIfValid(&result));
1709 EXPECT_TRUE(CheckMul<uint64_t>(short_one_thousand, short_one_thousand)
1710 .AssignIfValid<uint64_t>(&result));
1711
1712 uint64_t big_one_thousand = 1000u;
1713 // Order doesn't matter here: if one of the parameters is uint64_t then the
1714 // operation is done on a uint64_t.
1715 EXPECT_TRUE(
1716 CheckMul(big_one_thousand, short_one_thousand).AssignIfValid(&result));
1717 EXPECT_TRUE(
1718 CheckMul(short_one_thousand, big_one_thousand).AssignIfValid(&result));
1719
1720 // Checked math functions can also take two template type parameters. Here are
1721 // the results of all four combinations.
1722 EXPECT_TRUE((CheckMul<short, uint64_t>(1000, 1000).AssignIfValid(&result)));
1723
1724 // Note: Order here does not matter.
1725 EXPECT_TRUE((CheckMul<uint64_t, short>(1000, 1000).AssignIfValid(&result)));
1726
1727 // Only if both are short will the operation be invalid.
1728 EXPECT_FALSE((CheckMul<short, short>(1000, 1000).AssignIfValid(&result)));
1729
1730 // Same as above.
1731 EXPECT_TRUE(
1732 (CheckMul<uint64_t, uint64_t>(1000, 1000).AssignIfValid(&result)));
1733}
1734
jschuh4fcd6fa2016-11-24 11:58:391735TEST(SafeNumerics, VariadicNumericOperations) {
jschuhb180f392017-07-03 15:09:221736 { // Synthetic scope to avoid variable naming collisions.
1737 auto a = CheckAdd(1, 2UL, MakeCheckedNum(3LL), 4).ValueOrDie();
1738 EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
1739 auto b = CheckSub(MakeCheckedNum(20.0), 2UL, 4).ValueOrDie();
1740 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
1741 auto c = CheckMul(20.0, MakeCheckedNum(1), 5, 3UL).ValueOrDie();
1742 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
1743 auto d = CheckDiv(20.0, 2.0, MakeCheckedNum(5LL), -4).ValueOrDie();
1744 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
1745 auto e = CheckMod(MakeCheckedNum(20), 3).ValueOrDie();
1746 EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
1747 auto f = CheckLsh(1, MakeCheckedNum(2)).ValueOrDie();
1748 EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
1749 auto g = CheckRsh(4, MakeCheckedNum(2)).ValueOrDie();
1750 EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
1751 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
1752 EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
1753 }
1754
1755 {
1756 auto a = ClampAdd(1, 2UL, MakeClampedNum(3LL), 4);
1757 EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
1758 auto b = ClampSub(MakeClampedNum(20.0), 2UL, 4);
1759 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
1760 auto c = ClampMul(20.0, MakeClampedNum(1), 5, 3UL);
1761 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
1762 auto d = ClampDiv(20.0, 2.0, MakeClampedNum(5LL), -4);
1763 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
1764 auto e = ClampMod(MakeClampedNum(20), 3);
1765 EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
1766 auto f = ClampLsh(1, MakeClampedNum(2U));
1767 EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
1768 auto g = ClampRsh(4, MakeClampedNum(2U));
1769 EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
1770 auto h = ClampRsh(ClampAdd(1, 1, 1, 1), ClampSub(4U, 2));
1771 EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
1772 }
jschuh4fcd6fa2016-11-24 11:58:391773}
Justin Schuha26da272017-07-13 23:04:301774
Peter Kastingfc5d8f32020-06-30 02:38:171775TEST(SafeNumerics, CeilInt) {
Peter Kastingfbb9e562021-06-27 02:57:371776 constexpr float kMax = static_cast<float>(std::numeric_limits<int>::max());
Peter Kastingfc5d8f32020-06-30 02:38:171777 constexpr float kMin = std::numeric_limits<int>::min();
1778 constexpr float kInfinity = std::numeric_limits<float>::infinity();
1779 constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();
1780
1781 constexpr int kIntMax = std::numeric_limits<int>::max();
1782 constexpr int kIntMin = std::numeric_limits<int>::min();
1783
Peter Kasting24e973d2020-07-20 06:13:091784 EXPECT_EQ(kIntMax, ClampCeil(kInfinity));
1785 EXPECT_EQ(kIntMax, ClampCeil(kMax));
1786 EXPECT_EQ(kIntMax, ClampCeil(kMax + 100.0f));
1787 EXPECT_EQ(0, ClampCeil(kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171788
Peter Kasting24e973d2020-07-20 06:13:091789 EXPECT_EQ(-100, ClampCeil(-100.5f));
1790 EXPECT_EQ(0, ClampCeil(0.0f));
1791 EXPECT_EQ(101, ClampCeil(100.5f));
Peter Kastingfc5d8f32020-06-30 02:38:171792
Peter Kasting24e973d2020-07-20 06:13:091793 EXPECT_EQ(kIntMin, ClampCeil(-kInfinity));
1794 EXPECT_EQ(kIntMin, ClampCeil(kMin));
1795 EXPECT_EQ(kIntMin, ClampCeil(kMin - 100.0f));
1796 EXPECT_EQ(0, ClampCeil(-kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171797}
1798
1799TEST(SafeNumerics, FloorInt) {
Peter Kastingfbb9e562021-06-27 02:57:371800 constexpr float kMax = static_cast<float>(std::numeric_limits<int>::max());
Peter Kastingfc5d8f32020-06-30 02:38:171801 constexpr float kMin = std::numeric_limits<int>::min();
1802 constexpr float kInfinity = std::numeric_limits<float>::infinity();
1803 constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();
1804
1805 constexpr int kIntMax = std::numeric_limits<int>::max();
1806 constexpr int kIntMin = std::numeric_limits<int>::min();
1807
Peter Kasting24e973d2020-07-20 06:13:091808 EXPECT_EQ(kIntMax, ClampFloor(kInfinity));
1809 EXPECT_EQ(kIntMax, ClampFloor(kMax));
1810 EXPECT_EQ(kIntMax, ClampFloor(kMax + 100.0f));
1811 EXPECT_EQ(0, ClampFloor(kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171812
Peter Kasting24e973d2020-07-20 06:13:091813 EXPECT_EQ(-101, ClampFloor(-100.5f));
1814 EXPECT_EQ(0, ClampFloor(0.0f));
1815 EXPECT_EQ(100, ClampFloor(100.5f));
Peter Kastingfc5d8f32020-06-30 02:38:171816
Peter Kasting24e973d2020-07-20 06:13:091817 EXPECT_EQ(kIntMin, ClampFloor(-kInfinity));
1818 EXPECT_EQ(kIntMin, ClampFloor(kMin));
1819 EXPECT_EQ(kIntMin, ClampFloor(kMin - 100.0f));
1820 EXPECT_EQ(0, ClampFloor(-kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171821}
1822
1823TEST(SafeNumerics, RoundInt) {
Peter Kastingfbb9e562021-06-27 02:57:371824 constexpr float kMax = static_cast<float>(std::numeric_limits<int>::max());
Peter Kastingfc5d8f32020-06-30 02:38:171825 constexpr float kMin = std::numeric_limits<int>::min();
1826 constexpr float kInfinity = std::numeric_limits<float>::infinity();
1827 constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();
1828
1829 constexpr int kIntMax = std::numeric_limits<int>::max();
1830 constexpr int kIntMin = std::numeric_limits<int>::min();
1831
Peter Kasting24e973d2020-07-20 06:13:091832 EXPECT_EQ(kIntMax, ClampRound(kInfinity));
1833 EXPECT_EQ(kIntMax, ClampRound(kMax));
1834 EXPECT_EQ(kIntMax, ClampRound(kMax + 100.0f));
1835 EXPECT_EQ(0, ClampRound(kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171836
Peter Kasting24e973d2020-07-20 06:13:091837 EXPECT_EQ(-100, ClampRound(-100.1f));
1838 EXPECT_EQ(-101, ClampRound(-100.5f));
1839 EXPECT_EQ(-101, ClampRound(-100.9f));
Steinar H. Gunderson32b29d32023-09-28 23:10:491840 EXPECT_EQ(0, ClampRound(std::nextafter(-0.5f, 0.0f)));
Peter Kasting24e973d2020-07-20 06:13:091841 EXPECT_EQ(0, ClampRound(0.0f));
Steinar H. Gunderson32b29d32023-09-28 23:10:491842 EXPECT_EQ(0, ClampRound(std::nextafter(0.5f, 0.0f)));
Peter Kasting24e973d2020-07-20 06:13:091843 EXPECT_EQ(100, ClampRound(100.1f));
1844 EXPECT_EQ(101, ClampRound(100.5f));
1845 EXPECT_EQ(101, ClampRound(100.9f));
Peter Kastingfc5d8f32020-06-30 02:38:171846
Peter Kasting24e973d2020-07-20 06:13:091847 EXPECT_EQ(kIntMin, ClampRound(-kInfinity));
1848 EXPECT_EQ(kIntMin, ClampRound(kMin));
1849 EXPECT_EQ(kIntMin, ClampRound(kMin - 100.0f));
1850 EXPECT_EQ(0, ClampRound(-kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171851}
1852
1853TEST(SafeNumerics, Int64) {
Peter Kastingfbb9e562021-06-27 02:57:371854 constexpr double kMax =
1855 static_cast<double>(std::numeric_limits<int64_t>::max());
Peter Kastingfc5d8f32020-06-30 02:38:171856 constexpr double kMin = std::numeric_limits<int64_t>::min();
1857 constexpr double kInfinity = std::numeric_limits<double>::infinity();
1858 constexpr double kNaN = std::numeric_limits<double>::quiet_NaN();
1859
1860 constexpr int64_t kInt64Max = std::numeric_limits<int64_t>::max();
1861 constexpr int64_t kInt64Min = std::numeric_limits<int64_t>::min();
1862
Peter Kasting24e973d2020-07-20 06:13:091863 EXPECT_EQ(kInt64Max, ClampFloor<int64_t>(kInfinity));
1864 EXPECT_EQ(kInt64Max, ClampCeil<int64_t>(kInfinity));
1865 EXPECT_EQ(kInt64Max, ClampRound<int64_t>(kInfinity));
1866 EXPECT_EQ(kInt64Max, ClampFloor<int64_t>(kMax));
1867 EXPECT_EQ(kInt64Max, ClampCeil<int64_t>(kMax));
1868 EXPECT_EQ(kInt64Max, ClampRound<int64_t>(kMax));
1869 EXPECT_EQ(kInt64Max, ClampFloor<int64_t>(kMax + 100.0));
1870 EXPECT_EQ(kInt64Max, ClampCeil<int64_t>(kMax + 100.0));
1871 EXPECT_EQ(kInt64Max, ClampRound<int64_t>(kMax + 100.0));
1872 EXPECT_EQ(0, ClampFloor<int64_t>(kNaN));
1873 EXPECT_EQ(0, ClampCeil<int64_t>(kNaN));
1874 EXPECT_EQ(0, ClampRound<int64_t>(kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171875
Peter Kasting24e973d2020-07-20 06:13:091876 EXPECT_EQ(kInt64Min, ClampFloor<int64_t>(-kInfinity));
1877 EXPECT_EQ(kInt64Min, ClampCeil<int64_t>(-kInfinity));
1878 EXPECT_EQ(kInt64Min, ClampRound<int64_t>(-kInfinity));
1879 EXPECT_EQ(kInt64Min, ClampFloor<int64_t>(kMin));
1880 EXPECT_EQ(kInt64Min, ClampCeil<int64_t>(kMin));
1881 EXPECT_EQ(kInt64Min, ClampRound<int64_t>(kMin));
1882 EXPECT_EQ(kInt64Min, ClampFloor<int64_t>(kMin - 100.0));
1883 EXPECT_EQ(kInt64Min, ClampCeil<int64_t>(kMin - 100.0));
1884 EXPECT_EQ(kInt64Min, ClampRound<int64_t>(kMin - 100.0));
1885 EXPECT_EQ(0, ClampFloor<int64_t>(-kNaN));
1886 EXPECT_EQ(0, ClampCeil<int64_t>(-kNaN));
1887 EXPECT_EQ(0, ClampRound<int64_t>(-kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:171888}
1889
David Benjamin954152b2023-10-24 17:46:201890template <typename T>
1891void TestWrappingMathSigned() {
1892 static_assert(std::is_signed_v<T>);
1893 constexpr T kMinusTwo = -2;
1894 constexpr T kMinusOne = -1;
1895 constexpr T kZero = 0;
1896 constexpr T kOne = 1;
1897 constexpr T kTwo = 2;
1898 constexpr T kThree = 3;
1899 constexpr T kMax = std::numeric_limits<T>::max();
1900 constexpr T kMin = std::numeric_limits<T>::min();
1901
1902 EXPECT_EQ(base::WrappingAdd(kOne, kTwo), kThree);
1903 static_assert(base::WrappingAdd(kOne, kTwo) == kThree);
1904 EXPECT_EQ(base::WrappingAdd(kMax, kOne), kMin);
1905 static_assert(base::WrappingAdd(kMax, kOne) == kMin);
1906 EXPECT_EQ(base::WrappingAdd(kMax, kTwo), kMin + 1);
1907 static_assert(base::WrappingAdd(kMax, kTwo) == kMin + 1);
1908 EXPECT_EQ(base::WrappingAdd(kMax, kMax), kMinusTwo);
1909 static_assert(base::WrappingAdd(kMax, kMax) == kMinusTwo);
1910 EXPECT_EQ(base::WrappingAdd(kMin, kMin), kZero);
1911 static_assert(base::WrappingAdd(kMin, kMin) == kZero);
1912
1913 EXPECT_EQ(base::WrappingSub(kTwo, kOne), kOne);
1914 static_assert(base::WrappingSub(kTwo, kOne) == kOne);
1915 EXPECT_EQ(base::WrappingSub(kOne, kTwo), kMinusOne);
1916 static_assert(base::WrappingSub(kOne, kTwo) == kMinusOne);
1917 EXPECT_EQ(base::WrappingSub(kMin, kOne), kMax);
1918 static_assert(base::WrappingSub(kMin, kOne) == kMax);
1919 EXPECT_EQ(base::WrappingSub(kMin, kTwo), kMax - 1);
1920 static_assert(base::WrappingSub(kMin, kTwo) == kMax - 1);
1921 EXPECT_EQ(base::WrappingSub(kMax, kMin), kMinusOne);
1922 static_assert(base::WrappingSub(kMax, kMin) == kMinusOne);
1923 EXPECT_EQ(base::WrappingSub(kMin, kMax), kOne);
1924 static_assert(base::WrappingSub(kMin, kMax) == kOne);
1925}
1926
1927template <typename T>
1928void TestWrappingMathUnsigned() {
1929 static_assert(std::is_unsigned_v<T>);
1930 constexpr T kZero = 0;
1931 constexpr T kOne = 1;
1932 constexpr T kTwo = 2;
1933 constexpr T kThree = 3;
1934 constexpr T kMax = std::numeric_limits<T>::max();
1935
1936 EXPECT_EQ(base::WrappingAdd(kOne, kTwo), kThree);
1937 static_assert(base::WrappingAdd(kOne, kTwo) == kThree);
1938 EXPECT_EQ(base::WrappingAdd(kMax, kOne), kZero);
1939 static_assert(base::WrappingAdd(kMax, kOne) == kZero);
1940 EXPECT_EQ(base::WrappingAdd(kMax, kTwo), kOne);
1941 static_assert(base::WrappingAdd(kMax, kTwo) == kOne);
1942 EXPECT_EQ(base::WrappingAdd(kMax, kMax), kMax - 1);
1943 static_assert(base::WrappingAdd(kMax, kMax) == kMax - 1);
1944
1945 EXPECT_EQ(base::WrappingSub(kTwo, kOne), kOne);
1946 static_assert(base::WrappingSub(kTwo, kOne) == kOne);
1947 EXPECT_EQ(base::WrappingSub(kOne, kTwo), kMax);
1948 static_assert(base::WrappingSub(kOne, kTwo) == kMax);
1949 EXPECT_EQ(base::WrappingSub(kZero, kOne), kMax);
1950 static_assert(base::WrappingSub(kZero, kOne) == kMax);
1951 EXPECT_EQ(base::WrappingSub(kZero, kTwo), kMax - 1);
1952 static_assert(base::WrappingSub(kZero, kTwo) == kMax - 1);
1953}
1954
1955TEST(SafeNumerics, WrappingMath) {
1956 TestWrappingMathSigned<int8_t>();
1957 TestWrappingMathUnsigned<uint8_t>();
1958 TestWrappingMathSigned<int16_t>();
1959 TestWrappingMathUnsigned<uint16_t>();
1960 TestWrappingMathSigned<int32_t>();
1961 TestWrappingMathUnsigned<uint32_t>();
1962 TestWrappingMathSigned<int64_t>();
1963 TestWrappingMathUnsigned<uint64_t>();
1964}
1965
Mostyn Bramley-Moore2c1339ee72018-03-28 21:10:041966#if defined(__clang__)
1967#pragma clang diagnostic pop // -Winteger-overflow
1968#endif
1969
Justin Schuha26da272017-07-13 23:04:301970} // namespace internal
1971} // namespace base