tint: add CheckedDiv for abstract numbers

Bug: tint:1581
Change-Id: Iafed168a916ac3a1062bcf53299e8ff17fc389fb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/101041
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
Antonio Maiorano 2022-09-03 21:31:23 +00:00 committed by Dawn LUCI CQ
parent 5dcdf5d910
commit 1741f4443e
2 changed files with 76 additions and 0 deletions

View File

@ -479,6 +479,28 @@ inline std::optional<AFloat> CheckedMul(AFloat a, AFloat b) {
return AFloat{result};
}
/// @returns a / b, or an empty optional if the resulting value overflowed the AInt
inline std::optional<AInt> CheckedDiv(AInt a, AInt b) {
if (b == 0) {
return {};
}
if (b == -1 && a == AInt::Lowest()) {
return {};
}
return AInt{a.value / b.value};
}
/// @returns a / b, or an empty optional if the resulting value overflowed the AFloat
inline std::optional<AFloat> CheckedDiv(AFloat a, AFloat b) {
auto result = a.value / b.value;
if (!std::isfinite(result)) {
return {};
}
return AFloat{result};
}
/// @returns a * b + c, or an empty optional if the value overflowed the AInt
inline std::optional<AInt> CheckedMadd(AInt a, AInt b, AInt c) {
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80635

View File

@ -537,6 +537,60 @@ INSTANTIATE_TEST_SUITE_P(
////////////////////////////////////////////////////////////////////////
}));
using CheckedDivTest_AInt = testing::TestWithParam<BinaryCheckedCase_AInt>;
TEST_P(CheckedDivTest_AInt, Test) {
auto expect = std::get<0>(GetParam());
auto a = std::get<1>(GetParam());
auto b = std::get<2>(GetParam());
EXPECT_EQ(CheckedDiv(a, b), expect) << std::hex << "0x" << a << " - 0x" << b;
}
INSTANTIATE_TEST_SUITE_P(
CheckedDivTest_AInt,
CheckedDivTest_AInt,
testing::ValuesIn(std::vector<BinaryCheckedCase_AInt>{
{AInt(0), AInt(0), AInt(1)},
{AInt(1), AInt(1), AInt(1)},
{AInt(1), AInt(1), AInt(1)},
{AInt(2), AInt(2), AInt(1)},
{AInt(2), AInt(4), AInt(2)},
{AInt::Highest(), AInt::Highest(), AInt(1)},
{AInt::Lowest(), AInt::Lowest(), AInt(1)},
{AInt(1), AInt::Highest(), AInt::Highest()},
{AInt(0), AInt(0), AInt::Highest()},
{AInt(0), AInt(0), AInt::Lowest()},
{OVERFLOW, AInt(123), AInt(0)},
{OVERFLOW, AInt(-123), AInt(0)},
////////////////////////////////////////////////////////////////////////
}));
using CheckedDivTest_AFloat = testing::TestWithParam<BinaryCheckedCase_AFloat>;
TEST_P(CheckedDivTest_AFloat, Test) {
auto expect = std::get<0>(GetParam());
auto a = std::get<1>(GetParam());
auto b = std::get<2>(GetParam());
EXPECT_EQ(CheckedDiv(a, b), expect) << std::hex << "0x" << a << " - 0x" << b;
}
INSTANTIATE_TEST_SUITE_P(
CheckedDivTest_AFloat,
CheckedDivTest_AFloat,
testing::ValuesIn(std::vector<BinaryCheckedCase_AFloat>{
{AFloat(0), AFloat(0), AFloat(1)},
{AFloat(1), AFloat(1), AFloat(1)},
{AFloat(1), AFloat(1), AFloat(1)},
{AFloat(2), AFloat(2), AFloat(1)},
{AFloat(2), AFloat(4), AFloat(2)},
{AFloat::Highest(), AFloat::Highest(), AFloat(1)},
{AFloat::Lowest(), AFloat::Lowest(), AFloat(1)},
{AFloat(1), AFloat::Highest(), AFloat::Highest()},
{AFloat(0), AFloat(0), AFloat::Highest()},
{-AFloat(0), AFloat(0), AFloat::Lowest()},
{OVERFLOW, AFloat(123), AFloat(0)},
{OVERFLOW, AFloat(123), AFloat(-0)},
{OVERFLOW, AFloat(-123), AFloat(0)},
{OVERFLOW, AFloat(-123), AFloat(-0)},
////////////////////////////////////////////////////////////////////////
}));
using TernaryCheckedCase = std::tuple<std::optional<AInt>, AInt, AInt, AInt>;
using CheckedMaddTest_AInt = testing::TestWithParam<TernaryCheckedCase>;