summaryrefslogtreecommitdiffstats
path: root/libc/test/src/__support/math_extras_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libc/test/src/__support/math_extras_test.cpp')
-rw-r--r--libc/test/src/__support/math_extras_test.cpp57
1 files changed, 57 insertions, 0 deletions
diff --git a/libc/test/src/__support/math_extras_test.cpp b/libc/test/src/__support/math_extras_test.cpp
index e88b3e1d6b68..401e631ea4ba 100644
--- a/libc/test/src/__support/math_extras_test.cpp
+++ b/libc/test/src/__support/math_extras_test.cpp
@@ -101,4 +101,61 @@ TYPED_TEST(LlvmLibcBitTest, CountZeros, UnsignedTypesNoBigInt) {
EXPECT_EQ(count_zeros<T>(cpp::numeric_limits<T>::max() >> i), i);
}
+using UnsignedTypes = testing::TypeList<
+#if defined(__SIZEOF_INT128__)
+ __uint128_t,
+#endif
+ unsigned char, unsigned short, unsigned int, unsigned long,
+ unsigned long long>;
+
+TYPED_TEST(LlvmLibcBlockMathExtrasTest, add_overflow, UnsignedTypes) {
+ constexpr T ZERO = cpp::numeric_limits<T>::min();
+ constexpr T ONE(1);
+ constexpr T MAX = cpp::numeric_limits<T>::max();
+ constexpr T BEFORE_MAX = MAX - 1;
+
+ const struct {
+ T lhs;
+ T rhs;
+ T sum;
+ bool carry;
+ } TESTS[] = {
+ {ZERO, ONE, ONE, false}, // 0x00 + 0x01 = 0x01
+ {BEFORE_MAX, ONE, MAX, false}, // 0xFE + 0x01 = 0xFF
+ {MAX, ONE, ZERO, true}, // 0xFF + 0x01 = 0x00 (carry)
+ {MAX, MAX, BEFORE_MAX, true}, // 0xFF + 0xFF = 0xFE (carry)
+ };
+ for (auto tc : TESTS) {
+ T sum;
+ bool carry = add_overflow<T>(tc.lhs, tc.rhs, sum);
+ EXPECT_EQ(sum, tc.sum);
+ EXPECT_EQ(carry, tc.carry);
+ }
+}
+
+TYPED_TEST(LlvmLibcBlockMathExtrasTest, sub_overflow, UnsignedTypes) {
+ constexpr T ZERO = cpp::numeric_limits<T>::min();
+ constexpr T ONE(1);
+ constexpr T MAX = cpp::numeric_limits<T>::max();
+ constexpr T BEFORE_MAX = MAX - 1;
+
+ const struct {
+ T lhs;
+ T rhs;
+ T sub;
+ bool carry;
+ } TESTS[] = {
+ {ONE, ZERO, ONE, false}, // 0x01 - 0x00 = 0x01
+ {MAX, MAX, ZERO, false}, // 0xFF - 0xFF = 0x00
+ {ZERO, ONE, MAX, true}, // 0x00 - 0x01 = 0xFF (carry)
+ {BEFORE_MAX, MAX, MAX, true}, // 0xFE - 0xFF = 0xFF (carry)
+ };
+ for (auto tc : TESTS) {
+ T sub;
+ bool carry = sub_overflow<T>(tc.lhs, tc.rhs, sub);
+ EXPECT_EQ(sub, tc.sub);
+ EXPECT_EQ(carry, tc.carry);
+ }
+}
+
} // namespace LIBC_NAMESPACE