Added saturating math functions
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
#include <stdint.h>
|
||||
|
||||
/** Implementation of saturated operation on uintaa_t.
|
||||
* Opaerations are clamped betweehn 0 and UINTaa_MAa instead of
|
||||
* wrapping around*/
|
||||
|
||||
#define UC_SAT_ADD(a, b, type, max_val)\
|
||||
((type)((a) + (b)) >= (a) ? (a) + (b) : (max_val))
|
||||
|
||||
#define UC_SAT_SUB(a, b)\
|
||||
(a >= b ? (a) - (b) : 0)
|
||||
|
||||
#define UC_SAT_MULT(a, b, type, max_val)\
|
||||
((b) == 0 ? 0 :\
|
||||
(a) <= (max_val) / (b) ? (type) (a) * (type) (b) \
|
||||
: (max_val))
|
||||
|
||||
|
||||
static inline uint8_t uc_sat_addu8(uint8_t a, uint8_t b)
|
||||
{
|
||||
return UC_SAT_ADD(a, b, uint8_t, UINT8_MAX);
|
||||
}
|
||||
|
||||
static inline uint8_t uc_sat_subu8(uint8_t a, uint8_t b)
|
||||
{
|
||||
return UC_SAT_SUB(a, b);
|
||||
}
|
||||
|
||||
static inline uint8_t uc_sat_multu8(uint8_t a, uint8_t b)
|
||||
{
|
||||
return UC_SAT_MULT(a, b, uint8_t, UINT8_MAX);
|
||||
}
|
||||
|
||||
static inline uint16_t uc_sat_addu16(uint16_t a, uint16_t b)
|
||||
{
|
||||
return UC_SAT_ADD(a, b, uint16_t, UINT16_MAX);
|
||||
}
|
||||
|
||||
static inline uint16_t uc_sat_subu16(uint16_t a, uint16_t b)
|
||||
{
|
||||
return UC_SAT_SUB(a, b);
|
||||
}
|
||||
|
||||
static inline uint16_t uc_sat_multu16(uint16_t a, uint16_t b)
|
||||
{
|
||||
return UC_SAT_MULT(a, b, uint16_t, UINT16_MAX);
|
||||
}
|
||||
|
||||
static inline uint32_t uc_sat_addu32(uint32_t a, uint32_t b)
|
||||
{
|
||||
return UC_SAT_ADD(a, b, uint32_t, UINT32_MAX);
|
||||
}
|
||||
|
||||
static inline uint32_t uc_sat_subu32(uint32_t a, uint32_t b)
|
||||
{
|
||||
return UC_SAT_SUB(a, b);
|
||||
}
|
||||
|
||||
static inline uint32_t uc_sat_multu32(uint32_t a, uint32_t b)
|
||||
{
|
||||
return UC_SAT_MULT(a, b, uint32_t, UINT32_MAX);
|
||||
}
|
||||
|
||||
static inline uint64_t uc_sat_addu64(uint64_t a, uint64_t b)
|
||||
{
|
||||
return UC_SAT_ADD(a, b, uint64_t, UINT64_MAX);
|
||||
}
|
||||
|
||||
static inline uint64_t uc_sat_subu64(uint64_t a, uint64_t b)
|
||||
{
|
||||
return UC_SAT_SUB(a, b);
|
||||
}
|
||||
|
||||
static inline uint64_t uc_sat_multu64(uint64_t a, uint64_t b)
|
||||
{
|
||||
return UC_SAT_MULT(a, b, uint64_t, UINT64_MAX);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ extern Suite *threadqueue_suite(void);
|
||||
extern Suite *buffer_suite(void);
|
||||
extern Suite *clock_suite(void);
|
||||
extern Suite *seq_suite(void);
|
||||
extern Suite *sat_math_suite(void);
|
||||
|
||||
static suite_func suites[] = {
|
||||
bitvec_suite,
|
||||
@@ -30,6 +31,7 @@ static suite_func suites[] = {
|
||||
buffer_suite,
|
||||
clock_suite,
|
||||
seq_suite,
|
||||
sat_math_suite
|
||||
};
|
||||
|
||||
int
|
||||
|
||||
@@ -0,0 +1,509 @@
|
||||
#include <check.h>
|
||||
#include <ucore/saturating_math.h>
|
||||
|
||||
|
||||
START_TEST (test_sat_uc_addu8)
|
||||
uint8_t a;
|
||||
uint8_t b;
|
||||
|
||||
a = UINT8_MAX;
|
||||
b = 1;
|
||||
fail_if(uc_sat_addu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = 1;
|
||||
b = UINT8_MAX;
|
||||
fail_if(uc_sat_addu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = UINT8_MAX;
|
||||
b = UINT8_MAX;
|
||||
fail_if(uc_sat_addu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = UINT8_MAX - 2;
|
||||
b = 2;
|
||||
fail_if(uc_sat_addu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = 2;
|
||||
b = UINT8_MAX - 2;
|
||||
fail_if(uc_sat_addu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = UINT8_MAX - 3;
|
||||
b = 2;
|
||||
fail_if(uc_sat_addu8(a,b) != UINT8_MAX - 1);
|
||||
|
||||
a = 2;
|
||||
b = UINT8_MAX - 3;
|
||||
fail_if(uc_sat_addu8(a,b) != UINT8_MAX - 1);
|
||||
|
||||
a = 0;
|
||||
b = UINT8_MAX;
|
||||
fail_if(uc_sat_addu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = UINT8_MAX;
|
||||
b = 0;
|
||||
fail_if(uc_sat_addu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = 0;
|
||||
b = 0;
|
||||
fail_if(uc_sat_addu8(a,b) != 0);
|
||||
|
||||
a = 100;
|
||||
b = 100;
|
||||
fail_if(uc_sat_addu8(a,b) != 200);
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_sat_uc_subu8)
|
||||
uint8_t a;
|
||||
uint8_t b;
|
||||
|
||||
a = UINT8_MAX;
|
||||
b = 0;
|
||||
fail_if(uc_sat_subu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = 0;
|
||||
b = UINT8_MAX;
|
||||
fail_if(uc_sat_subu8(a,b) != 0);
|
||||
|
||||
a = UINT8_MAX;
|
||||
b = UINT8_MAX;
|
||||
fail_if(uc_sat_subu8(a,b) != 0);
|
||||
|
||||
a = 0;
|
||||
b = 1;
|
||||
fail_if(uc_sat_subu8(a,b) != 0);
|
||||
|
||||
a = 1;
|
||||
b = UINT8_MAX - 1;
|
||||
fail_if(uc_sat_subu8(a,b) != 0);
|
||||
|
||||
a = UINT8_MAX;
|
||||
b = 100;
|
||||
fail_if(uc_sat_subu8(a,b) != UINT8_MAX - 100);
|
||||
|
||||
a = 100;
|
||||
b = 100;
|
||||
fail_if(uc_sat_subu8(a,b) != 0);
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_sat_uc_multu8)
|
||||
uint8_t a;
|
||||
uint8_t b;
|
||||
|
||||
a = UINT8_MAX;
|
||||
b = 0;
|
||||
fail_if(uc_sat_multu8(a,b) != 0);
|
||||
|
||||
a = 0;
|
||||
b = UINT8_MAX;
|
||||
fail_if(uc_sat_multu8(a,b) != 0);
|
||||
|
||||
a = UINT8_MAX;
|
||||
b = UINT8_MAX;
|
||||
fail_if(uc_sat_multu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = UINT8_MAX;
|
||||
b = 2;
|
||||
fail_if(uc_sat_multu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = 2;
|
||||
b = UINT8_MAX;
|
||||
fail_if(uc_sat_multu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = UINT8_MAX;
|
||||
b = UINT8_MAX/2 - 1;
|
||||
fail_if(uc_sat_multu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = UINT8_MAX/2 - 1;
|
||||
b = UINT8_MAX;
|
||||
fail_if(uc_sat_multu8(a,b) != UINT8_MAX);
|
||||
|
||||
a = 10;
|
||||
b = 10;
|
||||
fail_if(uc_sat_multu8(a,b) != 100);
|
||||
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST (test_sat_uc_addu16)
|
||||
uint16_t a;
|
||||
uint16_t b;
|
||||
|
||||
a = UINT16_MAX;
|
||||
b = 1;
|
||||
fail_if(uc_sat_addu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = 1;
|
||||
b = UINT16_MAX;
|
||||
fail_if(uc_sat_addu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = UINT16_MAX;
|
||||
b = UINT16_MAX;
|
||||
fail_if(uc_sat_addu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = UINT16_MAX - 2;
|
||||
b = 2;
|
||||
fail_if(uc_sat_addu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = 2;
|
||||
b = UINT16_MAX - 2;
|
||||
fail_if(uc_sat_addu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = UINT16_MAX - 3;
|
||||
b = 2;
|
||||
fail_if(uc_sat_addu16(a,b) != UINT16_MAX - 1);
|
||||
|
||||
a = 2;
|
||||
b = UINT16_MAX - 3;
|
||||
fail_if(uc_sat_addu16(a,b) != UINT16_MAX - 1);
|
||||
|
||||
a = 0;
|
||||
b = UINT16_MAX;
|
||||
fail_if(uc_sat_addu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = UINT16_MAX;
|
||||
b = 0;
|
||||
fail_if(uc_sat_addu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = 0;
|
||||
b = 0;
|
||||
fail_if(uc_sat_addu16(a,b) != 0);
|
||||
|
||||
a = 100;
|
||||
b = 100;
|
||||
fail_if(uc_sat_addu16(a,b) != 200);
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_sat_uc_subu16)
|
||||
uint16_t a;
|
||||
uint16_t b;
|
||||
|
||||
a = UINT16_MAX;
|
||||
b = 0;
|
||||
fail_if(uc_sat_subu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = 0;
|
||||
b = UINT16_MAX;
|
||||
fail_if(uc_sat_subu16(a,b) != 0);
|
||||
|
||||
a = UINT16_MAX;
|
||||
b = UINT16_MAX;
|
||||
fail_if(uc_sat_subu16(a,b) != 0);
|
||||
|
||||
a = 0;
|
||||
b = 1;
|
||||
fail_if(uc_sat_subu16(a,b) != 0);
|
||||
|
||||
a = 1;
|
||||
b = UINT16_MAX - 1;
|
||||
fail_if(uc_sat_subu16(a,b) != 0);
|
||||
|
||||
a = UINT16_MAX;
|
||||
b = 100;
|
||||
fail_if(uc_sat_subu16(a,b) != UINT16_MAX - 100);
|
||||
|
||||
a = 100;
|
||||
b = 100;
|
||||
fail_if(uc_sat_subu16(a,b) != 0);
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_sat_uc_multu16)
|
||||
uint16_t a;
|
||||
uint16_t b;
|
||||
|
||||
a = UINT16_MAX;
|
||||
b = 0;
|
||||
fail_if(uc_sat_multu16(a,b) != 0);
|
||||
|
||||
a = 0;
|
||||
b = UINT16_MAX;
|
||||
fail_if(uc_sat_multu16(a,b) != 0);
|
||||
|
||||
a = UINT16_MAX;
|
||||
b = UINT16_MAX;
|
||||
fail_if(uc_sat_multu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = UINT16_MAX;
|
||||
b = 2;
|
||||
fail_if(uc_sat_multu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = 2;
|
||||
b = UINT16_MAX;
|
||||
fail_if(uc_sat_multu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = UINT16_MAX;
|
||||
b = UINT16_MAX/2 - 1;
|
||||
fail_if(uc_sat_multu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = UINT16_MAX/2 - 1;
|
||||
b = UINT16_MAX;
|
||||
fail_if(uc_sat_multu16(a,b) != UINT16_MAX);
|
||||
|
||||
a = 10;
|
||||
b = 10;
|
||||
fail_if(uc_sat_multu16(a,b) != 100);
|
||||
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_sat_uc_addu32)
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
|
||||
a = UINT32_MAX;
|
||||
b = 1;
|
||||
fail_if(uc_sat_addu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = 1;
|
||||
b = UINT32_MAX;
|
||||
fail_if(uc_sat_addu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = UINT32_MAX;
|
||||
b = UINT32_MAX;
|
||||
fail_if(uc_sat_addu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = UINT32_MAX - 2;
|
||||
b = 2;
|
||||
fail_if(uc_sat_addu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = 2;
|
||||
b = UINT32_MAX - 2;
|
||||
fail_if(uc_sat_addu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = UINT32_MAX - 3;
|
||||
b = 2;
|
||||
fail_if(uc_sat_addu32(a,b) != UINT32_MAX - 1);
|
||||
|
||||
a = 2;
|
||||
b = UINT32_MAX - 3;
|
||||
fail_if(uc_sat_addu32(a,b) != UINT32_MAX - 1);
|
||||
|
||||
a = 0;
|
||||
b = UINT32_MAX;
|
||||
fail_if(uc_sat_addu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = UINT32_MAX;
|
||||
b = 0;
|
||||
fail_if(uc_sat_addu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = 0;
|
||||
b = 0;
|
||||
fail_if(uc_sat_addu32(a,b) != 0);
|
||||
|
||||
a = 0x1fffffff;
|
||||
b = 0x80000000;
|
||||
fail_if(uc_sat_addu32(a,b) != 0x9fffffff);
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_sat_uc_subu32)
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
|
||||
a = UINT32_MAX;
|
||||
b = 0;
|
||||
fail_if(uc_sat_subu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = 0;
|
||||
b = UINT32_MAX;
|
||||
fail_if(uc_sat_subu32(a,b) != 0);
|
||||
|
||||
a = UINT32_MAX;
|
||||
b = UINT32_MAX;
|
||||
fail_if(uc_sat_subu32(a,b) != 0);
|
||||
|
||||
a = 0;
|
||||
b = 1;
|
||||
fail_if(uc_sat_subu32(a,b) != 0);
|
||||
|
||||
a = 1;
|
||||
b = UINT32_MAX - 1;
|
||||
fail_if(uc_sat_subu32(a,b) != 0);
|
||||
|
||||
a = UINT32_MAX;
|
||||
b = 100;
|
||||
fail_if(uc_sat_subu32(a,b) != UINT32_MAX - 100);
|
||||
|
||||
a = 100;
|
||||
b = 100;
|
||||
fail_if(uc_sat_subu32(a,b) != 0);
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_sat_uc_multu32)
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
|
||||
a = UINT32_MAX;
|
||||
b = 0;
|
||||
fail_if(uc_sat_multu32(a,b) != 0);
|
||||
|
||||
a = 0;
|
||||
b = UINT32_MAX;
|
||||
fail_if(uc_sat_multu32(a,b) != 0);
|
||||
|
||||
a = UINT32_MAX;
|
||||
b = UINT32_MAX;
|
||||
fail_if(uc_sat_multu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = UINT32_MAX;
|
||||
b = 2;
|
||||
fail_if(uc_sat_multu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = 2;
|
||||
b = UINT32_MAX;
|
||||
fail_if(uc_sat_multu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = UINT32_MAX;
|
||||
b = UINT32_MAX/2 - 1;
|
||||
fail_if(uc_sat_multu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = UINT32_MAX/2 - 1;
|
||||
b = UINT32_MAX;
|
||||
fail_if(uc_sat_multu32(a,b) != UINT32_MAX);
|
||||
|
||||
a = 10;
|
||||
b = 10;
|
||||
fail_if(uc_sat_multu32(a,b) != 100);
|
||||
|
||||
END_TEST
|
||||
START_TEST (test_sat_uc_addu64)
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
|
||||
a = UINT64_MAX;
|
||||
b = 1;
|
||||
fail_if(uc_sat_addu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = 1;
|
||||
b = UINT64_MAX;
|
||||
fail_if(uc_sat_addu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = UINT64_MAX;
|
||||
b = UINT64_MAX;
|
||||
fail_if(uc_sat_addu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = UINT64_MAX - 2;
|
||||
b = 2;
|
||||
fail_if(uc_sat_addu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = 2;
|
||||
b = UINT64_MAX - 2;
|
||||
fail_if(uc_sat_addu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = UINT64_MAX - 3;
|
||||
b = 2;
|
||||
fail_if(uc_sat_addu64(a,b) != UINT64_MAX - 1);
|
||||
|
||||
a = 2;
|
||||
b = UINT64_MAX - 3;
|
||||
fail_if(uc_sat_addu64(a,b) != UINT64_MAX - 1);
|
||||
|
||||
a = 0;
|
||||
b = UINT64_MAX;
|
||||
fail_if(uc_sat_addu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = UINT64_MAX;
|
||||
b = 0;
|
||||
fail_if(uc_sat_addu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = 0;
|
||||
b = 0;
|
||||
fail_if(uc_sat_addu64(a,b) != 0);
|
||||
|
||||
a = 0x1fffffffffffffffULL;
|
||||
b = 0x8000000000000000ULL;
|
||||
fail_if(uc_sat_addu64(a,b) != 0x9fffffffffffffffULL);
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_sat_uc_subu64)
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
|
||||
a = UINT64_MAX;
|
||||
b = 0;
|
||||
fail_if(uc_sat_subu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = 0;
|
||||
b = UINT64_MAX;
|
||||
fail_if(uc_sat_subu64(a,b) != 0);
|
||||
|
||||
a = UINT64_MAX;
|
||||
b = UINT64_MAX;
|
||||
fail_if(uc_sat_subu64(a,b) != 0);
|
||||
|
||||
a = 0;
|
||||
b = 1;
|
||||
fail_if(uc_sat_subu64(a,b) != 0);
|
||||
|
||||
a = 1;
|
||||
b = UINT64_MAX - 1;
|
||||
fail_if(uc_sat_subu64(a,b) != 0);
|
||||
|
||||
a = UINT64_MAX;
|
||||
b = 100;
|
||||
fail_if(uc_sat_subu64(a,b) != UINT64_MAX - 100);
|
||||
|
||||
a = 100;
|
||||
b = 100;
|
||||
fail_if(uc_sat_subu64(a,b) != 0);
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_sat_uc_multu64)
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
|
||||
a = UINT64_MAX;
|
||||
b = 0;
|
||||
fail_if(uc_sat_multu64(a,b) != 0);
|
||||
|
||||
a = 0;
|
||||
b = UINT64_MAX;
|
||||
fail_if(uc_sat_multu64(a,b) != 0);
|
||||
|
||||
a = UINT64_MAX;
|
||||
b = UINT64_MAX;
|
||||
fail_if(uc_sat_multu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = UINT64_MAX;
|
||||
b = 2;
|
||||
fail_if(uc_sat_multu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = 2;
|
||||
b = UINT64_MAX;
|
||||
fail_if(uc_sat_multu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = UINT64_MAX;
|
||||
b = UINT64_MAX/2 - 1;
|
||||
fail_if(uc_sat_multu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = UINT64_MAX/2 - 1;
|
||||
b = UINT64_MAX;
|
||||
fail_if(uc_sat_multu64(a,b) != UINT64_MAX);
|
||||
|
||||
a = 10;
|
||||
b = 10;
|
||||
fail_if(uc_sat_multu64(a,b) != 100);
|
||||
|
||||
END_TEST
|
||||
Suite *sat_math_suite(void)
|
||||
{
|
||||
Suite *s = suite_create("saturating_math");
|
||||
TCase *tc = tcase_create("saturating_math tests");
|
||||
|
||||
tcase_add_test(tc, test_sat_uc_addu8);
|
||||
tcase_add_test(tc, test_sat_uc_subu8);
|
||||
tcase_add_test(tc, test_sat_uc_multu8);
|
||||
|
||||
tcase_add_test(tc, test_sat_uc_addu16);
|
||||
tcase_add_test(tc, test_sat_uc_subu16);
|
||||
tcase_add_test(tc, test_sat_uc_multu16);
|
||||
|
||||
tcase_add_test(tc, test_sat_uc_addu32);
|
||||
tcase_add_test(tc, test_sat_uc_subu32);
|
||||
tcase_add_test(tc, test_sat_uc_multu32);
|
||||
|
||||
tcase_add_test(tc, test_sat_uc_addu64);
|
||||
tcase_add_test(tc, test_sat_uc_subu64);
|
||||
tcase_add_test(tc, test_sat_uc_multu64);
|
||||
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user