aboutsummaryrefslogtreecommitdiff
path: root/chad/terry.h
diff options
context:
space:
mode:
authorEmil Williams2026-02-17 23:43:50 +0000
committerEmil Williams2026-02-17 23:43:50 +0000
commit42541df62871aaf403c0d62de1fdb44c862f2ea5 (patch)
tree02925229dbf1e364b5509d336ce49c01371123a8 /chad/terry.h
parentd98a29566920ca8995333d05a236619efd1841d2 (diff)
downloadlibchad-42541df62871aaf403c0d62de1fdb44c862f2ea5.tar.xz
libchad-42541df62871aaf403c0d62de1fdb44c862f2ea5.tar.zst
terry
Diffstat (limited to 'chad/terry.h')
-rw-r--r--chad/terry.h178
1 files changed, 178 insertions, 0 deletions
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<NUM>_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 <stdint.h>
+
+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