Add unsigned integer wrapping functions

This commit is contained in:
jun 2025-05-16 13:44:27 +02:00
parent 8b78803ad8
commit 7ec2af0c33
4 changed files with 70 additions and 0 deletions

View File

@ -10,6 +10,11 @@
#include <inttypes.h> #include <inttypes.h>
#include <stddef.h> #include <stddef.h>
#define GUF_UINT8_MAX 0xffu
#define GUF_UINT16_MAX 0xffffu
#define GUF_UINT32_MAX 0xfffffffful
#define GUF_UINT64_MAX 0xffffffffffffffffull
#ifndef GUF_PLATFORM_BIG_ENDIAN #ifndef GUF_PLATFORM_BIG_ENDIAN
#define GUF_PLATFORM_LITTLE_ENDIAN #define GUF_PLATFORM_LITTLE_ENDIAN
#endif #endif

View File

@ -19,6 +19,28 @@
static inline uint64_t guf_rotl_u64(uint64_t x, int k) {return (1u*x << k) | (1u*x >> (64 - k));} static inline uint64_t guf_rotl_u64(uint64_t x, int k) {return (1u*x << k) | (1u*x >> (64 - k));}
static inline uint32_t guf_rotl_u32(uint32_t x, int k) {return (1u*x << k) | (1u*x >> (32 - k));} static inline uint32_t guf_rotl_u32(uint32_t x, int k) {return (1u*x << k) | (1u*x >> (32 - k));}
// Typesafe unsigned integer wrapping functions (generated with libguf/tools/intwrap-gen.py)
static inline uint_least8_t guf_wrap8_uint_least8_t(uint_least8_t a) { return a & GUF_UINT8_MAX; }
static inline uint_fast8_t guf_wrap8_uint_fast8_t(uint_fast8_t a) { return a & GUF_UINT8_MAX; }
static inline uint_least16_t guf_wrap16_uint_least16_t(uint_least16_t a) { return a & GUF_UINT16_MAX; }
static inline uint_fast16_t guf_wrap16_uint_fast16_t(uint_fast16_t a) { return a & GUF_UINT16_MAX; }
static inline uint_least32_t guf_wrap32_uint_least32_t(uint_least32_t a) { return a & GUF_UINT32_MAX; }
static inline uint_fast32_t guf_wrap32_uint_fast32_t(uint_fast32_t a) { return a & GUF_UINT32_MAX; }
static inline uint_least64_t guf_wrap64_uint_least64_t(uint_least64_t a) { return a & GUF_UINT64_MAX; }
static inline uint_fast64_t guf_wrap64_uint_fast64_t(uint_fast64_t a) { return a & GUF_UINT64_MAX; }
static inline unsigned char guf_wrap8_uchar(unsigned char a) { return a & GUF_UINT8_MAX; } // unsigned char: >= 8 bits
static inline unsigned short guf_wrap16_ushort(unsigned short a) { return a & GUF_UINT16_MAX; } // unsigned short: >= 16 bits
static inline unsigned long guf_wrap32_ulong(unsigned long a) { return a & GUF_UINT32_MAX; } // unsigned long: >= 32 bits
static inline unsigned long long guf_wrap64_ulong_long(unsigned long long a) { return a & GUF_UINT64_MAX; } // unsigned long long: >= 64 bits
#define GUF_UWRAP_8(UINT) ( (UINT) & GUF_UINT8_MAX )
#define GUF_UWRAP_16(UINT) ( (UINT) & GUF_UINT16_MAX )
#define GUF_UWRAP_32(UINT) ( (UINT) & GUF_UINT32_MAX )
#define GUF_UWRAP_64(UINT) ( (UINT) & GUF_UINT64_MAX )
// Signed min, max, clamp functions (generated with libguf/tools/min_max_clamp-gen.py) // Signed min, max, clamp functions (generated with libguf/tools/min_max_clamp-gen.py)

View File

@ -1,6 +1,8 @@
- guf_stack, guf_queue, guf_dqueue, guf_prio_queue (using a heap), guf_ringbuf - guf_stack, guf_queue, guf_dqueue, guf_prio_queue (using a heap), guf_ringbuf
- sort: add cpp #ifdef to remove restrict from declaration - sort: add cpp #ifdef to remove restrict from declaration
- str: start_with, ends_with, find
- guf_wrapping_mul_TYPE: Not 100 % sure if it does not depend on implementation defined behaviour, but it shouldn't - guf_wrapping_mul_TYPE: Not 100 % sure if it does not depend on implementation defined behaviour, but it shouldn't
- https://en.cppreference.com/w/c/types/integer (apparently the signed fixed width integer types are guaranteed to be two's complement...) - https://en.cppreference.com/w/c/types/integer (apparently the signed fixed width integer types are guaranteed to be two's complement...)

41
tools/intwrap-gen.py Normal file
View File

@ -0,0 +1,41 @@
"""
Generate typesafe unsigned integer wrapping functions
"""
def gen_uwrap_code(uint_type: str, uint_type_abbr: str, wrap_width: int, wrap_max_uint: str) -> str:
template = "static inline {uint_type} guf_wrap{wrap_width}_{uint_type_abbr}({uint_type} a) {{ return a & {wrap_max_uint}; }}\n"
return template.format(uint_type = uint_type, uint_type_abbr = uint_type_abbr, wrap_width = wrap_width, wrap_max_uint = wrap_max_uint)
if __name__ == "__main__":
uint_types = [
{"uint_type": "uint_least8_t", "uint_type_abbr": "uint_least8_t", "wrap_width": 8, "wrap_max_uint": "GUF_UINT8_MAX"},
{"uint_type": "uint_fast8_t", "uint_type_abbr": "uint_fast8_t", "wrap_width": 8, "wrap_max_uint": "GUF_UINT8_MAX"},
"\n",
{"uint_type": "uint_least16_t", "uint_type_abbr": "uint_least16_t", "wrap_width": 16, "wrap_max_uint": "GUF_UINT16_MAX"},
{"uint_type": "uint_fast16_t", "uint_type_abbr": "uint_fast16_t", "wrap_width": 16, "wrap_max_uint": "GUF_UINT16_MAX"},
"\n",
{"uint_type": "uint_least32_t", "uint_type_abbr": "uint_least32_t", "wrap_width": 32, "wrap_max_uint": "GUF_UINT32_MAX"},
{"uint_type": "uint_fast32_t", "uint_type_abbr": "uint_fast32_t", "wrap_width": 32, "wrap_max_uint": "GUF_UINT32_MAX"},
"\n",
{"uint_type": "uint_least64_t", "uint_type_abbr": "uint_least64_t", "wrap_width": 64, "wrap_max_uint": "GUF_UINT64_MAX"},
{"uint_type": "uint_fast64_t", "uint_type_abbr": "uint_fast64_t", "wrap_width": 64, "wrap_max_uint": "GUF_UINT64_MAX"},
"\n",
{"uint_type": "unsigned char", "uint_type_abbr": "uchar", "wrap_width": 8, "wrap_max_uint": "GUF_UINT8_MAX"},
{"uint_type": "unsigned short", "uint_type_abbr": "ushort", "wrap_width": 16, "wrap_max_uint": "GUF_UINT16_MAX"},
{"uint_type": "unsigned long", "uint_type_abbr": "ulong", "wrap_width": 32, "wrap_max_uint": "GUF_UINT32_MAX"},
{"uint_type": "unsigned long long", "uint_type_abbr": "ulong_long", "wrap_width": 64, "wrap_max_uint": "GUF_UINT64_MAX"},
]
code = "// Typesafe unsigned integer wrapping functions (generated with tools/intwrap-gen.py)\n"
for uint_t in uint_types:
if isinstance(uint_t, str):
code += uint_t
else:
code += gen_uwrap_code(**uint_t)
print(code)