Use better terminology for overflow and integer 'underflow'
This commit is contained in:
parent
ec074d5753
commit
466982ffcb
File diff suppressed because it is too large
Load Diff
@ -28,31 +28,31 @@ void CkdIntTest::test_ckd()
|
|||||||
const guf_math_ckd_result ckd_add = guf_ckd_add_i8((int8_t)a, (int8_t)b);
|
const guf_math_ckd_result ckd_add = guf_ckd_add_i8((int8_t)a, (int8_t)b);
|
||||||
TEST_CHECK(ckd_add == guf_ckd_add_i8((int8_t)b, (int8_t)a));
|
TEST_CHECK(ckd_add == guf_ckd_add_i8((int8_t)b, (int8_t)a));
|
||||||
if (add_res > INT8_MAX) {
|
if (add_res > INT8_MAX) {
|
||||||
TEST_CHECK(ckd_add == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(ckd_add == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
int8_t saturated, saturated2;
|
int8_t saturated, saturated2;
|
||||||
TEST_CHECK(guf_saturating_add_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_saturating_add_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(saturated == INT8_MAX);
|
TEST_CHECK(saturated == INT8_MAX);
|
||||||
TEST_CHECK(guf_saturating_add_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &saturated2) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_saturating_add_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &saturated2) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(saturated == saturated2);
|
TEST_CHECK(saturated == saturated2);
|
||||||
|
|
||||||
int8_t wrapped, wrapped2;
|
int8_t wrapped, wrapped2;
|
||||||
TEST_CHECK(guf_wrapping_add_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_wrapping_add_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(static_cast<int32_t>(wrapped) == INT8_MIN + (add_res % (INT8_MAX + 1)));
|
TEST_CHECK(static_cast<int32_t>(wrapped) == INT8_MIN + (add_res % (INT8_MAX + 1)));
|
||||||
TEST_CHECK(guf_wrapping_add_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &wrapped2) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_wrapping_add_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &wrapped2) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(wrapped == wrapped2);
|
TEST_CHECK(wrapped == wrapped2);
|
||||||
}
|
}
|
||||||
else if (add_res < INT8_MIN) {
|
else if (add_res < INT8_MIN) {
|
||||||
TEST_CHECK(ckd_add == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(ckd_add == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
int8_t saturated, saturated2;
|
int8_t saturated, saturated2;
|
||||||
TEST_CHECK(guf_saturating_add_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &saturated) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_saturating_add_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(saturated == INT8_MIN);
|
TEST_CHECK(saturated == INT8_MIN);
|
||||||
TEST_CHECK(guf_saturating_add_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &saturated2) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_saturating_add_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &saturated2) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(saturated == saturated2);
|
TEST_CHECK(saturated == saturated2);
|
||||||
|
|
||||||
int8_t wrapped, wrapped2;
|
int8_t wrapped, wrapped2;
|
||||||
TEST_CHECK(guf_wrapping_add_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &wrapped) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_wrapping_add_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(static_cast<int32_t>(wrapped) == INT8_MAX - (-add_res % (-INT8_MIN + 1)));
|
TEST_CHECK(static_cast<int32_t>(wrapped) == INT8_MAX - (-add_res % (-INT8_MIN + 1)));
|
||||||
TEST_CHECK(guf_wrapping_add_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &wrapped2) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_wrapping_add_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &wrapped2) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(wrapped == wrapped2);
|
TEST_CHECK(wrapped == wrapped2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -73,20 +73,20 @@ void CkdIntTest::test_ckd()
|
|||||||
const int32_t sub_res = a - b;
|
const int32_t sub_res = a - b;
|
||||||
const guf_math_ckd_result ckd_sub = guf_ckd_sub_i8((int8_t)a, (int8_t)b);
|
const guf_math_ckd_result ckd_sub = guf_ckd_sub_i8((int8_t)a, (int8_t)b);
|
||||||
if (sub_res > INT8_MAX) {
|
if (sub_res > INT8_MAX) {
|
||||||
TEST_CHECK(ckd_sub == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(ckd_sub == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
int8_t saturated;
|
int8_t saturated;
|
||||||
TEST_CHECK(guf_saturating_sub_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_saturating_sub_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(saturated == INT8_MAX);
|
TEST_CHECK(saturated == INT8_MAX);
|
||||||
int8_t wrapped;
|
int8_t wrapped;
|
||||||
TEST_CHECK(guf_wrapping_sub_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_wrapping_sub_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(static_cast<int32_t>(wrapped) == INT8_MIN + (sub_res % (INT8_MAX + 1)));
|
TEST_CHECK(static_cast<int32_t>(wrapped) == INT8_MIN + (sub_res % (INT8_MAX + 1)));
|
||||||
} else if (sub_res < INT8_MIN) {
|
} else if (sub_res < INT8_MIN) {
|
||||||
TEST_CHECK(ckd_sub == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(ckd_sub == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
int8_t saturated;
|
int8_t saturated;
|
||||||
TEST_CHECK(guf_saturating_sub_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &saturated) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_saturating_sub_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(saturated == INT8_MIN);
|
TEST_CHECK(saturated == INT8_MIN);
|
||||||
int8_t wrapped;
|
int8_t wrapped;
|
||||||
TEST_CHECK(guf_wrapping_sub_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &wrapped) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_wrapping_sub_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(static_cast<int32_t>(wrapped) == INT8_MAX - (-sub_res % (-INT8_MIN + 1)));
|
TEST_CHECK(static_cast<int32_t>(wrapped) == INT8_MAX - (-sub_res % (-INT8_MIN + 1)));
|
||||||
} else {
|
} else {
|
||||||
TEST_CHECK(ckd_sub == GUF_MATH_CKD_SUCCESS);
|
TEST_CHECK(ckd_sub == GUF_MATH_CKD_SUCCESS);
|
||||||
@ -102,31 +102,31 @@ void CkdIntTest::test_ckd()
|
|||||||
const guf_math_ckd_result ckd_mul = guf_ckd_mul_i8((int8_t)a, (int8_t)b);
|
const guf_math_ckd_result ckd_mul = guf_ckd_mul_i8((int8_t)a, (int8_t)b);
|
||||||
TEST_CHECK(ckd_mul == guf_ckd_mul_i8((int8_t)b, (int8_t)a));
|
TEST_CHECK(ckd_mul == guf_ckd_mul_i8((int8_t)b, (int8_t)a));
|
||||||
if (mul_res > INT8_MAX) {
|
if (mul_res > INT8_MAX) {
|
||||||
TEST_CHECK(ckd_mul == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(ckd_mul == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
int8_t saturated, saturated2;
|
int8_t saturated, saturated2;
|
||||||
TEST_CHECK(guf_saturating_mul_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_saturating_mul_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(saturated == INT8_MAX);
|
TEST_CHECK(saturated == INT8_MAX);
|
||||||
|
|
||||||
TEST_CHECK(guf_saturating_mul_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &saturated2) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_saturating_mul_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &saturated2) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(saturated == saturated2);
|
TEST_CHECK(saturated == saturated2);
|
||||||
|
|
||||||
int8_t wrapped, wrapped2;
|
int8_t wrapped, wrapped2;
|
||||||
TEST_CHECK(guf_wrapping_mul_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_wrapping_mul_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(guf_wrapping_mul_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &wrapped2) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_wrapping_mul_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &wrapped2) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(wrapped == wrapped2);
|
TEST_CHECK(wrapped == wrapped2);
|
||||||
// TODO: check wrapped
|
// TODO: check wrapped
|
||||||
} else if (mul_res < INT8_MIN) {
|
} else if (mul_res < INT8_MIN) {
|
||||||
TEST_CHECK(ckd_mul == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(ckd_mul == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
int8_t saturated, saturated2;
|
int8_t saturated, saturated2;
|
||||||
TEST_CHECK(guf_saturating_mul_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &saturated) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_saturating_mul_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(saturated == INT8_MIN);
|
TEST_CHECK(saturated == INT8_MIN);
|
||||||
|
|
||||||
TEST_CHECK(guf_saturating_mul_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &saturated2) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_saturating_mul_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &saturated2) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(saturated == saturated2);
|
TEST_CHECK(saturated == saturated2);
|
||||||
|
|
||||||
int8_t wrapped, wrapped2;
|
int8_t wrapped, wrapped2;
|
||||||
TEST_CHECK(guf_wrapping_mul_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &wrapped) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_wrapping_mul_i8(static_cast<int8_t>(a), static_cast<int8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(guf_wrapping_mul_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &wrapped2) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_wrapping_mul_i8(static_cast<int8_t>(b), static_cast<int8_t>(a), &wrapped2) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(wrapped == wrapped2);
|
TEST_CHECK(wrapped == wrapped2);
|
||||||
// TODO: check wrapped
|
// TODO: check wrapped
|
||||||
} else {
|
} else {
|
||||||
@ -148,10 +148,10 @@ void CkdIntTest::test_ckd()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int8_t mul_i8_res = -1;
|
int8_t mul_i8_res = -1;
|
||||||
TEST_CHECK(guf_wrapping_mul_i8(42, 5, &mul_i8_res) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_wrapping_mul_i8(42, 5, &mul_i8_res) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(mul_i8_res == -46);
|
TEST_CHECK(mul_i8_res == -46);
|
||||||
mul_i8_res = -1;
|
mul_i8_res = -1;
|
||||||
TEST_CHECK(guf_wrapping_mul_i8(5, 42, &mul_i8_res) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_wrapping_mul_i8(5, 42, &mul_i8_res) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(mul_i8_res == -46);
|
TEST_CHECK(mul_i8_res == -46);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -167,10 +167,10 @@ void CkdIntTest::test_ckd()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int32_t mul_i32_res = -1;
|
int32_t mul_i32_res = -1;
|
||||||
TEST_CHECK(guf_wrapping_mul_i32(42002718, 314159265, &mul_i32_res) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_wrapping_mul_i32(42002718, 314159265, &mul_i32_res) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(mul_i32_res == -972735522);
|
TEST_CHECK(mul_i32_res == -972735522);
|
||||||
mul_i32_res = -1;
|
mul_i32_res = -1;
|
||||||
TEST_CHECK(guf_wrapping_mul_i32(314159265, 42002718, &mul_i32_res) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_wrapping_mul_i32(314159265, 42002718, &mul_i32_res) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(mul_i32_res == -972735522);
|
TEST_CHECK(mul_i32_res == -972735522);
|
||||||
|
|
||||||
mul_i32_res = 12345;
|
mul_i32_res = 12345;
|
||||||
@ -202,14 +202,14 @@ void CkdIntTest::test_ckd()
|
|||||||
TEST_CHECK(mul_i32_res == 1693839360);
|
TEST_CHECK(mul_i32_res == 1693839360);
|
||||||
|
|
||||||
ptrdiff_t ptrdiff_res = -1234;
|
ptrdiff_t ptrdiff_res = -1234;
|
||||||
TEST_CHECK(guf_saturating_add_ptrdiff_t(PTRDIFF_MAX, 1, &ptrdiff_res) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_saturating_add_ptrdiff_t(PTRDIFF_MAX, 1, &ptrdiff_res) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(ptrdiff_res == PTRDIFF_MAX);
|
TEST_CHECK(ptrdiff_res == PTRDIFF_MAX);
|
||||||
TEST_CHECK(guf_saturating_add_ptrdiff_t(PTRDIFF_MIN, -1, &ptrdiff_res) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_saturating_add_ptrdiff_t(PTRDIFF_MIN, -1, &ptrdiff_res) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(ptrdiff_res == PTRDIFF_MIN);
|
TEST_CHECK(ptrdiff_res == PTRDIFF_MIN);
|
||||||
|
|
||||||
TEST_CHECK(guf_saturating_mul_ptrdiff_t(PTRDIFF_MAX, 2, &ptrdiff_res) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_saturating_mul_ptrdiff_t(PTRDIFF_MAX, 2, &ptrdiff_res) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(ptrdiff_res == PTRDIFF_MAX);
|
TEST_CHECK(ptrdiff_res == PTRDIFF_MAX);
|
||||||
TEST_CHECK(guf_saturating_mul_ptrdiff_t(PTRDIFF_MIN, 2, &ptrdiff_res) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_saturating_mul_ptrdiff_t(PTRDIFF_MIN, 2, &ptrdiff_res) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(ptrdiff_res == PTRDIFF_MIN);
|
TEST_CHECK(ptrdiff_res == PTRDIFF_MIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,12 +220,12 @@ void CkdIntTest::test_ckd_uint()
|
|||||||
const int32_t add_res = a + b;
|
const int32_t add_res = a + b;
|
||||||
const guf_math_ckd_result ckd_add = guf_ckd_add_u8((uint8_t)a, (uint8_t)b);
|
const guf_math_ckd_result ckd_add = guf_ckd_add_u8((uint8_t)a, (uint8_t)b);
|
||||||
if (add_res > UINT8_MAX) {
|
if (add_res > UINT8_MAX) {
|
||||||
TEST_CHECK(ckd_add == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(ckd_add == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
uint8_t saturated;
|
uint8_t saturated;
|
||||||
TEST_CHECK(guf_saturating_add_u8(static_cast<uint8_t>(a), static_cast<uint8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_saturating_add_u8(static_cast<uint8_t>(a), static_cast<uint8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(saturated == UINT8_MAX);
|
TEST_CHECK(saturated == UINT8_MAX);
|
||||||
uint8_t wrapped;
|
uint8_t wrapped;
|
||||||
TEST_CHECK(guf_wrapping_add_u8(static_cast<uint8_t>(a), static_cast<uint8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_wrapping_add_u8(static_cast<uint8_t>(a), static_cast<uint8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(static_cast<int32_t>(wrapped) == 0 + (add_res % (UINT8_MAX + 1)));
|
TEST_CHECK(static_cast<int32_t>(wrapped) == 0 + (add_res % (UINT8_MAX + 1)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -241,12 +241,12 @@ void CkdIntTest::test_ckd_uint()
|
|||||||
const int32_t sub_res = a - b;
|
const int32_t sub_res = a - b;
|
||||||
const guf_math_ckd_result ckd_sub = guf_ckd_sub_u8((uint8_t)a, (uint8_t)b);
|
const guf_math_ckd_result ckd_sub = guf_ckd_sub_u8((uint8_t)a, (uint8_t)b);
|
||||||
if (sub_res < 0) {
|
if (sub_res < 0) {
|
||||||
TEST_CHECK(ckd_sub == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(ckd_sub == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
uint8_t saturated;
|
uint8_t saturated;
|
||||||
TEST_CHECK(guf_saturating_sub_u8(static_cast<uint8_t>(a), static_cast<uint8_t>(b), &saturated) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_saturating_sub_u8(static_cast<uint8_t>(a), static_cast<uint8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(saturated == 0);
|
TEST_CHECK(saturated == 0);
|
||||||
uint8_t wrapped;
|
uint8_t wrapped;
|
||||||
TEST_CHECK(guf_wrapping_sub_u8(static_cast<uint8_t>(a), static_cast<uint8_t>(b), &wrapped) == GUF_MATH_CKD_UNDERFLOW);
|
TEST_CHECK(guf_wrapping_sub_u8(static_cast<uint8_t>(a), static_cast<uint8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
TEST_CHECK(wrapped == static_cast<uint8_t>(static_cast<uint8_t>(a) - static_cast<uint8_t>(b)));
|
TEST_CHECK(wrapped == static_cast<uint8_t>(static_cast<uint8_t>(a) - static_cast<uint8_t>(b)));
|
||||||
} else {
|
} else {
|
||||||
TEST_CHECK(ckd_sub == GUF_MATH_CKD_SUCCESS);
|
TEST_CHECK(ckd_sub == GUF_MATH_CKD_SUCCESS);
|
||||||
@ -261,12 +261,12 @@ void CkdIntTest::test_ckd_uint()
|
|||||||
const int32_t mul_res = a * b;
|
const int32_t mul_res = a * b;
|
||||||
const guf_math_ckd_result ckd_mul = guf_ckd_mul_u8((uint8_t)a, (uint8_t)b);
|
const guf_math_ckd_result ckd_mul = guf_ckd_mul_u8((uint8_t)a, (uint8_t)b);
|
||||||
if (mul_res > UINT8_MAX) {
|
if (mul_res > UINT8_MAX) {
|
||||||
TEST_CHECK(ckd_mul == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(ckd_mul == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
uint8_t saturated;
|
uint8_t saturated;
|
||||||
TEST_CHECK(guf_saturating_mul_u8(static_cast<uint8_t>(a), static_cast<uint8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_saturating_mul_u8(static_cast<uint8_t>(a), static_cast<uint8_t>(b), &saturated) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(saturated == UINT8_MAX);
|
TEST_CHECK(saturated == UINT8_MAX);
|
||||||
uint8_t wrapped;
|
uint8_t wrapped;
|
||||||
TEST_CHECK(guf_wrapping_mul_u8(static_cast<uint8_t>(a), static_cast<uint8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW);
|
TEST_CHECK(guf_wrapping_mul_u8(static_cast<uint8_t>(a), static_cast<uint8_t>(b), &wrapped) == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
TEST_CHECK(wrapped == static_cast<uint8_t>(static_cast<uint8_t>(a) * static_cast<uint8_t>(b)));
|
TEST_CHECK(wrapped == static_cast<uint8_t>(static_cast<uint8_t>(a) * static_cast<uint8_t>(b)));
|
||||||
} else {
|
} else {
|
||||||
TEST_CHECK(ckd_mul == GUF_MATH_CKD_SUCCESS);
|
TEST_CHECK(ckd_mul == GUF_MATH_CKD_SUCCESS);
|
||||||
|
|||||||
@ -32,7 +32,7 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_{type_abbr}({type} a, {type} b)
|
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_{type_abbr}({type} a, {type} b)
|
||||||
{{
|
{{
|
||||||
if (b > 0 && a > {int_max} - b) {{
|
if (b > 0 && a > {int_max} - b) {{
|
||||||
return GUF_MATH_CKD_OVERFLOW;
|
return GUF_MATH_CKD_OVERFLOW_POS;
|
||||||
}} else {{
|
}} else {{
|
||||||
return GUF_MATH_CKD_SUCCESS;
|
return GUF_MATH_CKD_SUCCESS;
|
||||||
}}
|
}}
|
||||||
@ -40,7 +40,7 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_{type_abbr}({type} a, {type} b)
|
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_{type_abbr}({type} a, {type} b)
|
||||||
{{
|
{{
|
||||||
if (b > a) {{
|
if (b > a) {{
|
||||||
return GUF_MATH_CKD_UNDERFLOW;
|
return GUF_MATH_CKD_OVERFLOW_NEG;
|
||||||
}} else {{
|
}} else {{
|
||||||
return GUF_MATH_CKD_SUCCESS;
|
return GUF_MATH_CKD_SUCCESS;
|
||||||
}}
|
}}
|
||||||
@ -48,7 +48,7 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_{type_abbr}({type} a, {type} b)
|
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_{type_abbr}({type} a, {type} b)
|
||||||
{{
|
{{
|
||||||
const {type} c = 1u * a * b;
|
const {type} c = 1u * a * b;
|
||||||
return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW : GUF_MATH_CKD_SUCCESS;
|
return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS;
|
||||||
}}
|
}}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
@ -62,9 +62,9 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_{type_abbr}({type} a, {type} b)
|
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_{type_abbr}({type} a, {type} b)
|
||||||
{{
|
{{
|
||||||
if (b > 0 && a > {int_max} - b) {{
|
if (b > 0 && a > {int_max} - b) {{
|
||||||
return GUF_MATH_CKD_OVERFLOW;
|
return GUF_MATH_CKD_OVERFLOW_POS;
|
||||||
}} else if (b < 0 && a < {int_min} - b) {{
|
}} else if (b < 0 && a < {int_min} - b) {{
|
||||||
return GUF_MATH_CKD_UNDERFLOW;
|
return GUF_MATH_CKD_OVERFLOW_NEG;
|
||||||
}} else {{
|
}} else {{
|
||||||
return GUF_MATH_CKD_SUCCESS;
|
return GUF_MATH_CKD_SUCCESS;
|
||||||
}}
|
}}
|
||||||
@ -72,9 +72,9 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_{type_abbr}({type} a, {type} b)
|
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_{type_abbr}({type} a, {type} b)
|
||||||
{{
|
{{
|
||||||
if (b < 0 && a > {int_max} + b) {{
|
if (b < 0 && a > {int_max} + b) {{
|
||||||
return GUF_MATH_CKD_OVERFLOW;
|
return GUF_MATH_CKD_OVERFLOW_POS;
|
||||||
}} else if (b > 0 && a < {int_min} + b) {{
|
}} else if (b > 0 && a < {int_min} + b) {{
|
||||||
return GUF_MATH_CKD_UNDERFLOW;
|
return GUF_MATH_CKD_OVERFLOW_NEG;
|
||||||
}} else {{
|
}} else {{
|
||||||
return GUF_MATH_CKD_SUCCESS;
|
return GUF_MATH_CKD_SUCCESS;
|
||||||
}}
|
}}
|
||||||
@ -83,19 +83,19 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
{{
|
{{
|
||||||
if (b > 0) {{
|
if (b > 0) {{
|
||||||
if (a > {int_max} / b) {{
|
if (a > {int_max} / b) {{
|
||||||
return GUF_MATH_CKD_OVERFLOW;
|
return GUF_MATH_CKD_OVERFLOW_POS;
|
||||||
}} else if (a < {int_min} / b) {{
|
}} else if (a < {int_min} / b) {{
|
||||||
return GUF_MATH_CKD_UNDERFLOW;
|
return GUF_MATH_CKD_OVERFLOW_NEG;
|
||||||
}} else {{
|
}} else {{
|
||||||
return GUF_MATH_CKD_SUCCESS;
|
return GUF_MATH_CKD_SUCCESS;
|
||||||
}}
|
}}
|
||||||
}} else if (b < 0) {{
|
}} else if (b < 0) {{
|
||||||
if ({int_min} != -{int_max} && b == -1) {{ // Prevent potential ({int_min} / b) overflow for b == -1
|
if ({int_min} != -{int_max} && b == -1) {{ // Prevent potential ({int_min} / b) overflow for b == -1
|
||||||
return a == {int_min} ? GUF_MATH_CKD_OVERFLOW : GUF_MATH_CKD_SUCCESS;
|
return a == {int_min} ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS;
|
||||||
}} else if (a < {int_max} / b) {{
|
}} else if (a < {int_max} / b) {{
|
||||||
return GUF_MATH_CKD_OVERFLOW;
|
return GUF_MATH_CKD_OVERFLOW_POS;
|
||||||
}} else if (a > {int_min} / b) {{
|
}} else if (a > {int_min} / b) {{
|
||||||
return GUF_MATH_CKD_UNDERFLOW;
|
return GUF_MATH_CKD_OVERFLOW_NEG;
|
||||||
}} else {{
|
}} else {{
|
||||||
return GUF_MATH_CKD_SUCCESS;
|
return GUF_MATH_CKD_SUCCESS;
|
||||||
}}
|
}}
|
||||||
@ -125,10 +125,10 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
case GUF_MATH_CKD_SUCCESS:
|
case GUF_MATH_CKD_SUCCESS:
|
||||||
*result = a + b;
|
*result = a + b;
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_OVERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_POS:
|
||||||
*result = {int_max};
|
*result = {int_max};
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_UNDERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_NEG:
|
||||||
*result = {int_min};
|
*result = {int_min};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -145,10 +145,10 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
case GUF_MATH_CKD_SUCCESS:
|
case GUF_MATH_CKD_SUCCESS:
|
||||||
*result = a - b;
|
*result = a - b;
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_OVERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_POS:
|
||||||
*result = {int_max};
|
*result = {int_max};
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_UNDERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_NEG:
|
||||||
*result = {int_min};
|
*result = {int_min};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -165,10 +165,10 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
case GUF_MATH_CKD_SUCCESS:
|
case GUF_MATH_CKD_SUCCESS:
|
||||||
*result = a * b;
|
*result = a * b;
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_OVERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_POS:
|
||||||
*result = {int_max};
|
*result = {int_max};
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_UNDERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_NEG:
|
||||||
*result = {int_min};
|
*result = {int_min};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -186,10 +186,10 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
case GUF_MATH_CKD_SUCCESS:
|
case GUF_MATH_CKD_SUCCESS:
|
||||||
*result = a + b;
|
*result = a + b;
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_OVERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_POS:
|
||||||
*result = (a + {int_min}) + (b + {int_min});
|
*result = (a + {int_min}) + (b + {int_min});
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_UNDERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_NEG:
|
||||||
*result = (a - {int_min}) + (b - {int_min});
|
*result = (a - {int_min}) + (b - {int_min});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -206,11 +206,11 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
case GUF_MATH_CKD_SUCCESS:
|
case GUF_MATH_CKD_SUCCESS:
|
||||||
*result = a - b;
|
*result = a - b;
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_OVERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_POS:
|
||||||
GUF_ASSERT(b < 0);
|
GUF_ASSERT(b < 0);
|
||||||
*result = (a + {int_min}) - (b - {int_min}); // TODO: not sure
|
*result = (a + {int_min}) - (b - {int_min}); // TODO: not sure
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_UNDERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_NEG:
|
||||||
GUF_ASSERT(b > 0);
|
GUF_ASSERT(b > 0);
|
||||||
*result = (a - {int_min}) - (b + {int_min}); // TODO: not sure
|
*result = (a - {int_min}) - (b + {int_min}); // TODO: not sure
|
||||||
break;
|
break;
|
||||||
@ -228,8 +228,8 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
case GUF_MATH_CKD_SUCCESS:
|
case GUF_MATH_CKD_SUCCESS:
|
||||||
*result = a * b;
|
*result = a * b;
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_OVERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_POS:
|
||||||
case GUF_MATH_CKD_UNDERFLOW: {{
|
case GUF_MATH_CKD_OVERFLOW_NEG: {{
|
||||||
{uint_type} res = 1u * ({uint_type})a * ({uint_type})b;
|
{uint_type} res = 1u * ({uint_type})a * ({uint_type})b;
|
||||||
if (res > {int_max}) {{ // This is the fix for implementation defined conversion from unsigned to signed.
|
if (res > {int_max}) {{ // This is the fix for implementation defined conversion from unsigned to signed.
|
||||||
const {uint_type} mod = (1u * ({uint_type}){int_max} + 1u);
|
const {uint_type} mod = (1u * ({uint_type}){int_max} + 1u);
|
||||||
@ -263,13 +263,13 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_{type_abbr}({type} a, {type} b, {type} *result)
|
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_{type_abbr}({type} a, {type} b, {type} *result)
|
||||||
{{
|
{{
|
||||||
const guf_math_ckd_result check = guf_ckd_add_{type_abbr}(a, b);
|
const guf_math_ckd_result check = guf_ckd_add_{type_abbr}(a, b);
|
||||||
GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW);
|
GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
if (result) {{
|
if (result) {{
|
||||||
switch (check) {{
|
switch (check) {{
|
||||||
case GUF_MATH_CKD_SUCCESS:
|
case GUF_MATH_CKD_SUCCESS:
|
||||||
*result = a + b;
|
*result = a + b;
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_OVERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_POS:
|
||||||
*result = {int_max};
|
*result = {int_max};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -281,13 +281,13 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_{type_abbr}({type} a, {type} b, {type} *result)
|
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_{type_abbr}({type} a, {type} b, {type} *result)
|
||||||
{{
|
{{
|
||||||
const guf_math_ckd_result check = guf_ckd_sub_{type_abbr}(a, b);
|
const guf_math_ckd_result check = guf_ckd_sub_{type_abbr}(a, b);
|
||||||
GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_UNDERFLOW);
|
GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG);
|
||||||
if (result) {{
|
if (result) {{
|
||||||
switch (check) {{
|
switch (check) {{
|
||||||
case GUF_MATH_CKD_SUCCESS:
|
case GUF_MATH_CKD_SUCCESS:
|
||||||
*result = a - b;
|
*result = a - b;
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_UNDERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_NEG:
|
||||||
*result = 0;
|
*result = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -299,13 +299,13 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s
|
|||||||
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_{type_abbr}({type} a, {type} b, {type} *result)
|
GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_{type_abbr}({type} a, {type} b, {type} *result)
|
||||||
{{
|
{{
|
||||||
const guf_math_ckd_result check = guf_ckd_mul_{type_abbr}(a, b);
|
const guf_math_ckd_result check = guf_ckd_mul_{type_abbr}(a, b);
|
||||||
GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW);
|
GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS);
|
||||||
if (result) {{
|
if (result) {{
|
||||||
switch (check) {{
|
switch (check) {{
|
||||||
case GUF_MATH_CKD_SUCCESS:
|
case GUF_MATH_CKD_SUCCESS:
|
||||||
*result = a * b;
|
*result = a * b;
|
||||||
break;
|
break;
|
||||||
case GUF_MATH_CKD_OVERFLOW:
|
case GUF_MATH_CKD_OVERFLOW_POS:
|
||||||
*result = {int_max};
|
*result = {int_max};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -404,7 +404,7 @@ if __name__ == "__main__":
|
|||||||
#define GUF_MATH_CKDINT_H
|
#define GUF_MATH_CKDINT_H
|
||||||
#include "guf_common.h"
|
#include "guf_common.h"
|
||||||
|
|
||||||
typedef enum guf_math_ckd_result {GUF_MATH_CKD_SUCCESS = 0, GUF_MATH_CKD_OVERFLOW, GUF_MATH_CKD_UNDERFLOW} guf_math_ckd_result;
|
typedef enum guf_math_ckd_result {GUF_MATH_CKD_SUCCESS = 0, GUF_MATH_CKD_OVERFLOW_POS, GUF_MATH_CKD_OVERFLOW_NEG} guf_math_ckd_result;
|
||||||
|
|
||||||
"""))
|
"""))
|
||||||
|
|
||||||
@ -416,9 +416,9 @@ if __name__ == "__main__":
|
|||||||
print("#if defined(GUF_MATH_CKDINT_IMPL) || defined(GUF_MATH_CKDINT_IMPL_STATIC)")
|
print("#if defined(GUF_MATH_CKDINT_IMPL) || defined(GUF_MATH_CKDINT_IMPL_STATIC)")
|
||||||
print('#include "guf_assert.h"')
|
print('#include "guf_assert.h"')
|
||||||
print(code_impl)
|
print(code_impl)
|
||||||
print("#endif\n")
|
print("#endif /* End impl */\n")
|
||||||
|
|
||||||
print("#endif")
|
print("#endif /* End header-guard */\n")
|
||||||
|
|
||||||
print("#undef GUF_MATH_CKDINT_KWRDS")
|
print("#undef GUF_MATH_CKDINT_KWRDS")
|
||||||
print("#undef GUF_MATH_CKDINT_IMPL")
|
print("#undef GUF_MATH_CKDINT_IMPL")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user