/* is parametrized: no */ /* // Functions for safely checking for over- and underflow of arithmetic operations guf_math_ckd_result guf_ckd_add_TYPE(TYPE a, TYPE b); - if a + b doesn't over/underflow TYPE: return GUF_MATH_CKD_SUCCESS (falsy) - if a + b overflows TYPE: return GUF_MATH_CKD_OVERFLOW_POS (truthy) - if a + b "underflows" TYPE: return GUF_MATH_CKD_OVERFLOW_NEG (truthy) guf_math_ckd_result guf_ckd_sub_TYPE(TYPE a, TYPE b); - if a - b doesn't over/underflow TYPE: return GUF_MATH_CKD_SUCCESS (falsy) - if a - b overflows TYPE: return GUF_MATH_CKD_OVERFLOW_POS (truthy) - if a - b "underflows" TYPE: return GUF_MATH_CKD_OVERFLOW_NEG (truthy) guf_math_ckd_result guf_ckd_mul_TYPE(TYPE a, TYPE b); - if a * b doesn't over/underflow TYPE: return GUF_MATH_CKD_SUCCESS (falsy) - if a * b overflows TYPE: return GUF_MATH_CKD_OVERFLOW_POS (truthy) - if a * b "underflows" TYPE: return GUF_MATH_CKD_OVERFLOW_NEG (truthy) // Functions for safely computing arithmetic operations with saturating over- and underflow semantics // (cf. https://doc.rust-lang.org/std/intrinsics/fn.saturating_add.html (last-retrieved 2025-05-10)) guf_math_ckd_result guf_saturating_add_TYPE(TYPE a, TYPE b, TYPE *result); - if a + b does not over-/underflow TYPE: return GUF_MATH_CKD_SUCCESS (if result is not NULL, set result to a + b) - if a + b overflows TYPE: return GUF_MATH_CKD_OVERFLOW_POS (if result is not NULL, set result to TYPE_MAX, i.e. use saturating overflow semantics). - if a + b "underflows" TYPE: return GUF_MATH_CKD_OVERFLOW_NEG (if result is not NULL, set result to TYPE_MIN, i.e. use saturating underflow semantics). guf_math_ckd_result guf_saturating_sub_TYPE(TYPE a, TYPE b, TYPE *result); - if a - b does not over-/underflow TYPE: return GUF_MATH_CKD_SUCCESS (if result is not NULL, set result to a - b) - if a - b overflows TYPE: return GUF_MATH_CKD_OVERFLOW_POS (if result is not NULL, set result to TYPE_MAX, i.e. use saturating overflow semantics). - if a - b "underflows" TYPE: return GUF_MATH_CKD_OVERFLOW_NEG (if result is not NULL, set result to TYPE_MIN, i.e. use saturating underflow semantics). guf_math_ckd_result guf_saturating_mul_TYPE(TYPE a, TYPE b, TYPE *result); - if a * b does not over-/underflow TYPE: return GUF_MATH_CKD_SUCCESS (if result is not NULL, set result to a * b) - if a * b overflows TYPE: return GUF_MATH_CKD_OVERFLOW_POS (if result is not NULL, set result to TYPE_MAX, i.e. use saturating overflow semantics). - if a * b "underflows" TYPE: return GUF_MATH_CKD_OVERFLOW_NEG (if result is not NULL, set result to TYPE_MIN, i.e. use saturating underflow semantics). // Functions for safely computing arithmetic operations with wrapping over- and underflow semantics // (cf. https://doc.rust-lang.org/std/intrinsics/fn.wrapping_add.html (last-retrieved 2025-05-10)) guf_math_ckd_result guf_wrapping_add_TYPE(TYPE a, TYPE b, TYPE *result); - if a + b does not over-/underflow TYPE: return GUF_MATH_CKD_SUCCESS (if result is not NULL, set result to a + b) - if a + b overflows TYPE: return GUF_MATH_CKD_OVERFLOW_POS (if result is not NULL, set result using two's complement wrap-around overflow semantics). - if a + b "underflows" TYPE: return GUF_MATH_CKD_OVERFLOW_NEG (if result is not NULL, set result using two's complement wrap-around underflow semantics). guf_math_ckd_result guf_wrapping_sub_TYPE(TYPE a, TYPE b, TYPE *result); - if a - b doesn't over-/underflow TYPE: return GUF_MATH_CKD_SUCCESS (if result is not NULL, set result to a - b) - if a - b overflows TYPE: return GUF_MATH_CKD_OVERFLOW_POS (if result is not NULL, set result using two's complement wrap-around overflow semantics). - if a - b "underflows" TYPE: return GUF_MATH_CKD_OVERFLOW_NEG (if result is not NULL, set result using two's complement wrap-around underflow semantics). guf_math_ckd_result guf_wrapping_mul_TYPE(TYPE a, TYPE b, TYPE *result); // NOTE/TODO: guf_wrapping_mul_TYPE relies on implementation-defined unsigned-to-signed two's complement conversion on over/underflow // cf. https://stackoverflow.com/questions/76900522/can-you-ensure-overflow-wrapping-behavior-for-signed-integer-arithmetic-in-c (last-retrieved 2025-05-13) - if a * b doesn't over-/underflow TYPE: return GUF_MATH_CKD_SUCCESS (if result is not NULL, set result to a * b) - if a * b overflows TYPE: return GUF_MATH_CKD_OVERFLOW_POS (if result is not NULL, set result using two's complement wrap-around overflow semantics). - if a * b "underflows" TYPE: return GUF_MATH_CKD_OVERFLOW_NEG (if result is not NULL, set result using two's complement wrap-around underflow semantics). cf. https://stackoverflow.com/questions/199333/how-do-i-detect-unsigned-integer-overflow (last-retrieved 2025-03-17) cf. https://stackoverflow.com/questions/59307930/how-to-implement-wrapping-signed-int-addition-in-c (last-retrieved 2025-05-10) cf. https://stackoverflow.com/questions/54318815/integer-overflow-w-multiplication-in-c (last-retrieved 2025-05-11) cf. https://stackoverflow.com/questions/29808397/how-to-portably-find-out-minint-max-absint-min (last-retrieved 2025-05-11) cf. https://stackoverflow.com/questions/27001604/32-bit-unsigned-multiply-on-64-bit-causing-undefined-behavior (last-retrieved 2025-05-15) */ #if defined(GUF_MATH_CKDINT_IMPL_STATIC) #define GUF_MATH_CKDINT_KWRDS static inline #else #define GUF_MATH_CKDINT_KWRDS #endif #ifndef GUF_MATH_CKDINT_H #define GUF_MATH_CKDINT_H #include "guf_common.h" 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; #if !defined(GUF_MATH_CKDINT_IMPL_STATIC) && !defined(GUF_MATH_CKDINT_IMPL) // Signed integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int(int a, int b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_int(int a, int b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_int(int a, int b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_long(long a, long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_long(long a, long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_long(long a, long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_long_long(long long a, long long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_long_long(long long a, long long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_long_long(long long a, long long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_ptrdiff_t(ptrdiff_t a, ptrdiff_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_ptrdiff_t(ptrdiff_t a, ptrdiff_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_ptrdiff_t(ptrdiff_t a, ptrdiff_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_i8(int_least8_t a, int_least8_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_i8(int_least8_t a, int_least8_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_i8(int_least8_t a, int_least8_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_i16(int_least16_t a, int_least16_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_i16(int_least16_t a, int_least16_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_i16(int_least16_t a, int_least16_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_i32(int_least32_t a, int_least32_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_i32(int_least32_t a, int_least32_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_i32(int_least32_t a, int_least32_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_i64(int_least64_t a, int_least64_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_i64(int_least64_t a, int_least64_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_i64(int_least64_t a, int_least64_t b); #ifdef INT8_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i8(int8_t a, int8_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i8(int8_t a, int8_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i8(int8_t a, int8_t b); #endif #ifdef INT16_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i16(int16_t a, int16_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i16(int16_t a, int16_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i16(int16_t a, int16_t b); #endif #ifdef INT32_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i32(int32_t a, int32_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i32(int32_t a, int32_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i32(int32_t a, int32_t b); #endif #ifdef INT64_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i64(int64_t a, int64_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i64(int64_t a, int64_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i64(int64_t a, int64_t b); #endif // Unsigned integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_uchar(unsigned char a, unsigned char b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_uchar(unsigned char a, unsigned char b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_uchar(unsigned char a, unsigned char b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_unsigned(unsigned a, unsigned b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_unsigned(unsigned a, unsigned b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_unsigned(unsigned a, unsigned b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_ulong(unsigned long a, unsigned long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_ulong(unsigned long a, unsigned long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_ulong(unsigned long a, unsigned long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_ulong_long(unsigned long long a, unsigned long long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_ulong_long(unsigned long long a, unsigned long long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_ulong_long(unsigned long long a, unsigned long long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_size_t(size_t a, size_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_size_t(size_t a, size_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_size_t(size_t a, size_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_u8(uint_least8_t a, uint_least8_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_u8(uint_least8_t a, uint_least8_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_u8(uint_least8_t a, uint_least8_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_u16(uint_least16_t a, uint_least16_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_u16(uint_least16_t a, uint_least16_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_u16(uint_least16_t a, uint_least16_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_u32(uint_least32_t a, uint_least32_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_u32(uint_least32_t a, uint_least32_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_u32(uint_least32_t a, uint_least32_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_u64(uint_least64_t a, uint_least64_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_u64(uint_least64_t a, uint_least64_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_u64(uint_least64_t a, uint_least64_t b); #ifdef UINT8_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u8(uint8_t a, uint8_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u8(uint8_t a, uint8_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u8(uint8_t a, uint8_t b); #endif #ifdef UINT16_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u16(uint16_t a, uint16_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u16(uint16_t a, uint16_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u16(uint16_t a, uint16_t b); #endif #ifdef UINT32_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u32(uint32_t a, uint32_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u32(uint32_t a, uint32_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u32(uint32_t a, uint32_t b); #endif #ifdef UINT64_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u64(uint64_t a, uint64_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u64(uint64_t a, uint64_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u64(uint64_t a, uint64_t b); #endif // Signed saturating/wrapping arithmetic (generated with libguf/tools/ckdint-gen.py) GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_int(int a, int b, int *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_int(int a, int b, int *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_int(int a, int b, int *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_int(int a, int b, int *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_int(int a, int b, int *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int(int a, int b, int *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_long(long a, long b, long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_long(long a, long b, long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_long(long a, long b, long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_long(long a, long b, long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_long(long a, long b, long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_long(long a, long b, long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_long_long(long long a, long long b, long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_long_long(long long a, long long b, long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_long_long(long long a, long long b, long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_long_long(long long a, long long b, long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_long_long(long long a, long long b, long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_long_long(long long a, long long b, long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_i8(int_least8_t a, int_least8_t b, int_least8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_i8(int_least8_t a, int_least8_t b, int_least8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_i8(int_least8_t a, int_least8_t b, int_least8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_i8(int_least8_t a, int_least8_t b, int_least8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_i8(int_least8_t a, int_least8_t b, int_least8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_i8(int_least8_t a, int_least8_t b, int_least8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_i16(int_least16_t a, int_least16_t b, int_least16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_i16(int_least16_t a, int_least16_t b, int_least16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_i16(int_least16_t a, int_least16_t b, int_least16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_i16(int_least16_t a, int_least16_t b, int_least16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_i16(int_least16_t a, int_least16_t b, int_least16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_i16(int_least16_t a, int_least16_t b, int_least16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_i32(int_least32_t a, int_least32_t b, int_least32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_i32(int_least32_t a, int_least32_t b, int_least32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_i32(int_least32_t a, int_least32_t b, int_least32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_i32(int_least32_t a, int_least32_t b, int_least32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_i32(int_least32_t a, int_least32_t b, int_least32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_i32(int_least32_t a, int_least32_t b, int_least32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_i64(int_least64_t a, int_least64_t b, int_least64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_i64(int_least64_t a, int_least64_t b, int_least64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_i64(int_least64_t a, int_least64_t b, int_least64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_i64(int_least64_t a, int_least64_t b, int_least64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_i64(int_least64_t a, int_least64_t b, int_least64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_i64(int_least64_t a, int_least64_t b, int_least64_t *result); #ifdef INT8_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i8(int8_t a, int8_t b, int8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i8(int8_t a, int8_t b, int8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i8(int8_t a, int8_t b, int8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i8(int8_t a, int8_t b, int8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i8(int8_t a, int8_t b, int8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i8(int8_t a, int8_t b, int8_t *result); #endif #ifdef INT16_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i16(int16_t a, int16_t b, int16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i16(int16_t a, int16_t b, int16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i16(int16_t a, int16_t b, int16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i16(int16_t a, int16_t b, int16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i16(int16_t a, int16_t b, int16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i16(int16_t a, int16_t b, int16_t *result); #endif #ifdef INT32_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i32(int32_t a, int32_t b, int32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i32(int32_t a, int32_t b, int32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i32(int32_t a, int32_t b, int32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i32(int32_t a, int32_t b, int32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i32(int32_t a, int32_t b, int32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i32(int32_t a, int32_t b, int32_t *result); #endif #ifdef INT64_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i64(int64_t a, int64_t b, int64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i64(int64_t a, int64_t b, int64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i64(int64_t a, int64_t b, int64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i64(int64_t a, int64_t b, int64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i64(int64_t a, int64_t b, int64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i64(int64_t a, int64_t b, int64_t *result); #endif // Unsigned saturating/wrapping arithmetic (generated with libguf/tools/ckdint-gen.py) GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_uchar(unsigned char a, unsigned char b, unsigned char *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_uchar(unsigned char a, unsigned char b, unsigned char *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_uchar(unsigned char a, unsigned char b, unsigned char *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_uchar(unsigned char a, unsigned char b, unsigned char *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_uchar(unsigned char a, unsigned char b, unsigned char *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_uchar(unsigned char a, unsigned char b, unsigned char *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_unsigned(unsigned a, unsigned b, unsigned *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_unsigned(unsigned a, unsigned b, unsigned *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_unsigned(unsigned a, unsigned b, unsigned *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_unsigned(unsigned a, unsigned b, unsigned *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_unsigned(unsigned a, unsigned b, unsigned *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_unsigned(unsigned a, unsigned b, unsigned *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_ulong(unsigned long a, unsigned long b, unsigned long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_ulong(unsigned long a, unsigned long b, unsigned long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_ulong(unsigned long a, unsigned long b, unsigned long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_ulong(unsigned long a, unsigned long b, unsigned long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_ulong(unsigned long a, unsigned long b, unsigned long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ulong(unsigned long a, unsigned long b, unsigned long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_size_t(size_t a, size_t b, size_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_size_t(size_t a, size_t b, size_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_size_t(size_t a, size_t b, size_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_size_t(size_t a, size_t b, size_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_size_t(size_t a, size_t b, size_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_size_t(size_t a, size_t b, size_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_u8(uint_least8_t a, uint_least8_t b, uint_least8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_u8(uint_least8_t a, uint_least8_t b, uint_least8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_u8(uint_least8_t a, uint_least8_t b, uint_least8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_u8(uint_least8_t a, uint_least8_t b, uint_least8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_u8(uint_least8_t a, uint_least8_t b, uint_least8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_u8(uint_least8_t a, uint_least8_t b, uint_least8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_u16(uint_least16_t a, uint_least16_t b, uint_least16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_u16(uint_least16_t a, uint_least16_t b, uint_least16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_u16(uint_least16_t a, uint_least16_t b, uint_least16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_u16(uint_least16_t a, uint_least16_t b, uint_least16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_u16(uint_least16_t a, uint_least16_t b, uint_least16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_u16(uint_least16_t a, uint_least16_t b, uint_least16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_u32(uint_least32_t a, uint_least32_t b, uint_least32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_u32(uint_least32_t a, uint_least32_t b, uint_least32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_u32(uint_least32_t a, uint_least32_t b, uint_least32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_u32(uint_least32_t a, uint_least32_t b, uint_least32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_u32(uint_least32_t a, uint_least32_t b, uint_least32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_u32(uint_least32_t a, uint_least32_t b, uint_least32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_u64(uint_least64_t a, uint_least64_t b, uint_least64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_u64(uint_least64_t a, uint_least64_t b, uint_least64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_u64(uint_least64_t a, uint_least64_t b, uint_least64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_u64(uint_least64_t a, uint_least64_t b, uint_least64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_u64(uint_least64_t a, uint_least64_t b, uint_least64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_u64(uint_least64_t a, uint_least64_t b, uint_least64_t *result); #ifdef UINT8_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u8(uint8_t a, uint8_t b, uint8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u8(uint8_t a, uint8_t b, uint8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u8(uint8_t a, uint8_t b, uint8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u8(uint8_t a, uint8_t b, uint8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u8(uint8_t a, uint8_t b, uint8_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u8(uint8_t a, uint8_t b, uint8_t *result); #endif #ifdef UINT16_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u16(uint16_t a, uint16_t b, uint16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u16(uint16_t a, uint16_t b, uint16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u16(uint16_t a, uint16_t b, uint16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u16(uint16_t a, uint16_t b, uint16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u16(uint16_t a, uint16_t b, uint16_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u16(uint16_t a, uint16_t b, uint16_t *result); #endif #ifdef UINT32_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u32(uint32_t a, uint32_t b, uint32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u32(uint32_t a, uint32_t b, uint32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u32(uint32_t a, uint32_t b, uint32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u32(uint32_t a, uint32_t b, uint32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u32(uint32_t a, uint32_t b, uint32_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u32(uint32_t a, uint32_t b, uint32_t *result); #endif #ifdef UINT64_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u64(uint64_t a, uint64_t b, uint64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u64(uint64_t a, uint64_t b, uint64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u64(uint64_t a, uint64_t b, uint64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u64(uint64_t a, uint64_t b, uint64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u64(uint64_t a, uint64_t b, uint64_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u64(uint64_t a, uint64_t b, uint64_t *result); #endif #endif #if defined(GUF_MATH_CKDINT_IMPL) || defined(GUF_MATH_CKDINT_IMPL_STATIC) #include "guf_assert.h" // Signed integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int(int a, int b) { if (b > 0 && a > INT_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b < 0 && a < INT_MIN - b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_int(int a, int b) { if (b < 0 && a > INT_MAX + b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b > 0 && a < INT_MIN + b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_int(int a, int b) { if (b > 0) { if (a > INT_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a < INT_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else if (b < 0) { if (INT_MIN != -INT_MAX && b == -1) { // Prevent potential (INT_MIN / b) overflow for b == -1 return a == INT_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } else if (a < INT_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a > INT_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_long(long a, long b) { if (b > 0 && a > LONG_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b < 0 && a < LONG_MIN - b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_long(long a, long b) { if (b < 0 && a > LONG_MAX + b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b > 0 && a < LONG_MIN + b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_long(long a, long b) { if (b > 0) { if (a > LONG_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a < LONG_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else if (b < 0) { if (LONG_MIN != -LONG_MAX && b == -1) { // Prevent potential (LONG_MIN / b) overflow for b == -1 return a == LONG_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } else if (a < LONG_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a > LONG_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_long_long(long long a, long long b) { if (b > 0 && a > LLONG_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b < 0 && a < LLONG_MIN - b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_long_long(long long a, long long b) { if (b < 0 && a > LLONG_MAX + b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b > 0 && a < LLONG_MIN + b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_long_long(long long a, long long b) { if (b > 0) { if (a > LLONG_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a < LLONG_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else if (b < 0) { if (LLONG_MIN != -LLONG_MAX && b == -1) { // Prevent potential (LLONG_MIN / b) overflow for b == -1 return a == LLONG_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } else if (a < LLONG_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a > LLONG_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_ptrdiff_t(ptrdiff_t a, ptrdiff_t b) { if (b > 0 && a > PTRDIFF_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b < 0 && a < PTRDIFF_MIN - b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_ptrdiff_t(ptrdiff_t a, ptrdiff_t b) { if (b < 0 && a > PTRDIFF_MAX + b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b > 0 && a < PTRDIFF_MIN + b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_ptrdiff_t(ptrdiff_t a, ptrdiff_t b) { if (b > 0) { if (a > PTRDIFF_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a < PTRDIFF_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else if (b < 0) { if (PTRDIFF_MIN != -PTRDIFF_MAX && b == -1) { // Prevent potential (PTRDIFF_MIN / b) overflow for b == -1 return a == PTRDIFF_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } else if (a < PTRDIFF_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a > PTRDIFF_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_i8(int_least8_t a, int_least8_t b) { if (b > 0 && a > GUF_INT8_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b < 0 && a < GUF_INT8_MIN - b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_i8(int_least8_t a, int_least8_t b) { if (b < 0 && a > GUF_INT8_MAX + b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b > 0 && a < GUF_INT8_MIN + b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_i8(int_least8_t a, int_least8_t b) { if (b > 0) { if (a > GUF_INT8_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a < GUF_INT8_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else if (b < 0) { if (GUF_INT8_MIN != -GUF_INT8_MAX && b == -1) { // Prevent potential (GUF_INT8_MIN / b) overflow for b == -1 return a == GUF_INT8_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } else if (a < GUF_INT8_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a > GUF_INT8_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_i16(int_least16_t a, int_least16_t b) { if (b > 0 && a > GUF_INT16_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b < 0 && a < GUF_INT16_MIN - b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_i16(int_least16_t a, int_least16_t b) { if (b < 0 && a > GUF_INT16_MAX + b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b > 0 && a < GUF_INT16_MIN + b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_i16(int_least16_t a, int_least16_t b) { if (b > 0) { if (a > GUF_INT16_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a < GUF_INT16_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else if (b < 0) { if (GUF_INT16_MIN != -GUF_INT16_MAX && b == -1) { // Prevent potential (GUF_INT16_MIN / b) overflow for b == -1 return a == GUF_INT16_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } else if (a < GUF_INT16_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a > GUF_INT16_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_i32(int_least32_t a, int_least32_t b) { if (b > 0 && a > GUF_INT32_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b < 0 && a < GUF_INT32_MIN - b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_i32(int_least32_t a, int_least32_t b) { if (b < 0 && a > GUF_INT32_MAX + b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b > 0 && a < GUF_INT32_MIN + b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_i32(int_least32_t a, int_least32_t b) { if (b > 0) { if (a > GUF_INT32_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a < GUF_INT32_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else if (b < 0) { if (GUF_INT32_MIN != -GUF_INT32_MAX && b == -1) { // Prevent potential (GUF_INT32_MIN / b) overflow for b == -1 return a == GUF_INT32_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } else if (a < GUF_INT32_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a > GUF_INT32_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_i64(int_least64_t a, int_least64_t b) { if (b > 0 && a > GUF_INT64_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b < 0 && a < GUF_INT64_MIN - b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_i64(int_least64_t a, int_least64_t b) { if (b < 0 && a > GUF_INT64_MAX + b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b > 0 && a < GUF_INT64_MIN + b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_i64(int_least64_t a, int_least64_t b) { if (b > 0) { if (a > GUF_INT64_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a < GUF_INT64_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else if (b < 0) { if (GUF_INT64_MIN != -GUF_INT64_MAX && b == -1) { // Prevent potential (GUF_INT64_MIN / b) overflow for b == -1 return a == GUF_INT64_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } else if (a < GUF_INT64_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a > GUF_INT64_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else { return GUF_MATH_CKD_SUCCESS; } } #ifdef INT8_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i8(int8_t a, int8_t b) { if (b > 0 && a > INT8_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b < 0 && a < INT8_MIN - b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i8(int8_t a, int8_t b) { if (b < 0 && a > INT8_MAX + b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b > 0 && a < INT8_MIN + b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i8(int8_t a, int8_t b) { if (b > 0) { if (a > INT8_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a < INT8_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else if (b < 0) { if (INT8_MIN != -INT8_MAX && b == -1) { // Prevent potential (INT8_MIN / b) overflow for b == -1 return a == INT8_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } else if (a < INT8_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a > INT8_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else { return GUF_MATH_CKD_SUCCESS; } } #endif #ifdef INT16_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i16(int16_t a, int16_t b) { if (b > 0 && a > INT16_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b < 0 && a < INT16_MIN - b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i16(int16_t a, int16_t b) { if (b < 0 && a > INT16_MAX + b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b > 0 && a < INT16_MIN + b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i16(int16_t a, int16_t b) { if (b > 0) { if (a > INT16_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a < INT16_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else if (b < 0) { if (INT16_MIN != -INT16_MAX && b == -1) { // Prevent potential (INT16_MIN / b) overflow for b == -1 return a == INT16_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } else if (a < INT16_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a > INT16_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else { return GUF_MATH_CKD_SUCCESS; } } #endif #ifdef INT32_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i32(int32_t a, int32_t b) { if (b > 0 && a > INT32_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b < 0 && a < INT32_MIN - b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i32(int32_t a, int32_t b) { if (b < 0 && a > INT32_MAX + b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b > 0 && a < INT32_MIN + b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i32(int32_t a, int32_t b) { if (b > 0) { if (a > INT32_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a < INT32_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else if (b < 0) { if (INT32_MIN != -INT32_MAX && b == -1) { // Prevent potential (INT32_MIN / b) overflow for b == -1 return a == INT32_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } else if (a < INT32_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a > INT32_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else { return GUF_MATH_CKD_SUCCESS; } } #endif #ifdef INT64_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i64(int64_t a, int64_t b) { if (b > 0 && a > INT64_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b < 0 && a < INT64_MIN - b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i64(int64_t a, int64_t b) { if (b < 0 && a > INT64_MAX + b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (b > 0 && a < INT64_MIN + b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i64(int64_t a, int64_t b) { if (b > 0) { if (a > INT64_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a < INT64_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else if (b < 0) { if (INT64_MIN != -INT64_MAX && b == -1) { // Prevent potential (INT64_MIN / b) overflow for b == -1 return a == INT64_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } else if (a < INT64_MAX / b) { return GUF_MATH_CKD_OVERFLOW_POS; } else if (a > INT64_MIN / b) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } else { return GUF_MATH_CKD_SUCCESS; } } #endif // Unsigned integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_uchar(unsigned char a, unsigned char b) { if (b > 0 && a > UCHAR_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_uchar(unsigned char a, unsigned char b) { if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_uchar(unsigned char a, unsigned char b) { const unsigned char c = 1u * a * b; return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_unsigned(unsigned a, unsigned b) { if (b > 0 && a > UINT_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_unsigned(unsigned a, unsigned b) { if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_unsigned(unsigned a, unsigned b) { const unsigned c = 1u * a * b; return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_ulong(unsigned long a, unsigned long b) { if (b > 0 && a > ULONG_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_ulong(unsigned long a, unsigned long b) { if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_ulong(unsigned long a, unsigned long b) { const unsigned long c = 1u * a * b; return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_ulong_long(unsigned long long a, unsigned long long b) { if (b > 0 && a > ULLONG_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_ulong_long(unsigned long long a, unsigned long long b) { if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_ulong_long(unsigned long long a, unsigned long long b) { const unsigned long long c = 1u * a * b; return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_size_t(size_t a, size_t b) { if (b > 0 && a > SIZE_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_size_t(size_t a, size_t b) { if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_size_t(size_t a, size_t b) { const size_t c = 1u * a * b; return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_u8(uint_least8_t a, uint_least8_t b) { a = GUF_UWRAP_8(a); b = GUF_UWRAP_8(b); if (b > 0 && a > GUF_UINT8_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_u8(uint_least8_t a, uint_least8_t b) { a = GUF_UWRAP_8(a); b = GUF_UWRAP_8(b); if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_u8(uint_least8_t a, uint_least8_t b) { a = GUF_UWRAP_8(a); b = GUF_UWRAP_8(b); const uint_least8_t c = GUF_UWRAP_8( 1u * a * b ); return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_u16(uint_least16_t a, uint_least16_t b) { a = GUF_UWRAP_16(a); b = GUF_UWRAP_16(b); if (b > 0 && a > GUF_UINT16_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_u16(uint_least16_t a, uint_least16_t b) { a = GUF_UWRAP_16(a); b = GUF_UWRAP_16(b); if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_u16(uint_least16_t a, uint_least16_t b) { a = GUF_UWRAP_16(a); b = GUF_UWRAP_16(b); const uint_least16_t c = GUF_UWRAP_16( 1u * a * b ); return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_u32(uint_least32_t a, uint_least32_t b) { a = GUF_UWRAP_32(a); b = GUF_UWRAP_32(b); if (b > 0 && a > GUF_UINT32_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_u32(uint_least32_t a, uint_least32_t b) { a = GUF_UWRAP_32(a); b = GUF_UWRAP_32(b); if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_u32(uint_least32_t a, uint_least32_t b) { a = GUF_UWRAP_32(a); b = GUF_UWRAP_32(b); const uint_least32_t c = GUF_UWRAP_32( 1u * a * b ); return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_least_u64(uint_least64_t a, uint_least64_t b) { a = GUF_UWRAP_64(a); b = GUF_UWRAP_64(b); if (b > 0 && a > GUF_UINT64_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_least_u64(uint_least64_t a, uint_least64_t b) { a = GUF_UWRAP_64(a); b = GUF_UWRAP_64(b); if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_least_u64(uint_least64_t a, uint_least64_t b) { a = GUF_UWRAP_64(a); b = GUF_UWRAP_64(b); const uint_least64_t c = GUF_UWRAP_64( 1u * a * b ); return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } #ifdef UINT8_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u8(uint8_t a, uint8_t b) { if (b > 0 && a > UINT8_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u8(uint8_t a, uint8_t b) { if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u8(uint8_t a, uint8_t b) { const uint8_t c = 1u * a * b; return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } #endif #ifdef UINT16_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u16(uint16_t a, uint16_t b) { if (b > 0 && a > UINT16_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u16(uint16_t a, uint16_t b) { if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u16(uint16_t a, uint16_t b) { const uint16_t c = 1u * a * b; return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } #endif #ifdef UINT32_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u32(uint32_t a, uint32_t b) { if (b > 0 && a > UINT32_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u32(uint32_t a, uint32_t b) { if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u32(uint32_t a, uint32_t b) { const uint32_t c = 1u * a * b; return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } #endif #ifdef UINT64_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u64(uint64_t a, uint64_t b) { if (b > 0 && a > UINT64_MAX - b) { return GUF_MATH_CKD_OVERFLOW_POS; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u64(uint64_t a, uint64_t b) { if (b > a) { return GUF_MATH_CKD_OVERFLOW_NEG; } else { return GUF_MATH_CKD_SUCCESS; } } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u64(uint64_t a, uint64_t b) { const uint64_t c = 1u * a * b; return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } #endif // Signed saturating/wrapping arithmetic (generated with libguf/tools/ckdint-gen.py) GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_int(int a, int b, int *result) { const guf_math_ckd_result check = guf_ckd_add_int(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_int(int a, int b, int *result) { const guf_math_ckd_result check = guf_ckd_sub_int(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_int(int a, int b, int *result) { const guf_math_ckd_result check = guf_ckd_mul_int(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_int(int a, int b, int *result) { const guf_math_ckd_result check = guf_ckd_add_int(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = (int)( (a + (int)INT_MIN) + (b + (int)INT_MIN) ); break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = (int)( (a - (int)INT_MIN) + (b - (int)INT_MIN) ); break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_int(int a, int b, int *result) { const guf_math_ckd_result check = guf_ckd_sub_int(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: GUF_ASSERT(b < 0); *result = (int)( (a + (int)INT_MIN) - (b - (int)INT_MIN) ); // TODO: not sure break; case GUF_MATH_CKD_OVERFLOW_NEG: GUF_ASSERT(b > 0); *result = (int)( (a - (int)INT_MIN) - (b + (int)INT_MIN) ); // TODO: not sure break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int(int a, int b, int *result) { const guf_math_ckd_result check = guf_ckd_mul_int(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: case GUF_MATH_CKD_OVERFLOW_NEG: { unsigned res = 1u * (unsigned)a * (unsigned)b; if (res > INT_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. const unsigned mod = (unsigned)INT_MAX + 1u; GUF_ASSERT(mod > 0); res = 1u * res % mod; *result = (int)INT_MIN + (int)res; } else { *result = (int)res; } break; } default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_long(long a, long b, long *result) { const guf_math_ckd_result check = guf_ckd_add_long(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = LONG_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = LONG_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_long(long a, long b, long *result) { const guf_math_ckd_result check = guf_ckd_sub_long(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = LONG_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = LONG_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_long(long a, long b, long *result) { const guf_math_ckd_result check = guf_ckd_mul_long(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = LONG_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = LONG_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_long(long a, long b, long *result) { const guf_math_ckd_result check = guf_ckd_add_long(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = (long)( (a + (long)LONG_MIN) + (b + (long)LONG_MIN) ); break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = (long)( (a - (long)LONG_MIN) + (b - (long)LONG_MIN) ); break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_long(long a, long b, long *result) { const guf_math_ckd_result check = guf_ckd_sub_long(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: GUF_ASSERT(b < 0); *result = (long)( (a + (long)LONG_MIN) - (b - (long)LONG_MIN) ); // TODO: not sure break; case GUF_MATH_CKD_OVERFLOW_NEG: GUF_ASSERT(b > 0); *result = (long)( (a - (long)LONG_MIN) - (b + (long)LONG_MIN) ); // TODO: not sure break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_long(long a, long b, long *result) { const guf_math_ckd_result check = guf_ckd_mul_long(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: case GUF_MATH_CKD_OVERFLOW_NEG: { unsigned long res = 1u * (unsigned long)a * (unsigned long)b; if (res > LONG_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. const unsigned long mod = (unsigned long)LONG_MAX + 1u; GUF_ASSERT(mod > 0); res = 1u * res % mod; *result = (long)LONG_MIN + (long)res; } else { *result = (long)res; } break; } default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_long_long(long long a, long long b, long long *result) { const guf_math_ckd_result check = guf_ckd_add_long_long(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = LLONG_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = LLONG_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_long_long(long long a, long long b, long long *result) { const guf_math_ckd_result check = guf_ckd_sub_long_long(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = LLONG_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = LLONG_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_long_long(long long a, long long b, long long *result) { const guf_math_ckd_result check = guf_ckd_mul_long_long(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = LLONG_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = LLONG_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_long_long(long long a, long long b, long long *result) { const guf_math_ckd_result check = guf_ckd_add_long_long(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = (long long)( (a + (long long)LLONG_MIN) + (b + (long long)LLONG_MIN) ); break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = (long long)( (a - (long long)LLONG_MIN) + (b - (long long)LLONG_MIN) ); break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_long_long(long long a, long long b, long long *result) { const guf_math_ckd_result check = guf_ckd_sub_long_long(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: GUF_ASSERT(b < 0); *result = (long long)( (a + (long long)LLONG_MIN) - (b - (long long)LLONG_MIN) ); // TODO: not sure break; case GUF_MATH_CKD_OVERFLOW_NEG: GUF_ASSERT(b > 0); *result = (long long)( (a - (long long)LLONG_MIN) - (b + (long long)LLONG_MIN) ); // TODO: not sure break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_long_long(long long a, long long b, long long *result) { const guf_math_ckd_result check = guf_ckd_mul_long_long(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: case GUF_MATH_CKD_OVERFLOW_NEG: { unsigned long long res = 1u * (unsigned long long)a * (unsigned long long)b; if (res > LLONG_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. const unsigned long long mod = (unsigned long long)LLONG_MAX + 1u; GUF_ASSERT(mod > 0); res = 1u * res % mod; *result = (long long)LLONG_MIN + (long long)res; } else { *result = (long long)res; } break; } default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result) { const guf_math_ckd_result check = guf_ckd_add_ptrdiff_t(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = PTRDIFF_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = PTRDIFF_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result) { const guf_math_ckd_result check = guf_ckd_sub_ptrdiff_t(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = PTRDIFF_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = PTRDIFF_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result) { const guf_math_ckd_result check = guf_ckd_mul_ptrdiff_t(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = PTRDIFF_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = PTRDIFF_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result) { const guf_math_ckd_result check = guf_ckd_add_ptrdiff_t(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = (ptrdiff_t)( (a + (ptrdiff_t)PTRDIFF_MIN) + (b + (ptrdiff_t)PTRDIFF_MIN) ); break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = (ptrdiff_t)( (a - (ptrdiff_t)PTRDIFF_MIN) + (b - (ptrdiff_t)PTRDIFF_MIN) ); break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result) { const guf_math_ckd_result check = guf_ckd_sub_ptrdiff_t(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: GUF_ASSERT(b < 0); *result = (ptrdiff_t)( (a + (ptrdiff_t)PTRDIFF_MIN) - (b - (ptrdiff_t)PTRDIFF_MIN) ); // TODO: not sure break; case GUF_MATH_CKD_OVERFLOW_NEG: GUF_ASSERT(b > 0); *result = (ptrdiff_t)( (a - (ptrdiff_t)PTRDIFF_MIN) - (b + (ptrdiff_t)PTRDIFF_MIN) ); // TODO: not sure break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result) { const guf_math_ckd_result check = guf_ckd_mul_ptrdiff_t(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: case GUF_MATH_CKD_OVERFLOW_NEG: { size_t res = 1u * (size_t)a * (size_t)b; if (res > PTRDIFF_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. const size_t mod = (size_t)PTRDIFF_MAX + 1u; GUF_ASSERT(mod > 0); res = 1u * res % mod; *result = (ptrdiff_t)PTRDIFF_MIN + (ptrdiff_t)res; } else { *result = (ptrdiff_t)res; } break; } default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_i8(int_least8_t a, int_least8_t b, int_least8_t *result) { const guf_math_ckd_result check = guf_ckd_add_least_i8(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_INT8_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = GUF_INT8_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_i8(int_least8_t a, int_least8_t b, int_least8_t *result) { const guf_math_ckd_result check = guf_ckd_sub_least_i8(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_INT8_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = GUF_INT8_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_i8(int_least8_t a, int_least8_t b, int_least8_t *result) { const guf_math_ckd_result check = guf_ckd_mul_least_i8(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_INT8_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = GUF_INT8_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_i8(int_least8_t a, int_least8_t b, int_least8_t *result) { const guf_math_ckd_result check = guf_ckd_add_least_i8(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = (int_least8_t)( (a + (int_least8_t)GUF_INT8_MIN) + (b + (int_least8_t)GUF_INT8_MIN) ); break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = (int_least8_t)( (a - (int_least8_t)GUF_INT8_MIN) + (b - (int_least8_t)GUF_INT8_MIN) ); break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_i8(int_least8_t a, int_least8_t b, int_least8_t *result) { const guf_math_ckd_result check = guf_ckd_sub_least_i8(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: GUF_ASSERT(b < 0); *result = (int_least8_t)( (a + (int_least8_t)GUF_INT8_MIN) - (b - (int_least8_t)GUF_INT8_MIN) ); // TODO: not sure break; case GUF_MATH_CKD_OVERFLOW_NEG: GUF_ASSERT(b > 0); *result = (int_least8_t)( (a - (int_least8_t)GUF_INT8_MIN) - (b + (int_least8_t)GUF_INT8_MIN) ); // TODO: not sure break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_i8(int_least8_t a, int_least8_t b, int_least8_t *result) { const guf_math_ckd_result check = guf_ckd_mul_least_i8(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: case GUF_MATH_CKD_OVERFLOW_NEG: { uint_least8_t res = 1u * (uint_least8_t)a * (uint_least8_t)b; if (res > GUF_INT8_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. const uint_least8_t mod = (uint_least8_t)GUF_INT8_MAX + 1u; GUF_ASSERT(mod > 0); res = 1u * res % mod; *result = (int_least8_t)GUF_INT8_MIN + (int_least8_t)res; } else { *result = (int_least8_t)res; } break; } default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_i16(int_least16_t a, int_least16_t b, int_least16_t *result) { const guf_math_ckd_result check = guf_ckd_add_least_i16(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_INT16_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = GUF_INT16_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_i16(int_least16_t a, int_least16_t b, int_least16_t *result) { const guf_math_ckd_result check = guf_ckd_sub_least_i16(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_INT16_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = GUF_INT16_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_i16(int_least16_t a, int_least16_t b, int_least16_t *result) { const guf_math_ckd_result check = guf_ckd_mul_least_i16(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_INT16_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = GUF_INT16_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_i16(int_least16_t a, int_least16_t b, int_least16_t *result) { const guf_math_ckd_result check = guf_ckd_add_least_i16(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = (int_least16_t)( (a + (int_least16_t)GUF_INT16_MIN) + (b + (int_least16_t)GUF_INT16_MIN) ); break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = (int_least16_t)( (a - (int_least16_t)GUF_INT16_MIN) + (b - (int_least16_t)GUF_INT16_MIN) ); break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_i16(int_least16_t a, int_least16_t b, int_least16_t *result) { const guf_math_ckd_result check = guf_ckd_sub_least_i16(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: GUF_ASSERT(b < 0); *result = (int_least16_t)( (a + (int_least16_t)GUF_INT16_MIN) - (b - (int_least16_t)GUF_INT16_MIN) ); // TODO: not sure break; case GUF_MATH_CKD_OVERFLOW_NEG: GUF_ASSERT(b > 0); *result = (int_least16_t)( (a - (int_least16_t)GUF_INT16_MIN) - (b + (int_least16_t)GUF_INT16_MIN) ); // TODO: not sure break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_i16(int_least16_t a, int_least16_t b, int_least16_t *result) { const guf_math_ckd_result check = guf_ckd_mul_least_i16(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: case GUF_MATH_CKD_OVERFLOW_NEG: { uint_least16_t res = 1u * (uint_least16_t)a * (uint_least16_t)b; if (res > GUF_INT16_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. const uint_least16_t mod = (uint_least16_t)GUF_INT16_MAX + 1u; GUF_ASSERT(mod > 0); res = 1u * res % mod; *result = (int_least16_t)GUF_INT16_MIN + (int_least16_t)res; } else { *result = (int_least16_t)res; } break; } default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_i32(int_least32_t a, int_least32_t b, int_least32_t *result) { const guf_math_ckd_result check = guf_ckd_add_least_i32(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_INT32_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = GUF_INT32_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_i32(int_least32_t a, int_least32_t b, int_least32_t *result) { const guf_math_ckd_result check = guf_ckd_sub_least_i32(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_INT32_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = GUF_INT32_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_i32(int_least32_t a, int_least32_t b, int_least32_t *result) { const guf_math_ckd_result check = guf_ckd_mul_least_i32(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_INT32_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = GUF_INT32_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_i32(int_least32_t a, int_least32_t b, int_least32_t *result) { const guf_math_ckd_result check = guf_ckd_add_least_i32(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = (int_least32_t)( (a + (int_least32_t)GUF_INT32_MIN) + (b + (int_least32_t)GUF_INT32_MIN) ); break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = (int_least32_t)( (a - (int_least32_t)GUF_INT32_MIN) + (b - (int_least32_t)GUF_INT32_MIN) ); break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_i32(int_least32_t a, int_least32_t b, int_least32_t *result) { const guf_math_ckd_result check = guf_ckd_sub_least_i32(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: GUF_ASSERT(b < 0); *result = (int_least32_t)( (a + (int_least32_t)GUF_INT32_MIN) - (b - (int_least32_t)GUF_INT32_MIN) ); // TODO: not sure break; case GUF_MATH_CKD_OVERFLOW_NEG: GUF_ASSERT(b > 0); *result = (int_least32_t)( (a - (int_least32_t)GUF_INT32_MIN) - (b + (int_least32_t)GUF_INT32_MIN) ); // TODO: not sure break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_i32(int_least32_t a, int_least32_t b, int_least32_t *result) { const guf_math_ckd_result check = guf_ckd_mul_least_i32(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: case GUF_MATH_CKD_OVERFLOW_NEG: { uint_least32_t res = 1u * (uint_least32_t)a * (uint_least32_t)b; if (res > GUF_INT32_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. const uint_least32_t mod = (uint_least32_t)GUF_INT32_MAX + 1u; GUF_ASSERT(mod > 0); res = 1u * res % mod; *result = (int_least32_t)GUF_INT32_MIN + (int_least32_t)res; } else { *result = (int_least32_t)res; } break; } default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_i64(int_least64_t a, int_least64_t b, int_least64_t *result) { const guf_math_ckd_result check = guf_ckd_add_least_i64(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_INT64_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = GUF_INT64_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_i64(int_least64_t a, int_least64_t b, int_least64_t *result) { const guf_math_ckd_result check = guf_ckd_sub_least_i64(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_INT64_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = GUF_INT64_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_i64(int_least64_t a, int_least64_t b, int_least64_t *result) { const guf_math_ckd_result check = guf_ckd_mul_least_i64(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_INT64_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = GUF_INT64_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_i64(int_least64_t a, int_least64_t b, int_least64_t *result) { const guf_math_ckd_result check = guf_ckd_add_least_i64(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = (int_least64_t)( (a + (int_least64_t)GUF_INT64_MIN) + (b + (int_least64_t)GUF_INT64_MIN) ); break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = (int_least64_t)( (a - (int_least64_t)GUF_INT64_MIN) + (b - (int_least64_t)GUF_INT64_MIN) ); break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_i64(int_least64_t a, int_least64_t b, int_least64_t *result) { const guf_math_ckd_result check = guf_ckd_sub_least_i64(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: GUF_ASSERT(b < 0); *result = (int_least64_t)( (a + (int_least64_t)GUF_INT64_MIN) - (b - (int_least64_t)GUF_INT64_MIN) ); // TODO: not sure break; case GUF_MATH_CKD_OVERFLOW_NEG: GUF_ASSERT(b > 0); *result = (int_least64_t)( (a - (int_least64_t)GUF_INT64_MIN) - (b + (int_least64_t)GUF_INT64_MIN) ); // TODO: not sure break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_i64(int_least64_t a, int_least64_t b, int_least64_t *result) { const guf_math_ckd_result check = guf_ckd_mul_least_i64(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: case GUF_MATH_CKD_OVERFLOW_NEG: { uint_least64_t res = 1u * (uint_least64_t)a * (uint_least64_t)b; if (res > GUF_INT64_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. const uint_least64_t mod = (uint_least64_t)GUF_INT64_MAX + 1u; GUF_ASSERT(mod > 0); res = 1u * res % mod; *result = (int_least64_t)GUF_INT64_MIN + (int_least64_t)res; } else { *result = (int_least64_t)res; } break; } default: GUF_ASSERT(false); } } return check; } #ifdef INT8_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i8(int8_t a, int8_t b, int8_t *result) { const guf_math_ckd_result check = guf_ckd_add_i8(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT8_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT8_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i8(int8_t a, int8_t b, int8_t *result) { const guf_math_ckd_result check = guf_ckd_sub_i8(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT8_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT8_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i8(int8_t a, int8_t b, int8_t *result) { const guf_math_ckd_result check = guf_ckd_mul_i8(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT8_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT8_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i8(int8_t a, int8_t b, int8_t *result) { const guf_math_ckd_result check = guf_ckd_add_i8(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = (int8_t)( (a + (int8_t)INT8_MIN) + (b + (int8_t)INT8_MIN) ); break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = (int8_t)( (a - (int8_t)INT8_MIN) + (b - (int8_t)INT8_MIN) ); break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i8(int8_t a, int8_t b, int8_t *result) { const guf_math_ckd_result check = guf_ckd_sub_i8(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: GUF_ASSERT(b < 0); *result = (int8_t)( (a + (int8_t)INT8_MIN) - (b - (int8_t)INT8_MIN) ); // TODO: not sure break; case GUF_MATH_CKD_OVERFLOW_NEG: GUF_ASSERT(b > 0); *result = (int8_t)( (a - (int8_t)INT8_MIN) - (b + (int8_t)INT8_MIN) ); // TODO: not sure break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i8(int8_t a, int8_t b, int8_t *result) { const guf_math_ckd_result check = guf_ckd_mul_i8(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: case GUF_MATH_CKD_OVERFLOW_NEG: { uint8_t res = 1u * (uint8_t)a * (uint8_t)b; if (res > INT8_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. const uint8_t mod = (uint8_t)INT8_MAX + 1u; GUF_ASSERT(mod > 0); res = 1u * res % mod; *result = (int8_t)INT8_MIN + (int8_t)res; } else { *result = (int8_t)res; } break; } default: GUF_ASSERT(false); } } return check; } #endif #ifdef INT16_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i16(int16_t a, int16_t b, int16_t *result) { const guf_math_ckd_result check = guf_ckd_add_i16(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT16_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT16_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i16(int16_t a, int16_t b, int16_t *result) { const guf_math_ckd_result check = guf_ckd_sub_i16(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT16_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT16_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i16(int16_t a, int16_t b, int16_t *result) { const guf_math_ckd_result check = guf_ckd_mul_i16(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT16_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT16_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i16(int16_t a, int16_t b, int16_t *result) { const guf_math_ckd_result check = guf_ckd_add_i16(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = (int16_t)( (a + (int16_t)INT16_MIN) + (b + (int16_t)INT16_MIN) ); break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = (int16_t)( (a - (int16_t)INT16_MIN) + (b - (int16_t)INT16_MIN) ); break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i16(int16_t a, int16_t b, int16_t *result) { const guf_math_ckd_result check = guf_ckd_sub_i16(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: GUF_ASSERT(b < 0); *result = (int16_t)( (a + (int16_t)INT16_MIN) - (b - (int16_t)INT16_MIN) ); // TODO: not sure break; case GUF_MATH_CKD_OVERFLOW_NEG: GUF_ASSERT(b > 0); *result = (int16_t)( (a - (int16_t)INT16_MIN) - (b + (int16_t)INT16_MIN) ); // TODO: not sure break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i16(int16_t a, int16_t b, int16_t *result) { const guf_math_ckd_result check = guf_ckd_mul_i16(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: case GUF_MATH_CKD_OVERFLOW_NEG: { uint16_t res = 1u * (uint16_t)a * (uint16_t)b; if (res > INT16_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. const uint16_t mod = (uint16_t)INT16_MAX + 1u; GUF_ASSERT(mod > 0); res = 1u * res % mod; *result = (int16_t)INT16_MIN + (int16_t)res; } else { *result = (int16_t)res; } break; } default: GUF_ASSERT(false); } } return check; } #endif #ifdef INT32_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i32(int32_t a, int32_t b, int32_t *result) { const guf_math_ckd_result check = guf_ckd_add_i32(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT32_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT32_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i32(int32_t a, int32_t b, int32_t *result) { const guf_math_ckd_result check = guf_ckd_sub_i32(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT32_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT32_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i32(int32_t a, int32_t b, int32_t *result) { const guf_math_ckd_result check = guf_ckd_mul_i32(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT32_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT32_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i32(int32_t a, int32_t b, int32_t *result) { const guf_math_ckd_result check = guf_ckd_add_i32(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = (int32_t)( (a + (int32_t)INT32_MIN) + (b + (int32_t)INT32_MIN) ); break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = (int32_t)( (a - (int32_t)INT32_MIN) + (b - (int32_t)INT32_MIN) ); break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i32(int32_t a, int32_t b, int32_t *result) { const guf_math_ckd_result check = guf_ckd_sub_i32(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: GUF_ASSERT(b < 0); *result = (int32_t)( (a + (int32_t)INT32_MIN) - (b - (int32_t)INT32_MIN) ); // TODO: not sure break; case GUF_MATH_CKD_OVERFLOW_NEG: GUF_ASSERT(b > 0); *result = (int32_t)( (a - (int32_t)INT32_MIN) - (b + (int32_t)INT32_MIN) ); // TODO: not sure break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i32(int32_t a, int32_t b, int32_t *result) { const guf_math_ckd_result check = guf_ckd_mul_i32(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: case GUF_MATH_CKD_OVERFLOW_NEG: { uint32_t res = 1u * (uint32_t)a * (uint32_t)b; if (res > INT32_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. const uint32_t mod = (uint32_t)INT32_MAX + 1u; GUF_ASSERT(mod > 0); res = 1u * res % mod; *result = (int32_t)INT32_MIN + (int32_t)res; } else { *result = (int32_t)res; } break; } default: GUF_ASSERT(false); } } return check; } #endif #ifdef INT64_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i64(int64_t a, int64_t b, int64_t *result) { const guf_math_ckd_result check = guf_ckd_add_i64(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT64_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT64_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i64(int64_t a, int64_t b, int64_t *result) { const guf_math_ckd_result check = guf_ckd_sub_i64(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT64_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT64_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i64(int64_t a, int64_t b, int64_t *result) { const guf_math_ckd_result check = guf_ckd_mul_i64(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = INT64_MAX; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = INT64_MIN; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i64(int64_t a, int64_t b, int64_t *result) { const guf_math_ckd_result check = guf_ckd_add_i64(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = (int64_t)( (a + (int64_t)INT64_MIN) + (b + (int64_t)INT64_MIN) ); break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = (int64_t)( (a - (int64_t)INT64_MIN) + (b - (int64_t)INT64_MIN) ); break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i64(int64_t a, int64_t b, int64_t *result) { const guf_math_ckd_result check = guf_ckd_sub_i64(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_POS: GUF_ASSERT(b < 0); *result = (int64_t)( (a + (int64_t)INT64_MIN) - (b - (int64_t)INT64_MIN) ); // TODO: not sure break; case GUF_MATH_CKD_OVERFLOW_NEG: GUF_ASSERT(b > 0); *result = (int64_t)( (a - (int64_t)INT64_MIN) - (b + (int64_t)INT64_MIN) ); // TODO: not sure break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i64(int64_t a, int64_t b, int64_t *result) { const guf_math_ckd_result check = guf_ckd_mul_i64(a, b); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: case GUF_MATH_CKD_OVERFLOW_NEG: { uint64_t res = 1u * (uint64_t)a * (uint64_t)b; if (res > INT64_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. const uint64_t mod = (uint64_t)INT64_MAX + 1u; GUF_ASSERT(mod > 0); res = 1u * res % mod; *result = (int64_t)INT64_MIN + (int64_t)res; } else { *result = (int64_t)res; } break; } default: GUF_ASSERT(false); } } return check; } #endif // Unsigned saturating/wrapping arithmetic (generated with libguf/tools/ckdint-gen.py) GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_uchar(unsigned char a, unsigned char b, unsigned char *result) { const guf_math_ckd_result check = guf_ckd_add_uchar(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = UCHAR_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_uchar(unsigned char a, unsigned char b, unsigned char *result) { const guf_math_ckd_result check = guf_ckd_sub_uchar(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_uchar(unsigned char a, unsigned char b, unsigned char *result) { const guf_math_ckd_result check = guf_ckd_mul_uchar(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = UCHAR_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_uchar(unsigned char a, unsigned char b, unsigned char *result) { const guf_math_ckd_result check = guf_ckd_add_uchar(a, b); if (result) { *result = 1u * a + b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_uchar(unsigned char a, unsigned char b, unsigned char *result) { const guf_math_ckd_result check = guf_ckd_sub_uchar(a, b); if (result) { *result = 1u * a - b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_uchar(unsigned char a, unsigned char b, unsigned char *result) { const guf_math_ckd_result check = guf_ckd_mul_uchar(a, b); if (result) { *result = 1u * a * b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_unsigned(unsigned a, unsigned b, unsigned *result) { const guf_math_ckd_result check = guf_ckd_add_unsigned(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = UINT_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_unsigned(unsigned a, unsigned b, unsigned *result) { const guf_math_ckd_result check = guf_ckd_sub_unsigned(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_unsigned(unsigned a, unsigned b, unsigned *result) { const guf_math_ckd_result check = guf_ckd_mul_unsigned(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = UINT_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_unsigned(unsigned a, unsigned b, unsigned *result) { const guf_math_ckd_result check = guf_ckd_add_unsigned(a, b); if (result) { *result = 1u * a + b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_unsigned(unsigned a, unsigned b, unsigned *result) { const guf_math_ckd_result check = guf_ckd_sub_unsigned(a, b); if (result) { *result = 1u * a - b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_unsigned(unsigned a, unsigned b, unsigned *result) { const guf_math_ckd_result check = guf_ckd_mul_unsigned(a, b); if (result) { *result = 1u * a * b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_ulong(unsigned long a, unsigned long b, unsigned long *result) { const guf_math_ckd_result check = guf_ckd_add_ulong(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = ULONG_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_ulong(unsigned long a, unsigned long b, unsigned long *result) { const guf_math_ckd_result check = guf_ckd_sub_ulong(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_ulong(unsigned long a, unsigned long b, unsigned long *result) { const guf_math_ckd_result check = guf_ckd_mul_ulong(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = ULONG_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_ulong(unsigned long a, unsigned long b, unsigned long *result) { const guf_math_ckd_result check = guf_ckd_add_ulong(a, b); if (result) { *result = 1u * a + b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_ulong(unsigned long a, unsigned long b, unsigned long *result) { const guf_math_ckd_result check = guf_ckd_sub_ulong(a, b); if (result) { *result = 1u * a - b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ulong(unsigned long a, unsigned long b, unsigned long *result) { const guf_math_ckd_result check = guf_ckd_mul_ulong(a, b); if (result) { *result = 1u * a * b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result) { const guf_math_ckd_result check = guf_ckd_add_ulong_long(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = ULLONG_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result) { const guf_math_ckd_result check = guf_ckd_sub_ulong_long(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result) { const guf_math_ckd_result check = guf_ckd_mul_ulong_long(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = ULLONG_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result) { const guf_math_ckd_result check = guf_ckd_add_ulong_long(a, b); if (result) { *result = 1u * a + b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result) { const guf_math_ckd_result check = guf_ckd_sub_ulong_long(a, b); if (result) { *result = 1u * a - b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result) { const guf_math_ckd_result check = guf_ckd_mul_ulong_long(a, b); if (result) { *result = 1u * a * b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_size_t(size_t a, size_t b, size_t *result) { const guf_math_ckd_result check = guf_ckd_add_size_t(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = SIZE_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_size_t(size_t a, size_t b, size_t *result) { const guf_math_ckd_result check = guf_ckd_sub_size_t(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_size_t(size_t a, size_t b, size_t *result) { const guf_math_ckd_result check = guf_ckd_mul_size_t(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = SIZE_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_size_t(size_t a, size_t b, size_t *result) { const guf_math_ckd_result check = guf_ckd_add_size_t(a, b); if (result) { *result = 1u * a + b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_size_t(size_t a, size_t b, size_t *result) { const guf_math_ckd_result check = guf_ckd_sub_size_t(a, b); if (result) { *result = 1u * a - b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_size_t(size_t a, size_t b, size_t *result) { const guf_math_ckd_result check = guf_ckd_mul_size_t(a, b); if (result) { *result = 1u * a * b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_u8(uint_least8_t a, uint_least8_t b, uint_least8_t *result) { const guf_math_ckd_result check = guf_ckd_add_least_u8(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_UINT8_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_u8(uint_least8_t a, uint_least8_t b, uint_least8_t *result) { const guf_math_ckd_result check = guf_ckd_sub_least_u8(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_u8(uint_least8_t a, uint_least8_t b, uint_least8_t *result) { const guf_math_ckd_result check = guf_ckd_mul_least_u8(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_UINT8_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_u8(uint_least8_t a, uint_least8_t b, uint_least8_t *result) { a = GUF_UWRAP_8(a); b = GUF_UWRAP_8(b); const guf_math_ckd_result check = guf_ckd_add_least_u8(a, b); if (result) { *result = GUF_UWRAP_8( 1u * a + b ); } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_u8(uint_least8_t a, uint_least8_t b, uint_least8_t *result) { a = GUF_UWRAP_8(a); b = GUF_UWRAP_8(b); const guf_math_ckd_result check = guf_ckd_sub_least_u8(a, b); if (result) { *result = GUF_UWRAP_8( 1u * a - b ); } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_u8(uint_least8_t a, uint_least8_t b, uint_least8_t *result) { a = GUF_UWRAP_8(a); b = GUF_UWRAP_8(b); const guf_math_ckd_result check = guf_ckd_mul_least_u8(a, b); if (result) { *result = GUF_UWRAP_8( 1u * a * b ); } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_u16(uint_least16_t a, uint_least16_t b, uint_least16_t *result) { const guf_math_ckd_result check = guf_ckd_add_least_u16(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_UINT16_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_u16(uint_least16_t a, uint_least16_t b, uint_least16_t *result) { const guf_math_ckd_result check = guf_ckd_sub_least_u16(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_u16(uint_least16_t a, uint_least16_t b, uint_least16_t *result) { const guf_math_ckd_result check = guf_ckd_mul_least_u16(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_UINT16_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_u16(uint_least16_t a, uint_least16_t b, uint_least16_t *result) { a = GUF_UWRAP_16(a); b = GUF_UWRAP_16(b); const guf_math_ckd_result check = guf_ckd_add_least_u16(a, b); if (result) { *result = GUF_UWRAP_16( 1u * a + b ); } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_u16(uint_least16_t a, uint_least16_t b, uint_least16_t *result) { a = GUF_UWRAP_16(a); b = GUF_UWRAP_16(b); const guf_math_ckd_result check = guf_ckd_sub_least_u16(a, b); if (result) { *result = GUF_UWRAP_16( 1u * a - b ); } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_u16(uint_least16_t a, uint_least16_t b, uint_least16_t *result) { a = GUF_UWRAP_16(a); b = GUF_UWRAP_16(b); const guf_math_ckd_result check = guf_ckd_mul_least_u16(a, b); if (result) { *result = GUF_UWRAP_16( 1u * a * b ); } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_u32(uint_least32_t a, uint_least32_t b, uint_least32_t *result) { const guf_math_ckd_result check = guf_ckd_add_least_u32(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_UINT32_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_u32(uint_least32_t a, uint_least32_t b, uint_least32_t *result) { const guf_math_ckd_result check = guf_ckd_sub_least_u32(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_u32(uint_least32_t a, uint_least32_t b, uint_least32_t *result) { const guf_math_ckd_result check = guf_ckd_mul_least_u32(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_UINT32_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_u32(uint_least32_t a, uint_least32_t b, uint_least32_t *result) { a = GUF_UWRAP_32(a); b = GUF_UWRAP_32(b); const guf_math_ckd_result check = guf_ckd_add_least_u32(a, b); if (result) { *result = GUF_UWRAP_32( 1u * a + b ); } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_u32(uint_least32_t a, uint_least32_t b, uint_least32_t *result) { a = GUF_UWRAP_32(a); b = GUF_UWRAP_32(b); const guf_math_ckd_result check = guf_ckd_sub_least_u32(a, b); if (result) { *result = GUF_UWRAP_32( 1u * a - b ); } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_u32(uint_least32_t a, uint_least32_t b, uint_least32_t *result) { a = GUF_UWRAP_32(a); b = GUF_UWRAP_32(b); const guf_math_ckd_result check = guf_ckd_mul_least_u32(a, b); if (result) { *result = GUF_UWRAP_32( 1u * a * b ); } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_least_u64(uint_least64_t a, uint_least64_t b, uint_least64_t *result) { const guf_math_ckd_result check = guf_ckd_add_least_u64(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_UINT64_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_least_u64(uint_least64_t a, uint_least64_t b, uint_least64_t *result) { const guf_math_ckd_result check = guf_ckd_sub_least_u64(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_least_u64(uint_least64_t a, uint_least64_t b, uint_least64_t *result) { const guf_math_ckd_result check = guf_ckd_mul_least_u64(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = GUF_UINT64_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_least_u64(uint_least64_t a, uint_least64_t b, uint_least64_t *result) { a = GUF_UWRAP_64(a); b = GUF_UWRAP_64(b); const guf_math_ckd_result check = guf_ckd_add_least_u64(a, b); if (result) { *result = GUF_UWRAP_64( 1u * a + b ); } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_least_u64(uint_least64_t a, uint_least64_t b, uint_least64_t *result) { a = GUF_UWRAP_64(a); b = GUF_UWRAP_64(b); const guf_math_ckd_result check = guf_ckd_sub_least_u64(a, b); if (result) { *result = GUF_UWRAP_64( 1u * a - b ); } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_least_u64(uint_least64_t a, uint_least64_t b, uint_least64_t *result) { a = GUF_UWRAP_64(a); b = GUF_UWRAP_64(b); const guf_math_ckd_result check = guf_ckd_mul_least_u64(a, b); if (result) { *result = GUF_UWRAP_64( 1u * a * b ); } return check; } #ifdef UINT8_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u8(uint8_t a, uint8_t b, uint8_t *result) { const guf_math_ckd_result check = guf_ckd_add_u8(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = UINT8_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u8(uint8_t a, uint8_t b, uint8_t *result) { const guf_math_ckd_result check = guf_ckd_sub_u8(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u8(uint8_t a, uint8_t b, uint8_t *result) { const guf_math_ckd_result check = guf_ckd_mul_u8(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = UINT8_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u8(uint8_t a, uint8_t b, uint8_t *result) { const guf_math_ckd_result check = guf_ckd_add_u8(a, b); if (result) { *result = 1u * a + b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u8(uint8_t a, uint8_t b, uint8_t *result) { const guf_math_ckd_result check = guf_ckd_sub_u8(a, b); if (result) { *result = 1u * a - b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u8(uint8_t a, uint8_t b, uint8_t *result) { const guf_math_ckd_result check = guf_ckd_mul_u8(a, b); if (result) { *result = 1u * a * b; } return check; } #endif #ifdef UINT16_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u16(uint16_t a, uint16_t b, uint16_t *result) { const guf_math_ckd_result check = guf_ckd_add_u16(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = UINT16_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u16(uint16_t a, uint16_t b, uint16_t *result) { const guf_math_ckd_result check = guf_ckd_sub_u16(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u16(uint16_t a, uint16_t b, uint16_t *result) { const guf_math_ckd_result check = guf_ckd_mul_u16(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = UINT16_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u16(uint16_t a, uint16_t b, uint16_t *result) { const guf_math_ckd_result check = guf_ckd_add_u16(a, b); if (result) { *result = 1u * a + b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u16(uint16_t a, uint16_t b, uint16_t *result) { const guf_math_ckd_result check = guf_ckd_sub_u16(a, b); if (result) { *result = 1u * a - b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u16(uint16_t a, uint16_t b, uint16_t *result) { const guf_math_ckd_result check = guf_ckd_mul_u16(a, b); if (result) { *result = 1u * a * b; } return check; } #endif #ifdef UINT32_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u32(uint32_t a, uint32_t b, uint32_t *result) { const guf_math_ckd_result check = guf_ckd_add_u32(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = UINT32_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u32(uint32_t a, uint32_t b, uint32_t *result) { const guf_math_ckd_result check = guf_ckd_sub_u32(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u32(uint32_t a, uint32_t b, uint32_t *result) { const guf_math_ckd_result check = guf_ckd_mul_u32(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = UINT32_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u32(uint32_t a, uint32_t b, uint32_t *result) { const guf_math_ckd_result check = guf_ckd_add_u32(a, b); if (result) { *result = 1u * a + b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u32(uint32_t a, uint32_t b, uint32_t *result) { const guf_math_ckd_result check = guf_ckd_sub_u32(a, b); if (result) { *result = 1u * a - b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u32(uint32_t a, uint32_t b, uint32_t *result) { const guf_math_ckd_result check = guf_ckd_mul_u32(a, b); if (result) { *result = 1u * a * b; } return check; } #endif #ifdef UINT64_MAX GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u64(uint64_t a, uint64_t b, uint64_t *result) { const guf_math_ckd_result check = guf_ckd_add_u64(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a + b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = UINT64_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u64(uint64_t a, uint64_t b, uint64_t *result) { const guf_math_ckd_result check = guf_ckd_sub_u64(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a - b; break; case GUF_MATH_CKD_OVERFLOW_NEG: *result = 0; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u64(uint64_t a, uint64_t b, uint64_t *result) { const guf_math_ckd_result check = guf_ckd_mul_u64(a, b); GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); if (result) { switch (check) { case GUF_MATH_CKD_SUCCESS: *result = a * b; break; case GUF_MATH_CKD_OVERFLOW_POS: *result = UINT64_MAX; break; default: GUF_ASSERT(false); } } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u64(uint64_t a, uint64_t b, uint64_t *result) { const guf_math_ckd_result check = guf_ckd_add_u64(a, b); if (result) { *result = 1u * a + b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u64(uint64_t a, uint64_t b, uint64_t *result) { const guf_math_ckd_result check = guf_ckd_sub_u64(a, b); if (result) { *result = 1u * a - b; } return check; } GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u64(uint64_t a, uint64_t b, uint64_t *result) { const guf_math_ckd_result check = guf_ckd_mul_u64(a, b); if (result) { *result = 1u * a * b; } return check; } #endif #endif /* End impl */ #endif /* End header-guard */ #undef GUF_MATH_CKDINT_KWRDS #undef GUF_MATH_CKDINT_IMPL #undef GUF_MATH_CKDINT_IMPL_STATIC