libguf/src/guf_math_ckdint.h
2025-12-23 14:11:05 +01:00

2065 lines
74 KiB
C

/*
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 (truthy)
- if a + b underflows TYPE: return GUF_MATH_CKD_UNDERFLOW (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 (truthy)
- if a - b underflows TYPE: return GUF_MATH_CKD_UNDERFLOW (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 (truthy)
- if a * b underflows TYPE: return GUF_MATH_CKD_UNDERFLOW (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 (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_UNDERFLOW (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 (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_UNDERFLOW (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 (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_UNDERFLOW (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 (if result is not NULL, set result using two's complement wrap-around overflow semantics).
- if a + b underflows TYPE: return GUF_MATH_CKD_UNDERFLOW (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 (if result is not NULL, set result using two's complement wrap-around overflow semantics).
- if a - b underflows TYPE: return GUF_MATH_CKD_UNDERFLOW (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 (if result is not NULL, set result using two's complement wrap-around overflow semantics).
- if a * b underflows TYPE: return GUF_MATH_CKD_UNDERFLOW (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)
*/
#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, GUF_MATH_CKD_UNDERFLOW} 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_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);
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);
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);
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);
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);
// 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_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);
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);
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);
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);
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);
// 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_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);
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);
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);
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);
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);
// 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_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);
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);
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);
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);
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);
#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;
} else if (b < 0 && a < INT_MIN - b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (b > 0 && a < INT_MIN + b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (a < INT_MIN / b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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 : GUF_MATH_CKD_SUCCESS;
} else if (a < INT_MAX / b) {
return GUF_MATH_CKD_OVERFLOW;
} else if (a > INT_MIN / b) {
return GUF_MATH_CKD_UNDERFLOW;
} else {
return GUF_MATH_CKD_SUCCESS;
}
} else {
return GUF_MATH_CKD_SUCCESS;
}
}
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;
} else if (b < 0 && a < INT8_MIN - b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (b > 0 && a < INT8_MIN + b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (a < INT8_MIN / b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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 : GUF_MATH_CKD_SUCCESS;
} else if (a < INT8_MAX / b) {
return GUF_MATH_CKD_OVERFLOW;
} else if (a > INT8_MIN / b) {
return GUF_MATH_CKD_UNDERFLOW;
} else {
return GUF_MATH_CKD_SUCCESS;
}
} else {
return GUF_MATH_CKD_SUCCESS;
}
}
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;
} else if (b < 0 && a < INT16_MIN - b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (b > 0 && a < INT16_MIN + b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (a < INT16_MIN / b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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 : GUF_MATH_CKD_SUCCESS;
} else if (a < INT16_MAX / b) {
return GUF_MATH_CKD_OVERFLOW;
} else if (a > INT16_MIN / b) {
return GUF_MATH_CKD_UNDERFLOW;
} else {
return GUF_MATH_CKD_SUCCESS;
}
} else {
return GUF_MATH_CKD_SUCCESS;
}
}
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;
} else if (b < 0 && a < INT32_MIN - b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (b > 0 && a < INT32_MIN + b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (a < INT32_MIN / b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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 : GUF_MATH_CKD_SUCCESS;
} else if (a < INT32_MAX / b) {
return GUF_MATH_CKD_OVERFLOW;
} else if (a > INT32_MIN / b) {
return GUF_MATH_CKD_UNDERFLOW;
} else {
return GUF_MATH_CKD_SUCCESS;
}
} else {
return GUF_MATH_CKD_SUCCESS;
}
}
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;
} else if (b < 0 && a < INT64_MIN - b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (b > 0 && a < INT64_MIN + b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (a < INT64_MIN / b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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 : GUF_MATH_CKD_SUCCESS;
} else if (a < INT64_MAX / b) {
return GUF_MATH_CKD_OVERFLOW;
} else if (a > INT64_MIN / b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (b < 0 && a < PTRDIFF_MIN - b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (b > 0 && a < PTRDIFF_MIN + b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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;
} else if (a < PTRDIFF_MIN / b) {
return GUF_MATH_CKD_UNDERFLOW;
} 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 : GUF_MATH_CKD_SUCCESS;
} else if (a < PTRDIFF_MAX / b) {
return GUF_MATH_CKD_OVERFLOW;
} else if (a > PTRDIFF_MIN / b) {
return GUF_MATH_CKD_UNDERFLOW;
} else {
return GUF_MATH_CKD_SUCCESS;
}
} else {
return GUF_MATH_CKD_SUCCESS;
}
}
// 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;
} 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_UNDERFLOW;
} 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 = a * b;
return a != 0 && ((c / a) != b) ? GUF_MATH_CKD_OVERFLOW : 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;
} 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_UNDERFLOW;
} 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 = a * b;
return a != 0 && ((c / a) != b) ? GUF_MATH_CKD_OVERFLOW : GUF_MATH_CKD_SUCCESS;
}
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;
} 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_UNDERFLOW;
} 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 = a * b;
return a != 0 && ((c / a) != b) ? GUF_MATH_CKD_OVERFLOW : GUF_MATH_CKD_SUCCESS;
}
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;
} 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_UNDERFLOW;
} 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 = a * b;
return a != 0 && ((c / a) != b) ? GUF_MATH_CKD_OVERFLOW : GUF_MATH_CKD_SUCCESS;
}
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;
} 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_UNDERFLOW;
} 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 = a * b;
return a != 0 && ((c / a) != b) ? GUF_MATH_CKD_OVERFLOW : GUF_MATH_CKD_SUCCESS;
}
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;
} 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_UNDERFLOW;
} 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 = a * b;
return a != 0 && ((c / a) != b) ? GUF_MATH_CKD_OVERFLOW : 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;
} 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_UNDERFLOW;
} 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 = a * b;
return a != 0 && ((c / a) != b) ? GUF_MATH_CKD_OVERFLOW : GUF_MATH_CKD_SUCCESS;
}
// 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:
*result = INT_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = INT_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = INT_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = (a + INT_MIN) + (b + INT_MIN);
break;
case GUF_MATH_CKD_UNDERFLOW:
*result = (a - INT_MIN) + (b - 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:
GUF_ASSERT(b < 0);
*result = (a + INT_MIN) - (b - INT_MIN); // TODO: not sure
break;
case GUF_MATH_CKD_UNDERFLOW:
GUF_ASSERT(b > 0);
*result = (a - INT_MIN) - (b + 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:
case GUF_MATH_CKD_UNDERFLOW: {
unsigned res = (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 && mod > INT_MAX);
res = res % mod;
*result = 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_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:
*result = INT8_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = INT8_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = INT8_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = (a + INT8_MIN) + (b + INT8_MIN);
break;
case GUF_MATH_CKD_UNDERFLOW:
*result = (a - INT8_MIN) + (b - 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:
GUF_ASSERT(b < 0);
*result = (a + INT8_MIN) - (b - INT8_MIN); // TODO: not sure
break;
case GUF_MATH_CKD_UNDERFLOW:
GUF_ASSERT(b > 0);
*result = (a - INT8_MIN) - (b + 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:
case GUF_MATH_CKD_UNDERFLOW: {
uint8_t res = (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 && mod > INT8_MAX);
res = res % mod;
*result = INT8_MIN + (int8_t)res;
} else {
*result = (int8_t)res;
}
break;
}
default:
GUF_ASSERT(false);
}
}
return check;
}
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:
*result = INT16_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = INT16_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = INT16_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = (a + INT16_MIN) + (b + INT16_MIN);
break;
case GUF_MATH_CKD_UNDERFLOW:
*result = (a - INT16_MIN) + (b - 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:
GUF_ASSERT(b < 0);
*result = (a + INT16_MIN) - (b - INT16_MIN); // TODO: not sure
break;
case GUF_MATH_CKD_UNDERFLOW:
GUF_ASSERT(b > 0);
*result = (a - INT16_MIN) - (b + 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:
case GUF_MATH_CKD_UNDERFLOW: {
uint16_t res = (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 && mod > INT16_MAX);
res = res % mod;
*result = INT16_MIN + (int16_t)res;
} else {
*result = (int16_t)res;
}
break;
}
default:
GUF_ASSERT(false);
}
}
return check;
}
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:
*result = INT32_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = INT32_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = INT32_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = (a + INT32_MIN) + (b + INT32_MIN);
break;
case GUF_MATH_CKD_UNDERFLOW:
*result = (a - INT32_MIN) + (b - 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:
GUF_ASSERT(b < 0);
*result = (a + INT32_MIN) - (b - INT32_MIN); // TODO: not sure
break;
case GUF_MATH_CKD_UNDERFLOW:
GUF_ASSERT(b > 0);
*result = (a - INT32_MIN) - (b + 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:
case GUF_MATH_CKD_UNDERFLOW: {
uint32_t res = (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 && mod > INT32_MAX);
res = res % mod;
*result = INT32_MIN + (int32_t)res;
} else {
*result = (int32_t)res;
}
break;
}
default:
GUF_ASSERT(false);
}
}
return check;
}
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:
*result = INT64_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = INT64_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = INT64_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = (a + INT64_MIN) + (b + INT64_MIN);
break;
case GUF_MATH_CKD_UNDERFLOW:
*result = (a - INT64_MIN) + (b - 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:
GUF_ASSERT(b < 0);
*result = (a + INT64_MIN) - (b - INT64_MIN); // TODO: not sure
break;
case GUF_MATH_CKD_UNDERFLOW:
GUF_ASSERT(b > 0);
*result = (a - INT64_MIN) - (b + 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:
case GUF_MATH_CKD_UNDERFLOW: {
uint64_t res = (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 && mod > INT64_MAX);
res = res % mod;
*result = INT64_MIN + (int64_t)res;
} else {
*result = (int64_t)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:
*result = PTRDIFF_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = PTRDIFF_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = PTRDIFF_MAX;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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:
*result = (a + PTRDIFF_MIN) + (b + PTRDIFF_MIN);
break;
case GUF_MATH_CKD_UNDERFLOW:
*result = (a - PTRDIFF_MIN) + (b - 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:
GUF_ASSERT(b < 0);
*result = (a + PTRDIFF_MIN) - (b - PTRDIFF_MIN); // TODO: not sure
break;
case GUF_MATH_CKD_UNDERFLOW:
GUF_ASSERT(b > 0);
*result = (a - PTRDIFF_MIN) - (b + 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:
case GUF_MATH_CKD_UNDERFLOW: {
size_t res = (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 && mod > PTRDIFF_MAX);
res = res % mod;
*result = PTRDIFF_MIN + (ptrdiff_t)res;
} else {
*result = (ptrdiff_t)res;
}
break;
}
default:
GUF_ASSERT(false);
}
}
return check;
}
// 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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a + b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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_UNDERFLOW);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a - b;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a * b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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 = 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 = 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 = 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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a + b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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_UNDERFLOW);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a - b;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a * b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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 = 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 = 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 = a * b;
}
return check;
}
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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a + b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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_UNDERFLOW);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a - b;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a * b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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 = 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 = 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 = a * b;
}
return check;
}
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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a + b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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_UNDERFLOW);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a - b;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a * b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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 = 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 = 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 = a * b;
}
return check;
}
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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a + b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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_UNDERFLOW);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a - b;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a * b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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 = 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 = 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 = a * b;
}
return check;
}
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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a + b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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_UNDERFLOW);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a - b;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a * b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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 = 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 = 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 = 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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a + b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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_UNDERFLOW);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a - b;
break;
case GUF_MATH_CKD_UNDERFLOW:
*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);
if (result) {
switch (check) {
case GUF_MATH_CKD_SUCCESS:
*result = a * b;
break;
case GUF_MATH_CKD_OVERFLOW:
*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 = 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 = 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 = a * b;
}
return check;
}
#endif /* End impl */
#endif /* End header-guard */
#undef GUF_MATH_CKDINT_IMPL
#undef GUF_MATH_CKDINT_IMPL_STATIC
#undef GUF_MATH_CKDINT_KWRDS