diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-03-21 21:48:53 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-03-21 21:48:53 -0400 |
| commit | 5ee185a4896e43c67b6d299becfa616da78fb9f4 (patch) | |
| tree | 183ceef2fd21230c89334d7d039255d1c86c5dca /stdlib/nums.c | |
| parent | f4aaf7b73481248f6768302be688700a364a1af8 (diff) | |
Move stdlib into src/
Diffstat (limited to 'stdlib/nums.c')
| -rw-r--r-- | stdlib/nums.c | 186 |
1 files changed, 0 insertions, 186 deletions
diff --git a/stdlib/nums.c b/stdlib/nums.c deleted file mode 100644 index 98f7b509..00000000 --- a/stdlib/nums.c +++ /dev/null @@ -1,186 +0,0 @@ -// Type infos and methods for Nums (floating point) - -#include <float.h> -#include <gc.h> -#include <math.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> - -#include "arrays.h" -#include "nums.h" -#include "string.h" -#include "text.h" -#include "types.h" - -public PUREFUNC Text_t Num$as_text(const void *f, bool colorize, const TypeInfo_t*) { - if (!f) return Text("Num"); - return Text$format(colorize ? "\x1b[35m%.16g\x1b[33;2m\x1b[m" : "%.16g", *(double*)f); -} - -public PUREFUNC int32_t Num$compare(const void *x, const void *y, const TypeInfo_t*) { - int64_t rx = *(int64_t*)x, - ry = *(int64_t*)y; - - if (rx == ry) return 0; - - if (rx < 0) rx ^= INT64_MAX; - if (ry < 0) ry ^= INT64_MAX; - - return (rx > ry) - (rx < ry); -} - -public PUREFUNC bool Num$equal(const void *x, const void *y, const TypeInfo_t*) { - return *(double*)x == *(double*)y; -} - -public CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute) { - if (ratio < 0) ratio = 0; - else if (ratio > 1) ratio = 1; - - if (a == b) return true; - - double diff = fabs(a - b); - if (diff < absolute) return true; - else if (isnan(diff)) return false; - - double epsilon = fabs(a * ratio) + fabs(b * ratio); - if (isinf(epsilon)) epsilon = DBL_MAX; - return (diff < epsilon); -} - -public Text_t Num$format(double f, Int_t precision) { - return Text$format("%.*f", (int)Int64$from_int(precision, false), f); -} - -public Text_t Num$scientific(double f, Int_t precision) { - return Text$format("%.*e", (int)Int64$from_int(precision, false), f); -} - -public CONSTFUNC double Num$mod(double num, double modulus) { - // Euclidean division, see: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf - double r = remainder(num, modulus); - r -= (r < 0) * (2*(modulus < 0) - 1) * modulus; - return r; -} - -public CONSTFUNC double Num$mod1(double num, double modulus) { - return 1.0 + Num$mod(num-1, modulus); -} - -public CONSTFUNC double Num$mix(double amount, double x, double y) { - return (1.0-amount)*x + amount*y; -} - -public OptionalNum_t Num$parse(Text_t text) { - const char *str = Text$as_c_string(text); - char *end = NULL; - double d = strtod(str, &end); - if (end > str && end[0] == '\0') - return d; - else - return nan("null"); -} - -static bool Num$is_none(const void *n, const TypeInfo_t*) -{ - return isnan(*(Num_t*)n); -} - -public CONSTFUNC bool Num$isinf(double n) { return (fpclassify(n) == FP_INFINITE); } -public CONSTFUNC bool Num$finite(double n) { return (fpclassify(n) != FP_INFINITE); } -public CONSTFUNC bool Num$isnan(double n) { return (fpclassify(n) == FP_NAN); } - -public const TypeInfo_t Num$info = { - .size=sizeof(double), - .align=__alignof__(double), - .metamethods={ - .compare=Num$compare, - .equal=Num$equal, - .as_text=Num$as_text, - .is_none=Num$is_none, - }, -}; - -public PUREFUNC Text_t Num32$as_text(const void *f, bool colorize, const TypeInfo_t*) { - if (!f) return Text("Num32"); - return Text$format(colorize ? "\x1b[35m%.8g\x1b[33;2m\x1b[m" : "%.8g", (double)*(float*)f); -} - -public PUREFUNC int32_t Num32$compare(const void *x, const void *y, const TypeInfo_t*) { - return (*(float*)x > *(float*)y) - (*(float*)x < *(float*)y); -} - -public PUREFUNC bool Num32$equal(const void *x, const void *y, const TypeInfo_t*) { - return *(float*)x == *(float*)y; -} - -public CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute) { - if (ratio < 0) ratio = 0; - else if (ratio > 1) ratio = 1; - - if (a == b) return true; - - float diff = fabs(a - b); - if (diff < absolute) return true; - else if (isnan(diff)) return false; - - float epsilon = fabs(a * ratio) + fabs(b * ratio); - if (isinf(epsilon)) epsilon = FLT_MAX; - return (diff < epsilon); -} - -public Text_t Num32$format(float f, Int_t precision) { - return Text$format("%.*f", (int)Int64$from_int(precision, false), (double)f); -} - -public Text_t Num32$scientific(float f, Int_t precision) { - return Text$format("%.*e", (int)Int64$from_int(precision, false), (double)f); -} - -public CONSTFUNC float Num32$mod(float num, float modulus) { - // Euclidean division, see: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf - float r = remainderf(num, modulus); - r -= (r < 0) * (2*(modulus < 0) - 1) * modulus; - return r; -} - -public CONSTFUNC float Num32$mod1(float num, float modulus) { - return 1.0f + Num32$mod(num-1, modulus); -} - -public CONSTFUNC float Num32$mix(float amount, float x, float y) { - return (1.0f-amount)*x + amount*y; -} - -public OptionalNum32_t Num32$parse(Text_t text) { - const char *str = Text$as_c_string(text); - char *end = NULL; - double d = strtod(str, &end); - if (end > str && end[0] == '\0') - return d; - else - return nan("null"); -} - -static bool Num32$is_none(const void *n, const TypeInfo_t*) -{ - return isnan(*(Num32_t*)n); -} - -public CONSTFUNC bool Num32$isinf(float n) { return (fpclassify(n) == FP_INFINITE); } -public CONSTFUNC bool Num32$finite(float n) { return (fpclassify(n) != FP_INFINITE); } -public CONSTFUNC bool Num32$isnan(float n) { return (fpclassify(n) == FP_NAN); } - -public const TypeInfo_t Num32$info = { - .size=sizeof(float), - .align=__alignof__(float), - .metamethods={ - .compare=Num32$compare, - .equal=Num32$equal, - .as_text=Num32$as_text, - .is_none=Num32$is_none, - }, -}; - -// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 |
