diff --git a/apps/test-fpclassify.c b/apps/test-fpclassify.c new file mode 100644 index 00000000..f50ca4f5 --- /dev/null +++ b/apps/test-fpclassify.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +int main(int argc, char * argv[]) { + if (argc < 2) return 1; + + union { + double asFloat; + uint64_t asInt; + } bits; + + if (!strcmp(argv[1], "inf")) { + bits.asFloat = INFINITY; + } else if (!strcmp(argv[1], "nan")) { + bits.asFloat = NAN; + } else { + bits.asFloat = strtod(argv[1], NULL); + } + + printf("0x%016zx %d\n", bits.asInt, fpclassify(bits.asFloat)); + return 0; +} diff --git a/base/usr/include/math.h b/base/usr/include/math.h index eb3709ec..d616bde3 100644 --- a/base/usr/include/math.h +++ b/base/usr/include/math.h @@ -46,4 +46,26 @@ extern double modf(double x, double *iptr); extern double hypot(double x, double y); +extern double trunc(double x); +extern double acosh(double x); +extern double asinh(double x); +extern double atanh(double x); +extern double erf(double x); +extern double erfc(double x); +extern double gamma(double x); +extern double lgamma(double x); +extern double copysign(double x, double y); +extern double remainder(double x, double y); + +enum { + FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL +}; + +extern int fpclassify(double x); + +#define isfinite(x) ((fpclassify(x) != FP_NAN && fpclassify(x) != FP_INFINITE)) +#define isnormal(x) (fpclassify(x) == FP_NORMAL) +#define isnan(x) (fpclassify(x) == FP_NAN) +#define isinf(x) (fpclassify(x) == FP_INFINITE) + _End_C_Header diff --git a/libc/math/bad.c b/libc/math/bad.c index a42b934b..934e6e06 100644 --- a/libc/math/bad.c +++ b/libc/math/bad.c @@ -49,3 +49,28 @@ double expm1(double x) { BAD; return exp(x) - 1.0; } + +double trunc(double x) { + BAD; + return (double)(long)x; +} + +double acosh(double x) { BAD; return 0.0; } +double asinh(double x) { BAD; return 0.0; } +double atanh(double x) { BAD; return 0.0; } +double erf(double x) { BAD; return 0.0; } +double erfc(double x) { BAD; return 0.0; } +double gamma(double x) { BAD; return 0.0; } +double lgamma(double x){ BAD; return 0.0; } +double remainder(double x, double y) { BAD; return 0.0; } + +double copysign(double x, double y) { + if (y < 0) { + if (x < 0) return x; + return -x; + } else { + if (x < 0) return -x; + return x; + } +} + diff --git a/libc/math/math.c b/libc/math/math.c index 44bc406d..bc3e1eff 100644 --- a/libc/math/math.c +++ b/libc/math/math.c @@ -469,3 +469,18 @@ double tanh(double x) { return (exp(2.0*x) - 1.0) / (exp(2.0*x) + 1.0); } +int fpclassify(double x) { + union { + double asFloat; + uint64_t asInt; + } bits = {x}; + uint64_t exponent = (bits.asInt >> 52) & 0x7FF; + uint64_t mantissa = (bits.asInt & 0xFffffFFFFffffULL); + + if (exponent == 0x7FF) { + return mantissa ? FP_NAN : FP_INFINITE; + } else if (exponent == 0) { + return mantissa ? FP_SUBNORMAL : FP_ZERO; + } + return FP_NORMAL; +}