#ifndef GUF_INT_H #define GUF_INT_H #include "guf_common.h" #define GUF_MIN(X, Y) ((X) <= (Y) ? (X) : (Y)) #define GUF_MAX(X, Y) ((X) >= (Y) ? (X) : (Y)) #define GUF_CLAMP(X, MIN, MAX) GUF_MAX(GUF_MIN((X), (MAX)), (MIN)) #define GUF_DEFINE_MIN_MAX_CLAMP(int_type, int_type_name)\ static inline int_type GUFCAT(guf_min_, int_type_name)(int_type a, int_type b) {return a >= b ? a : b;}\ static inline int_type GUFCAT(guf_max_, int_type_name)(int_type a, int_type b) {return a >= b ? a : b;}\ static inline int_type GUFCAT(guf_clamp_, int_type_name)(int_type x, int_type min, int_type max) {return GUFCAT(guf_max_, int_type_name)(GUFCAT(guf_min_, int_type_name)(x, max), min);} GUF_DEFINE_MIN_MAX_CLAMP(int, int) GUF_DEFINE_MIN_MAX_CLAMP(short, short) GUF_DEFINE_MIN_MAX_CLAMP(long, long) GUF_DEFINE_MIN_MAX_CLAMP(long long, long_long) GUF_DEFINE_MIN_MAX_CLAMP(int8_t, i8) GUF_DEFINE_MIN_MAX_CLAMP(int16_t, i16) GUF_DEFINE_MIN_MAX_CLAMP(int32_t, i32) GUF_DEFINE_MIN_MAX_CLAMP(int64_t, i64) GUF_DEFINE_MIN_MAX_CLAMP(unsigned, unsigned) GUF_DEFINE_MIN_MAX_CLAMP(unsigned short, unsigned_short) GUF_DEFINE_MIN_MAX_CLAMP(unsigned long, unsigned_long) GUF_DEFINE_MIN_MAX_CLAMP(unsigned long long, unsigned_long_long) GUF_DEFINE_MIN_MAX_CLAMP(uint8_t, u8) GUF_DEFINE_MIN_MAX_CLAMP(uint16_t, u16) GUF_DEFINE_MIN_MAX_CLAMP(uint32_t, u32) GUF_DEFINE_MIN_MAX_CLAMP(uint64_t, u64) GUF_DEFINE_MIN_MAX_CLAMP(char, guf_char) GUF_DEFINE_MIN_MAX_CLAMP(unsigned char, guf_unsigned_char) #undef GUF_DEFINE_MIN_MAX_CLAMP static inline int guf_int(int x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT_MIN ); return -x;} static inline long guf_abs_long(long x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > LONG_MIN ); return -x;} static inline long long guf_abs_long_long(long long x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > LLONG_MIN ); return -x;} static inline int8_t guf_abs_i8 (int8_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT8_MIN ); return -x;} static inline int16_t guf_abs_i16(int16_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT16_MIN); return -x;} static inline int32_t guf_abs_i32(int32_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT32_MIN); return -x;} static inline int64_t guf_abs_i64(int64_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT64_MIN); return -x;} static inline ptrdiff_t guf_abs_ptrdiff(ptrdiff_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > PTRDIFF_MIN); return -x;} static inline bool guf_is_mul_overflow_size_t(size_t a, size_t b) { size_t c = a * b; return a != 0 && ((c / a) != b); } static inline size_t guf_safe_mul_size_t(size_t a, size_t b) { GUF_ASSERT_RELEASE(!guf_is_mul_overflow_size_t(a, b)); return a * b; } static inline bool guf_is_safe_size_calc(ptrdiff_t count, ptrdiff_t sizeof_elem) { if (count < 0 || sizeof_elem <= 0) { return false; } if (guf_is_mul_overflow_size_t(count, sizeof_elem)) { return false; } size_t size = (size_t)count * (size_t)sizeof_elem; return size <= PTRDIFF_MAX; } static inline ptrdiff_t guf_safe_size_calc(ptrdiff_t count, ptrdiff_t sizeof_elem) { GUF_ASSERT_RELEASE(count >= 0); GUF_ASSERT_RELEASE(sizeof_elem > 0); size_t size = guf_safe_mul_size_t(count, sizeof_elem); GUF_ASSERT_RELEASE(size <= PTRDIFF_MAX); return size; } // Signed integer types: #define GUF_OBJ_TYPE int #define GUF_OBJ_OPS_TYPENAME guf_int_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE short #define GUF_OBJ_OPS_TYPENAME guf_short_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE long #define GUF_OBJ_OPS_TYPENAME guf_long_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE long long #define GUF_OBJ_OPS_TYPENAME guf_long_long_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE int8_t #define GUF_OBJ_OPS_TYPENAME guf_int8_t_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE int16_t #define GUF_OBJ_OPS_TYPENAME guf_int16_t_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE int32_t #define GUF_OBJ_OPS_TYPENAME guf_int32_t_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE int64_t #define GUF_OBJ_OPS_TYPENAME guf_int64_t_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE ptrdiff_t #define GUF_OBJ_OPS_TYPENAME guf_ptrdiff_t_ops_type #include "guf_obj.h" // Unsigned integer types: #define GUF_OBJ_TYPE unsigned #define GUF_OBJ_OPS_TYPENAME guf_unsigned_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE unsigned short #define GUF_OBJ_OPS_TYPENAME guf_unsigned_short_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE unsigned long #define GUF_OBJ_OPS_TYPENAME guf_unsigned_long_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE unsigned long long #define GUF_OBJ_OPS_TYPENAME guf_unsigned_long_long_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE uint8_t #define GUF_OBJ_OPS_TYPENAME guf_uint8_t_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE uint16_t #define GUF_OBJ_OPS_TYPENAME guf_uint16_t_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE uint32_t #define GUF_OBJ_OPS_TYPENAME guf_uint32_t_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE uint64_t #define GUF_OBJ_OPS_TYPENAME guf_uint64_t_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE size_t #define GUF_OBJ_OPS_TYPENAME guf_size_t_ops_type #include "guf_obj.h" // Signed/Unsigned character types: #define GUF_OBJ_TYPE char #define GUF_OBJ_OPS_TYPENAME guf_char_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE unsigned char #define GUF_OBJ_OPS_TYPENAME guf_unsigned_char_ops_type #include "guf_obj.h" // Floating point: #define GUF_OBJ_TYPE float #define GUF_OBJ_OPS_TYPENAME guf_float_ops_type #include "guf_obj.h" #define GUF_OBJ_TYPE double #define GUF_OBJ_OPS_TYPENAME guf_double_ops_type #include "guf_obj.h" extern const guf_int_ops_type guf_int_ops; extern const guf_short_ops_type guf_short_ops; extern const guf_long_ops_type guf_long_ops; extern const guf_long_long_ops_type guf_long_long_ops; extern const guf_ptrdiff_t_ops_type guf_ptrdiff_t_ops; extern const guf_int8_t_ops_type guf_int8_t_ops; extern const guf_int16_t_ops_type guf_int16_t_ops; extern const guf_int32_t_ops_type guf_int32_t_ops; extern const guf_int64_t_ops_type guf_int64_t_ops; extern const guf_unsigned_ops_type guf_unsigned_ops; extern const guf_unsigned_short_ops_type guf_unsigned_short_ops; extern const guf_unsigned_long_ops_type guf_unsigned_long_ops; extern const guf_unsigned_long_long_ops_type guf_unsigned_long_long_ops; extern const guf_size_t_ops_type guf_size_t_ops; extern const guf_uint8_t_ops_type guf_uint8_t_ops; extern const guf_uint16_t_ops_type guf_uint16_t_ops; extern const guf_uint32_t_ops_type guf_uint32_t_ops; extern const guf_uint64_t_ops_type guf_uint64_t_ops; extern const guf_char_ops_type guf_char_ops; extern const guf_unsigned_char_ops_type guf_unsigned_char_ops; extern const guf_float_ops_type guf_float_ops; extern const guf_double_ops_type guf_double_ops; #ifdef GUF_IMPLEMENTATION #define GUF_DEFINE_INTEGER_CMP(int_type, fn_name) \ int fn_name(const int_type *a, const int_type *b) {GUF_ASSERT(a && b); return (*a == *b ? 0 : *a < *b ? -1 : 1);} \ GUF_OBJ_OPS_DEFINE_CMP_VOID(int_type, fn_name) \ GUF_OBJ_OPS_DEFINE_CMP_VOID_INV(int_type, fn_name) #define GUF_DEFINE_INTEGER_OPS(int_type)\ const GUFCAT(int_type, _ops_type) GUFCAT(int_type, _ops) = {\ .cmp = GUFCAT(int_type, _cmp),\ .cmp_void = GUFCAT(int_type, _cmp_void), \ .cmp_void_inv = GUFCAT(int_type, _cmp_void_inv), \ .default_value = 0,\ .eq = NULL, \ .copy_init = NULL,\ .move_init = NULL,\ .free = NULL\ };\ GUF_DEFINE_INTEGER_CMP(int, guf_int_cmp) GUF_DEFINE_INTEGER_CMP(short, guf_short_cmp) GUF_DEFINE_INTEGER_CMP(long, guf_long_cmp) GUF_DEFINE_INTEGER_CMP(long long, guf_long_long_cmp) GUF_DEFINE_INTEGER_CMP(int8_t, guf_int8_t_cmp) GUF_DEFINE_INTEGER_CMP(int16_t, guf_int16_t_cmp) GUF_DEFINE_INTEGER_CMP(int32_t, guf_int32_t_cmp) GUF_DEFINE_INTEGER_CMP(int64_t, guf_int64_t_cmp) GUF_DEFINE_INTEGER_CMP(ptrdiff_t, guf_ptrdiff_t_cmp) GUF_DEFINE_INTEGER_CMP(unsigned, guf_unsigned_cmp) GUF_DEFINE_INTEGER_CMP(unsigned short, guf_unsigned_short_cmp) GUF_DEFINE_INTEGER_CMP(unsigned long, guf_unsigned_long_cmp) GUF_DEFINE_INTEGER_CMP(unsigned long long, guf_unsigned_long_long_cmp) GUF_DEFINE_INTEGER_CMP(uint8_t, guf_uint8_t_cmp) GUF_DEFINE_INTEGER_CMP(uint16_t, guf_uint16_t_cmp) GUF_DEFINE_INTEGER_CMP(uint32_t, guf_uint32_t_cmp) GUF_DEFINE_INTEGER_CMP(uint64_t, guf_uint64_t_cmp) GUF_DEFINE_INTEGER_CMP(size_t, guf_size_t_cmp) GUF_DEFINE_INTEGER_CMP(char, guf_char_cmp) GUF_DEFINE_INTEGER_CMP(unsigned char, guf_unsigned_char_cmp) GUF_DEFINE_INTEGER_CMP(float, guf_float_cmp) GUF_DEFINE_INTEGER_CMP(double, guf_double_cmp) GUF_DEFINE_INTEGER_OPS(guf_int) GUF_DEFINE_INTEGER_OPS(guf_short) GUF_DEFINE_INTEGER_OPS(guf_long_long) GUF_DEFINE_INTEGER_OPS(guf_int8_t) GUF_DEFINE_INTEGER_OPS(guf_int16_t) GUF_DEFINE_INTEGER_OPS(guf_int32_t) GUF_DEFINE_INTEGER_OPS(guf_int64_t) GUF_DEFINE_INTEGER_OPS(guf_unsigned) GUF_DEFINE_INTEGER_OPS(guf_unsigned_short) GUF_DEFINE_INTEGER_OPS(guf_unsigned_long_long) GUF_DEFINE_INTEGER_OPS(guf_uint8_t) GUF_DEFINE_INTEGER_OPS(guf_uint16_t) GUF_DEFINE_INTEGER_OPS(guf_uint32_t) GUF_DEFINE_INTEGER_OPS(guf_uint64_t) GUF_DEFINE_INTEGER_OPS(guf_char) GUF_DEFINE_INTEGER_OPS(guf_unsigned_char) GUF_DEFINE_INTEGER_OPS(guf_float) GUF_DEFINE_INTEGER_OPS(guf_double) #undef GUF_DEFINE_INTEGER_OPS #undef GUF_DEFINE_INTEGER_CMP #endif #endif