aboutsummaryrefslogtreecommitdiff
path: root/builtins
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-03-03 17:14:11 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-03-03 17:14:11 -0500
commitc607b97732c9922aa6fef3a0fe1055b028d5f0c2 (patch)
treec314f3fb014d34b919998f58c701b2a0b800515a /builtins
parentc5f315e338adb09bcfc4c192ccefedfaf88202fe (diff)
Add Num.near() function
Diffstat (limited to 'builtins')
-rw-r--r--builtins/nums.c36
-rw-r--r--builtins/nums.h8
2 files changed, 34 insertions, 10 deletions
diff --git a/builtins/nums.c b/builtins/nums.c
index 26bc1457..ec4c445b 100644
--- a/builtins/nums.c
+++ b/builtins/nums.c
@@ -1,8 +1,6 @@
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
#include <gc.h>
#include <gc/cord.h>
+#include <float.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
@@ -33,6 +31,21 @@ public bool Num__equal(const double *x, const double *y, const TypeInfo *type) {
return *x == *y;
}
+public bool Num__near(double a, double b, double ratio, double absolute) {
+ if (ratio < 0) ratio = 0;
+ else if (ratio > 0) 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 CORD Num__format(double f, int64_t precision) {
return CORD_asprintf("%.*f", (int)precision, f);
}
@@ -86,7 +99,22 @@ public int32_t Num32__compare(const float *x, const float *y, const TypeInfo *ty
public bool Num32__equal(const float *x, const float *y, const TypeInfo *type) {
(void)type;
return *x == *y;
-}
+}
+
+public bool Num32__near(float a, float b, float ratio, float absolute) {
+ if (ratio < 0) ratio = 0;
+ else if (ratio > 0) 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 CORD Num32__format(float f, int64_t precision) {
return CORD_asprintf("%.*f", (int)precision, f);
diff --git a/builtins/nums.h b/builtins/nums.h
index e8fdceaa..a468e928 100644
--- a/builtins/nums.h
+++ b/builtins/nums.h
@@ -12,6 +12,7 @@
CORD Num__as_str(const double *f, bool colorize, const TypeInfo *type);
int32_t Num__compare(const double *x, const double *y, const TypeInfo *type);
bool Num__equal(const double *x, const double *y, const TypeInfo *type);
+bool Num__near(double a, double b, double ratio, double absolute);
CORD Num__format(double f, int64_t precision);
CORD Num__scientific(double f, int64_t precision);
double Num__mod(double num, double modulus);
@@ -25,9 +26,6 @@ C(2_SQRTPI) C(E) C(PI_2) C(2_PI) C(1_PI) C(LN10) C(LN2) C(LOG2E) C(PI) C(PI_4) C
const double Num__INF = INFINITY, Num__TAU = 2.*M_PI;
#undef C
double Num__random(void);
-bool Num__finite(double n);
-bool Num__isinf(double n);
-bool Num__isnan(double n);
#define F(name) double (*Num__##name)(double n) = name;
double (*Num__abs)(double) = fabs;
F(acos) F(acosh) F(asin) F(asinh) F(atan) F(atanh) F(cbrt) F(ceil) F(cos) F(cosh) F(erf) F(erfc)
@@ -43,6 +41,7 @@ extern const TypeInfo Num;
CORD Num32__as_str(const float *f, bool colorize, const TypeInfo *type);
int32_t Num32__compare(const float *x, const float *y, const TypeInfo *type);
bool Num32__equal(const float *x, const float *y, const TypeInfo *type);
+bool Num32__near(float a, float b, float ratio, float absolute);
CORD Num32__format(float f, int64_t precision);
CORD Num32__scientific(float f, int64_t precision);
float Num32__mod(float num, float modulus);
@@ -55,9 +54,6 @@ C(2_SQRTPI) C(E) C(PI_2) C(2_PI) C(1_PI) C(LN10) C(LN2) C(LOG2E) C(PI) C(PI_4) C
const float Num32__INF = INFINITY, Num32__TAU = 2.*M_PI;
#undef C
float Num32__random(void);
-bool Num32__finite(float n);
-bool Num32__isinf(float n);
-bool Num32__isnan(float n);
float Num32__nan(CORD tag);
#define F(name) float (*Num32__##name)(float n) = name##f;
float (*Num32__abs)(float) = fabsf;