diff options
Diffstat (limited to 'src/stdlib/nums.c')
| -rw-r--r-- | src/stdlib/nums.c | 214 |
1 files changed, 115 insertions, 99 deletions
diff --git a/src/stdlib/nums.c b/src/stdlib/nums.c index 83166659..05ed14a8 100644 --- a/src/stdlib/nums.c +++ b/src/stdlib/nums.c @@ -13,20 +13,21 @@ #include "text.h" #include "types.h" -public PUREFUNC Text_t Num$as_text(const void *f, bool colorize, const TypeInfo_t *info) { +public +PUREFUNC Text_t Num$as_text(const void *f, bool colorize, const TypeInfo_t *info) { (void)info; if (!f) return Text("Num"); char *str = GC_MALLOC_ATOMIC(24); - int len = fpconv_dtoa(*(double*)f, str); + int len = fpconv_dtoa(*(double *)f, str); static const Text_t color_prefix = Text("\x1b[35m"), color_suffix = Text("\x1b[m"); Text_t text = Text$from_strn(str, (size_t)len); return colorize ? Texts(color_prefix, text, color_suffix) : text; -} +} -public PUREFUNC int32_t Num$compare(const void *x, const void *y, const TypeInfo_t *info) { +public +PUREFUNC int32_t Num$compare(const void *x, const void *y, const TypeInfo_t *info) { (void)info; - int64_t rx = *(int64_t*)x, - ry = *(int64_t*)y; + int64_t rx = *(int64_t *)x, ry = *(int64_t *)y; if (rx == ry) return 0; @@ -34,14 +35,16 @@ public PUREFUNC int32_t Num$compare(const void *x, const void *y, const TypeInfo 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 *info) { +public +PUREFUNC bool Num$equal(const void *x, const void *y, const TypeInfo_t *info) { (void)info; - return *(double*)x == *(double*)y; -} + return *(double *)x == *(double *)y; +} -public CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute) { +public +CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute) { if (ratio < 0) ratio = 0; else if (ratio > 1) ratio = 1; @@ -56,17 +59,19 @@ public CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute return (diff < epsilon); } -public Text_t Num$percent(double f, double precision) { +public +Text_t Num$percent(double f, double precision) { double d = 100. * f; d = Num$with_precision(d, precision); return Texts(Num$as_text(&d, false, &Num$info), Text("%")); } -public CONSTFUNC double Num$with_precision(double num, double precision) { +public +CONSTFUNC double Num$with_precision(double num, double precision) { if (precision == 0.0) return num; // Precision will be, e.g. 0.01 or 100. if (precision < 1.) { - double inv = round(1./precision); // Necessary to make the math work + double inv = round(1. / precision); // Necessary to make the math work double k = num * inv; return round(k) / inv; } else { @@ -75,37 +80,34 @@ public CONSTFUNC double Num$with_precision(double num, double precision) { } } -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 +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; + 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$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 +CONSTFUNC double Num$mix(double amount, double x, double y) { return (1.0 - amount) * x + amount * y; } -public CONSTFUNC bool Num$is_between(const double x, const double low, const double high) { - return low <= x && x <= high; -} -public CONSTFUNC double Num$clamped(double x, double low, double high) { - return (x <= low) ? low : (x >= high ? high : x); -} +public +CONSTFUNC bool Num$is_between(const double x, const double low, const double high) { return low <= x && x <= high; } +public +CONSTFUNC double Num$clamped(double x, double low, double high) { return (x <= low) ? low : (x >= high ? high : x); } -public OptionalNum_t Num$parse(Text_t text, Text_t *remainder) { +public +OptionalNum_t Num$parse(Text_t text, Text_t *remainder) { const char *str = Text$as_c_string(text); char *end = NULL; double d = strtod(str, &end); if (end > str) { - if (remainder) - *remainder = Text$from_str(end); - else if (*end != '\0') - return nan("none"); + if (remainder) *remainder = Text$from_str(end); + else if (*end != '\0') return nan("none"); return d; } else { if (remainder) *remainder = text; @@ -113,45 +115,54 @@ public OptionalNum_t Num$parse(Text_t text, Text_t *remainder) { } } -public CONSTFUNC bool Num$is_none(const void *n, const TypeInfo_t *info) -{ +public +CONSTFUNC bool Num$is_none(const void *n, const TypeInfo_t *info) { (void)info; - 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, - }, + 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 *info) { +public +PUREFUNC Text_t Num32$as_text(const void *f, bool colorize, const TypeInfo_t *info) { (void)info; if (!f) return Text("Num32"); - double d = (double)(*(float*)f); + double d = (double)(*(float *)f); return Num$as_text(&d, colorize, &Num$info); } -public PUREFUNC int32_t Num32$compare(const void *x, const void *y, const TypeInfo_t *info) { +public +PUREFUNC int32_t Num32$compare(const void *x, const void *y, const TypeInfo_t *info) { (void)info; - return (*(float*)x > *(float*)y) - (*(float*)x < *(float*)y); -} + return (*(float *)x > *(float *)y) - (*(float *)x < *(float *)y); +} -public PUREFUNC bool Num32$equal(const void *x, const void *y, const TypeInfo_t *info) { +public +PUREFUNC bool Num32$equal(const void *x, const void *y, const TypeInfo_t *info) { (void)info; - return *(float*)x == *(float*)y; + return *(float *)x == *(float *)y; } -public CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute) { +public +CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute) { if (ratio < 0) ratio = 0; else if (ratio > 1) ratio = 1; @@ -166,17 +177,19 @@ public CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute) return (diff < epsilon); } -public Text_t Num32$percent(float f, float precision) { +public +Text_t Num32$percent(float f, float precision) { double d = 100. * (double)f; d = Num$with_precision(d, (double)precision); return Texts(Num$as_text(&d, false, &Num$info), Text("%")); } -public CONSTFUNC float Num32$with_precision(float num, float precision) { +public +CONSTFUNC float Num32$with_precision(float num, float precision) { if (precision == 0.0f) return num; // Precision will be, e.g. 0.01 or 100. if (precision < 1.f) { - float inv = roundf(1.f/precision); // Necessary to make the math work + float inv = roundf(1.f / precision); // Necessary to make the math work float k = num * inv; return roundf(k) / inv; } else { @@ -185,37 +198,35 @@ public CONSTFUNC float Num32$with_precision(float num, float precision) { } } -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 +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; + 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$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 +CONSTFUNC float Num32$mix(float amount, float x, float y) { return (1.0f - amount) * x + amount * y; } -public CONSTFUNC bool Num32$is_between(const float x, const float low, const float high) { - return low <= x && x <= high; -} +public +CONSTFUNC bool Num32$is_between(const float x, const float low, const float high) { return low <= x && x <= high; } -public CONSTFUNC float Num32$clamped(float x, float low, float high) { - return (x <= low) ? low : (x >= high ? high : x); -} +public +CONSTFUNC float Num32$clamped(float x, float low, float high) { return (x <= low) ? low : (x >= high ? high : x); } -public OptionalNum32_t Num32$parse(Text_t text, Text_t *remainder) { +public +OptionalNum32_t Num32$parse(Text_t text, Text_t *remainder) { const char *str = Text$as_c_string(text); char *end = NULL; double d = strtod(str, &end); if (end > str && end[0] == '\0') { if (remainder) *remainder = Text$from_str(end); - else if (*end != '\0') - return nan("none"); + else if (*end != '\0') return nan("none"); return d; } else { if (remainder) *remainder = text; @@ -223,25 +234,30 @@ public OptionalNum32_t Num32$parse(Text_t text, Text_t *remainder) { } } -public CONSTFUNC bool Num32$is_none(const void *n, const TypeInfo_t *info) -{ +public +CONSTFUNC bool Num32$is_none(const void *n, const TypeInfo_t *info) { (void)info; - 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, - }, + 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 |
