Thanks to visit codestin.com
Credit goes to chromium.googlesource.com

blob: 85c3663e343b7de6dd421a2c1c2c5447a7399761 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2013 The Chromium Authors
[email protected]c1c090d32013-01-16 23:34:042// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
danakj51d26a402024-04-25 14:23:565#ifdef UNSAFE_BUFFERS_BUILD
6// TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7#pragma allow_unsafe_buffers
8#endif
9
avi9b6f42932015-12-26 22:15:1410#include <stddef.h>
[email protected]4efb2c32014-01-16 06:57:2511#include <stdint.h>
12
Peter Kasting134183e2024-11-13 01:22:3913#include <concepts>
[email protected]4efb2c32014-01-16 06:57:2514#include <limits>
vmpstr98a2fad2015-11-30 20:15:1715#include <type_traits>
[email protected]4efb2c32014-01-16 06:57:2516
17#include "base/compiler_specific.h"
Peter Kastingfbb9e562021-06-27 02:57:3718#include "build/build_config.h"
Justin Schuhaeed1e42017-08-01 19:46:4319
20// WARNING: This block must come before the base/numerics headers are included.
21// These tests deliberately cause arithmetic boundary errors. If the compiler is
22// aggressive enough, it can const detect these errors, so we disable warnings.
Xiaohan Wang38e4ebb2022-01-19 06:57:4323#if BUILDFLAG(IS_WIN)
Justin Schuhaeed1e42017-08-01 19:46:4324#pragma warning(disable : 4756) // Arithmetic overflow.
25#pragma warning(disable : 4293) // Invalid shift.
26#endif
27
Mostyn Bramley-Moore2c1339ee72018-03-28 21:10:0428// This may not need to come before the base/numerics headers, but let's keep
29// it close to the MSVC equivalent.
30#if defined(__clang__)
31#pragma clang diagnostic push
32#pragma clang diagnostic ignored "-Winteger-overflow"
33#endif
34
jschuh224f1d72016-11-25 20:08:4835#include "base/logging.h"
[email protected]5bfecbc52014-02-27 13:49:0436#include "base/numerics/safe_conversions.h"
37#include "base/numerics/safe_math.h"
David Benjamin954152b2023-10-24 17:46:2038#include "base/numerics/wrapping_math.h"
gab190f7542016-08-01 20:03:4139#include "base/test/gtest_util.h"
[email protected]4efb2c32014-01-16 06:57:2540#include "testing/gtest/include/gtest/gtest.h"
41
avi9b6f42932015-12-26 22:15:1442#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
43#include <mmintrin.h>
44#endif
45
Daniel Chengb8069cb12025-11-12 18:19:2246namespace base::numerics_internal {
Justin Schuha26da272017-07-13 23:04:3047
[email protected]5bfecbc52014-02-27 13:49:0448using std::numeric_limits;
[email protected]5bfecbc52014-02-27 13:49:0449
jschuhfafe0712015-09-14 20:21:2450// This is a helper function for finding the maximum value in Src that can be
Peter Kasting5e7c9bf22024-11-13 01:25:2251// wholly represented as the destination floating-point type.
Peter Kasting134183e2024-11-13 01:22:3952template <typename Dst,
53 typename Src,
54 typename DstLimits = std::numeric_limits<Dst>,
55 typename SrcLimits = std::numeric_limits<Src>>
56 requires(DstLimits::is_specialized && SrcLimits::is_specialized &&
57 DstLimits::is_iec559)
58constexpr Dst GetMaxConvertibleToFloat() {
59 if constexpr (SrcLimits::digits <= DstLimits::digits &&
Peter Kastingabcf60a2024-11-13 01:24:3760 kMaxExponent<Src> <= kMaxExponent<Dst>) {
jschuhfafe0712015-09-14 20:21:2461 return SrcLimits::max();
Peter Kasting134183e2024-11-13 01:22:3962 } else {
63 Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
64 while (max != static_cast<Src>(static_cast<Dst>(max))) {
65 max /= 2;
66 }
67 return static_cast<Dst>(max);
jschuhfafe0712015-09-14 20:21:2468 }
jschuhfafe0712015-09-14 20:21:2469}
70
jschuh33232e02017-01-03 20:33:3671// Test corner case promotions used
Peter Kastingabcf60a2024-11-13 01:24:3772static_assert(kIsIntegerArithmeticSafe<int32_t, int8_t, int8_t>);
73static_assert(kIsIntegerArithmeticSafe<int32_t, int16_t, int8_t>);
74static_assert(kIsIntegerArithmeticSafe<int32_t, int8_t, int16_t>);
75static_assert(!kIsIntegerArithmeticSafe<int32_t, int32_t, int8_t>);
76static_assert(kIsBigEnoughPromotionContained<int16_t, int8_t>);
77static_assert(kIsBigEnoughPromotionContained<int32_t, uint32_t>);
78static_assert(kIsBigEnoughPromotionContained<intmax_t, int8_t>);
79static_assert(!kIsBigEnoughPromotionContained<uintmax_t, int8_t>);
80static_assert(std::same_as<BigEnoughPromotion<int16_t, int8_t>, int16_t>);
81static_assert(std::same_as<BigEnoughPromotion<int32_t, uint32_t>, int64_t>);
82static_assert(std::same_as<BigEnoughPromotion<intmax_t, int8_t>, intmax_t>);
83static_assert(std::same_as<BigEnoughPromotion<uintmax_t, int8_t>, uintmax_t>);
84static_assert(kIsBigEnoughPromotionContained<int16_t, int8_t>);
85static_assert(kIsBigEnoughPromotionContained<int32_t, uint32_t>);
86static_assert(kIsBigEnoughPromotionContained<intmax_t, int8_t>);
87static_assert(!kIsBigEnoughPromotionContained<uintmax_t, int8_t>);
jschuh33232e02017-01-03 20:33:3688static_assert(
Peter Kastingabcf60a2024-11-13 01:24:3789 std::same_as<FastIntegerArithmeticPromotion<int16_t, int8_t>, int32_t>);
jschuh33232e02017-01-03 20:33:3690static_assert(
Peter Kastingabcf60a2024-11-13 01:24:3791 std::same_as<FastIntegerArithmeticPromotion<int32_t, uint32_t>, int64_t>);
jschuh33232e02017-01-03 20:33:3692static_assert(
Peter Kastingabcf60a2024-11-13 01:24:3793 std::same_as<FastIntegerArithmeticPromotion<intmax_t, int8_t>, intmax_t>);
jschuh33232e02017-01-03 20:33:3694static_assert(
Peter Kastingabcf60a2024-11-13 01:24:3795 std::same_as<FastIntegerArithmeticPromotion<uintmax_t, int8_t>, uintmax_t>);
96static_assert(kIsFastIntegerArithmeticPromotionContained<int16_t, int8_t>);
97static_assert(kIsFastIntegerArithmeticPromotionContained<int32_t, uint32_t>);
98static_assert(!kIsFastIntegerArithmeticPromotionContained<intmax_t, int8_t>);
99static_assert(!kIsFastIntegerArithmeticPromotionContained<uintmax_t, int8_t>);
jschuh33232e02017-01-03 20:33:36100
Justin Schuhe2eefe612022-01-13 22:48:50101// Test compile-time (constexpr) evaluation of checking and saturation.
102constexpr int32_t kIntOne = 1;
Peter Kasting134183e2024-11-13 01:22:39103static_assert(1 == checked_cast<uint8_t>(kIntOne));
104static_assert(1 == saturated_cast<uint8_t>(kIntOne));
105static_assert(2U == MakeClampedNum(kIntOne) + 1);
106static_assert(2U == (MakeCheckedNum(kIntOne) + 1).ValueOrDie());
107static_assert(0U == MakeClampedNum(kIntOne) - 1);
108static_assert(0U == (MakeCheckedNum(kIntOne) - 1).ValueOrDie());
109static_assert(-1 == -MakeClampedNum(kIntOne));
110static_assert(-1 == (-MakeCheckedNum(kIntOne)).ValueOrDie());
111static_assert(1U == MakeClampedNum(kIntOne) * 1);
112static_assert(1U == (MakeCheckedNum(kIntOne) * 1).ValueOrDie());
113static_assert(1U == MakeClampedNum(kIntOne) / 1);
114static_assert(1U == (MakeCheckedNum(kIntOne) / 1).ValueOrDie());
115static_assert(1 == MakeClampedNum(-kIntOne).Abs());
116static_assert(1 == MakeCheckedNum(-kIntOne).Abs().ValueOrDie());
117static_assert(1U == MakeClampedNum(kIntOne) % 2);
118static_assert(1U == (MakeCheckedNum(kIntOne) % 2).ValueOrDie());
119static_assert(0U == MakeClampedNum(kIntOne) >> 1U);
120static_assert(0U == (MakeCheckedNum(kIntOne) >> 1U).ValueOrDie());
121static_assert(2U == MakeClampedNum(kIntOne) << 1U);
122static_assert(2U == (MakeCheckedNum(kIntOne) << 1U).ValueOrDie());
123static_assert(1 == MakeClampedNum(kIntOne) & 1U);
124static_assert(1 == (MakeCheckedNum(kIntOne) & 1U).ValueOrDie());
125static_assert(1 == MakeClampedNum(kIntOne) | 1U);
126static_assert(1 == (MakeCheckedNum(kIntOne) | 1U).ValueOrDie());
127static_assert(0 == MakeClampedNum(kIntOne) ^ 1U);
128static_assert(0 == (MakeCheckedNum(kIntOne) ^ 1U).ValueOrDie());
Justin Schuhe2eefe612022-01-13 22:48:50129constexpr float kFloatOne = 1.0;
Peter Kasting134183e2024-11-13 01:22:39130static_assert(1 == int{checked_cast<int8_t>(kFloatOne)});
131static_assert(1 == int{saturated_cast<int8_t>(kFloatOne)});
132static_assert(2U == unsigned{MakeClampedNum(kFloatOne) + 1});
Justin Schuhe2eefe612022-01-13 22:48:50133static_assert(2U ==
Peter Kasting134183e2024-11-13 01:22:39134 (MakeCheckedNum(kFloatOne) + 1).Cast<unsigned>().ValueOrDie());
135static_assert(0U == unsigned{MakeClampedNum(kFloatOne) - 1});
Justin Schuhe2eefe612022-01-13 22:48:50136static_assert(0U ==
Peter Kasting134183e2024-11-13 01:22:39137 (MakeCheckedNum(kFloatOne) - 1).Cast<unsigned>().ValueOrDie());
138static_assert(-1 == int{-MakeClampedNum(kFloatOne)});
139static_assert(-1 == (-MakeCheckedNum(kFloatOne)).Cast<int>().ValueOrDie());
140static_assert(1U == unsigned{MakeClampedNum(kFloatOne) * 1});
Justin Schuhe2eefe612022-01-13 22:48:50141static_assert(1U ==
Peter Kasting134183e2024-11-13 01:22:39142 (MakeCheckedNum(kFloatOne) * 1).Cast<unsigned>().ValueOrDie());
143static_assert(1U == unsigned{MakeClampedNum(kFloatOne) / 1});
Justin Schuhe2eefe612022-01-13 22:48:50144static_assert(1U ==
Peter Kasting134183e2024-11-13 01:22:39145 (MakeCheckedNum(kFloatOne) / 1).Cast<unsigned>().ValueOrDie());
146static_assert(1 == int{MakeClampedNum(-kFloatOne).Abs()});
147static_assert(1 == MakeCheckedNum(-kFloatOne).Abs().Cast<int>().ValueOrDie());
Justin Schuhe2eefe612022-01-13 22:48:50148
jschuhd1c1f2e2016-11-21 21:45:48149template <typename U>
150U GetNumericValueForTest(const CheckedNumeric<U>& src) {
151 return src.state_.value();
152}
jschuhb180f392017-07-03 15:09:22153
154template <typename U>
155U GetNumericValueForTest(const ClampedNumeric<U>& src) {
156 return static_cast<U>(src);
157}
158
159template <typename U>
160U GetNumericValueForTest(const U& src) {
161 return src;
162}
163
jschuh224f1d72016-11-25 20:08:48164// Logs the ValueOrDie() failure instead of crashing.
165struct LogOnFailure {
166 template <typename T>
167 static T HandleFailure() {
168 LOG(WARNING) << "ValueOrDie() failed unexpectedly.";
169 return T();
170 }
171};
172
jschuhb180f392017-07-03 15:09:22173template <typename T>
174constexpr T GetValue(const T& src) {
175 return src;
176}
177
178template <typename T, typename U>
179constexpr T GetValueAsDest(const U& src) {
180 return static_cast<T>(src);
181}
182
183template <typename T>
184constexpr T GetValue(const CheckedNumeric<T>& src) {
185 return src.template ValueOrDie<T, LogOnFailure>();
186}
187
188template <typename T, typename U>
189constexpr T GetValueAsDest(const CheckedNumeric<U>& src) {
190 return src.template ValueOrDie<T, LogOnFailure>();
191}
192
193template <typename T>
194constexpr T GetValue(const ClampedNumeric<T>& src) {
195 return static_cast<T>(src);
196}
197
198template <typename T, typename U>
199constexpr T GetValueAsDest(const ClampedNumeric<U>& src) {
200 return static_cast<T>(src);
201}
202
[email protected]5bfecbc52014-02-27 13:49:04203// Helper macros to wrap displaying the conversion types and line numbers.
204#define TEST_EXPECTED_VALIDITY(expected, actual) \
jschuh4fcd6fa2016-11-24 11:58:39205 EXPECT_EQ(expected, (actual).template Cast<Dst>().IsValid()) \
jschuhd1c1f2e2016-11-21 21:45:48206 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
207 << dst << " on line " << line
[email protected]5bfecbc52014-02-27 13:49:04208
jschuh819c8262016-05-21 01:39:03209#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
210#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
211
jschuhba3c4f942016-12-10 14:03:55212// We have to handle promotions, so infer the underlying type below from actual.
213#define TEST_EXPECTED_VALUE(expected, actual) \
jschuhb180f392017-07-03 15:09:22214 EXPECT_EQ(GetValue(expected), GetValueAsDest<decltype(expected)>(actual)) \
jschuhba3c4f942016-12-10 14:03:55215 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
jschuhd1c1f2e2016-11-21 21:45:48216 << dst << " on line " << line
[email protected]5bfecbc52014-02-27 13:49:04217
jschuh23a4b062016-12-02 02:55:08218// Test the simple pointer arithmetic overrides.
219template <typename Dst>
220void TestStrictPointerMath() {
221 Dst dummy_value = 0;
222 Dst* dummy_ptr = &dummy_value;
223 static const Dst kDummyOffset = 2; // Don't want to go too far.
224 EXPECT_EQ(dummy_ptr + kDummyOffset,
225 dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
226 EXPECT_EQ(dummy_ptr - kDummyOffset,
227 dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
228 EXPECT_NE(dummy_ptr, dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
229 EXPECT_NE(dummy_ptr, dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
230 EXPECT_DEATH_IF_SUPPORTED(
231 dummy_ptr + StrictNumeric<size_t>(std::numeric_limits<size_t>::max()),
232 "");
233}
234
[email protected]5bfecbc52014-02-27 13:49:04235// Signed integer arithmetic.
236template <typename Dst>
Peter Kasting134183e2024-11-13 01:22:39237 requires std::signed_integral<Dst>
238static void TestSpecializedArithmetic(const char* dst, int line) {
jschuhb180f392017-07-03 15:09:22239 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b00c2016-12-05 18:21:48240 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::lowest()));
241 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
[email protected]5bfecbc52014-02-27 13:49:04242 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
jschuhba3c4f942016-12-10 14:03:55243 TEST_EXPECTED_VALUE(DstLimits::max(),
244 MakeCheckedNum(-DstLimits::max()).Abs());
[email protected]5bfecbc52014-02-27 13:49:04245
jschuhb180f392017-07-03 15:09:22246 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
247 -ClampedNumeric<Dst>(DstLimits::lowest()));
248 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
249 ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
250 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).Abs());
251 TEST_EXPECTED_VALUE(DstLimits::max(),
252 MakeClampedNum(-DstLimits::max()).Abs());
253
jschuh819c8262016-05-21 01:39:03254 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
jschuh5030b00c2016-12-05 18:21:48255 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
256 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
257 DstLimits::lowest());
[email protected]5bfecbc52014-02-27 13:49:04258
jschuhb180f392017-07-03 15:09:22259 TEST_EXPECTED_VALUE(DstLimits::max() - 1,
260 ClampedNumeric<Dst>(DstLimits::max()) + -1);
261 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
262 ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
263 TEST_EXPECTED_VALUE(
264 DstLimits::Underflow(),
265 ClampedNumeric<Dst>(DstLimits::lowest()) + DstLimits::lowest());
266
jschuh5030b00c2016-12-05 18:21:48267 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
268 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) - -1);
jschuh819c8262016-05-21 01:39:03269 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
jschuh5030b00c2016-12-05 18:21:48270 DstLimits::lowest());
271 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
jschuh819c8262016-05-21 01:39:03272 DstLimits::max());
[email protected]5bfecbc52014-02-27 13:49:04273
jschuhb180f392017-07-03 15:09:22274 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
275 ClampedNumeric<Dst>(DstLimits::lowest()) - 1);
276 TEST_EXPECTED_VALUE(DstLimits::lowest() + 1,
277 ClampedNumeric<Dst>(DstLimits::lowest()) - -1);
278 TEST_EXPECTED_VALUE(
279 DstLimits::Overflow(),
280 ClampedNumeric<Dst>(DstLimits::max()) - DstLimits::lowest());
281 TEST_EXPECTED_VALUE(
282 DstLimits::Underflow(),
283 ClampedNumeric<Dst>(DstLimits::lowest()) - DstLimits::max());
284
jschuh5030b00c2016-12-05 18:21:48285 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
jschuhb180f392017-07-03 15:09:22286 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
287 ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
[email protected]5bfecbc52014-02-27 13:49:04288
jschuh5030b00c2016-12-05 18:21:48289 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) / -1);
[email protected]5bfecbc52014-02-27 13:49:04290 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
jschuh5030b00c2016-12-05 18:21:48291 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * -1);
jschuh33232e02017-01-03 20:33:36292 TEST_EXPECTED_VALUE(DstLimits::max(),
293 CheckedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
294 TEST_EXPECTED_VALUE(DstLimits::max(),
295 CheckedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
296 TEST_EXPECTED_VALUE(DstLimits::lowest(),
297 CheckedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
298 TEST_EXPECTED_VALUE(DstLimits::lowest(),
299 CheckedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
jschuhb180f392017-07-03 15:09:22300 TEST_EXPECTED_VALUE(
301 typename std::make_unsigned<Dst>::type(0) - DstLimits::lowest(),
302 MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
jschuhba3c4f942016-12-10 14:03:55303 TEST_EXPECTED_VALUE(DstLimits::max(),
304 MakeCheckedNum(DstLimits::max()).UnsignedAbs());
305 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
306 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
307 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).UnsignedAbs());
[email protected]5bfecbc52014-02-27 13:49:04308
jschuhb180f392017-07-03 15:09:22309 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
310 ClampedNumeric<Dst>(DstLimits::lowest()) / -1);
311 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) / 2);
312 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
313 ClampedNumeric<Dst>(DstLimits::lowest()) * -1);
314 TEST_EXPECTED_VALUE(DstLimits::max(),
315 ClampedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
316 TEST_EXPECTED_VALUE(DstLimits::max(),
317 ClampedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
318 TEST_EXPECTED_VALUE(DstLimits::lowest(),
319 ClampedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
320 TEST_EXPECTED_VALUE(DstLimits::lowest(),
321 ClampedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
322 TEST_EXPECTED_VALUE(
323 typename std::make_unsigned<Dst>::type(0) - DstLimits::lowest(),
324 MakeClampedNum(DstLimits::lowest()).UnsignedAbs());
325 TEST_EXPECTED_VALUE(DstLimits::max(),
326 MakeClampedNum(DstLimits::max()).UnsignedAbs());
327 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0).UnsignedAbs());
328 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).UnsignedAbs());
329 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).UnsignedAbs());
330
[email protected]5bfecbc52014-02-27 13:49:04331 // Modulus is legal only for integers.
Tom Sepezfe88d4192020-05-28 16:41:05332 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % 2);
333 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % 1);
334 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % -1);
335 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) % -2);
336 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
[email protected]5bfecbc52014-02-27 13:49:04337 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
Tom Sepezfe88d4192020-05-28 16:41:05338 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % -1);
339 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % -2);
[email protected]5bfecbc52014-02-27 13:49:04340 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05341 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) % 1);
342 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) % -1);
jschuhb180f392017-07-03 15:09:22343 TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % -2);
jschuh5030b00c2016-12-05 18:21:48344 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05345 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 1);
346 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % -1);
347 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % -2);
[email protected]5bfecbc52014-02-27 13:49:04348 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05349 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::max()) % 1);
350 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::max()) % -1);
351 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % -2);
[email protected]5bfecbc52014-02-27 13:49:04352 // Test all the different modulus combinations.
353 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
354 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
355 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
356 CheckedNumeric<Dst> checked_dst = 1;
357 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
tsepezdfd77a92016-11-02 20:18:06358 // Test that div by 0 is avoided but returns invalid result.
359 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
jschuh3ab54042016-11-17 06:58:44360 // Test bit shifts.
361 volatile Dst negative_one = -1;
362 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
jschuh5030b00c2016-12-05 18:21:48363 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
Peter Kastingabcf60a2024-11-13 01:24:37364 << (kIntegerBitsPlusSign<Dst> - 1));
365 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0) << kIntegerBitsPlusSign<Dst>);
jschuh3ab54042016-11-17 06:58:44366 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
Peter Kastingabcf60a2024-11-13 01:24:37367 TEST_EXPECTED_VALUE(static_cast<Dst>(1) << (kIntegerBitsPlusSign<Dst> - 2),
368 CheckedNumeric<Dst>(1)
369 << (kIntegerBitsPlusSign<Dst> - 2));
jschuh3ab54042016-11-17 06:58:44370 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0)
Peter Kastingabcf60a2024-11-13 01:24:37371 << (kIntegerBitsPlusSign<Dst> - 1));
jschuh3ab54042016-11-17 06:58:44372 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
373 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
Peter Kastingabcf60a2024-11-13 01:24:37374 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> kIntegerBitsPlusSign<Dst>);
jschuh5030b00c2016-12-05 18:21:48375 TEST_EXPECTED_VALUE(
Peter Kastingabcf60a2024-11-13 01:24:37376 0, CheckedNumeric<Dst>(1) >> (kIntegerBitsPlusSign<Dst> - 1));
jschuh3ab54042016-11-17 06:58:44377 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
jschuh23a4b062016-12-02 02:55:08378
jschuhb180f392017-07-03 15:09:22379 // Modulus is legal only for integers.
Tom Sepezfe88d4192020-05-28 16:41:05380 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % 2);
381 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % 1);
382 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % -1);
383 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) % -2);
384 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % 2);
jschuhb180f392017-07-03 15:09:22385 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
Tom Sepezfe88d4192020-05-28 16:41:05386 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % -1);
387 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % -2);
jschuhb180f392017-07-03 15:09:22388 TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(-1) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05389 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) % 1);
390 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) % -1);
jschuhb180f392017-07-03 15:09:22391 TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(-1) % -2);
392 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05393 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 1);
394 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % -1);
395 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % -2);
jschuhb180f392017-07-03 15:09:22396 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % 2);
Tom Sepezfe88d4192020-05-28 16:41:05397 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) % 1);
398 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) % -1);
399 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % -2);
jschuhb180f392017-07-03 15:09:22400 // Test all the different modulus combinations.
401 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % ClampedNumeric<Dst>(1));
402 TEST_EXPECTED_VALUE(0, 1 % ClampedNumeric<Dst>(1));
403 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
404 ClampedNumeric<Dst> clamped_dst = 1;
405 TEST_EXPECTED_VALUE(0, clamped_dst %= 1);
406 TEST_EXPECTED_VALUE(Dst(1), ClampedNumeric<Dst>(1) % 0);
407 // Test bit shifts.
408 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
409 ClampedNumeric<Dst>(1)
Peter Kastingabcf60a2024-11-13 01:24:37410 << (kIntegerBitsPlusSign<Dst> - 1U));
jschuhb180f392017-07-03 15:09:22411 TEST_EXPECTED_VALUE(Dst(0), ClampedNumeric<Dst>(0)
Peter Kastingabcf60a2024-11-13 01:24:37412 << (kIntegerBitsPlusSign<Dst> + 0U));
jschuhb180f392017-07-03 15:09:22413 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
414 ClampedNumeric<Dst>(DstLimits::max()) << 1U);
Peter Kastingabcf60a2024-11-13 01:24:37415 TEST_EXPECTED_VALUE(static_cast<Dst>(1) << (kIntegerBitsPlusSign<Dst> - 2U),
416 ClampedNumeric<Dst>(1)
417 << (kIntegerBitsPlusSign<Dst> - 2U));
jschuhb180f392017-07-03 15:09:22418 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0)
Peter Kastingabcf60a2024-11-13 01:24:37419 << (kIntegerBitsPlusSign<Dst> - 1U));
jschuhb180f392017-07-03 15:09:22420 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) << 0U);
421 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) << 1U);
422 TEST_EXPECTED_VALUE(
Peter Kastingabcf60a2024-11-13 01:24:37423 0, ClampedNumeric<Dst>(1) >> (kIntegerBitsPlusSign<Dst> + 0U));
jschuhb180f392017-07-03 15:09:22424 TEST_EXPECTED_VALUE(
Peter Kastingabcf60a2024-11-13 01:24:37425 0, ClampedNumeric<Dst>(1) >> (kIntegerBitsPlusSign<Dst> - 1U));
jschuhb180f392017-07-03 15:09:22426 TEST_EXPECTED_VALUE(
Peter Kastingabcf60a2024-11-13 01:24:37427 -1, ClampedNumeric<Dst>(-1) >> (kIntegerBitsPlusSign<Dst> - 1U));
jschuhb180f392017-07-03 15:09:22428 TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(DstLimits::lowest()) >>
Peter Kastingabcf60a2024-11-13 01:24:37429 (kIntegerBitsPlusSign<Dst> - 0U));
jschuhb180f392017-07-03 15:09:22430
jschuh23a4b062016-12-02 02:55:08431 TestStrictPointerMath<Dst>();
[email protected]5bfecbc52014-02-27 13:49:04432}
433
434// Unsigned integer arithmetic.
435template <typename Dst>
Peter Kasting134183e2024-11-13 01:22:39436 requires std::unsigned_integral<Dst>
437static void TestSpecializedArithmetic(const char* dst, int line) {
jschuhb180f392017-07-03 15:09:22438 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b00c2016-12-05 18:21:48439 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
440 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
441 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
442 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
443 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
[email protected]5bfecbc52014-02-27 13:49:04444 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
jschuh5030b00c2016-12-05 18:21:48445 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
jschuh819c8262016-05-21 01:39:03446 TEST_EXPECTED_SUCCESS(
jschuh5030b00c2016-12-05 18:21:48447 CheckedNumeric<typename std::make_signed<Dst>::type>(
448 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
jschuheaf375f2015-09-17 01:04:28449 .UnsignedAbs());
jschuhba3c4f942016-12-10 14:03:55450 TEST_EXPECTED_VALUE(DstLimits::lowest(),
451 MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
452 TEST_EXPECTED_VALUE(DstLimits::max(),
453 MakeCheckedNum(DstLimits::max()).UnsignedAbs());
454 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
455 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
[email protected]5bfecbc52014-02-27 13:49:04456
jschuhb180f392017-07-03 15:09:22457 TEST_EXPECTED_VALUE(0, -ClampedNumeric<Dst>(DstLimits::lowest()));
458 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
459 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
460 ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
461 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
462 ClampedNumeric<Dst>(DstLimits::lowest()) - 1);
463 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
464 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) / 2);
465 TEST_EXPECTED_VALUE(0,
466 ClampedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
467 TEST_EXPECTED_VALUE(
468 as_unsigned(
469 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest()),
470 ClampedNumeric<typename std::make_signed<Dst>::type>(
471 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
472 .UnsignedAbs());
473 TEST_EXPECTED_VALUE(DstLimits::lowest(),
474 MakeClampedNum(DstLimits::lowest()).UnsignedAbs());
475 TEST_EXPECTED_VALUE(DstLimits::max(),
476 MakeClampedNum(DstLimits::max()).UnsignedAbs());
477 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0).UnsignedAbs());
478 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).UnsignedAbs());
479
[email protected]5bfecbc52014-02-27 13:49:04480 // Modulus is legal only for integers.
481 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
482 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
483 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
jschuh5030b00c2016-12-05 18:21:48484 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
[email protected]5bfecbc52014-02-27 13:49:04485 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
486 // Test all the different modulus combinations.
487 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
488 TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
489 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
490 CheckedNumeric<Dst> checked_dst = 1;
491 TEST_EXPECTED_VALUE(0, checked_dst %= 1);
tsepezdfd77a92016-11-02 20:18:06492 // Test that div by 0 is avoided but returns invalid result.
493 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
Peter Kastingabcf60a2024-11-13 01:24:37494 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << kIntegerBitsPlusSign<Dst>);
jschuh3ab54042016-11-17 06:58:44495 // Test bit shifts.
496 volatile int negative_one = -1;
497 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
Peter Kastingabcf60a2024-11-13 01:24:37498 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << kIntegerBitsPlusSign<Dst>);
499 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0) << kIntegerBitsPlusSign<Dst>);
jschuh3ab54042016-11-17 06:58:44500 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
Peter Kastingabcf60a2024-11-13 01:24:37501 TEST_EXPECTED_VALUE(static_cast<Dst>(1) << (kIntegerBitsPlusSign<Dst> - 1),
502 CheckedNumeric<Dst>(1)
503 << (kIntegerBitsPlusSign<Dst> - 1));
jschuh3ab54042016-11-17 06:58:44504 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
505 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
Peter Kastingabcf60a2024-11-13 01:24:37506 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> kIntegerBitsPlusSign<Dst>);
jschuh5030b00c2016-12-05 18:21:48507 TEST_EXPECTED_VALUE(
Peter Kastingabcf60a2024-11-13 01:24:37508 0, CheckedNumeric<Dst>(1) >> (kIntegerBitsPlusSign<Dst> - 1));
jschuh3ab54042016-11-17 06:58:44509 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
jschuhb6737bb2016-11-29 03:06:59510 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) & 1);
511 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
512 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) & 1);
513 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
514 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
jschuh4bc919cb52016-12-04 15:08:27515 MakeCheckedNum(DstLimits::max()) & -1);
jschuhb6737bb2016-11-29 03:06:59516 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 1);
517 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 0);
518 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) | 1);
519 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0);
520 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
521 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1));
522 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1);
523 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0);
524 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1);
525 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0);
526 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
527 CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
jschuh970313c2016-11-24 21:40:58528 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0));
jschuh23a4b062016-12-02 02:55:08529
jschuhb180f392017-07-03 15:09:22530 // Modulus is legal only for integers.
531 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() % 1);
532 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
533 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % 2);
534 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 2);
535 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % 2);
536 // Test all the different modulus combinations.
537 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % ClampedNumeric<Dst>(1));
538 TEST_EXPECTED_VALUE(0, 1 % ClampedNumeric<Dst>(1));
539 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
540 ClampedNumeric<Dst> clamped_dst = 1;
541 TEST_EXPECTED_VALUE(0, clamped_dst %= 1);
542 // Test that div by 0 is avoided but returns invalid result.
543 TEST_EXPECTED_VALUE(Dst(1), ClampedNumeric<Dst>(1) % 0);
544 // Test bit shifts.
545 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
546 ClampedNumeric<Dst>(1)
Peter Kastingabcf60a2024-11-13 01:24:37547 << as_unsigned(kIntegerBitsPlusSign<Dst>));
548 TEST_EXPECTED_VALUE(Dst(0), ClampedNumeric<Dst>(0)
549 << as_unsigned(kIntegerBitsPlusSign<Dst>));
jschuhb180f392017-07-03 15:09:22550 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
551 ClampedNumeric<Dst>(DstLimits::max()) << 1U);
Peter Kastingabcf60a2024-11-13 01:24:37552 TEST_EXPECTED_VALUE(static_cast<Dst>(1) << (kIntegerBitsPlusSign<Dst> - 1U),
553 ClampedNumeric<Dst>(1)
554 << (kIntegerBitsPlusSign<Dst> - 1U));
jschuhb180f392017-07-03 15:09:22555 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) << 0U);
556 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) << 1U);
jschuhb180f392017-07-03 15:09:22557 TEST_EXPECTED_VALUE(
Peter Kastingabcf60a2024-11-13 01:24:37558 0, ClampedNumeric<Dst>(1) >> as_unsigned(kIntegerBitsPlusSign<Dst>));
559 TEST_EXPECTED_VALUE(
560 0, ClampedNumeric<Dst>(1) >> (kIntegerBitsPlusSign<Dst> - 1U));
jschuhb180f392017-07-03 15:09:22561 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) & 1);
562 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) & 0);
563 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) & 1);
564 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) & 0);
565 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
566 MakeClampedNum(DstLimits::max()) & -1);
567 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) | 1);
568 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) | 0);
569 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(0) | 1);
570 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) | 0);
571 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
572 ClampedNumeric<Dst>(0) | static_cast<Dst>(-1));
573 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) ^ 1);
574 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) ^ 0);
575 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(0) ^ 1);
576 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) ^ 0);
577 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
578 ClampedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
579 TEST_EXPECTED_VALUE(DstLimits::max(), ~ClampedNumeric<Dst>(0));
580
jschuh23a4b062016-12-02 02:55:08581 TestStrictPointerMath<Dst>();
[email protected]5bfecbc52014-02-27 13:49:04582}
583
584// Floating point arithmetic.
585template <typename Dst>
Peter Kasting134183e2024-11-13 01:22:39586 requires std::numeric_limits<Dst>::is_iec559
587void TestSpecializedArithmetic(const char* dst, int line) {
jschuhb180f392017-07-03 15:09:22588 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b00c2016-12-05 18:21:48589 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
[email protected]5bfecbc52014-02-27 13:49:04590
jschuh5030b00c2016-12-05 18:21:48591 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
[email protected]5bfecbc52014-02-27 13:49:04592 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
593
jschuh5030b00c2016-12-05 18:21:48594 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
jschuh819c8262016-05-21 01:39:03595 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
jschuh5030b00c2016-12-05 18:21:48596 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
597 DstLimits::lowest());
[email protected]5bfecbc52014-02-27 13:49:04598
jschuh819c8262016-05-21 01:39:03599 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
jschuh5030b00c2016-12-05 18:21:48600 DstLimits::lowest());
601 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
jschuh819c8262016-05-21 01:39:03602 DstLimits::max());
[email protected]5bfecbc52014-02-27 13:49:04603
jschuh5030b00c2016-12-05 18:21:48604 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
[email protected]5bfecbc52014-02-27 13:49:04605
606 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
jschuhb180f392017-07-03 15:09:22607
608 TEST_EXPECTED_VALUE(DstLimits::max(),
609 -ClampedNumeric<Dst>(DstLimits::lowest()));
610
611 TEST_EXPECTED_VALUE(DstLimits::max(),
612 ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
613 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).Abs());
614
615 TEST_EXPECTED_VALUE(DstLimits::lowest() - 1,
616 ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
617 TEST_EXPECTED_VALUE(DstLimits::max() + 1,
618 ClampedNumeric<Dst>(DstLimits::max()) + 1);
619 TEST_EXPECTED_VALUE(
620 DstLimits::Underflow(),
621 ClampedNumeric<Dst>(DstLimits::lowest()) + DstLimits::lowest());
622
623 TEST_EXPECTED_VALUE(
624 DstLimits::Overflow(),
625 ClampedNumeric<Dst>(DstLimits::max()) - DstLimits::lowest());
626 TEST_EXPECTED_VALUE(
627 DstLimits::Underflow(),
628 ClampedNumeric<Dst>(DstLimits::lowest()) - DstLimits::max());
629
630 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
631 ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
632
633 TEST_EXPECTED_VALUE(-0.5, ClampedNumeric<Dst>(-1.0) / 2);
[email protected]5bfecbc52014-02-27 13:49:04634}
635
636// Generic arithmetic tests.
637template <typename Dst>
638static void TestArithmetic(const char* dst, int line) {
jschuhb180f392017-07-03 15:09:22639 using DstLimits = SaturationDefaultLimits<Dst>;
[email protected]5bfecbc52014-02-27 13:49:04640
Daniel Chengef817202022-08-27 09:01:15641 // Test C++17 class template argument deduction
642 static_assert(
Peter Kasting134183e2024-11-13 01:22:39643 std::same_as<Dst, typename decltype(CheckedNumeric(Dst{0}))::type>);
Daniel Chengef817202022-08-27 09:01:15644 static_assert(
Peter Kasting134183e2024-11-13 01:22:39645 std::same_as<Dst, typename decltype(ClampedNumeric(Dst{0}))::type>);
Daniel Chengef817202022-08-27 09:01:15646 static_assert(
Peter Kasting134183e2024-11-13 01:22:39647 std::same_as<Dst, typename decltype(StrictNumeric(Dst{0}))::type>);
Daniel Chengef817202022-08-27 09:01:15648
[email protected]5bfecbc52014-02-27 13:49:04649 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
Justin Schuh5cc331de2017-07-25 18:05:22650 EXPECT_EQ(false, CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
651 DstLimits::max())
652 .IsValid());
[email protected]5bfecbc52014-02-27 13:49:04653 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
654 EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
655 EXPECT_EQ(static_cast<Dst>(1),
656 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
Justin Schuh5cc331de2017-07-25 18:05:22657 DstLimits::max())
658 .ValueOrDefault(1));
[email protected]5bfecbc52014-02-27 13:49:04659
660 // Test the operator combinations.
661 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
662 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
663 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
664 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
665 TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
666 TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
667 TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
668 TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
669 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
670 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
671 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
672 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
673 CheckedNumeric<Dst> checked_dst = 1;
674 TEST_EXPECTED_VALUE(2, checked_dst += 1);
675 checked_dst = 1;
676 TEST_EXPECTED_VALUE(0, checked_dst -= 1);
677 checked_dst = 1;
678 TEST_EXPECTED_VALUE(1, checked_dst *= 1);
679 checked_dst = 1;
680 TEST_EXPECTED_VALUE(1, checked_dst /= 1);
681
jschuhb180f392017-07-03 15:09:22682 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) + ClampedNumeric<Dst>(1));
683 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) - ClampedNumeric<Dst>(1));
684 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) * ClampedNumeric<Dst>(1));
685 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / ClampedNumeric<Dst>(1));
686 TEST_EXPECTED_VALUE(2, 1 + ClampedNumeric<Dst>(1));
687 TEST_EXPECTED_VALUE(0, 1 - ClampedNumeric<Dst>(1));
688 TEST_EXPECTED_VALUE(1, 1 * ClampedNumeric<Dst>(1));
689 TEST_EXPECTED_VALUE(1, 1 / ClampedNumeric<Dst>(1));
690 TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) + 1);
691 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) - 1);
692 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) * 1);
693 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / 1);
694 ClampedNumeric<Dst> clamped_dst = 1;
695 TEST_EXPECTED_VALUE(2, clamped_dst += 1);
696 clamped_dst = 1;
697 TEST_EXPECTED_VALUE(0, clamped_dst -= 1);
698 clamped_dst = 1;
699 TEST_EXPECTED_VALUE(1, clamped_dst *= 1);
700 clamped_dst = 1;
701 TEST_EXPECTED_VALUE(1, clamped_dst /= 1);
702
[email protected]5bfecbc52014-02-27 13:49:04703 // Generic negation.
Peter Kasting134183e2024-11-13 01:22:39704 if constexpr (DstLimits::is_signed) {
jschuh749c7f72016-09-07 16:22:26705 TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
706 TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
707 TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
708 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
709 -CheckedNumeric<Dst>(DstLimits::max()));
jschuhb180f392017-07-03 15:09:22710
711 TEST_EXPECTED_VALUE(0, -ClampedNumeric<Dst>());
712 TEST_EXPECTED_VALUE(-1, -ClampedNumeric<Dst>(1));
713 TEST_EXPECTED_VALUE(1, -ClampedNumeric<Dst>(-1));
714 TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
715 -ClampedNumeric<Dst>(DstLimits::max()));
Justin Schuha15cf3c2017-07-14 23:16:58716
717 // The runtime paths for saturated negation differ significantly from what
718 // gets evaluated at compile-time. Making this test volatile forces the
719 // compiler to generate code rather than fold constant expressions.
720 volatile Dst value = Dst(0);
721 TEST_EXPECTED_VALUE(0, -MakeClampedNum(value));
722 value = Dst(1);
723 TEST_EXPECTED_VALUE(-1, -MakeClampedNum(value));
724 value = Dst(2);
725 TEST_EXPECTED_VALUE(-2, -MakeClampedNum(value));
726 value = Dst(-1);
727 TEST_EXPECTED_VALUE(1, -MakeClampedNum(value));
728 value = Dst(-2);
729 TEST_EXPECTED_VALUE(2, -MakeClampedNum(value));
730 value = DstLimits::max();
731 TEST_EXPECTED_VALUE(Dst(DstLimits::max() * -1), -MakeClampedNum(value));
732 value = Dst(-1 * DstLimits::max());
733 TEST_EXPECTED_VALUE(DstLimits::max(), -MakeClampedNum(value));
734 value = DstLimits::lowest();
735 TEST_EXPECTED_VALUE(DstLimits::max(), -MakeClampedNum(value));
jschuh749c7f72016-09-07 16:22:26736 }
[email protected]5bfecbc52014-02-27 13:49:04737
738 // Generic absolute value.
739 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
740 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
741 TEST_EXPECTED_VALUE(DstLimits::max(),
742 CheckedNumeric<Dst>(DstLimits::max()).Abs());
743
jschuhb180f392017-07-03 15:09:22744 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>().Abs());
745 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).Abs());
746 TEST_EXPECTED_VALUE(DstLimits::max(),
747 ClampedNumeric<Dst>(DstLimits::max()).Abs());
748
[email protected]5bfecbc52014-02-27 13:49:04749 // Generic addition.
750 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
751 TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
Peter Kasting134183e2024-11-13 01:22:39752 if constexpr (numeric_limits<Dst>::is_signed) {
jschuh216b62a92016-11-08 03:53:08753 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
Peter Kasting134183e2024-11-13 01:22:39754 }
jschuh5030b00c2016-12-05 18:21:48755 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + 1);
jschuh819c8262016-05-21 01:39:03756 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) +
757 DstLimits::max());
[email protected]5bfecbc52014-02-27 13:49:04758
jschuhb180f392017-07-03 15:09:22759 TEST_EXPECTED_VALUE(1, (ClampedNumeric<Dst>() + 1));
760 TEST_EXPECTED_VALUE(2, (ClampedNumeric<Dst>(1) + 1));
Peter Kasting134183e2024-11-13 01:22:39761 if constexpr (numeric_limits<Dst>::is_signed) {
jschuhb180f392017-07-03 15:09:22762 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(-1) + 1));
Peter Kasting134183e2024-11-13 01:22:39763 }
jschuhb180f392017-07-03 15:09:22764 TEST_EXPECTED_VALUE(DstLimits::lowest() + 1,
765 ClampedNumeric<Dst>(DstLimits::lowest()) + 1);
766 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
767 ClampedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
768
[email protected]5bfecbc52014-02-27 13:49:04769 // Generic subtraction.
[email protected]5bfecbc52014-02-27 13:49:04770 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
jschuh819c8262016-05-21 01:39:03771 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
Peter Kasting134183e2024-11-13 01:22:39772 if constexpr (numeric_limits<Dst>::is_signed) {
jschuh216b62a92016-11-08 03:53:08773 TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
774 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
jschuh657a3d62016-11-15 18:23:45775 } else {
776 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -1);
jschuh216b62a92016-11-08 03:53:08777 }
[email protected]5bfecbc52014-02-27 13:49:04778
jschuhb180f392017-07-03 15:09:22779 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(1) - 1));
780 TEST_EXPECTED_VALUE(DstLimits::max() - 1,
781 ClampedNumeric<Dst>(DstLimits::max()) - 1);
Peter Kasting134183e2024-11-13 01:22:39782 if constexpr (numeric_limits<Dst>::is_signed) {
jschuhb180f392017-07-03 15:09:22783 TEST_EXPECTED_VALUE(-1, (ClampedNumeric<Dst>() - 1));
784 TEST_EXPECTED_VALUE(-2, (ClampedNumeric<Dst>(-1) - 1));
785 } else {
786 TEST_EXPECTED_VALUE(DstLimits::max(),
787 ClampedNumeric<Dst>(DstLimits::max()) - -1);
788 }
789
[email protected]5bfecbc52014-02-27 13:49:04790 // Generic multiplication.
791 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
792 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
eroman0397125f2015-05-18 14:44:32793 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
Peter Kasting134183e2024-11-13 01:22:39794 if constexpr (numeric_limits<Dst>::is_signed) {
jschuh216b62a92016-11-08 03:53:08795 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
796 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
jschuh749c7f72016-09-07 16:22:26797 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
jschuh657a3d62016-11-15 18:23:45798 } else {
799 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * -2);
800 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
801 CheckedNumeric<uintmax_t>(-2));
jschuh749c7f72016-09-07 16:22:26802 }
jschuh216b62a92016-11-08 03:53:08803 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
804 DstLimits::max());
[email protected]5bfecbc52014-02-27 13:49:04805
jschuhb180f392017-07-03 15:09:22806 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>() * 1));
807 TEST_EXPECTED_VALUE(1, (ClampedNumeric<Dst>(1) * 1));
808 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(0) * 0));
Peter Kasting134183e2024-11-13 01:22:39809 if constexpr (numeric_limits<Dst>::is_signed) {
jschuhb180f392017-07-03 15:09:22810 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(-1) * 0));
811 TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(0) * -1));
812 TEST_EXPECTED_VALUE(-2, (ClampedNumeric<Dst>(-1) * 2));
813 } else {
814 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
815 ClampedNumeric<Dst>(DstLimits::max()) * -2);
816 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) *
817 ClampedNumeric<uintmax_t>(-2));
818 }
819 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
820 ClampedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
821
[email protected]5bfecbc52014-02-27 13:49:04822 // Generic division.
823 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
824 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
jschuh5030b00c2016-12-05 18:21:48825 TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
826 CheckedNumeric<Dst>(DstLimits::lowest()) / 2);
[email protected]5bfecbc52014-02-27 13:49:04827 TEST_EXPECTED_VALUE(DstLimits::max() / 2,
828 CheckedNumeric<Dst>(DstLimits::max()) / 2);
jschuhb180f392017-07-03 15:09:22829 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) / 0);
830
831 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() / 1);
832 TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / 1);
833 TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
834 ClampedNumeric<Dst>(DstLimits::lowest()) / 2);
835 TEST_EXPECTED_VALUE(DstLimits::max() / 2,
836 ClampedNumeric<Dst>(DstLimits::max()) / 2);
837 TEST_EXPECTED_VALUE(DstLimits::Overflow(), ClampedNumeric<Dst>(1) / 0);
838 TEST_EXPECTED_VALUE(DstLimits::Underflow(), ClampedNumeric<Dst>(-1) / 0);
839 TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) / 0);
[email protected]5bfecbc52014-02-27 13:49:04840
841 TestSpecializedArithmetic<Dst>(dst, line);
842}
843
844// Helper macro to wrap displaying the conversion types and line numbers.
845#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
846
847TEST(SafeNumerics, SignedIntegerMath) {
848 TEST_ARITHMETIC(int8_t);
Justin Schuha26da272017-07-13 23:04:30849 TEST_ARITHMETIC(int16_t);
[email protected]5bfecbc52014-02-27 13:49:04850 TEST_ARITHMETIC(int);
851 TEST_ARITHMETIC(intptr_t);
852 TEST_ARITHMETIC(intmax_t);
853}
854
855TEST(SafeNumerics, UnsignedIntegerMath) {
856 TEST_ARITHMETIC(uint8_t);
Justin Schuha26da272017-07-13 23:04:30857 TEST_ARITHMETIC(uint16_t);
[email protected]5bfecbc52014-02-27 13:49:04858 TEST_ARITHMETIC(unsigned int);
859 TEST_ARITHMETIC(uintptr_t);
860 TEST_ARITHMETIC(uintmax_t);
861}
862
863TEST(SafeNumerics, FloatingPointMath) {
864 TEST_ARITHMETIC(float);
865 TEST_ARITHMETIC(double);
866}
[email protected]c1c090d32013-01-16 23:34:04867
[email protected]4efb2c32014-01-16 06:57:25868// Enumerates the five different conversions types we need to test.
869enum NumericConversionType {
870 SIGN_PRESERVING_VALUE_PRESERVING,
871 SIGN_PRESERVING_NARROW,
872 SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
873 SIGN_TO_UNSIGN_NARROW,
874 UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
875};
[email protected]c1c090d32013-01-16 23:34:04876
[email protected]4efb2c32014-01-16 06:57:25877// Template covering the different conversion tests.
878template <typename Dst, typename Src, NumericConversionType conversion>
879struct TestNumericConversion {};
[email protected]c1c090d32013-01-16 23:34:04880
jschuh082b2ba2017-01-06 11:40:54881enum RangeConstraint {
882 RANGE_VALID = 0x0, // Value can be represented by the destination type.
883 RANGE_UNDERFLOW = 0x1, // Value would underflow.
884 RANGE_OVERFLOW = 0x2, // Value would overflow.
885 RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN).
886};
887
888// These are some wrappers to make the tests a bit cleaner.
889constexpr RangeConstraint RangeCheckToEnum(const RangeCheck constraint) {
890 return static_cast<RangeConstraint>(
891 static_cast<int>(constraint.IsOverflowFlagSet()) << 1 |
892 static_cast<int>(constraint.IsUnderflowFlagSet()));
893}
894
[email protected]5bfecbc52014-02-27 13:49:04895// EXPECT_EQ wrappers providing specific detail on test failures.
jschuh082b2ba2017-01-06 11:40:54896#define TEST_EXPECTED_RANGE(expected, actual) \
897 EXPECT_EQ(expected, \
Justin Schuha26da272017-07-13 23:04:30898 RangeCheckToEnum(DstRangeRelationToSrcRange<Dst>(actual))) \
jschuh082b2ba2017-01-06 11:40:54899 << "Conversion test: " << src << " value " << actual << " to " << dst \
jschuh657a3d62016-11-15 18:23:45900 << " on line " << line
[email protected]4efb2c32014-01-16 06:57:25901
902template <typename Dst, typename Src>
Justin Schuh5cc2abf2017-08-01 04:58:07903void TestStrictComparison(const char* dst, const char* src, int line) {
jschuh5030b00c2016-12-05 18:21:48904 using DstLimits = numeric_limits<Dst>;
905 using SrcLimits = numeric_limits<Src>;
Peter Kasting134183e2024-11-13 01:22:39906 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < DstLimits::max());
907 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < SrcLimits::max());
908 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= DstLimits::max()));
909 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= SrcLimits::max()));
910 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= DstLimits::max());
911 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= SrcLimits::max());
912 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > DstLimits::max()));
913 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > SrcLimits::max()));
914 static_assert(StrictNumeric<Src>(SrcLimits::max()) > DstLimits::lowest());
915 static_assert(StrictNumeric<Src>(SrcLimits::max()) > SrcLimits::lowest());
916 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= DstLimits::lowest()));
917 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= SrcLimits::lowest()));
918 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= DstLimits::lowest());
919 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= SrcLimits::lowest());
920 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < DstLimits::lowest()));
921 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < SrcLimits::lowest()));
922 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(1));
923 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(0));
924 static_assert(StrictNumeric<Src>(SrcLimits::max()) != static_cast<Dst>(0));
925 static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::lowest());
jschuh23a4b062016-12-02 02:55:08926 static_assert(
Peter Kasting134183e2024-11-13 01:22:39927 !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)));
jschuh23a4b062016-12-02 02:55:08928 static_assert(
Peter Kasting134183e2024-11-13 01:22:39929 !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)));
jschuh711ac6a2016-12-04 07:17:48930
931 // Due to differences in float handling between compilers, these aren't
932 // compile-time constants everywhere. So, we use run-time tests.
jschuh4bc919cb52016-12-04 15:08:27933 EXPECT_EQ(
934 SrcLimits::max(),
935 MakeCheckedNum(SrcLimits::max()).Max(DstLimits::lowest()).ValueOrDie());
936 EXPECT_EQ(
937 DstLimits::max(),
938 MakeCheckedNum(SrcLimits::lowest()).Max(DstLimits::max()).ValueOrDie());
939 EXPECT_EQ(
940 DstLimits::lowest(),
941 MakeCheckedNum(SrcLimits::max()).Min(DstLimits::lowest()).ValueOrDie());
942 EXPECT_EQ(
943 SrcLimits::lowest(),
944 MakeCheckedNum(SrcLimits::lowest()).Min(DstLimits::max()).ValueOrDie());
945 EXPECT_EQ(SrcLimits::lowest(), CheckMin(MakeStrictNum(1), MakeCheckedNum(0),
jschuh711ac6a2016-12-04 07:17:48946 DstLimits::max(), SrcLimits::lowest())
947 .ValueOrDie());
jschuh4bc919cb52016-12-04 15:08:27948 EXPECT_EQ(DstLimits::max(), CheckMax(MakeStrictNum(1), MakeCheckedNum(0),
jschuh711ac6a2016-12-04 07:17:48949 DstLimits::max(), SrcLimits::lowest())
950 .ValueOrDie());
Justin Schuha81d2e52017-07-14 02:53:34951
952 EXPECT_EQ(SrcLimits::max(),
953 MakeClampedNum(SrcLimits::max()).Max(DstLimits::lowest()));
954 EXPECT_EQ(DstLimits::max(),
955 MakeClampedNum(SrcLimits::lowest()).Max(DstLimits::max()));
956 EXPECT_EQ(DstLimits::lowest(),
957 MakeClampedNum(SrcLimits::max()).Min(DstLimits::lowest()));
958 EXPECT_EQ(SrcLimits::lowest(),
959 MakeClampedNum(SrcLimits::lowest()).Min(DstLimits::max()));
960 EXPECT_EQ(SrcLimits::lowest(),
961 ClampMin(MakeStrictNum(1), MakeClampedNum(0), DstLimits::max(),
962 SrcLimits::lowest()));
963 EXPECT_EQ(DstLimits::max(), ClampMax(MakeStrictNum(1), MakeClampedNum(0),
964 DstLimits::max(), SrcLimits::lowest()));
Justin Schuh5cc2abf2017-08-01 04:58:07965
Peter Kasting134183e2024-11-13 01:22:39966 if constexpr (IsValueInRangeForNumericType<Dst>(SrcLimits::max())) {
Peter Kastingabcf60a2024-11-13 01:24:37967 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()), (kCommonMax<Dst, Src>));
Justin Schuh5cc2abf2017-08-01 04:58:07968 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()),
969 (CommonMaxOrMin<Dst, Src>(false)));
970 } else {
Peter Kastingabcf60a2024-11-13 01:24:37971 TEST_EXPECTED_VALUE(DstLimits::max(), (kCommonMax<Dst, Src>));
Justin Schuh5cc2abf2017-08-01 04:58:07972 TEST_EXPECTED_VALUE(DstLimits::max(), (CommonMaxOrMin<Dst, Src>(false)));
973 }
974
Peter Kasting134183e2024-11-13 01:22:39975 if constexpr (IsValueInRangeForNumericType<Dst>(SrcLimits::lowest())) {
Peter Kastingabcf60a2024-11-13 01:24:37976 TEST_EXPECTED_VALUE(Dst(SrcLimits::lowest()), (kCommonMin<Dst, Src>));
Justin Schuh5cc2abf2017-08-01 04:58:07977 TEST_EXPECTED_VALUE(Dst(SrcLimits::lowest()),
978 (CommonMaxOrMin<Dst, Src>(true)));
979 } else {
Peter Kastingabcf60a2024-11-13 01:24:37980 TEST_EXPECTED_VALUE(DstLimits::lowest(), (kCommonMin<Dst, Src>));
Justin Schuh5cc2abf2017-08-01 04:58:07981 TEST_EXPECTED_VALUE(DstLimits::lowest(), (CommonMaxOrMin<Dst, Src>(true)));
982 }
jschuh23a4b062016-12-02 02:55:08983}
984
985template <typename Dst, typename Src>
[email protected]4efb2c32014-01-16 06:57:25986struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
Justin Schuh5cc331de2017-07-25 18:05:22987 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:22988 using SrcLimits = SaturationDefaultLimits<Src>;
989 using DstLimits = SaturationDefaultLimits<Dst>;
jschuh5030b00c2016-12-05 18:21:48990 // Integral to floating.
jschuhd2d9fe02014-10-14 14:31:37991 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
jschuh5030b00c2016-12-05 18:21:48992 // Not floating to integral and...
993 (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
994 // Same sign, same numeric, source is narrower or same.
995 ((SrcLimits::is_signed == DstLimits::is_signed &&
Peter Kastingabcf60a2024-11-13 01:24:37996 kMaxExponent<Dst> >= kMaxExponent<Src>) ||
jschuh5030b00c2016-12-05 18:21:48997 // Or signed destination and source is smaller
998 (DstLimits::is_signed &&
Peter Kastingabcf60a2024-11-13 01:24:37999 kMaxExponent<Dst> >= kMaxExponent<Src>))),
jschuhd2d9fe02014-10-14 14:31:371000 "Comparison must be sign preserving and value preserving");
[email protected]4efb2c32014-01-16 06:57:251001
Justin Schuh5cc2abf2017-08-01 04:58:071002 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081003
[email protected]5bfecbc52014-02-27 13:49:041004 const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
jschuhb180f392017-07-03 15:09:221005 const ClampedNumeric<Dst> clamped_dst = SrcLimits::max();
jschuh819c8262016-05-21 01:39:031006 TEST_EXPECTED_SUCCESS(checked_dst);
jschuhb180f392017-07-03 15:09:221007 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()), clamped_dst);
Peter Kastingabcf60a2024-11-13 01:24:371008 if constexpr (kMaxExponent<Dst> > kMaxExponent<Src>) {
1009 if constexpr (kMaxExponent<Dst> >= kMaxExponent<Src> * 2 - 1) {
[email protected]5bfecbc52014-02-27 13:49:041010 // At least twice larger type.
jschuh819c8262016-05-21 01:39:031011 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
jschuhb180f392017-07-03 15:09:221012 TEST_EXPECTED_VALUE(SrcLimits::max() * clamped_dst,
Peter Kastingfbb9e562021-06-27 02:57:371013 Dst(SrcLimits::max()) * Dst(SrcLimits::max()));
[email protected]5bfecbc52014-02-27 13:49:041014 } else { // Larger, but not at least twice as large.
jschuh819c8262016-05-21 01:39:031015 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
1016 TEST_EXPECTED_SUCCESS(checked_dst + 1);
jschuhb180f392017-07-03 15:09:221017 TEST_EXPECTED_VALUE(DstLimits::Overflow(),
1018 SrcLimits::max() * clamped_dst);
1019 TEST_EXPECTED_VALUE(Dst(SrcLimits::max()) + Dst(1),
1020 clamped_dst + Dst(1));
[email protected]5bfecbc52014-02-27 13:49:041021 }
1022 } else { // Same width type.
jschuh819c8262016-05-21 01:39:031023 TEST_EXPECTED_FAILURE(checked_dst + 1);
jschuhb180f392017-07-03 15:09:221024 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + Dst(1));
[email protected]5bfecbc52014-02-27 13:49:041025 }
1026
1027 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
1028 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
Peter Kasting134183e2024-11-13 01:22:391029 if constexpr (SrcLimits::is_iec559) {
[email protected]5bfecbc52014-02-27 13:49:041030 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
1031 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
1032 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
1033 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
Peter Kasting134183e2024-11-13 01:22:391034 } else if constexpr (numeric_limits<Src>::is_signed) {
Justin Schuh4ad909a2017-08-03 13:40:421035 // This block reverses the Src to Dst relationship so we don't have to
1036 // complicate the test macros.
Peter Kasting134183e2024-11-13 01:22:391037 if constexpr (!std::same_as<Src, Dst>) {
Justin Schuh4ad909a2017-08-03 13:40:421038 TEST_EXPECTED_SUCCESS(CheckDiv(SrcLimits::lowest(), Dst(-1)));
1039 }
[email protected]5bfecbc52014-02-27 13:49:041040 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
jschuh5030b00c2016-12-05 18:21:481041 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
[email protected]4efb2c32014-01-16 06:57:251042 }
[email protected]c1c090d32013-01-16 23:34:041043 }
[email protected]4efb2c32014-01-16 06:57:251044};
1045
1046template <typename Dst, typename Src>
1047struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
Justin Schuh5cc331de2017-07-25 18:05:221048 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221049 using SrcLimits = SaturationDefaultLimits<Src>;
1050 using DstLimits = SaturationDefaultLimits<Dst>;
jschuhd2d9fe02014-10-14 14:31:371051 static_assert(SrcLimits::is_signed == DstLimits::is_signed,
1052 "Destination and source sign must be the same");
Peter Kastingabcf60a2024-11-13 01:24:371053 static_assert(kMaxExponent<Dst> <= kMaxExponent<Src>,
jschuhd2d9fe02014-10-14 14:31:371054 "Destination must be narrower than source");
[email protected]4efb2c32014-01-16 06:57:251055
Justin Schuh5cc2abf2017-08-01 04:58:071056 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081057
[email protected]5bfecbc52014-02-27 13:49:041058 const CheckedNumeric<Dst> checked_dst;
jschuh819c8262016-05-21 01:39:031059 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
jschuhb180f392017-07-03 15:09:221060 TEST_EXPECTED_VALUE(1, checked_dst + Src(1));
jschuh819c8262016-05-21 01:39:031061 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
[email protected]5bfecbc52014-02-27 13:49:041062
Justin Schuh3725ec32017-10-01 03:44:271063 ClampedNumeric<Dst> clamped_dst;
jschuhb180f392017-07-03 15:09:221064 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
1065 TEST_EXPECTED_VALUE(1, clamped_dst + Src(1));
1066 TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst - SrcLimits::max());
Justin Schuh3725ec32017-10-01 03:44:271067 clamped_dst += SrcLimits::max();
1068 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1069 clamped_dst = DstLimits::max();
1070 clamped_dst += SrcLimits::max();
1071 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1072 clamped_dst = DstLimits::max();
1073 clamped_dst -= SrcLimits::max();
1074 TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst);
1075 clamped_dst = 0;
jschuhb180f392017-07-03 15:09:221076
[email protected]5bfecbc52014-02-27 13:49:041077 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
1078 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
Peter Kasting134183e2024-11-13 01:22:391079 if constexpr (SrcLimits::is_iec559) {
[email protected]5bfecbc52014-02-27 13:49:041080 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
1081 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
1082 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
1083 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
1084 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
Peter Kasting134183e2024-11-13 01:22:391085 if constexpr (DstLimits::is_integer) {
1086 if constexpr (SrcLimits::digits < DstLimits::digits) {
jschuhfafe0712015-09-14 20:21:241087 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
1088 static_cast<Src>(DstLimits::max()));
1089 } else {
1090 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
1091 }
1092 TEST_EXPECTED_RANGE(
1093 RANGE_VALID,
1094 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
jschuh5030b00c2016-12-05 18:21:481095 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
jschuhfafe0712015-09-14 20:21:241096 }
Peter Kasting134183e2024-11-13 01:22:391097 } else if constexpr (SrcLimits::is_signed) {
[email protected]5bfecbc52014-02-27 13:49:041098 TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
jschuhb180f392017-07-03 15:09:221099 TEST_EXPECTED_VALUE(-1, clamped_dst - static_cast<Src>(1));
Justin Schuh4ad909a2017-08-03 13:40:421100 TEST_EXPECTED_VALUE(Src(Src(0) - DstLimits::lowest()),
1101 ClampDiv(DstLimits::lowest(), Src(-1)));
jschuh5030b00c2016-12-05 18:21:481102 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
[email protected]5bfecbc52014-02-27 13:49:041103 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
[email protected]4efb2c32014-01-16 06:57:251104 } else {
jschuh819c8262016-05-21 01:39:031105 TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
jschuhb180f392017-07-03 15:09:221106 TEST_EXPECTED_VALUE(Dst(0), clamped_dst - static_cast<Src>(1));
jschuh5030b00c2016-12-05 18:21:481107 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
[email protected]4efb2c32014-01-16 06:57:251108 }
1109 }
1110};
1111
1112template <typename Dst, typename Src>
1113struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
Justin Schuh5cc331de2017-07-25 18:05:221114 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221115 using SrcLimits = SaturationDefaultLimits<Src>;
1116 using DstLimits = SaturationDefaultLimits<Dst>;
Peter Kastingabcf60a2024-11-13 01:24:371117 static_assert(kMaxExponent<Dst> >= kMaxExponent<Src>,
jschuhd2d9fe02014-10-14 14:31:371118 "Destination must be equal or wider than source.");
1119 static_assert(SrcLimits::is_signed, "Source must be signed");
1120 static_assert(!DstLimits::is_signed, "Destination must be unsigned");
[email protected]4efb2c32014-01-16 06:57:251121
Justin Schuh5cc2abf2017-08-01 04:58:071122 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081123
[email protected]5bfecbc52014-02-27 13:49:041124 const CheckedNumeric<Dst> checked_dst;
1125 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
jschuh819c8262016-05-21 01:39:031126 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
jschuhb180f392017-07-03 15:09:221127 TEST_EXPECTED_SUCCESS(checked_dst * static_cast<Src>(-1));
jschuh5030b00c2016-12-05 18:21:481128 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
Justin Schuh4ad909a2017-08-03 13:40:421129 TEST_EXPECTED_VALUE(Dst(0), CheckDiv(Dst(0), Src(-1)));
[email protected]5bfecbc52014-02-27 13:49:041130
jschuhb180f392017-07-03 15:09:221131 const ClampedNumeric<Dst> clamped_dst;
1132 TEST_EXPECTED_VALUE(SrcLimits::max(), clamped_dst + SrcLimits::max());
1133 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1134 clamped_dst + static_cast<Src>(-1));
1135 TEST_EXPECTED_VALUE(0, clamped_dst * static_cast<Src>(-1));
1136 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1137 clamped_dst + SrcLimits::lowest());
1138
jschuh5030b00c2016-12-05 18:21:481139 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
[email protected]5bfecbc52014-02-27 13:49:041140 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
1141 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
1142 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
[email protected]4efb2c32014-01-16 06:57:251143 }
1144};
1145
1146template <typename Dst, typename Src>
1147struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
Justin Schuh5cc331de2017-07-25 18:05:221148 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221149 using SrcLimits = SaturationDefaultLimits<Src>;
1150 using DstLimits = SaturationDefaultLimits<Dst>;
Peter Kastingabcf60a2024-11-13 01:24:371151 static_assert(kMaxExponent<Dst> < kMaxExponent<Src>,
jschuhd2d9fe02014-10-14 14:31:371152 "Destination must be narrower than source.");
1153 static_assert(SrcLimits::is_signed, "Source must be signed.");
1154 static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
[email protected]4efb2c32014-01-16 06:57:251155
Justin Schuh5cc2abf2017-08-01 04:58:071156 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081157
[email protected]5bfecbc52014-02-27 13:49:041158 const CheckedNumeric<Dst> checked_dst;
1159 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:031160 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
1161 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
jschuh5030b00c2016-12-05 18:21:481162 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
[email protected]5bfecbc52014-02-27 13:49:041163
Justin Schuh3725ec32017-10-01 03:44:271164 ClampedNumeric<Dst> clamped_dst;
jschuhb180f392017-07-03 15:09:221165 TEST_EXPECTED_VALUE(1, clamped_dst + static_cast<Src>(1));
1166 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
1167 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1168 clamped_dst + static_cast<Src>(-1));
1169 TEST_EXPECTED_VALUE(DstLimits::Underflow(),
1170 clamped_dst + SrcLimits::lowest());
Justin Schuh3725ec32017-10-01 03:44:271171 clamped_dst += SrcLimits::max();
1172 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1173 clamped_dst = DstLimits::max();
1174 clamped_dst += SrcLimits::max();
1175 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
1176 clamped_dst = DstLimits::max();
1177 clamped_dst -= SrcLimits::max();
1178 TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst);
1179 clamped_dst = 0;
jschuhb180f392017-07-03 15:09:221180
[email protected]5bfecbc52014-02-27 13:49:041181 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
1182 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
1183 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
jschuhe3bd1f62016-12-20 05:11:301184
1185 // Additional saturation tests.
jschuhb180f392017-07-03 15:09:221186 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
jschuhe3bd1f62016-12-20 05:11:301187 EXPECT_EQ(DstLimits::lowest(), saturated_cast<Dst>(SrcLimits::lowest()));
1188
Peter Kasting134183e2024-11-13 01:22:391189 if constexpr (SrcLimits::is_iec559) {
jschuhe3bd1f62016-12-20 05:11:301190 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::quiet_NaN()));
1191
[email protected]5bfecbc52014-02-27 13:49:041192 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
1193 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
1194 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
1195 TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
Peter Kasting134183e2024-11-13 01:22:391196 if constexpr (DstLimits::is_integer) {
1197 if constexpr (SrcLimits::digits < DstLimits::digits) {
jschuhfafe0712015-09-14 20:21:241198 TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
1199 static_cast<Src>(DstLimits::max()));
1200 } else {
1201 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
1202 }
1203 TEST_EXPECTED_RANGE(
1204 RANGE_VALID,
1205 static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
jschuh5030b00c2016-12-05 18:21:481206 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
jschuhfafe0712015-09-14 20:21:241207 }
[email protected]4efb2c32014-01-16 06:57:251208 } else {
jschuh5030b00c2016-12-05 18:21:481209 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
[email protected]4efb2c32014-01-16 06:57:251210 }
1211 }
1212};
1213
1214template <typename Dst, typename Src>
1215struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
Justin Schuh5cc331de2017-07-25 18:05:221216 static void Test(const char* dst, const char* src, int line) {
jschuhb180f392017-07-03 15:09:221217 using SrcLimits = SaturationDefaultLimits<Src>;
1218 using DstLimits = SaturationDefaultLimits<Dst>;
Peter Kastingabcf60a2024-11-13 01:24:371219 static_assert(kMaxExponent<Dst> <= kMaxExponent<Src>,
jschuhd2d9fe02014-10-14 14:31:371220 "Destination must be narrower or equal to source.");
1221 static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
1222 static_assert(DstLimits::is_signed, "Destination must be signed.");
[email protected]4efb2c32014-01-16 06:57:251223
Justin Schuh5cc2abf2017-08-01 04:58:071224 TestStrictComparison<Dst, Src>(dst, src, line);
jschuh23a4b062016-12-02 02:55:081225
[email protected]5bfecbc52014-02-27 13:49:041226 const CheckedNumeric<Dst> checked_dst;
1227 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:031228 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
jschuh5030b00c2016-12-05 18:21:481229 TEST_EXPECTED_VALUE(SrcLimits::lowest(), checked_dst + SrcLimits::lowest());
[email protected]5bfecbc52014-02-27 13:49:041230
jschuhb180f392017-07-03 15:09:221231 const ClampedNumeric<Dst> clamped_dst;
1232 TEST_EXPECTED_VALUE(1, clamped_dst + static_cast<Src>(1));
1233 TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
1234 TEST_EXPECTED_VALUE(SrcLimits::lowest(), clamped_dst + SrcLimits::lowest());
1235
jschuh5030b00c2016-12-05 18:21:481236 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
[email protected]5bfecbc52014-02-27 13:49:041237 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
1238 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuhe3bd1f62016-12-20 05:11:301239
1240 // Additional saturation tests.
1241 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
1242 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::lowest()));
[email protected]4efb2c32014-01-16 06:57:251243 }
1244};
1245
1246// Helper macro to wrap displaying the conversion types and line numbers
1247#define TEST_NUMERIC_CONVERSION(d, s, t) \
1248 TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
1249
[email protected]5bfecbc52014-02-27 13:49:041250TEST(SafeNumerics, IntMinOperations) {
[email protected]4efb2c32014-01-16 06:57:251251 TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1252 TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1253
Justin Schuha26da272017-07-13 23:04:301254 TEST_NUMERIC_CONVERSION(int8_t, int16_t, SIGN_PRESERVING_NARROW);
[email protected]4efb2c32014-01-16 06:57:251255 TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
Justin Schuha26da272017-07-13 23:04:301256 TEST_NUMERIC_CONVERSION(uint8_t, uint16_t, SIGN_PRESERVING_NARROW);
[email protected]4efb2c32014-01-16 06:57:251257 TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
1258 TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
1259
1260 TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1261
Justin Schuha26da272017-07-13 23:04:301262 TEST_NUMERIC_CONVERSION(uint8_t, int16_t, SIGN_TO_UNSIGN_NARROW);
[email protected]4efb2c32014-01-16 06:57:251263 TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
1264 TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
1265 TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
1266
Justin Schuha26da272017-07-13 23:04:301267 TEST_NUMERIC_CONVERSION(int8_t, uint16_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
[email protected]4efb2c32014-01-16 06:57:251268 TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1269 TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
[email protected]c1c090d32013-01-16 23:34:041270}
1271
Justin Schuha26da272017-07-13 23:04:301272TEST(SafeNumerics, Int16Operations) {
1273 TEST_NUMERIC_CONVERSION(int16_t, int16_t, SIGN_PRESERVING_VALUE_PRESERVING);
1274 TEST_NUMERIC_CONVERSION(uint16_t, uint16_t, SIGN_PRESERVING_VALUE_PRESERVING);
1275
1276 TEST_NUMERIC_CONVERSION(int16_t, int, SIGN_PRESERVING_NARROW);
1277 TEST_NUMERIC_CONVERSION(uint16_t, unsigned int, SIGN_PRESERVING_NARROW);
1278 TEST_NUMERIC_CONVERSION(int16_t, float, SIGN_PRESERVING_NARROW);
1279
1280 TEST_NUMERIC_CONVERSION(uint16_t, int16_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1281
1282 TEST_NUMERIC_CONVERSION(uint16_t, int, SIGN_TO_UNSIGN_NARROW);
1283 TEST_NUMERIC_CONVERSION(uint16_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
1284 TEST_NUMERIC_CONVERSION(uint16_t, float, SIGN_TO_UNSIGN_NARROW);
1285
1286 TEST_NUMERIC_CONVERSION(int16_t, unsigned int,
1287 UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1288 TEST_NUMERIC_CONVERSION(int16_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1289}
1290
[email protected]5bfecbc52014-02-27 13:49:041291TEST(SafeNumerics, IntOperations) {
[email protected]4efb2c32014-01-16 06:57:251292 TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
1293 TEST_NUMERIC_CONVERSION(unsigned int, unsigned int,
1294 SIGN_PRESERVING_VALUE_PRESERVING);
1295 TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1296 TEST_NUMERIC_CONVERSION(unsigned int, uint8_t,
1297 SIGN_PRESERVING_VALUE_PRESERVING);
1298 TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1299
1300 TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
1301 TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
1302 TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
1303 TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
1304
1305 TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1306 TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1307
1308 TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
1309 TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
1310 TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
1311
1312 TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1313 TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
[email protected]c1c090d32013-01-16 23:34:041314}
1315
[email protected]5bfecbc52014-02-27 13:49:041316TEST(SafeNumerics, IntMaxOperations) {
[email protected]4efb2c32014-01-16 06:57:251317 TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
1318 TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t,
1319 SIGN_PRESERVING_VALUE_PRESERVING);
1320 TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
1321 TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int,
1322 SIGN_PRESERVING_VALUE_PRESERVING);
1323 TEST_NUMERIC_CONVERSION(intmax_t, unsigned int,
1324 SIGN_PRESERVING_VALUE_PRESERVING);
1325 TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
1326
1327 TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
1328 TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
1329
1330 TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1331 TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1332
1333 TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
1334 TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
1335
1336 TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1337}
1338
[email protected]5bfecbc52014-02-27 13:49:041339TEST(SafeNumerics, FloatOperations) {
[email protected]4efb2c32014-01-16 06:57:251340 TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
Justin Schuh5cc331de2017-07-25 18:05:221341 TEST_NUMERIC_CONVERSION(float, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
[email protected]4efb2c32014-01-16 06:57:251342 TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
1343 TEST_NUMERIC_CONVERSION(float, unsigned int,
1344 SIGN_PRESERVING_VALUE_PRESERVING);
1345
1346 TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
1347}
1348
[email protected]5bfecbc52014-02-27 13:49:041349TEST(SafeNumerics, DoubleOperations) {
[email protected]4efb2c32014-01-16 06:57:251350 TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
Justin Schuh5cc331de2017-07-25 18:05:221351 TEST_NUMERIC_CONVERSION(double, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
[email protected]4efb2c32014-01-16 06:57:251352 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
1353 TEST_NUMERIC_CONVERSION(double, unsigned int,
1354 SIGN_PRESERVING_VALUE_PRESERVING);
1355}
1356
[email protected]5bfecbc52014-02-27 13:49:041357TEST(SafeNumerics, SizeTOperations) {
[email protected]4efb2c32014-01-16 06:57:251358 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
1359 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
1360}
1361
jschuh23a4b062016-12-02 02:55:081362// A one-off test to ensure StrictNumeric won't resolve to an incorrect type.
1363// If this fails we'll just get a compiler error on an ambiguous overload.
1364int TestOverload(int) { // Overload fails.
1365 return 0;
1366}
1367uint8_t TestOverload(uint8_t) { // Overload fails.
1368 return 0;
1369}
1370size_t TestOverload(size_t) { // Overload succeeds.
1371 return 0;
1372}
1373
Peter Kasting134183e2024-11-13 01:22:391374static_assert(std::same_as<decltype(TestOverload(StrictNumeric<int>())), int>);
Andrew Rayskiy6f021362023-10-19 19:55:061375static_assert(
Peter Kasting134183e2024-11-13 01:22:391376 std::same_as<decltype(TestOverload(StrictNumeric<size_t>())), size_t>);
jschuh23a4b062016-12-02 02:55:081377
jschuh71b669a2016-12-17 01:13:311378template <typename T>
1379struct CastTest1 {
jschuhc8f03cd2017-01-05 03:40:511380 static constexpr T NaN() { return -1; }
jschuh71b669a2016-12-17 01:13:311381 static constexpr T max() { return numeric_limits<T>::max() - 1; }
jschuhc8f03cd2017-01-05 03:40:511382 static constexpr T Overflow() { return max(); }
jschuh71b669a2016-12-17 01:13:311383 static constexpr T lowest() { return numeric_limits<T>::lowest() + 1; }
jschuhc8f03cd2017-01-05 03:40:511384 static constexpr T Underflow() { return lowest(); }
jschuh71b669a2016-12-17 01:13:311385};
1386
1387template <typename T>
1388struct CastTest2 {
jschuhc8f03cd2017-01-05 03:40:511389 static constexpr T NaN() { return 11; }
jschuh71b669a2016-12-17 01:13:311390 static constexpr T max() { return 10; }
jschuhc8f03cd2017-01-05 03:40:511391 static constexpr T Overflow() { return max(); }
jschuh71b669a2016-12-17 01:13:311392 static constexpr T lowest() { return 1; }
jschuhc8f03cd2017-01-05 03:40:511393 static constexpr T Underflow() { return lowest(); }
jschuh71b669a2016-12-17 01:13:311394};
1395
Peter Kastingb2dc55042025-01-16 16:30:541396TEST(CheckedNumeric, AddendOutOfRange) {
1397 // When adding a value that doesn't fit in the CheckedNumeric, the result
1398 // should not depend on the addend's type, but should work as if the math was
1399 // done without checking/clamping and then checked_cast back to the right
1400 // value.
1401 CheckedNumeric<int64_t> n1(std::numeric_limits<int64_t>::lowest() + 2);
1402 n1 += std::numeric_limits<uint64_t>::max() - 5;
1403 EXPECT_EQ(std::numeric_limits<int64_t>::max() - 3, n1.ValueOrDefault(0));
1404
1405 // The same procedure shouldn't work if the result wouldn't have fit, though.
1406 CheckedNumeric<int64_t> n2(-2);
1407 n2 += (static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) + 5);
1408 EXPECT_FALSE(n2.IsValid());
1409}
1410
agrieve7772a0502016-12-16 18:18:481411TEST(SafeNumerics, CastTests) {
[email protected]4efb2c32014-01-16 06:57:251412// MSVC catches and warns that we're forcing saturation in these tests.
1413// Since that's intentional, we need to shut this warning off.
1414#if defined(COMPILER_MSVC)
1415#pragma warning(disable : 4756)
[email protected]c1c090d32013-01-16 23:34:041416#endif
1417
[email protected]c1c090d32013-01-16 23:34:041418 int small_positive = 1;
1419 int small_negative = -1;
[email protected]4efb2c32014-01-16 06:57:251420 double double_small = 1.0;
[email protected]5bfecbc52014-02-27 13:49:041421 double double_large = numeric_limits<double>::max();
1422 double double_infinity = numeric_limits<float>::infinity();
danakj3193742f2015-06-05 18:15:101423 double double_large_int = numeric_limits<int>::max();
jschuh5030b00c2016-12-05 18:21:481424 double double_small_int = numeric_limits<int>::lowest();
[email protected]c1c090d32013-01-16 23:34:041425
jschuh4bf22c6d2015-05-28 02:29:251426 // Just test that the casts compile, since the other tests cover logic.
[email protected]5bfecbc52014-02-27 13:49:041427 EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
jschuh4bf22c6d2015-05-28 02:29:251428 EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
1429 EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
1430 EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
Peter Kasting6d970742024-12-06 05:06:271431 EXPECT_EQ(0U,
1432 strict_cast<unsigned>(std::integral_constant<unsigned char, 0>()));
jschuh4bf22c6d2015-05-28 02:29:251433 EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
1434 EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
1435 EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
1436
1437 EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
1438 EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
1439 EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
1440
jschuh07345e62015-09-22 22:13:361441 EXPECT_TRUE(IsValueNegative(-1));
jschuh5030b00c2016-12-05 18:21:481442 EXPECT_TRUE(IsValueNegative(numeric_limits<int>::lowest()));
1443 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::lowest()));
1444 EXPECT_TRUE(IsValueNegative(numeric_limits<double>::lowest()));
jschuh07345e62015-09-22 22:13:361445 EXPECT_FALSE(IsValueNegative(0));
1446 EXPECT_FALSE(IsValueNegative(1));
1447 EXPECT_FALSE(IsValueNegative(0u));
1448 EXPECT_FALSE(IsValueNegative(1u));
1449 EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
1450 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
1451 EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
1452
[email protected]4efb2c32014-01-16 06:57:251453 // Test various saturation corner cases.
1454 EXPECT_EQ(saturated_cast<int>(small_negative),
1455 static_cast<int>(small_negative));
1456 EXPECT_EQ(saturated_cast<int>(small_positive),
1457 static_cast<int>(small_positive));
Justin Schuh5cc331de2017-07-25 18:05:221458 EXPECT_EQ(saturated_cast<unsigned>(small_negative), static_cast<unsigned>(0));
1459 EXPECT_EQ(saturated_cast<int>(double_small), static_cast<int>(double_small));
[email protected]5bfecbc52014-02-27 13:49:041460 EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
[email protected]4efb2c32014-01-16 06:57:251461 EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
1462 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
jschuh5030b00c2016-12-05 18:21:481463 EXPECT_EQ(numeric_limits<int>::lowest(),
1464 saturated_cast<int>(double_small_int));
danakj3193742f2015-06-05 18:15:101465 EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
vmpstredf1e182015-12-14 20:09:421466
jschuh71b669a2016-12-17 01:13:311467 // Test the saturated cast overrides.
1468 using FloatLimits = numeric_limits<float>;
1469 using IntLimits = numeric_limits<int>;
1470 EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(FloatLimits::quiet_NaN())));
1471 EXPECT_EQ(CastTest1<int>::max(),
1472 (saturated_cast<int, CastTest1>(FloatLimits::infinity())));
1473 EXPECT_EQ(CastTest1<int>::max(),
1474 (saturated_cast<int, CastTest1>(FloatLimits::max())));
1475 EXPECT_EQ(CastTest1<int>::max(),
1476 (saturated_cast<int, CastTest1>(float(IntLimits::max()))));
1477 EXPECT_EQ(CastTest1<int>::lowest(),
1478 (saturated_cast<int, CastTest1>(-FloatLimits::infinity())));
1479 EXPECT_EQ(CastTest1<int>::lowest(),
1480 (saturated_cast<int, CastTest1>(FloatLimits::lowest())));
1481 EXPECT_EQ(0, (saturated_cast<int, CastTest1>(0.0)));
1482 EXPECT_EQ(1, (saturated_cast<int, CastTest1>(1.0)));
1483 EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(-1.0)));
1484 EXPECT_EQ(0, (saturated_cast<int, CastTest1>(0)));
1485 EXPECT_EQ(1, (saturated_cast<int, CastTest1>(1)));
1486 EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(-1)));
1487 EXPECT_EQ(CastTest1<int>::lowest(),
1488 (saturated_cast<int, CastTest1>(float(IntLimits::lowest()))));
1489 EXPECT_EQ(11, (saturated_cast<int, CastTest2>(FloatLimits::quiet_NaN())));
1490 EXPECT_EQ(10, (saturated_cast<int, CastTest2>(FloatLimits::infinity())));
1491 EXPECT_EQ(10, (saturated_cast<int, CastTest2>(FloatLimits::max())));
1492 EXPECT_EQ(1, (saturated_cast<int, CastTest2>(-FloatLimits::infinity())));
1493 EXPECT_EQ(1, (saturated_cast<int, CastTest2>(FloatLimits::lowest())));
1494 EXPECT_EQ(1, (saturated_cast<int, CastTest2>(0U)));
1495
vmpstredf1e182015-12-14 20:09:421496 float not_a_number = std::numeric_limits<float>::infinity() -
1497 std::numeric_limits<float>::infinity();
1498 EXPECT_TRUE(std::isnan(not_a_number));
1499 EXPECT_EQ(0, saturated_cast<int>(not_a_number));
jschuh224f1d72016-11-25 20:08:481500
1501 // Test the CheckedNumeric value extractions functions.
jschuh5030b00c2016-12-05 18:21:481502 auto int8_min = MakeCheckedNum(numeric_limits<int8_t>::lowest());
jschuh4bc919cb52016-12-04 15:08:271503 auto int8_max = MakeCheckedNum(numeric_limits<int8_t>::max());
1504 auto double_max = MakeCheckedNum(numeric_limits<double>::max());
jschuh224f1d72016-11-25 20:08:481505 static_assert(
Peter Kasting134183e2024-11-13 01:22:391506 std::same_as<int16_t, decltype(int8_min.ValueOrDie<int16_t>())::type>,
jschuh224f1d72016-11-25 20:08:481507 "ValueOrDie returning incorrect type.");
1508 static_assert(
Peter Kasting134183e2024-11-13 01:22:391509 std::same_as<int16_t,
1510 decltype(int8_min.ValueOrDefault<int16_t>(0))::type>,
jschuh224f1d72016-11-25 20:08:481511 "ValueOrDefault returning incorrect type.");
jschuh23a4b062016-12-02 02:55:081512 EXPECT_FALSE(IsValidForType<uint8_t>(int8_min));
1513 EXPECT_TRUE(IsValidForType<uint8_t>(int8_max));
jschuh5030b00c2016-12-05 18:21:481514 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::lowest()),
jschuh23a4b062016-12-02 02:55:081515 ValueOrDieForType<int>(int8_min));
1516 EXPECT_TRUE(IsValidForType<uint32_t>(int8_max));
jschuh224f1d72016-11-25 20:08:481517 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()),
jschuh23a4b062016-12-02 02:55:081518 ValueOrDieForType<int>(int8_max));
1519 EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0));
jschuhe17e0f12016-11-26 03:00:081520 uint8_t uint8_dest = 0;
1521 int16_t int16_dest = 0;
1522 double double_dest = 0;
1523 EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest));
1524 EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest);
1525 EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest));
1526 EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest));
1527 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest);
1528 EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest));
jschuh5030b00c2016-12-05 18:21:481529 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::lowest()), int16_dest);
jschuhe17e0f12016-11-26 03:00:081530 EXPECT_FALSE(double_max.AssignIfValid(&uint8_dest));
1531 EXPECT_FALSE(double_max.AssignIfValid(&int16_dest));
1532 EXPECT_TRUE(double_max.AssignIfValid(&double_dest));
1533 EXPECT_EQ(numeric_limits<double>::max(), double_dest);
jschuh23a4b062016-12-02 02:55:081534 EXPECT_EQ(1, checked_cast<int>(StrictNumeric<int>(1)));
1535 EXPECT_EQ(1, saturated_cast<int>(StrictNumeric<int>(1)));
1536 EXPECT_EQ(1, strict_cast<int>(StrictNumeric<int>(1)));
Justin Schuh4d93ee32017-08-14 20:06:281537
1538 enum class EnumTest { kOne = 1 };
1539 EXPECT_EQ(1, checked_cast<int>(EnumTest::kOne));
1540 EXPECT_EQ(1, saturated_cast<int>(EnumTest::kOne));
1541 EXPECT_EQ(1, strict_cast<int>(EnumTest::kOne));
[email protected]c1c090d32013-01-16 23:34:041542}
1543
jschuhfafe0712015-09-14 20:21:241544TEST(SafeNumerics, IsValueInRangeForNumericType) {
1545 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
1546 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
1547 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
1548 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
1549 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
1550 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
1551 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
1552 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
1553 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
jschuh5030b00c2016-12-05 18:21:481554 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241555 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
jschuh5030b00c2016-12-05 18:21:481556 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241557
Ng Zhi An280ed262020-10-22 00:10:121558 // Converting to integer types will discard the fractional part first, so -0.9
1559 // will be truncated to -0.0.
1560 EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(-0.9));
1561 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1.0));
1562
jschuhfafe0712015-09-14 20:21:241563 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
1564 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
1565 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
1566 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
1567 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
1568 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
1569 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
1570 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
1571 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
1572 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
1573 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
1574 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b00c2016-12-05 18:21:481575 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241576 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b00c2016-12-05 18:21:481577 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
jschuhfafe0712015-09-14 20:21:241578 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b00c2016-12-05 18:21:481579 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest()) - 1));
jschuhfafe0712015-09-14 20:21:241580 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b00c2016-12-05 18:21:481581 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241582
1583 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
1584 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
1585 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
1586 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
1587 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
1588 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
1589 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
1590 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
1591 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
jschuh5030b00c2016-12-05 18:21:481592 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241593 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
1594 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
jschuh5030b00c2016-12-05 18:21:481595 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241596
Ng Zhi An280ed262020-10-22 00:10:121597 // Converting to integer types will discard the fractional part first, so -0.9
1598 // will be truncated to -0.0.
1599 EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(-0.9));
1600 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1.0));
1601
jschuhfafe0712015-09-14 20:21:241602 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
1603 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
1604 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
1605 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
1606 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
1607 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
1608 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
1609 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
1610 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
1611 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
1612 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
1613 EXPECT_TRUE(
1614 IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
1615 EXPECT_TRUE(
1616 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
1617 EXPECT_FALSE(
1618 IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
1619 EXPECT_FALSE(
1620 IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
1621 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b00c2016-12-05 18:21:481622 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241623 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b00c2016-12-05 18:21:481624 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
jschuhfafe0712015-09-14 20:21:241625 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b00c2016-12-05 18:21:481626 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241627}
vmpstr19477492015-09-29 22:34:491628
1629TEST(SafeNumerics, CompoundNumericOperations) {
1630 CheckedNumeric<int> a = 1;
1631 CheckedNumeric<int> b = 2;
1632 CheckedNumeric<int> c = 3;
1633 CheckedNumeric<int> d = 4;
1634 a += b;
1635 EXPECT_EQ(3, a.ValueOrDie());
1636 a -= c;
1637 EXPECT_EQ(0, a.ValueOrDie());
1638 d /= b;
1639 EXPECT_EQ(2, d.ValueOrDie());
1640 d *= d;
1641 EXPECT_EQ(4, d.ValueOrDie());
Peter Kasting0559fb62020-08-12 00:02:051642 d *= 0.5;
1643 EXPECT_EQ(2, d.ValueOrDie());
vmpstr19477492015-09-29 22:34:491644
1645 CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
1646 EXPECT_TRUE(too_large.IsValid());
1647 too_large += d;
1648 EXPECT_FALSE(too_large.IsValid());
1649 too_large -= d;
1650 EXPECT_FALSE(too_large.IsValid());
1651 too_large /= d;
1652 EXPECT_FALSE(too_large.IsValid());
1653}
jschuh4fcd6fa2016-11-24 11:58:391654
Daniel Cheng465fc122025-11-15 02:16:451655static bool* did_call_predicate = nullptr;
1656
1657class ScopedPredicateCallObserver {
1658 public:
1659 ScopedPredicateCallObserver() { did_call_predicate = &did_call_; }
1660 ~ScopedPredicateCallObserver() { did_call_predicate = nullptr; }
1661
1662 bool did_call() const { return did_call_; }
1663
1664 private:
1665 bool did_call_ = false;
1666};
1667
1668static bool IntGreaterThanZero(int value) {
1669 *did_call_predicate = true;
1670 return value > 0;
1671}
1672
1673static bool IntLessThanZero(int value) {
1674 *did_call_predicate = true;
1675 return value < 0;
1676}
1677
1678static bool Int64GreaterThanZero(int64_t value) {
1679 *did_call_predicate = true;
1680 return value > 0;
1681}
1682
1683static bool Int64LessThanZero(int64_t value) {
1684 *did_call_predicate = true;
1685 return value < 0;
1686}
1687
1688static bool Int16GreaterThanZero(int16_t value) {
1689 *did_call_predicate = true;
1690 return value > 0;
1691}
1692
1693static bool Int16LessThanZero(int16_t value) {
1694 *did_call_predicate = true;
1695 return value < 0;
1696}
1697
1698TEST(SafeNumerics, IsValidAnd) {
1699 {
1700 const CheckedNumeric<int> invalid =
1701 CheckAdd(std::numeric_limits<int>::max(), 1);
1702
1703 {
1704 ScopedPredicateCallObserver observer;
1705 EXPECT_FALSE(invalid.IsValidAnd(IntGreaterThanZero));
1706 EXPECT_FALSE(observer.did_call());
1707 }
1708 {
1709 ScopedPredicateCallObserver observer;
1710 EXPECT_FALSE(invalid.IsValidAnd(IntLessThanZero));
1711 EXPECT_FALSE(observer.did_call());
1712 }
1713 {
1714 ScopedPredicateCallObserver observer;
1715 EXPECT_FALSE(invalid.IsValidAnd(Int64GreaterThanZero));
1716 EXPECT_FALSE(observer.did_call());
1717 }
1718 {
1719 ScopedPredicateCallObserver observer;
1720 EXPECT_FALSE(invalid.IsValidAnd(Int64LessThanZero));
1721 EXPECT_FALSE(observer.did_call());
1722 }
1723 {
1724 ScopedPredicateCallObserver observer;
1725 EXPECT_FALSE(invalid.IsValidAnd(Int16GreaterThanZero));
1726 EXPECT_FALSE(observer.did_call());
1727 }
1728 {
1729 ScopedPredicateCallObserver observer;
1730 EXPECT_FALSE(invalid.IsValidAnd(Int16LessThanZero));
1731 EXPECT_FALSE(observer.did_call());
1732 }
1733
1734 {
1735 bool did_call = false;
1736 EXPECT_FALSE(invalid.IsValidAnd([&](int x) {
1737 did_call = true;
1738 return x > 0;
1739 }));
1740 EXPECT_FALSE(did_call);
1741 }
1742 {
1743 bool did_call = false;
1744 EXPECT_FALSE(invalid.IsValidAnd([&](int x) {
1745 did_call = true;
1746 return x < 0;
1747 }));
1748 EXPECT_FALSE(did_call);
1749 }
1750 {
1751 bool did_call = false;
1752 EXPECT_FALSE(invalid.IsValidAnd([&](int64_t x) {
1753 did_call = true;
1754 return x > 0;
1755 }));
1756 EXPECT_FALSE(did_call);
1757 }
1758 {
1759 bool did_call = false;
1760 EXPECT_FALSE(invalid.IsValidAnd([&](int64_t x) {
1761 did_call = true;
1762 return x < 0;
1763 }));
1764 EXPECT_FALSE(did_call);
1765 }
1766 {
1767 bool did_call = false;
1768 EXPECT_FALSE(invalid.IsValidAnd([&](int16_t x) {
1769 did_call = true;
1770 return x > 0;
1771 }));
1772 EXPECT_FALSE(did_call);
1773 }
1774 {
1775 bool did_call = false;
1776 EXPECT_FALSE(invalid.IsValidAnd([&](int16_t x) {
1777 did_call = true;
1778 return x < 0;
1779 }));
1780 EXPECT_FALSE(did_call);
1781 }
1782 }
1783
1784 {
1785 const CheckedNumeric<int> value = std::numeric_limits<int>::max();
1786
1787 {
1788 ScopedPredicateCallObserver observer;
1789 EXPECT_TRUE(value.IsValidAnd(IntGreaterThanZero));
1790 EXPECT_TRUE(observer.did_call());
1791 }
1792 {
1793 ScopedPredicateCallObserver observer;
1794 EXPECT_FALSE(value.IsValidAnd(IntLessThanZero));
1795 EXPECT_TRUE(observer.did_call());
1796 }
1797
1798 {
1799 ScopedPredicateCallObserver observer;
1800 EXPECT_TRUE(value.IsValidAnd(Int64GreaterThanZero));
1801 EXPECT_TRUE(observer.did_call());
1802 }
1803 {
1804 ScopedPredicateCallObserver observer;
1805 EXPECT_FALSE(value.IsValidAnd(Int64LessThanZero));
1806 EXPECT_TRUE(observer.did_call());
1807 }
1808
1809 // Always invalid since `std::numeric_limits<int>::max()` does not fit in
1810 // an `int16_t`.
1811 {
1812 ScopedPredicateCallObserver observer;
1813 EXPECT_FALSE(value.IsValidAnd(Int16GreaterThanZero));
1814 EXPECT_FALSE(observer.did_call());
1815 }
1816 {
1817 ScopedPredicateCallObserver observer;
1818 EXPECT_FALSE(value.IsValidAnd(Int16LessThanZero));
1819 EXPECT_FALSE(observer.did_call());
1820 }
1821
1822 {
1823 bool did_call = false;
1824 EXPECT_TRUE(value.IsValidAnd([&](int x) {
1825 did_call = true;
1826 return x > 0;
1827 }));
1828 EXPECT_TRUE(did_call);
1829 }
1830 {
1831 bool did_call = false;
1832 EXPECT_FALSE(value.IsValidAnd([&](int x) {
1833 did_call = true;
1834 return x < 0;
1835 }));
1836 EXPECT_TRUE(did_call);
1837 }
1838
1839 {
1840 bool did_call = false;
1841 EXPECT_TRUE(value.IsValidAnd([&](int64_t x) {
1842 did_call = true;
1843 return x > 0;
1844 }));
1845 EXPECT_TRUE(did_call);
1846 }
1847 {
1848 bool did_call = false;
1849 EXPECT_FALSE(value.IsValidAnd([&](int64_t x) {
1850 did_call = true;
1851 return x < 0;
1852 }));
1853 EXPECT_TRUE(did_call);
1854 }
1855
1856 // Always invalid since `std::numeric_limits<int>::max()` does not fit in
1857 // an `int16_t`.
1858 {
1859 bool did_call = false;
1860 EXPECT_FALSE(value.IsValidAnd([&](int16_t x) {
1861 did_call = true;
1862 return x > 0;
1863 }));
1864 EXPECT_FALSE(did_call);
1865 }
1866 {
1867 bool did_call = false;
1868 EXPECT_FALSE(value.IsValidAnd([&](int16_t x) {
1869 did_call = true;
1870 return x < 0;
1871 }));
1872 EXPECT_FALSE(did_call);
1873 }
1874 }
1875}
1876
1877TEST(SafeNumerics, IsInvalidOr) {
1878 {
1879 const CheckedNumeric<int> invalid =
1880 CheckAdd(std::numeric_limits<int>::max(), 1);
1881
1882 {
1883 ScopedPredicateCallObserver observer;
1884 EXPECT_TRUE(invalid.IsInvalidOr(IntGreaterThanZero));
1885 EXPECT_FALSE(observer.did_call());
1886 }
1887 {
1888 ScopedPredicateCallObserver observer;
1889 EXPECT_TRUE(invalid.IsInvalidOr(IntLessThanZero));
1890 EXPECT_FALSE(observer.did_call());
1891 }
1892 {
1893 ScopedPredicateCallObserver observer;
1894 EXPECT_TRUE(invalid.IsInvalidOr(Int64GreaterThanZero));
1895 EXPECT_FALSE(observer.did_call());
1896 }
1897 {
1898 ScopedPredicateCallObserver observer;
1899 EXPECT_TRUE(invalid.IsInvalidOr(Int64LessThanZero));
1900 EXPECT_FALSE(observer.did_call());
1901 }
1902 {
1903 ScopedPredicateCallObserver observer;
1904 EXPECT_TRUE(invalid.IsInvalidOr(Int16GreaterThanZero));
1905 EXPECT_FALSE(observer.did_call());
1906 }
1907 {
1908 ScopedPredicateCallObserver observer;
1909 EXPECT_TRUE(invalid.IsInvalidOr(Int16LessThanZero));
1910 EXPECT_FALSE(observer.did_call());
1911 }
1912
1913 {
1914 bool did_call = false;
1915 EXPECT_TRUE(invalid.IsInvalidOr([&](int x) {
1916 did_call = true;
1917 return x > 0;
1918 }));
1919 EXPECT_FALSE(did_call);
1920 }
1921 {
1922 bool did_call = false;
1923 EXPECT_TRUE(invalid.IsInvalidOr([&](int x) {
1924 did_call = true;
1925 return x < 0;
1926 }));
1927 EXPECT_FALSE(did_call);
1928 }
1929 {
1930 bool did_call = false;
1931 EXPECT_TRUE(invalid.IsInvalidOr([&](int64_t x) {
1932 did_call = true;
1933 return x > 0;
1934 }));
1935 EXPECT_FALSE(did_call);
1936 }
1937 {
1938 bool did_call = false;
1939 EXPECT_TRUE(invalid.IsInvalidOr([&](int64_t x) {
1940 did_call = true;
1941 return x < 0;
1942 }));
1943 EXPECT_FALSE(did_call);
1944 }
1945 {
1946 bool did_call = false;
1947 EXPECT_TRUE(invalid.IsInvalidOr([&](int16_t x) {
1948 did_call = true;
1949 return x > 0;
1950 }));
1951 EXPECT_FALSE(did_call);
1952 }
1953 {
1954 bool did_call = false;
1955 EXPECT_TRUE(invalid.IsInvalidOr([&](int16_t x) {
1956 did_call = true;
1957 return x < 0;
1958 }));
1959 EXPECT_FALSE(did_call);
1960 }
1961 }
1962
1963 {
1964 const CheckedNumeric<int> value = std::numeric_limits<int>::max();
1965
1966 {
1967 ScopedPredicateCallObserver observer;
1968 EXPECT_TRUE(value.IsInvalidOr(IntGreaterThanZero));
1969 EXPECT_TRUE(observer.did_call());
1970 }
1971 {
1972 ScopedPredicateCallObserver observer;
1973 EXPECT_FALSE(value.IsInvalidOr(IntLessThanZero));
1974 EXPECT_TRUE(observer.did_call());
1975 }
1976
1977 {
1978 ScopedPredicateCallObserver observer;
1979 EXPECT_TRUE(value.IsInvalidOr(Int64GreaterThanZero));
1980 EXPECT_TRUE(observer.did_call());
1981 }
1982 {
1983 ScopedPredicateCallObserver observer;
1984 EXPECT_FALSE(value.IsInvalidOr(Int64LessThanZero));
1985 EXPECT_TRUE(observer.did_call());
1986 }
1987
1988 // Always invalid since `std::numeric_limits<int>::max()` does not fit in
1989 // an `int16_t`.
1990 {
1991 ScopedPredicateCallObserver observer;
1992 EXPECT_TRUE(value.IsInvalidOr(Int16GreaterThanZero));
1993 EXPECT_FALSE(observer.did_call());
1994 }
1995 {
1996 ScopedPredicateCallObserver observer;
1997 EXPECT_TRUE(value.IsInvalidOr(Int16LessThanZero));
1998 EXPECT_FALSE(observer.did_call());
1999 }
2000
2001 {
2002 bool did_call = false;
2003 EXPECT_TRUE(value.IsInvalidOr([&](int x) {
2004 did_call = true;
2005 return x > 0;
2006 }));
2007 EXPECT_TRUE(did_call);
2008 }
2009 {
2010 bool did_call = false;
2011 EXPECT_FALSE(value.IsInvalidOr([&](int x) {
2012 did_call = true;
2013 return x < 0;
2014 }));
2015 EXPECT_TRUE(did_call);
2016 }
2017
2018 {
2019 bool did_call = false;
2020 EXPECT_TRUE(value.IsInvalidOr([&](int64_t x) {
2021 did_call = true;
2022 return x > 0;
2023 }));
2024 EXPECT_TRUE(did_call);
2025 }
2026 {
2027 bool did_call = false;
2028 EXPECT_FALSE(value.IsInvalidOr([&](int64_t x) {
2029 did_call = true;
2030 return x < 0;
2031 }));
2032 EXPECT_TRUE(did_call);
2033 }
2034
2035 // Always invalid since `std::numeric_limits<int>::max()` does not fit in
2036 // an `int16_t`.
2037 {
2038 bool did_call = false;
2039 EXPECT_TRUE(value.IsInvalidOr([&](int16_t x) {
2040 did_call = true;
2041 return x > 0;
2042 }));
2043 EXPECT_FALSE(did_call);
2044 }
2045 {
2046 bool did_call = false;
2047 EXPECT_TRUE(value.IsInvalidOr([&](int16_t x) {
2048 did_call = true;
2049 return x < 0;
2050 }));
2051 EXPECT_FALSE(did_call);
2052 }
2053 }
2054}
2055
Will Harris128da002023-02-07 23:47:492056TEST(SafeNumerics, TemplatedSafeMath) {
2057 // CheckMul and friends can be confusing, as they change behavior depending on
2058 // where the template is specified.
2059 uint64_t result;
2060 short short_one_thousand = 1000;
2061 // In this case, CheckMul uses template deduction to use the <short> variant,
2062 // and this will overflow even if assigned to a uint64_t.
2063 EXPECT_FALSE(CheckMul(short_one_thousand, short_one_thousand)
2064 .AssignIfValid<uint64_t>(&result));
2065 EXPECT_FALSE(CheckMul(short_one_thousand, short_one_thousand).IsValid());
2066 // In both cases, CheckMul is forced to use the uint64_t template and will not
2067 // overflow.
2068 EXPECT_TRUE(CheckMul<uint64_t>(short_one_thousand, short_one_thousand)
2069 .AssignIfValid(&result));
2070 EXPECT_TRUE(CheckMul<uint64_t>(short_one_thousand, short_one_thousand)
2071 .AssignIfValid<uint64_t>(&result));
2072
2073 uint64_t big_one_thousand = 1000u;
2074 // Order doesn't matter here: if one of the parameters is uint64_t then the
2075 // operation is done on a uint64_t.
2076 EXPECT_TRUE(
2077 CheckMul(big_one_thousand, short_one_thousand).AssignIfValid(&result));
2078 EXPECT_TRUE(
2079 CheckMul(short_one_thousand, big_one_thousand).AssignIfValid(&result));
2080
2081 // Checked math functions can also take two template type parameters. Here are
2082 // the results of all four combinations.
2083 EXPECT_TRUE((CheckMul<short, uint64_t>(1000, 1000).AssignIfValid(&result)));
2084
2085 // Note: Order here does not matter.
2086 EXPECT_TRUE((CheckMul<uint64_t, short>(1000, 1000).AssignIfValid(&result)));
2087
2088 // Only if both are short will the operation be invalid.
2089 EXPECT_FALSE((CheckMul<short, short>(1000, 1000).AssignIfValid(&result)));
2090
2091 // Same as above.
2092 EXPECT_TRUE(
2093 (CheckMul<uint64_t, uint64_t>(1000, 1000).AssignIfValid(&result)));
2094}
2095
jschuh4fcd6fa2016-11-24 11:58:392096TEST(SafeNumerics, VariadicNumericOperations) {
jschuhb180f392017-07-03 15:09:222097 { // Synthetic scope to avoid variable naming collisions.
2098 auto a = CheckAdd(1, 2UL, MakeCheckedNum(3LL), 4).ValueOrDie();
2099 EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
2100 auto b = CheckSub(MakeCheckedNum(20.0), 2UL, 4).ValueOrDie();
2101 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
2102 auto c = CheckMul(20.0, MakeCheckedNum(1), 5, 3UL).ValueOrDie();
2103 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
2104 auto d = CheckDiv(20.0, 2.0, MakeCheckedNum(5LL), -4).ValueOrDie();
2105 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
2106 auto e = CheckMod(MakeCheckedNum(20), 3).ValueOrDie();
2107 EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
2108 auto f = CheckLsh(1, MakeCheckedNum(2)).ValueOrDie();
2109 EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
2110 auto g = CheckRsh(4, MakeCheckedNum(2)).ValueOrDie();
2111 EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
2112 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
2113 EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
2114 }
2115
2116 {
2117 auto a = ClampAdd(1, 2UL, MakeClampedNum(3LL), 4);
2118 EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
2119 auto b = ClampSub(MakeClampedNum(20.0), 2UL, 4);
2120 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
2121 auto c = ClampMul(20.0, MakeClampedNum(1), 5, 3UL);
2122 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
2123 auto d = ClampDiv(20.0, 2.0, MakeClampedNum(5LL), -4);
2124 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
2125 auto e = ClampMod(MakeClampedNum(20), 3);
2126 EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
2127 auto f = ClampLsh(1, MakeClampedNum(2U));
2128 EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
2129 auto g = ClampRsh(4, MakeClampedNum(2U));
2130 EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
2131 auto h = ClampRsh(ClampAdd(1, 1, 1, 1), ClampSub(4U, 2));
2132 EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
2133 }
jschuh4fcd6fa2016-11-24 11:58:392134}
Justin Schuha26da272017-07-13 23:04:302135
Peter Kastingfc5d8f32020-06-30 02:38:172136TEST(SafeNumerics, CeilInt) {
Peter Kastingfbb9e562021-06-27 02:57:372137 constexpr float kMax = static_cast<float>(std::numeric_limits<int>::max());
Peter Kastingfc5d8f32020-06-30 02:38:172138 constexpr float kMin = std::numeric_limits<int>::min();
2139 constexpr float kInfinity = std::numeric_limits<float>::infinity();
2140 constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();
2141
2142 constexpr int kIntMax = std::numeric_limits<int>::max();
2143 constexpr int kIntMin = std::numeric_limits<int>::min();
2144
Peter Kasting24e973d2020-07-20 06:13:092145 EXPECT_EQ(kIntMax, ClampCeil(kInfinity));
2146 EXPECT_EQ(kIntMax, ClampCeil(kMax));
2147 EXPECT_EQ(kIntMax, ClampCeil(kMax + 100.0f));
2148 EXPECT_EQ(0, ClampCeil(kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:172149
Peter Kasting24e973d2020-07-20 06:13:092150 EXPECT_EQ(-100, ClampCeil(-100.5f));
2151 EXPECT_EQ(0, ClampCeil(0.0f));
2152 EXPECT_EQ(101, ClampCeil(100.5f));
Peter Kastingfc5d8f32020-06-30 02:38:172153
Peter Kasting24e973d2020-07-20 06:13:092154 EXPECT_EQ(kIntMin, ClampCeil(-kInfinity));
2155 EXPECT_EQ(kIntMin, ClampCeil(kMin));
2156 EXPECT_EQ(kIntMin, ClampCeil(kMin - 100.0f));
2157 EXPECT_EQ(0, ClampCeil(-kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:172158}
2159
2160TEST(SafeNumerics, FloorInt) {
Peter Kastingfbb9e562021-06-27 02:57:372161 constexpr float kMax = static_cast<float>(std::numeric_limits<int>::max());
Peter Kastingfc5d8f32020-06-30 02:38:172162 constexpr float kMin = std::numeric_limits<int>::min();
2163 constexpr float kInfinity = std::numeric_limits<float>::infinity();
2164 constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();
2165
2166 constexpr int kIntMax = std::numeric_limits<int>::max();
2167 constexpr int kIntMin = std::numeric_limits<int>::min();
2168
Peter Kasting24e973d2020-07-20 06:13:092169 EXPECT_EQ(kIntMax, ClampFloor(kInfinity));
2170 EXPECT_EQ(kIntMax, ClampFloor(kMax));
2171 EXPECT_EQ(kIntMax, ClampFloor(kMax + 100.0f));
2172 EXPECT_EQ(0, ClampFloor(kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:172173
Peter Kasting24e973d2020-07-20 06:13:092174 EXPECT_EQ(-101, ClampFloor(-100.5f));
2175 EXPECT_EQ(0, ClampFloor(0.0f));
2176 EXPECT_EQ(100, ClampFloor(100.5f));
Peter Kastingfc5d8f32020-06-30 02:38:172177
Peter Kasting24e973d2020-07-20 06:13:092178 EXPECT_EQ(kIntMin, ClampFloor(-kInfinity));
2179 EXPECT_EQ(kIntMin, ClampFloor(kMin));
2180 EXPECT_EQ(kIntMin, ClampFloor(kMin - 100.0f));
2181 EXPECT_EQ(0, ClampFloor(-kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:172182}
2183
2184TEST(SafeNumerics, RoundInt) {
Peter Kastingfbb9e562021-06-27 02:57:372185 constexpr float kMax = static_cast<float>(std::numeric_limits<int>::max());
Peter Kastingfc5d8f32020-06-30 02:38:172186 constexpr float kMin = std::numeric_limits<int>::min();
2187 constexpr float kInfinity = std::numeric_limits<float>::infinity();
2188 constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();
2189
2190 constexpr int kIntMax = std::numeric_limits<int>::max();
2191 constexpr int kIntMin = std::numeric_limits<int>::min();
2192
Peter Kasting24e973d2020-07-20 06:13:092193 EXPECT_EQ(kIntMax, ClampRound(kInfinity));
2194 EXPECT_EQ(kIntMax, ClampRound(kMax));
2195 EXPECT_EQ(kIntMax, ClampRound(kMax + 100.0f));
2196 EXPECT_EQ(0, ClampRound(kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:172197
Peter Kasting24e973d2020-07-20 06:13:092198 EXPECT_EQ(-100, ClampRound(-100.1f));
2199 EXPECT_EQ(-101, ClampRound(-100.5f));
2200 EXPECT_EQ(-101, ClampRound(-100.9f));
Steinar H. Gunderson32b29d32023-09-28 23:10:492201 EXPECT_EQ(0, ClampRound(std::nextafter(-0.5f, 0.0f)));
Peter Kasting24e973d2020-07-20 06:13:092202 EXPECT_EQ(0, ClampRound(0.0f));
Steinar H. Gunderson32b29d32023-09-28 23:10:492203 EXPECT_EQ(0, ClampRound(std::nextafter(0.5f, 0.0f)));
Peter Kasting24e973d2020-07-20 06:13:092204 EXPECT_EQ(100, ClampRound(100.1f));
2205 EXPECT_EQ(101, ClampRound(100.5f));
2206 EXPECT_EQ(101, ClampRound(100.9f));
Peter Kastingfc5d8f32020-06-30 02:38:172207
Peter Kasting24e973d2020-07-20 06:13:092208 EXPECT_EQ(kIntMin, ClampRound(-kInfinity));
2209 EXPECT_EQ(kIntMin, ClampRound(kMin));
2210 EXPECT_EQ(kIntMin, ClampRound(kMin - 100.0f));
2211 EXPECT_EQ(0, ClampRound(-kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:172212}
2213
2214TEST(SafeNumerics, Int64) {
Peter Kastingfbb9e562021-06-27 02:57:372215 constexpr double kMax =
2216 static_cast<double>(std::numeric_limits<int64_t>::max());
Peter Kastingfc5d8f32020-06-30 02:38:172217 constexpr double kMin = std::numeric_limits<int64_t>::min();
2218 constexpr double kInfinity = std::numeric_limits<double>::infinity();
2219 constexpr double kNaN = std::numeric_limits<double>::quiet_NaN();
2220
2221 constexpr int64_t kInt64Max = std::numeric_limits<int64_t>::max();
2222 constexpr int64_t kInt64Min = std::numeric_limits<int64_t>::min();
2223
Peter Kasting24e973d2020-07-20 06:13:092224 EXPECT_EQ(kInt64Max, ClampFloor<int64_t>(kInfinity));
2225 EXPECT_EQ(kInt64Max, ClampCeil<int64_t>(kInfinity));
2226 EXPECT_EQ(kInt64Max, ClampRound<int64_t>(kInfinity));
2227 EXPECT_EQ(kInt64Max, ClampFloor<int64_t>(kMax));
2228 EXPECT_EQ(kInt64Max, ClampCeil<int64_t>(kMax));
2229 EXPECT_EQ(kInt64Max, ClampRound<int64_t>(kMax));
2230 EXPECT_EQ(kInt64Max, ClampFloor<int64_t>(kMax + 100.0));
2231 EXPECT_EQ(kInt64Max, ClampCeil<int64_t>(kMax + 100.0));
2232 EXPECT_EQ(kInt64Max, ClampRound<int64_t>(kMax + 100.0));
2233 EXPECT_EQ(0, ClampFloor<int64_t>(kNaN));
2234 EXPECT_EQ(0, ClampCeil<int64_t>(kNaN));
2235 EXPECT_EQ(0, ClampRound<int64_t>(kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:172236
Peter Kasting24e973d2020-07-20 06:13:092237 EXPECT_EQ(kInt64Min, ClampFloor<int64_t>(-kInfinity));
2238 EXPECT_EQ(kInt64Min, ClampCeil<int64_t>(-kInfinity));
2239 EXPECT_EQ(kInt64Min, ClampRound<int64_t>(-kInfinity));
2240 EXPECT_EQ(kInt64Min, ClampFloor<int64_t>(kMin));
2241 EXPECT_EQ(kInt64Min, ClampCeil<int64_t>(kMin));
2242 EXPECT_EQ(kInt64Min, ClampRound<int64_t>(kMin));
2243 EXPECT_EQ(kInt64Min, ClampFloor<int64_t>(kMin - 100.0));
2244 EXPECT_EQ(kInt64Min, ClampCeil<int64_t>(kMin - 100.0));
2245 EXPECT_EQ(kInt64Min, ClampRound<int64_t>(kMin - 100.0));
2246 EXPECT_EQ(0, ClampFloor<int64_t>(-kNaN));
2247 EXPECT_EQ(0, ClampCeil<int64_t>(-kNaN));
2248 EXPECT_EQ(0, ClampRound<int64_t>(-kNaN));
Peter Kastingfc5d8f32020-06-30 02:38:172249}
2250
David Benjamin954152b2023-10-24 17:46:202251template <typename T>
Peter Kasting134183e2024-11-13 01:22:392252 requires std::signed_integral<T>
2253void TestWrappingMath() {
David Benjamin954152b2023-10-24 17:46:202254 constexpr T kMinusTwo = -2;
2255 constexpr T kMinusOne = -1;
2256 constexpr T kZero = 0;
2257 constexpr T kOne = 1;
2258 constexpr T kTwo = 2;
2259 constexpr T kThree = 3;
2260 constexpr T kMax = std::numeric_limits<T>::max();
2261 constexpr T kMin = std::numeric_limits<T>::min();
2262
2263 EXPECT_EQ(base::WrappingAdd(kOne, kTwo), kThree);
2264 static_assert(base::WrappingAdd(kOne, kTwo) == kThree);
2265 EXPECT_EQ(base::WrappingAdd(kMax, kOne), kMin);
2266 static_assert(base::WrappingAdd(kMax, kOne) == kMin);
2267 EXPECT_EQ(base::WrappingAdd(kMax, kTwo), kMin + 1);
2268 static_assert(base::WrappingAdd(kMax, kTwo) == kMin + 1);
2269 EXPECT_EQ(base::WrappingAdd(kMax, kMax), kMinusTwo);
2270 static_assert(base::WrappingAdd(kMax, kMax) == kMinusTwo);
2271 EXPECT_EQ(base::WrappingAdd(kMin, kMin), kZero);
2272 static_assert(base::WrappingAdd(kMin, kMin) == kZero);
2273
2274 EXPECT_EQ(base::WrappingSub(kTwo, kOne), kOne);
2275 static_assert(base::WrappingSub(kTwo, kOne) == kOne);
2276 EXPECT_EQ(base::WrappingSub(kOne, kTwo), kMinusOne);
2277 static_assert(base::WrappingSub(kOne, kTwo) == kMinusOne);
2278 EXPECT_EQ(base::WrappingSub(kMin, kOne), kMax);
2279 static_assert(base::WrappingSub(kMin, kOne) == kMax);
2280 EXPECT_EQ(base::WrappingSub(kMin, kTwo), kMax - 1);
2281 static_assert(base::WrappingSub(kMin, kTwo) == kMax - 1);
2282 EXPECT_EQ(base::WrappingSub(kMax, kMin), kMinusOne);
2283 static_assert(base::WrappingSub(kMax, kMin) == kMinusOne);
2284 EXPECT_EQ(base::WrappingSub(kMin, kMax), kOne);
2285 static_assert(base::WrappingSub(kMin, kMax) == kOne);
2286}
2287
2288template <typename T>
Peter Kasting134183e2024-11-13 01:22:392289 requires std::unsigned_integral<T>
2290void TestWrappingMath() {
David Benjamin954152b2023-10-24 17:46:202291 constexpr T kZero = 0;
2292 constexpr T kOne = 1;
2293 constexpr T kTwo = 2;
2294 constexpr T kThree = 3;
2295 constexpr T kMax = std::numeric_limits<T>::max();
2296
2297 EXPECT_EQ(base::WrappingAdd(kOne, kTwo), kThree);
2298 static_assert(base::WrappingAdd(kOne, kTwo) == kThree);
2299 EXPECT_EQ(base::WrappingAdd(kMax, kOne), kZero);
2300 static_assert(base::WrappingAdd(kMax, kOne) == kZero);
2301 EXPECT_EQ(base::WrappingAdd(kMax, kTwo), kOne);
2302 static_assert(base::WrappingAdd(kMax, kTwo) == kOne);
2303 EXPECT_EQ(base::WrappingAdd(kMax, kMax), kMax - 1);
2304 static_assert(base::WrappingAdd(kMax, kMax) == kMax - 1);
2305
2306 EXPECT_EQ(base::WrappingSub(kTwo, kOne), kOne);
2307 static_assert(base::WrappingSub(kTwo, kOne) == kOne);
2308 EXPECT_EQ(base::WrappingSub(kOne, kTwo), kMax);
2309 static_assert(base::WrappingSub(kOne, kTwo) == kMax);
2310 EXPECT_EQ(base::WrappingSub(kZero, kOne), kMax);
2311 static_assert(base::WrappingSub(kZero, kOne) == kMax);
2312 EXPECT_EQ(base::WrappingSub(kZero, kTwo), kMax - 1);
2313 static_assert(base::WrappingSub(kZero, kTwo) == kMax - 1);
2314}
2315
2316TEST(SafeNumerics, WrappingMath) {
Peter Kasting134183e2024-11-13 01:22:392317 TestWrappingMath<int8_t>();
2318 TestWrappingMath<uint8_t>();
2319 TestWrappingMath<int16_t>();
2320 TestWrappingMath<uint16_t>();
2321 TestWrappingMath<int32_t>();
2322 TestWrappingMath<uint32_t>();
2323 TestWrappingMath<int64_t>();
2324 TestWrappingMath<uint64_t>();
David Benjamin954152b2023-10-24 17:46:202325}
2326
Andrew Paseltiner972cf6c2024-09-13 19:26:372327TEST(SafeNumerics, StrictNumeric_SupportsAssignment) {
2328 StrictNumeric<uint16_t> val(uint16_t{5});
2329 EXPECT_EQ(static_cast<uint16_t>(val), 5u);
2330
2331 // Same underlying type.
2332 val = uint16_t{6};
2333 EXPECT_EQ(static_cast<uint16_t>(val), 6u);
2334
2335 // Different but strictly convertible type.
2336 val = uint8_t{7};
2337 EXPECT_EQ(static_cast<uint16_t>(val), 7u);
2338
2339 // Same type.
2340 val = StrictNumeric<uint16_t>(uint16_t{8});
2341 EXPECT_EQ(static_cast<uint16_t>(val), 8u);
2342
2343 // Different but strictly convertible type.
2344 val = StrictNumeric<uint8_t>(uint8_t{9});
2345 EXPECT_EQ(static_cast<uint16_t>(val), 9u);
2346}
2347
Mostyn Bramley-Moore2c1339ee72018-03-28 21:10:042348#if defined(__clang__)
2349#pragma clang diagnostic pop // -Winteger-overflow
2350#endif
2351
Daniel Chengb8069cb12025-11-12 18:19:222352} // namespace base::numerics_internal