libguf/src/guf_int.h
2025-01-08 23:32:55 +01:00

273 lines
9.4 KiB
C

#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