111 lines
2.3 KiB
C
111 lines
2.3 KiB
C
#ifndef UC_SATMATH_H_
|
|
#define UC_SATMATH_H_
|
|
#include <stdint.h>
|
|
|
|
/** @file
|
|
* Implementation of saturated operation on uintxx_t.
|
|
*
|
|
* Operations are clamped between 0 and UINTxx_MAX instead of
|
|
* wrapping around.
|
|
*
|
|
* multiplication, subtraction and addition operations are provided.*/
|
|
|
|
//Use gcc builtins, supported since GCC 5
|
|
#if __GNUC__ >= 5
|
|
|
|
#define UC_SAT_ADD(a, b, type, max_val)\
|
|
({type res ;\
|
|
if (__builtin_add_overflow(a, b, &res)) {\
|
|
res = max_val;}\
|
|
res;})
|
|
|
|
|
|
#define UC_SAT_SUB(a, b, type)\
|
|
({type res ;\
|
|
if (__builtin_sub_overflow(a, b, &res)) {\
|
|
res = 0;}\
|
|
res;})
|
|
|
|
#define UC_SAT_MULT(a, b, type, max_val)\
|
|
({type res ;\
|
|
if (__builtin_mul_overflow(a, b, &res)) {\
|
|
res = max_val;}\
|
|
res;})
|
|
|
|
#else
|
|
|
|
#define UC_SAT_ADD(a, b, type, max_val)\
|
|
((type)((a) + (b)) >= (a) ? (a) + (b) : (max_val))
|
|
|
|
#define UC_SAT_SUB(a, b, type)\
|
|
((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))
|
|
|
|
#endif
|
|
|
|
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, uint8_t);
|
|
}
|
|
|
|
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, uint16_t);
|
|
}
|
|
|
|
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, uint32_t);
|
|
}
|
|
|
|
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, uint64_t);
|
|
}
|
|
|
|
static inline uint64_t uc_sat_multu64(uint64_t a, uint64_t b)
|
|
{
|
|
return UC_SAT_MULT(a, b, uint64_t, UINT64_MAX);
|
|
}
|
|
|
|
#endif
|