aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-11-09 18:42:16 -0500
committerBruce Hill <bruce@bruce-hill.com>2025-11-09 18:42:16 -0500
commit1d461611bac782c272d0e082d5da74b4fe353ae6 (patch)
tree0b1687a3edb507835f9aa3b7666fd590975b73ff /src/stdlib
parent78fd9141bb7dfcf817158a7a4d098e0e4b3d515b (diff)
Rename Num -> Float64, Num32 -> Float32
Diffstat (limited to 'src/stdlib')
-rw-r--r--src/stdlib/README.md4
-rw-r--r--src/stdlib/bigint.h5
-rw-r--r--src/stdlib/cli.c18
-rw-r--r--src/stdlib/datatypes.h4
-rw-r--r--src/stdlib/float32.c4
-rw-r--r--src/stdlib/float64.c4
-rw-r--r--src/stdlib/floatX.c.h (renamed from src/stdlib/numX.c.h)104
-rw-r--r--src/stdlib/floatX.h103
-rw-r--r--src/stdlib/floats.h13
-rw-r--r--src/stdlib/intX.h11
-rw-r--r--src/stdlib/lists.c12
-rw-r--r--src/stdlib/num32.c4
-rw-r--r--src/stdlib/num64.c4
-rw-r--r--src/stdlib/numX.h103
-rw-r--r--src/stdlib/nums.h13
-rw-r--r--src/stdlib/optionals.c6
-rw-r--r--src/stdlib/reals.c33
-rw-r--r--src/stdlib/stdlib.c2
-rw-r--r--src/stdlib/text.h6
-rw-r--r--src/stdlib/tomo.h2
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