libguf/tools/min_max_clamp-gen.py
jun 57f0e47efc Refactor to use portable minimum-width integers.
The signed and unsigned fixed-width integers (int32_t, uint32_t etc.) are optional
in C99 (and above). Use the non-optional minimum-width integers (int_fast32_t, uint_fast32_t and int_least32_t, uint_least32_t etc.) instead.

To simulate unsigned wrap-around, use the GUF_UWRAP macros in guf_common.h

cf. https://en.cppreference.com/w/c/types/integer (last-retrieved: 2025-05-18)
2025-05-18 22:03:03 +02:00

103 lines
5.4 KiB
Python

"""
Generate typesafe min, max and clamp functions for libguf/src/guf_math.h
"""
from dataclasses import dataclass
import textwrap
@dataclass
class IntType:
INT_TYPE: str
INT_TYPE_ABBR: str
INT_MIN: str
INT_MAX: str
is_optional: bool = False
@dataclass
class UintType:
INT_TYPE: str
INT_TYPE_ABBR: str
INT_MIN: str
INT_MAX: str
is_optional: bool = False
def gen_min_max_clamp(int_types: list, uint_types: list) -> str:
template = textwrap.dedent("""\
static inline {type} guf_min_{type_abbr}({type} a, {type} b) {{ return a < b ? a : b; }}
static inline {type} guf_max_{type_abbr}({type} a, {type} b) {{ return a > b ? a : b; }}
static inline {type} guf_clamp_{type_abbr}({type} x, {type} min, {type} max) {{ if (x < min) {{return min;}} if (x > max) {{return max;}} return x; }}
""")
result = "\n// Signed min, max, clamp functions (generated with libguf/tools/min_max_clamp-gen.py)\n"
for t in int_types:
if t.is_optional:
result += "#ifdef {int_max}\n".format(int_max = t.INT_MAX)
result += template.format(type = t.INT_TYPE, type_abbr = t.INT_TYPE_ABBR)
if t.is_optional:
result += "#endif\n"
result += "\n"
result += "\n// Unsigned min, max, clamp functions (generated with libguf/tools/min_max_clamp-gen.py)\n"
for t in uint_types:
if t.is_optional:
result +="#ifdef {int_max}\n".format(int_max = t.INT_MAX)
result += template.format(type = t.INT_TYPE, type_abbr = t.INT_TYPE_ABBR)
if t.is_optional:
result += "#endif\n"
result += "\n"
return result
if __name__ == "__main__":
int_types = [
IntType(INT_TYPE = "char", INT_TYPE_ABBR = "char", INT_MIN = "CHAR_MIN", INT_MAX = "CHAR_MAX"),
IntType(INT_TYPE = "int", INT_TYPE_ABBR = "int", INT_MIN = "INT_MIN", INT_MAX = "INT_MAX"),
IntType(INT_TYPE = "long", INT_TYPE_ABBR = "long", INT_MIN = "LONG_MIN", INT_MAX = "LONG_MAX"),
IntType(INT_TYPE = "long long", INT_TYPE_ABBR = "long_long", INT_MIN = "LLONG_MIN", INT_MAX = "LLONG_MAX"),
IntType(INT_TYPE = "ptrdiff_t", INT_TYPE_ABBR = "ptrdiff_t", INT_MIN = "PTRDIFF_MIN", INT_MAX = "PTRDIFF_MAX"),
IntType(INT_TYPE = "int_fast8_t", INT_TYPE_ABBR = "i8_fast", INT_MIN = "GUF_INT8_MIN", INT_MAX = "GUF_INT8_MAX"),
IntType(INT_TYPE = "int_fast16_t", INT_TYPE_ABBR = "i16_fast", INT_MIN = "GUF_INT16_MIN", INT_MAX = "GUF_INT16_MAX"),
IntType(INT_TYPE = "int_fast32_t", INT_TYPE_ABBR = "i32_fast", INT_MIN = "GUF_INT32_MIN", INT_MAX = "GUF_INT32_MAX"),
IntType(INT_TYPE = "int_fast64_t", INT_TYPE_ABBR = "i64_fast", INT_MIN = "GUF_INT64_MIN", INT_MAX = "GUF_INT64_MAX"),
IntType(INT_TYPE = "float", INT_TYPE_ABBR = "f32", INT_MIN = "-FLT_MAX", INT_MAX = "FLT_MAX"),
IntType(INT_TYPE = "double", INT_TYPE_ABBR = "f64", INT_MIN = "-DBL_MAX", INT_MAX = "DBL_MAX"),
IntType(INT_TYPE = "int8_t", INT_TYPE_ABBR = "i8", INT_MIN = "INT8_MIN", INT_MAX = "INT8_MAX", is_optional=True),
IntType(INT_TYPE = "int16_t", INT_TYPE_ABBR = "i16", INT_MIN = "INT16_MIN", INT_MAX = "INT16_MAX", is_optional=True),
IntType(INT_TYPE = "int32_t", INT_TYPE_ABBR = "i32", INT_MIN = "INT32_MIN", INT_MAX = "INT32_MAX", is_optional=True),
IntType(INT_TYPE = "int64_t", INT_TYPE_ABBR = "i64", INT_MIN = "INT64_MIN", INT_MAX = "INT64_MAX", is_optional=True),
]
uint_types = [
UintType(INT_TYPE = "unsigned char", INT_TYPE_ABBR = "uchar", INT_MIN = "0", INT_MAX = "UCHAR_MAX"),
UintType(INT_TYPE = "unsigned", INT_TYPE_ABBR = "unsigned", INT_MIN = "0", INT_MAX = "UINT_MAX"),
UintType(INT_TYPE = "unsigned long", INT_TYPE_ABBR = "ulong", INT_MIN = "0", INT_MAX = "ULONG_MAX"),
UintType(INT_TYPE = "unsigned long long", INT_TYPE_ABBR = "ulong_long", INT_MIN = "0", INT_MAX = "ULLONG_MAX"),
UintType(INT_TYPE = "size_t", INT_TYPE_ABBR = "size_t", INT_MIN = "0", INT_MAX = "SIZE_MAX"),
UintType(INT_TYPE = "uint_fast8_t", INT_TYPE_ABBR = "u8_fast", INT_MIN = "0", INT_MAX = "GUF_UINT8_MAX"),
UintType(INT_TYPE = "uint_fast16_t", INT_TYPE_ABBR = "u16_fast", INT_MIN = "0", INT_MAX = "GUF_UINT16_MAX"),
UintType(INT_TYPE = "uint_fast32_t", INT_TYPE_ABBR = "u32_fast", INT_MIN = "0", INT_MAX = "GUF_UINT32_MAX"),
UintType(INT_TYPE = "uint_fast64_t", INT_TYPE_ABBR = "u64_fast", INT_MIN = "0", INT_MAX = "GUF_UINT64_MAX"),
UintType(INT_TYPE = "uint8_t", INT_TYPE_ABBR = "u8", INT_MIN = "0", INT_MAX = "UINT8_MAX", is_optional=True),
UintType(INT_TYPE = "uint16_t", INT_TYPE_ABBR = "u16", INT_MIN = "0", INT_MAX = "UINT16_MAX", is_optional=True),
UintType(INT_TYPE = "uint32_t", INT_TYPE_ABBR = "u32", INT_MIN = "0", INT_MAX = "UINT32_MAX", is_optional=True),
UintType(INT_TYPE = "uint64_t", INT_TYPE_ABBR = "u64", INT_MIN = "0", INT_MAX = "UINT64_MAX", is_optional=True),
]
code = gen_min_max_clamp(int_types=int_types, uint_types=uint_types)
print(code)