diff options
Diffstat (limited to 'src/stdlib')
| -rw-r--r-- | src/stdlib/README.md | 4 | ||||
| -rw-r--r-- | src/stdlib/bigint.h | 5 | ||||
| -rw-r--r-- | src/stdlib/cli.c | 18 | ||||
| -rw-r--r-- | src/stdlib/datatypes.h | 4 | ||||
| -rw-r--r-- | src/stdlib/float32.c | 4 | ||||
| -rw-r--r-- | src/stdlib/float64.c | 4 | ||||
| -rw-r--r-- | src/stdlib/floatX.c.h (renamed from src/stdlib/numX.c.h) | 104 | ||||
| -rw-r--r-- | src/stdlib/floatX.h | 103 | ||||
| -rw-r--r-- | src/stdlib/floats.h | 13 | ||||
| -rw-r--r-- | src/stdlib/intX.h | 11 | ||||
| -rw-r--r-- | src/stdlib/lists.c | 12 | ||||
| -rw-r--r-- | src/stdlib/num32.c | 4 | ||||
| -rw-r--r-- | src/stdlib/num64.c | 4 | ||||
| -rw-r--r-- | src/stdlib/numX.h | 103 | ||||
| -rw-r--r-- | src/stdlib/nums.h | 13 | ||||
| -rw-r--r-- | src/stdlib/optionals.c | 6 | ||||
| -rw-r--r-- | src/stdlib/reals.c | 33 | ||||
| -rw-r--r-- | src/stdlib/stdlib.c | 2 | ||||
| -rw-r--r-- | src/stdlib/text.h | 6 | ||||
| -rw-r--r-- | src/stdlib/tomo.h | 2 |
20 files changed, 230 insertions, 225 deletions
diff --git a/src/stdlib/README.md b/src/stdlib/README.md index 671d330a..cf375ff6 100644 --- a/src/stdlib/README.md +++ b/src/stdlib/README.md @@ -22,9 +22,9 @@ some common functionality. - C Strings: [c_strings.h](c_strings.h), [c_strings.c](c_strings.c) - Files (used internally only): [files.h](files.h), [files.c](files.c) - Functiontype: [functiontype.h](functiontype.h), [functiontype.c](functiontype.c) -- Integers: [integers.h](integers.h), [integers.c](integers.c) +- Integers: [bigint.h](bigint.h), [bigint.c](bigint.c), [intX.h](intX.h), [intX.c.h](intX.c.h) - Memory: [memory.h](memory.h), [memory.c](memory.c) -- Nums: [nums.h](nums.h), [nums.c](nums.c) +- Floating point numbers: [floatX.h](floatX.h), [floatX.c.h](floatX.c.h) - Optionals: [optionals.h](optionals.h), [optionals.c](optionals.c) - Paths: [paths.h](paths.h), [paths.c](paths.c) - Pointers: [pointers.h](pointers.h), [pointers.c](pointers.c) diff --git a/src/stdlib/bigint.h b/src/stdlib/bigint.h index 614e1501..e50a6847 100644 --- a/src/stdlib/bigint.h +++ b/src/stdlib/bigint.h @@ -1,4 +1,5 @@ // Big integer type (`Int` in Tomo) +#pragma once #include <gmp.h> #include <stdbool.h> @@ -189,13 +190,13 @@ MACROLIKE PUREFUNC bool Int$is_negative(Int_t x) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" #endif -MACROLIKE PUREFUNC Int_t Int$from_num(double n, bool truncate) { +MACROLIKE PUREFUNC Int_t Int$from_float64(double n, bool truncate) { mpz_t result; mpz_init_set_d(result, n); if (!truncate && unlikely(mpz_get_d(result) != n)) fail("Could not convert to an integer without truncation: ", n); return Int$from_mpz(result); } -MACROLIKE PUREFUNC Int_t Int$from_num32(float n, bool truncate) { return Int$from_num((double)n, truncate); } +MACROLIKE PUREFUNC Int_t Int$from_float32(float n, bool truncate) { return Int$from_float64((double)n, truncate); } MACROLIKE Int_t Int$from_int64(int64_t i) { if likely (i >= SMALLEST_SMALL_INT && i <= BIGGEST_SMALL_INT) return (Int_t){.small = (i << 2L) | 1L}; mpz_t result; diff --git a/src/stdlib/cli.c b/src/stdlib/cli.c index 22ed9b94..8301a2c2 100644 --- a/src/stdlib/cli.c +++ b/src/stdlib/cli.c @@ -17,7 +17,7 @@ #include "cli.h" #include "integers.h" #include "metamethods.h" -#include "nums.h" +#include "floats.h" #include "optionals.h" #include "paths.h" #include "print.h" @@ -209,8 +209,8 @@ static List_t parse_arg_list(List_t args, const char *flag, void *dest, const Ty if (type->tag == OptionalInfo) { const TypeInfo_t *nonnull = type->OptionalInfo.type; if (streq(arg, "none")) { - if (nonnull == &Num$info) *(double *)dest = (double)NAN; - else if (nonnull == &Num32$info) *(float *)dest = (float)NAN; + if (nonnull == &Float64$info) *(double *)dest = (double)NAN; + else if (nonnull == &Float32$info) *(float *)dest = (float)NAN; else memset(dest, 0, (size_t)type->size); return List$from(args, I(2)); } else { @@ -258,14 +258,14 @@ static List_t parse_arg_list(List_t args, const char *flag, void *dest, const Ty OptionalBool_t parsed = Bool$parse(Text$from_str(arg), NULL); if (parsed == NONE_BOOL) print_err("Could not parse argument for ", flag, ": ", arg); *(Bool_t *)dest = parsed; - } else if (type == &Num$info) { - OptionalNum_t parsed = Num$parse(Text$from_str(arg), NULL); + } else if (type == &Float64$info) { + OptionalFloat64_t parsed = Float64$parse(Text$from_str(arg), NULL); if (isnan(parsed)) print_err("Could not parse argument for ", flag, ": ", arg); - *(Num_t *)dest = parsed; - } else if (type == &Num32$info) { - OptionalNum32_t parsed = Num32$parse(Text$from_str(arg), NULL); + *(Float64_t *)dest = parsed; + } else if (type == &Float32$info) { + OptionalFloat32_t parsed = Float32$parse(Text$from_str(arg), NULL); if (isnan(parsed)) print_err("Could not parse argument for ", flag, ": ", arg); - *(Num32_t *)dest = parsed; + *(Float32_t *)dest = parsed; } else if (type->tag == PointerInfo) { // For pointers, we can just allocate memory for the value and then parse the value void *value = GC_MALLOC((size_t)type->PointerInfo.pointed->size); diff --git a/src/stdlib/datatypes.h b/src/stdlib/datatypes.h index 446df0ef..c177a0a5 100644 --- a/src/stdlib/datatypes.h +++ b/src/stdlib/datatypes.h @@ -18,8 +18,8 @@ #define LIST_MAX_DATA_REFCOUNT MAX_FOR_N_BITS(LIST_REFCOUNT_BITS) #define LIST_MAX_FREE_ENTRIES MAX_FOR_N_BITS(LIST_FREE_BITS) -#define Num_t double -#define Num32_t float +#define Float64_t double +#define Float32_t float #define Int64_t int64_t #define Int32_t int32_t diff --git a/src/stdlib/float32.c b/src/stdlib/float32.c new file mode 100644 index 00000000..855118ba --- /dev/null +++ b/src/stdlib/float32.c @@ -0,0 +1,4 @@ +// Type infos and methods for Float32 (32-bit floating point) using a template file + +#define FLOATX_C_H__BITS 32 +#include "floatX.c.h" diff --git a/src/stdlib/float64.c b/src/stdlib/float64.c new file mode 100644 index 00000000..e41c01f5 --- /dev/null +++ b/src/stdlib/float64.c @@ -0,0 +1,4 @@ +// Type infos and methods for Float64 (64-bit floating point) using a template file + +#define FLOATX_C_H__BITS 64 +#include "floatX.c.h" diff --git a/src/stdlib/numX.c.h b/src/stdlib/floatX.c.h index 7b030ab4..0961631c 100644 --- a/src/stdlib/numX.c.h +++ b/src/stdlib/floatX.c.h @@ -1,8 +1,8 @@ -// Type infos and methods for Nums (floating point) -// This file is a template that expects `NUMSX_C_H__BITS` to be defined before including: +// Type infos and methods for Floats (floating point numbers) +// This file is a template that expects `FLOATX_C_H__BITS` to be defined before including: // -// #define NUMX_C_H__BITS 64 -// #include "numX.c.h" +// #define FLOATX_C_H__BITS 64 +// #include "floatX.c.h" // #include <float.h> #include <gc.h> @@ -14,32 +14,32 @@ #include "text.h" #include "types.h" -#ifndef NUMX_C_H__BITS -#define NUMX_C_H__BITS 64 +#ifndef FLOATX_C_H__BITS +#define FLOATX_C_H__BITS 64 #endif -#if NUMX_C_H__BITS == 64 -#define NUM_T double +#if FLOATX_C_H__BITS == 64 +#define FLOAT_T double #define OPT_T double -#define NAMESPACED(x) Num$##x -#define TYPE_STR "Num" +#define NAMESPACED(x) Float64$##x +#define TYPE_STR "Float64" #define SUFFIXED(x) x -#elif NUMX_C_H__BITS == 32 -#define NUM_T float +#elif FLOATX_C_H__BITS == 32 +#define FLOAT_T float #define OPT_T float -#define NAMESPACED(x) Num32$##x -#define TYPE_STR "Num32" +#define NAMESPACED(x) Float32$##x +#define TYPE_STR "Float32" #define SUFFIXED(x) x##f #else -#error "Unsupported bit width for Num" +#error "Unsupported bit width for Float" #endif -#if NUMX_C_H__BITS == 64 +#if FLOATX_C_H__BITS == 64 #include "fpconv.h" #include "string.h" public -PUREFUNC Text_t NAMESPACED(value_as_text)(NUM_T x) { +PUREFUNC Text_t NAMESPACED(value_as_text)(FLOAT_T x) { char *str = GC_MALLOC_ATOMIC(24); int len = fpconv_dtoa(x, str); return Text$from_strn(str, (size_t)len); @@ -49,7 +49,7 @@ PUREFUNC Text_t NAMESPACED(as_text)(const void *x, bool colorize, const TypeInfo (void)info; if (!x) return Text(TYPE_STR); static const Text_t color_prefix = Text("\x1b[35m"), color_suffix = Text("\x1b[m"); - Text_t text = NAMESPACED(value_as_text)(*(NUM_T *)x); + Text_t text = NAMESPACED(value_as_text)(*(FLOAT_T *)x); return colorize ? Texts(color_prefix, text, color_suffix) : text; } public @@ -64,14 +64,14 @@ PUREFUNC int32_t NAMESPACED(compare)(const void *x, const void *y, const TypeInf return (rx > ry) - (rx < ry); } -#elif NUMX_C_H__BITS == 32 +#elif FLOATX_C_H__BITS == 32 public -PUREFUNC Text_t NAMESPACED(value_as_text)(NUM_T x) { return Num$value_as_text((double)x); } +PUREFUNC Text_t NAMESPACED(value_as_text)(FLOAT_T x) { return Float64$value_as_text((double)x); } PUREFUNC Text_t NAMESPACED(as_text)(const void *x, bool colorize, const TypeInfo_t *info) { (void)info; if (!x) return Text(TYPE_STR); static const Text_t color_prefix = Text("\x1b[35m"), color_suffix = Text("\x1b[m"); - Text_t text = Num$value_as_text((double)*(NUM_T *)x); + Text_t text = Float64$value_as_text((double)*(FLOAT_T *)x); return colorize ? Texts(color_prefix, text, color_suffix) : text; } public @@ -91,69 +91,71 @@ PUREFUNC int32_t NAMESPACED(compare)(const void *x, const void *y, const TypeInf public PUREFUNC bool NAMESPACED(equal)(const void *x, const void *y, const TypeInfo_t *info) { (void)info; - return *(NUM_T *)x == *(NUM_T *)y; + return *(FLOAT_T *)x == *(FLOAT_T *)y; } public -CONSTFUNC bool NAMESPACED(near)(NUM_T a, NUM_T b, NUM_T ratio, NUM_T absolute) { +CONSTFUNC bool NAMESPACED(near)(FLOAT_T a, FLOAT_T b, FLOAT_T ratio, FLOAT_T absolute) { if (ratio < 0) ratio = 0; else if (ratio > 1) ratio = 1; if (a == b) return true; - NUM_T diff = SUFFIXED(fabs)(a - b); + FLOAT_T diff = SUFFIXED(fabs)(a - b); if (diff < absolute) return true; else if (isnan(diff)) return false; - NUM_T epsilon = SUFFIXED(fabs)(a * ratio) + SUFFIXED(fabs)(b * ratio); + FLOAT_T epsilon = SUFFIXED(fabs)(a * ratio) + SUFFIXED(fabs)(b * ratio); if (isinf(epsilon)) epsilon = DBL_MAX; return (diff < epsilon); } public -Text_t NAMESPACED(percent)(NUM_T x, NUM_T precision) { - NUM_T d = SUFFIXED(100.) * x; +Text_t NAMESPACED(percent)(FLOAT_T x, FLOAT_T precision) { + FLOAT_T d = SUFFIXED(100.) * x; d = NAMESPACED(with_precision)(d, precision); return Texts(NAMESPACED(value_as_text)(d), Text("%")); } public -CONSTFUNC NUM_T NAMESPACED(with_precision)(NUM_T num, NUM_T precision) { - if (precision == SUFFIXED(0.0)) return num; +CONSTFUNC FLOAT_T NAMESPACED(with_precision)(FLOAT_T n, FLOAT_T precision) { + if (precision == SUFFIXED(0.0)) return n; // Precision will be, e.g. 0.01 or 100. if (precision < SUFFIXED(1.)) { - NUM_T inv = SUFFIXED(round)(SUFFIXED(1.) / precision); // Necessary to make the math work - NUM_T k = num * inv; + FLOAT_T inv = SUFFIXED(round)(SUFFIXED(1.) / precision); // Necessary to make the math work + FLOAT_T k = n * inv; return SUFFIXED(round)(k) / inv; } else { - NUM_T k = num / precision; + FLOAT_T k = n / precision; return SUFFIXED(round)(k) * precision; } } public -CONSTFUNC NUM_T NAMESPACED(mod)(NUM_T num, NUM_T modulus) { +CONSTFUNC FLOAT_T NAMESPACED(mod)(FLOAT_T n, FLOAT_T modulus) { // Euclidean division, see: // https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf - NUM_T r = (NUM_T)remainder((double)num, (double)modulus); + FLOAT_T r = (FLOAT_T)remainder((double)n, (double)modulus); r -= (r < SUFFIXED(0.)) * (SUFFIXED(2.) * (modulus < SUFFIXED(0.)) - SUFFIXED(1.)) * modulus; return r; } public -CONSTFUNC NUM_T NAMESPACED(mod1)(NUM_T num, NUM_T modulus) { - return SUFFIXED(1.0) + NAMESPACED(mod)(num - SUFFIXED(1.0), modulus); +CONSTFUNC FLOAT_T NAMESPACED(mod1)(FLOAT_T n, FLOAT_T modulus) { + return SUFFIXED(1.0) + NAMESPACED(mod)(n - SUFFIXED(1.0), modulus); } public -CONSTFUNC NUM_T NAMESPACED(mix)(NUM_T amount, NUM_T x, NUM_T y) { return (SUFFIXED(1.0) - amount) * x + amount * y; } +CONSTFUNC FLOAT_T NAMESPACED(mix)(FLOAT_T amount, FLOAT_T x, FLOAT_T y) { + return (SUFFIXED(1.0) - amount) * x + amount * y; +} public -CONSTFUNC bool NAMESPACED(is_between)(const NUM_T x, const NUM_T low, const NUM_T high) { +CONSTFUNC bool NAMESPACED(is_between)(const FLOAT_T x, const FLOAT_T low, const FLOAT_T high) { return low <= x && x <= high; } public -CONSTFUNC NUM_T NAMESPACED(clamped)(NUM_T x, NUM_T low, NUM_T high) { +CONSTFUNC FLOAT_T NAMESPACED(clamped)(FLOAT_T x, FLOAT_T low, FLOAT_T high) { return (x <= low) ? low : (x >= high ? high : x); } @@ -161,10 +163,10 @@ public OPT_T NAMESPACED(parse)(Text_t text, Text_t *remainder) { const char *str = Text$as_c_string(text); char *end = NULL; -#if NUMX_C_H__BITS == 64 - NUM_T n = strtod(str, &end); -#elif NUMX_C_H__BITS == 32 - NUM_T n = strtof(str, &end); +#if FLOATX_C_H__BITS == 64 + FLOAT_T n = strtod(str, &end); +#elif FLOATX_C_H__BITS == 32 + FLOAT_T n = strtof(str, &end); #endif if (end > str) { if (remainder) *remainder = Text$from_str(end); @@ -179,20 +181,20 @@ OPT_T NAMESPACED(parse)(Text_t text, Text_t *remainder) { public CONSTFUNC bool NAMESPACED(is_none)(const void *n, const TypeInfo_t *info) { (void)info; - return isnan(*(NUM_T *)n); + return isnan(*(FLOAT_T *)n); } public -CONSTFUNC bool NAMESPACED(isinf)(NUM_T n) { return (fpclassify(n) == FP_INFINITE); } +CONSTFUNC bool NAMESPACED(isinf)(FLOAT_T n) { return (fpclassify(n) == FP_INFINITE); } public -CONSTFUNC bool NAMESPACED(finite)(NUM_T n) { return (fpclassify(n) != FP_INFINITE); } +CONSTFUNC bool NAMESPACED(finite)(FLOAT_T n) { return (fpclassify(n) != FP_INFINITE); } public -CONSTFUNC bool NAMESPACED(isnan)(NUM_T n) { return (fpclassify(n) == FP_NAN); } +CONSTFUNC bool NAMESPACED(isnan)(FLOAT_T n) { return (fpclassify(n) == FP_NAN); } public const TypeInfo_t NAMESPACED(info) = { - .size = sizeof(NUM_T), - .align = __alignof__(NUM_T), + .size = sizeof(FLOAT_T), + .align = __alignof__(FLOAT_T), .metamethods = { .compare = NAMESPACED(compare), @@ -202,9 +204,9 @@ const TypeInfo_t NAMESPACED(info) = { }, }; -#undef NUM_T +#undef FLOAT_T #undef OPT_T #undef NAMESPACED #undef TYPE_STR #undef SUFFIXED -#undef NUMX_C_H__BITS +#undef FLOATX_C_H__BITS diff --git a/src/stdlib/floatX.h b/src/stdlib/floatX.h new file mode 100644 index 00000000..ff2d0931 --- /dev/null +++ b/src/stdlib/floatX.h @@ -0,0 +1,103 @@ +// Template header for 64 and 32 bit floating point numbers +// This file expects `FLOATX_H__BITS` to be defined before including: +// +// #define FLOATX_H__BITS 64 +// #include "floatX.h" +// + +#include <stdbool.h> +#include <stdint.h> + +#include "datatypes.h" +#include "stdlib.h" +#include "types.h" +#include "util.h" + +#ifndef FLOATX_H__BITS +#define FLOATX_H__BITS 64 +#endif + +#if FLOATX_H__BITS == 64 +#define FLOAT_T double +#define OPT_T double +#define NAMESPACED(x) Float64$##x +#define TYPE_STR "Float64" +#define SUFFIXED(x) x +#elif FLOATX_H__BITS == 32 +#define FLOAT_T float +#define OPT_T float +#define NAMESPACED(x) Float32$##x +#define TYPE_STR "Float32" +#define SUFFIXED(x) x##f +#else +#error "Unsupported bit width for Float" +#endif + +Text_t NAMESPACED(as_text)(const void *x, bool colorize, const TypeInfo_t *type); +Text_t NAMESPACED(value_as_text)(FLOAT_T x); +PUREFUNC int32_t NAMESPACED(compare)(const void *x, const void *y, const TypeInfo_t *type); +PUREFUNC bool NAMESPACED(equal)(const void *x, const void *y, const TypeInfo_t *type); +CONSTFUNC bool NAMESPACED(near)(FLOAT_T a, FLOAT_T b, FLOAT_T ratio, FLOAT_T absolute); +Text_t NAMESPACED(percent)(FLOAT_T x, FLOAT_T precision); +FLOAT_T CONSTFUNC NAMESPACED(with_precision)(FLOAT_T n, FLOAT_T precision); +FLOAT_T NAMESPACED(mod)(FLOAT_T n, FLOAT_T modulus); +FLOAT_T NAMESPACED(mod1)(FLOAT_T n, FLOAT_T modulus); +CONSTFUNC bool NAMESPACED(isinf)(FLOAT_T n); +CONSTFUNC bool NAMESPACED(finite)(FLOAT_T n); +CONSTFUNC bool NAMESPACED(isnan)(FLOAT_T n); +bool NAMESPACED(is_none)(const void *n, const TypeInfo_t *info); +FLOAT_T NAMESPACED(nan)(Text_t tag); +CONSTFUNC FLOAT_T NAMESPACED(mix)(FLOAT_T amount, FLOAT_T x, FLOAT_T y); +OPT_T NAMESPACED(parse)(Text_t text, Text_t *remainder); +CONSTFUNC bool NAMESPACED(is_between)(const FLOAT_T x, const FLOAT_T low, const FLOAT_T high); +CONSTFUNC FLOAT_T NAMESPACED(clamped)(FLOAT_T x, FLOAT_T low, FLOAT_T high); + +#if FLOATX_H__BITS == 64 +MACROLIKE CONSTFUNC FLOAT_T NAMESPACED(from_float32)(float n) { return (FLOAT_T)n; } +#elif FLOATX_H__BITS == 32 +MACROLIKE CONSTFUNC FLOAT_T NAMESPACED(from_float64)(double n) { return (FLOAT_T)n; } +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif +MACROLIKE CONSTFUNC FLOAT_T NAMESPACED(from_int)(Int_t i, bool truncate) { + if likely (i.small & 0x1) { + FLOAT_T ret = (FLOAT_T)(i.small >> 2); + if unlikely (!truncate && (int64_t)ret != (i.small >> 2)) + fail("Could not convert integer to " TYPE_STR " without losing precision: ", i.small >> 2); + return ret; + } else { + FLOAT_T ret = mpz_get_d(i.big); + if (!truncate) { + mpz_t roundtrip; + mpz_init_set_d(roundtrip, (double)ret); + if unlikely (mpz_cmp(i.big, roundtrip) != 0) + fail("Could not convert integer to " TYPE_STR " without losing precision: ", i); + } + return ret; + } +} +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +MACROLIKE CONSTFUNC FLOAT_T NAMESPACED(from_int64)(Int64_t i, bool truncate) { + FLOAT_T n = (FLOAT_T)i; + if unlikely (!truncate && (Int64_t)n != i) + fail("Could not convert integer to " TYPE_STR " without losing precision: ", i); + return n; +} +MACROLIKE CONSTFUNC FLOAT_T NAMESPACED(from_int32)(Int32_t i) { return (FLOAT_T)i; } +MACROLIKE CONSTFUNC FLOAT_T NAMESPACED(from_int16)(Int16_t i) { return (FLOAT_T)i; } +MACROLIKE CONSTFUNC FLOAT_T NAMESPACED(from_int8)(Int8_t i) { return (FLOAT_T)i; } +MACROLIKE CONSTFUNC FLOAT_T NAMESPACED(from_byte)(Byte_t i) { return (FLOAT_T)i; } + +extern const TypeInfo_t NAMESPACED(info); + +#undef FLOAT_T +#undef OPT_T +#undef NAMESPACED +#undef TYPE_STR +#undef SUFFIXED +#undef FLOATX_H__BITS diff --git a/src/stdlib/floats.h b/src/stdlib/floats.h new file mode 100644 index 00000000..c23974c1 --- /dev/null +++ b/src/stdlib/floats.h @@ -0,0 +1,13 @@ +// Type infos and methods for Floats (floating point numbers) + +#pragma once + +#define F64(n) ((double)(n)) +#define OptionalFloat64_t double +#define FLOATX_H__BITS 64 +#include "floatX.h" + +#define F32(n) ((float)(n)) +#define OptionalFloat32_t float +#define FLOATX_H__BITS 32 +#include "floatX.h" diff --git a/src/stdlib/intX.h b/src/stdlib/intX.h index 765543fd..03aa7247 100644 --- a/src/stdlib/intX.h +++ b/src/stdlib/intX.h @@ -88,16 +88,17 @@ MACROLIKE PUREFUNC INTX_T NAMESPACED(unsigned_right_shifted)(INTX_T x, INTX_T y) void NAMESPACED(serialize)(const void *obj, FILE *out, Table_t *, const TypeInfo_t *); void NAMESPACED(deserialize)(FILE *in, void *outval, List_t *, const TypeInfo_t *); -MACROLIKE PUREFUNC INTX_T NAMESPACED(from_num)(Num_t n, bool truncate) { +MACROLIKE PUREFUNC INTX_T NAMESPACED(from_float64)(Float64_t n, bool truncate) { INTX_T i = (INTX_T)n; - if (!truncate && unlikely((Num_t)i != n)) fail("Could not convert Num to an " NAME_STR " without truncation: ", n); + if (!truncate && unlikely((Float64_t)i != n)) + fail("Could not convert Float64 to an " NAME_STR " without truncation: ", n); return i; } -MACROLIKE PUREFUNC INTX_T NAMESPACED(from_num32)(Num32_t n, bool truncate) { +MACROLIKE PUREFUNC INTX_T NAMESPACED(from_float32)(Float32_t n, bool truncate) { INTX_T i = (INTX_T)n; - if (!truncate && unlikely((Num32_t)i != n)) - fail("Could not convert Num32 to an " NAME_STR " without truncation: ", n); + if (!truncate && unlikely((Float32_t)i != n)) + fail("Could not convert Float32 to an " NAME_STR " without truncation: ", n); return i; } diff --git a/src/stdlib/lists.c b/src/stdlib/lists.c index db514671..1a47f2e3 100644 --- a/src/stdlib/lists.c +++ b/src/stdlib/lists.c @@ -345,18 +345,18 @@ Table_t List$counts(List_t list, const TypeInfo_t *type) { return counts; } -static double _default_random_num(void *userdata) { +static double _default_random_float64(void *userdata) { (void)userdata; union { - Num_t num; + Float64_t n; uint64_t bits; - } r = {.bits = 0}, one = {.num = 1.0}; + } r = {.bits = 0}, one = {.n = 1.0}; assert(getrandom((uint8_t *)&r, sizeof(r), 0) == sizeof(r)); - // Set r.num to 1.<random-bits> + // Set r.n to 1.<random-bits> r.bits &= ~(0xFFFULL << 52); r.bits |= (one.bits & (0xFFFULL << 52)); - return r.num - 1.0; + return r.n - 1.0; } public @@ -419,7 +419,7 @@ List_t List$sample(List_t list, Int_t int_n, List_t weights, OptionalClosure_t r if (aliases[i].alias == -1) aliases[i].alias = i; typedef double (*rng_fn_t)(void *); - rng_fn_t rng_fn = random_num.fn ? (rng_fn_t)random_num.fn : _default_random_num; + rng_fn_t rng_fn = random_num.fn ? (rng_fn_t)random_num.fn : _default_random_float64; List_t selected = {.data = list.atomic ? GC_MALLOC_ATOMIC((size_t)(n * padded_item_size)) : GC_MALLOC((size_t)(n * padded_item_size)), diff --git a/src/stdlib/num32.c b/src/stdlib/num32.c deleted file mode 100644 index 6d505f37..00000000 --- a/src/stdlib/num32.c +++ /dev/null @@ -1,4 +0,0 @@ -// Type infos and methods for Num32 (32-bit floating point) using a template file - -#define NUMX_C_H__BITS 32 -#include "numX.c.h" diff --git a/src/stdlib/num64.c b/src/stdlib/num64.c deleted file mode 100644 index 7fdc8f35..00000000 --- a/src/stdlib/num64.c +++ /dev/null @@ -1,4 +0,0 @@ -// Type infos and methods for Num (64-bit floating point) using a template file - -#define NUMX_C_H__BITS 64 -#include "numX.c.h" diff --git a/src/stdlib/numX.h b/src/stdlib/numX.h deleted file mode 100644 index 3d65cb59..00000000 --- a/src/stdlib/numX.h +++ /dev/null @@ -1,103 +0,0 @@ -// Template header for 64 and 32 bit Nums -// This file expects `NUMX_H__BITS` to be defined before including: -// -// #define NUMX_H__BITS 64 -// #include "numX.h" -// - -#include <stdbool.h> -#include <stdint.h> - -#include "datatypes.h" -#include "stdlib.h" -#include "types.h" -#include "util.h" - -#ifndef NUMX_H__BITS -#define NUMX_H__BITS 64 -#endif - -#if NUMX_H__BITS == 64 -#define NUM_T double -#define OPT_T double -#define NAMESPACED(x) Num$##x -#define TYPE_STR "Num" -#define SUFFIXED(x) x -#elif NUMX_H__BITS == 32 -#define NUM_T float -#define OPT_T float -#define NAMESPACED(x) Num32$##x -#define TYPE_STR "Num32" -#define SUFFIXED(x) x##f -#else -#error "Unsupported bit width for Num" -#endif - -Text_t NAMESPACED(as_text)(const void *x, bool colorize, const TypeInfo_t *type); -Text_t NAMESPACED(value_as_text)(NUM_T x); -PUREFUNC int32_t NAMESPACED(compare)(const void *x, const void *y, const TypeInfo_t *type); -PUREFUNC bool NAMESPACED(equal)(const void *x, const void *y, const TypeInfo_t *type); -CONSTFUNC bool NAMESPACED(near)(NUM_T a, NUM_T b, NUM_T ratio, NUM_T absolute); -Text_t NAMESPACED(percent)(NUM_T x, NUM_T precision); -NUM_T CONSTFUNC NAMESPACED(with_precision)(NUM_T num, NUM_T precision); -NUM_T NAMESPACED(mod)(NUM_T num, NUM_T modulus); -NUM_T NAMESPACED(mod1)(NUM_T num, NUM_T modulus); -CONSTFUNC bool NAMESPACED(isinf)(NUM_T n); -CONSTFUNC bool NAMESPACED(finite)(NUM_T n); -CONSTFUNC bool NAMESPACED(isnan)(NUM_T n); -bool NAMESPACED(is_none)(const void *n, const TypeInfo_t *info); -NUM_T NAMESPACED(nan)(Text_t tag); -CONSTFUNC NUM_T NAMESPACED(mix)(NUM_T amount, NUM_T x, NUM_T y); -OPT_T NAMESPACED(parse)(Text_t text, Text_t *remainder); -CONSTFUNC bool NAMESPACED(is_between)(const NUM_T x, const NUM_T low, const NUM_T high); -CONSTFUNC NUM_T NAMESPACED(clamped)(NUM_T x, NUM_T low, NUM_T high); - -#if NUMX_H__BITS == 64 -MACROLIKE CONSTFUNC NUM_T NAMESPACED(from_num32)(float n) { return (NUM_T)n; } -#elif NUMX_H__BITS == 32 -MACROLIKE CONSTFUNC NUM_T NAMESPACED(from_num64)(double n) { return (NUM_T)n; } -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wfloat-equal" -#endif -MACROLIKE CONSTFUNC NUM_T NAMESPACED(from_int)(Int_t i, bool truncate) { - if likely (i.small & 0x1) { - NUM_T ret = (NUM_T)(i.small >> 2); - if unlikely (!truncate && (int64_t)ret != (i.small >> 2)) - fail("Could not convert integer to " TYPE_STR " without losing precision: ", i.small >> 2); - return ret; - } else { - NUM_T ret = mpz_get_d(i.big); - if (!truncate) { - mpz_t roundtrip; - mpz_init_set_d(roundtrip, (double)ret); - if unlikely (mpz_cmp(i.big, roundtrip) != 0) - fail("Could not convert integer to " TYPE_STR " without losing precision: ", i); - } - return ret; - } -} -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif -MACROLIKE CONSTFUNC NUM_T NAMESPACED(from_int64)(Int64_t i, bool truncate) { - NUM_T n = (NUM_T)i; - if unlikely (!truncate && (Int64_t)n != i) - fail("Could not convert integer to " TYPE_STR " without losing precision: ", i); - return n; -} -MACROLIKE CONSTFUNC NUM_T NAMESPACED(from_int32)(Int32_t i) { return (NUM_T)i; } -MACROLIKE CONSTFUNC NUM_T NAMESPACED(from_int16)(Int16_t i) { return (NUM_T)i; } -MACROLIKE CONSTFUNC NUM_T NAMESPACED(from_int8)(Int8_t i) { return (NUM_T)i; } -MACROLIKE CONSTFUNC NUM_T NAMESPACED(from_byte)(Byte_t i) { return (NUM_T)i; } - -extern const TypeInfo_t NAMESPACED(info); - -#undef NUM_T -#undef OPT_T -#undef NAMESPACED -#undef TYPE_STR -#undef SUFFIXED -#undef NUMX_H__BITS diff --git a/src/stdlib/nums.h b/src/stdlib/nums.h deleted file mode 100644 index 8cea9e84..00000000 --- a/src/stdlib/nums.h +++ /dev/null @@ -1,13 +0,0 @@ -// Type infos and methods for Nums (floating point) - -#pragma once - -#define N64(n) ((double)(n)) -#define OptionalNum_t double -#define NUMX_H__BITS 64 -#include "numX.h" - -#define N32(n) ((float)(n)) -#define OptionalNum32_t float -#define NUMX_H__BITS 32 -#include "numX.h" diff --git a/src/stdlib/optionals.c b/src/stdlib/optionals.c index 3fe812b1..b2cd584d 100644 --- a/src/stdlib/optionals.c +++ b/src/stdlib/optionals.c @@ -3,8 +3,8 @@ #include <math.h> #include "datatypes.h" +#include "floats.h" #include "metamethods.h" -#include "nums.h" #include "optionals.h" #include "text.h" #include "util.h" @@ -66,8 +66,8 @@ void Optional$deserialize(FILE *in, void *outval, List_t *pointers, const TypeIn if (nonnull->tag == TextInfo) *(Text_t *)outval = NONE_TEXT; else if (nonnull->tag == ListInfo) *(List_t *)outval = NONE_LIST; else if (nonnull->tag == TableInfo) *(Table_t *)outval = NONE_TABLE; - else if (nonnull == &Num$info) *(double *)outval = (double)NAN; - else if (nonnull == &Num32$info) *(float *)outval = (float)NAN; + else if (nonnull == &Float64$info) *(double *)outval = (double)NAN; + else if (nonnull == &Float32$info) *(float *)outval = (float)NAN; else if (nonnull->tag == StructInfo || (nonnull->tag == OpaqueInfo && type->size > nonnull->size)) memset(outval + type->size, -1, (size_t)(type->size - nonnull->size)); else memset(outval, 0, (size_t)type->size); diff --git a/src/stdlib/reals.c b/src/stdlib/reals.c index a48cd9f2..0cfcfc81 100644 --- a/src/stdlib/reals.c +++ b/src/stdlib/reals.c @@ -6,7 +6,7 @@ #include "bigint.h" #include "datatypes.h" -#include "nums.h" +#include "floats.h" #include "text.h" struct ieee754_bits { @@ -54,10 +54,10 @@ static Int_t Real$compute_double(Real_t r, int64_t precision) { if (data.bits.biased_exponent + precision > 2047) { int64_t double_shift = 2047 - data.bits.biased_exponent; data.bits.biased_exponent += double_shift; - return Int$left_shifted(Int$from_num(data.n, true), Int$from_int64(precision - double_shift)); + return Int$left_shifted(Int$from_float64(data.n, true), Int$from_int64(precision - double_shift)); } else { data.bits.biased_exponent += precision; - return Int$from_num(data.n, true); + return Int$from_float64(data.n, true); } } @@ -67,26 +67,27 @@ double Real$as_float64(Real_t x) { int64_t my_msd = most_significant_bit(x, -1080 /* slightly > exp. range */); if (my_msd == INT64_MIN) return 0.0; int needed_prec = my_msd - 60; - double scaled_int = Num$from_int(Real$compute(x, needed_prec), true); + union { + double d; + uint64_t bits; + } scaled_int = {.d = Float64$from_int(Real$compute(x, needed_prec), true)}; bool may_underflow = (needed_prec < -1000); - int64_t scaled_int_rep = *(int64_t *)&scaled_int; - long exp_adj = may_underflow ? needed_prec + 96 : needed_prec; - long orig_exp = (scaled_int_rep >> 52) & 0x7ff; - if (((orig_exp + exp_adj) & ~0x7ff) != 0) { + uint64_t exp_adj = may_underflow ? (uint64_t)(needed_prec + 96l) : (uint64_t)needed_prec; + uint64_t orig_exp = (scaled_int.bits >> 52) & 0x7fful; + if (((orig_exp + exp_adj) & ~0x7fful) != 0) { // overflow - if (scaled_int < 0.0) { + if (scaled_int.d < 0.0) { return -INFINITY; } else { return INFINITY; } } - scaled_int_rep += exp_adj << 52; - double result = *(double *)&scaled_int_rep; + scaled_int.bits += exp_adj << 52; if (may_underflow) { double two48 = (double)(1L << 48); - return result / two48 / two48; + return scaled_int.d / two48 / two48; } else { - return result; + return scaled_int.d; } return 0.0; @@ -148,7 +149,7 @@ static Int_t Real$compute_times(Real_t r, int64_t precision) { Int_t approx_small = Real$compute(big, precision - MAX(lhs_msb, rhs_msb) - 3); if (approx_small.small == 0x1) return I(0); - Int_t approx_big = Real$compute(big, precision - MIN(lhs_msb, rhs_msb) - 3); + Int_t approx_big = Real$compute(small, precision - MIN(lhs_msb, rhs_msb) - 3); if (approx_big.small == 0x1) return I(0); return Int$right_shifted(Int$times(approx_big, approx_small), Int$from_int64(lhs_msb + rhs_msb - precision)); @@ -194,10 +195,10 @@ static Int_t Real$compute_sqrt(Real_t r, int64_t precision) { int64_t op_prec = (msd - fp_op_prec) & ~1L; int64_t working_prec = op_prec - fp_op_prec; Int_t scaled_bi_appr = Int$left_shifted(Real$compute(operand, op_prec), Int$from_int64(fp_op_prec)); - double scaled_appr = Num$from_int(scaled_bi_appr, true); + double scaled_appr = Float64$from_int(scaled_bi_appr, true); if (scaled_appr < 0.0) fail("Underflow?!?!"); double scaled_fp_sqrt = sqrt(scaled_appr); - Int_t scaled_sqrt = Int$from_num(scaled_fp_sqrt, true); + Int_t scaled_sqrt = Int$from_float64(scaled_fp_sqrt, true); int64_t shift_count = working_prec / 2 - precision; return Int$left_shifted(scaled_sqrt, Int$from_int64(shift_count)); } diff --git a/src/stdlib/stdlib.c b/src/stdlib/stdlib.c index 45a4bd00..c3ea1d36 100644 --- a/src/stdlib/stdlib.c +++ b/src/stdlib/stdlib.c @@ -204,7 +204,7 @@ cleanup: } public -void sleep_num(double seconds) { +void sleep_float64(double seconds) { struct timespec ts; ts.tv_sec = (time_t)seconds; ts.tv_nsec = (long)((seconds - (double)ts.tv_sec) * 1e9); diff --git a/src/stdlib/text.h b/src/stdlib/text.h index 821325a9..15630858 100644 --- a/src/stdlib/text.h +++ b/src/stdlib/text.h @@ -7,9 +7,9 @@ #include <stdint.h> #include "datatypes.h" +#include "floats.h" // IWYU pragma: export #include "integers.h" // IWYU pragma: export #include "mapmacro.h" -#include "nums.h" // IWYU pragma: export #include "types.h" #include "util.h" @@ -42,8 +42,8 @@ static inline Text_t Text_from_text(Text_t t) { return t; } int16_t: Int16$value_as_text, \ int32_t: Int32$value_as_text, \ int64_t: Int64$value_as_text, \ - double: Num$value_as_text, \ - float: Num32$value_as_text)(x) + double: Float64$value_as_text, \ + float: Float32$value_as_text)(x) Text_t Text$_concat(int n, Text_t items[n]); #define Text$concat(...) Text$_concat(sizeof((Text_t[]){__VA_ARGS__}) / sizeof(Text_t), (Text_t[]){__VA_ARGS__}) diff --git a/src/stdlib/tomo.h b/src/stdlib/tomo.h index 1ff065b9..4abf8856 100644 --- a/src/stdlib/tomo.h +++ b/src/stdlib/tomo.h @@ -15,12 +15,12 @@ #include "datatypes.h" // IWYU pragma: export #include "enums.h" // IWYU pragma: export #include "files.h" // IWYU pragma: export +#include "floats.h" // IWYU pragma: export #include "functiontype.h" // IWYU pragma: export #include "integers.h" // IWYU pragma: export #include "lists.h" // IWYU pragma: export #include "memory.h" // IWYU pragma: export #include "metamethods.h" // IWYU pragma: export -#include "nums.h" // IWYU pragma: export #include "optionals.h" // IWYU pragma: export #include "paths.h" // IWYU pragma: export #include "pointers.h" // IWYU pragma: export |
