From 42541df62871aaf403c0d62de1fdb44c862f2ea5 Mon Sep 17 00:00:00 2001 From: Emil Williams Date: Tue, 17 Feb 2026 23:43:50 +0000 Subject: terry --- chad/terry.h | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 chad/terry.h (limited to 'chad') diff --git a/chad/terry.h b/chad/terry.h new file mode 100644 index 0000000..a1616ec --- /dev/null +++ b/chad/terry.h @@ -0,0 +1,178 @@ +#ifndef TERRY_H +#define TERRY_H + +#if 0 + Promises the most accurate primitives as are allowable by (recent) compiler version and C standard. + Primitivie types: + signed int : i8>i128, s8>s128 + unsigned int : u8>u128 + float : f, f32 + double : fl, f64 + long double : fll, f128 + + NO_128_TYPES will not be defined if i128, s128, u128 exist. + NO_F_TYPE_NAME will remove hazardous declarations of f, fl, and fll. + + all floating bitmarked types will have F_PRECISE defined + if they are specified to that precise number of bits. + + Tested to work with gcc 14.2.0 and clang 19.1.7 on Debian + Backwards compat for gcc 14.2.0 + Not robustly tested, please report issues. + + --- Definitions --- + + Defining the following will change behavior within the typesystem. + the IMPRECISE groupings will always be provided with their respective types are present in full. + +#define TERRY_FLOAT_IMPRECISE /* supergroup of the below two groups */ +#define TERRY_SMALL_FLOAT_IMPRECISE /* groups the two below together */ +#define FLOAT_IS_F32 +#define DOUBLE_IS_F64 +#define TERRY_LARGE_FLOAT_IMPRECISE /* groups the two below together */ +#define LONG_DOUBLE_IS_F80 +#define LONG_DOUBLE_IS_F128 +#define NO_128_TYPES /* removes 128 declarations */ +#define NO_F_TYPE_NAME /* removes hazardous f, fl, fll */ +#endif + +/* --- */ + +#include + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +#ifndef NO_F_TYPE_NAME +typedef float f; +typedef double fl; +typedef long double fll; +#endif + +#ifndef NO_128_TYPES +# if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L && defined(__GNUC__) && !defined(__clang__)) \ + || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) +# define PRECISE_128 + typedef signed _BitInt(128) i128; + typedef signed _BitInt(128) s128; + typedef unsigned _BitInt(128) u128; +# else +# if __SIZEOF_INT128__ /* compiler specific macro */ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +# define PRECISE_128 + typedef signed __int128 i128; + typedef signed __int128 s128; + typedef unsigned __int128 u128; +# pragma GCC diagnostic pop +# else +# define NO_128_TYPES +# endif +# endif +#endif + +#if !(defined(__STDC_IEC_60559_BFP__) && defined(__STDC_IEC_60559_TYPES__)) +#define TERRY_FLOAT_IMPRECISE +#endif + +#ifdef TERRY_FLOAT_IMPRECISE +# define TERRY_SMALL_FLOAT_IMPRECISE +# define TERRY_LARGE_FLOAT_IMPRECISE +#endif + +#ifdef TERRY_SMALL_FLOAT_IMPRECISE +# define FLOAT_IS_F32 +# define DOUBLE_IS_F64 +#endif + +#ifdef TERRY_LARGE_FLOAT_IMPRECISE +# define LONG_DOUBLE_IS_F80 +# define LONG_DOUBLE_IS_F128 +#endif + +/* You can treat floats like _Float32, and doubles like _Float64, however *THEY ARE NOT THE SAME THING*. */ +/* go ask WG14 for the "why." GCC/Clang may complain but will work as expected. */ + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L && defined(__GNUC__) && !defined(__clang__)) \ +|| (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) +# if defined(FLOAT_IS_F32) || defined(TERRY_SMALL_FLOAT_IMPRECISE) + typedef float f32; +# else +# define F32_PRECISE + typedef _Float32 f32; +# endif + +# if defined(DOUBLE_IS_F64) || defined(TERRY_LARGE_FLOAT_IMPRECISE) + typedef double f64; +# else +# define F64_PRECISE + typedef _Float64 f64; +# endif + +# if defined(__GNUC__) && !defined(__clang__) +# define F80_PRECISE + typedef __float80 f80; +# else + #define LONG_DOUBLE_IS_F80 + typedef long double f80; +# endif + +# if defined(LONG_DOUBLE_IS_F128) || defined(TERRY_LARGE_FLOAT_IMPRECISE) + typedef long double f128; +# else +# define F128_PRECISE + typedef _Float128 f128; +# endif +#else +/* the below f32/64 definitions may behave erratically, as float != f32 && double != f64. + * We're just doing this for the sake of defining something that will *probably* work in most cases. + * Use newer C versions. */ +# if defined(__GNUC__) && !defined(__clang__) +# define TERRY_SMALL_FLOAT_IMPRECISE + +# define FLOAT_IS_F32 + typedef float f32; +# define DOUBLE_IS_F64 + typedef double f64; + +# if defined(LONG_DOUBLE_IS_F80) + typedef long double f80; +# else +# define F80_PRECISE + typedef __float80 f80; +# endif + +# if defined(LONG_DOUBLE_IS_F128) + typedef long double f128; +# else +# define F128_PRECISE + typedef __float128 f128; +# endif +# else +# define TERRY_FLOAT_IMPRECISE +# define TERRY_SMALL_FLOAT_IMPRECISE +# define TERRY_LARGE_FLOAT_IMPRECISE +# define FLOAT_IS_F32 + typedef float f32; +# define DOUBLE_IS_F64 + typedef double f64; + /* Usually 10-bytes with 128-bit alignment */ +# define LONG_DOUBLE_IS_F80 + typedef long double f80; +# define LONG_DOUBLE_IS_F128 + typedef long double f128; +# endif +#endif +#endif -- cgit v1.2.3