From ed40dc436e0a13f502b9621a72fc9b676e456437 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Sun, 23 Apr 2023 17:56:33 +0900 Subject: [PATCH] libc: Add some missing bit-twiddly libm functions --- base/usr/include/math.h | 5 ++++ libc/math/math.c | 56 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/base/usr/include/math.h b/base/usr/include/math.h index 084cb56b..8ba8355d 100644 --- a/base/usr/include/math.h +++ b/base/usr/include/math.h @@ -69,4 +69,9 @@ extern int fpclassify(double x); #define isnan(x) (fpclassify(x) == FP_NAN) #define isinf(x) (fpclassify(x) == FP_INFINITE) +extern float ceilf(float x); +extern double round(double x); +extern float roundf(float x); +extern long lroundf(float x); + _End_C_Header diff --git a/libc/math/math.c b/libc/math/math.c index bc3e1eff..509bdbb2 100644 --- a/libc/math/math.c +++ b/libc/math/math.c @@ -484,3 +484,59 @@ int fpclassify(double x) { } return FP_NORMAL; } + +double ceil(double x) { + union { + double asFloat; + uint64_t asInt; + } bits = {x}; + int64_t exponent = ((bits.asInt >> 52) & 0x7FF) - 0x3ff; + uint64_t mantissa = (bits.asInt & 0xFffffFFFFffffULL); + if (exponent >= 52 || x == 0) return x; + if (exponent <= -1) return (bits.asInt >> 63) ? -0.0 : 1.0; + uint64_t mask = (0xfffffFFFFffffULL >> exponent); + if (!(mask & mantissa)) return x; + if (!(bits.asInt >> 63)) { + bits.asInt += mask; + } + bits.asInt &= ~mask; + return bits.asFloat; +} + +double round(double x) { + union { + double asFloat; + uint64_t asInt; + } bits = {x}; + int64_t exponent = ((bits.asInt >> 52) & 0x7FF) - 0x3ff; + uint64_t mantissa = (bits.asInt & 0xFffffFFFFffffULL); + if (exponent >= 52 || x == 0) return x; + if (exponent < -1) return (bits.asInt >> 63) ? -0.0 : 0.0; + if (exponent == -1) return x >= 0.5 ? 1.0 : (x <= -0.5 ? -1.0 : ((bits.asInt >> 63) ? -0.0 : 0.0)); + + uint64_t mask = 0xfffffFFFFffffULL >> exponent; + uint64_t a = mantissa & mask; + uint64_t b = mantissa & (mask >> 1); + + if (a & ~b) { + bits.asInt += mask; + bits.asInt &= ~mask; + return bits.asFloat; + } + + bits.asInt &= ~mask; + return bits.asFloat; +} + +float ceilf(float x) { + return ceil(x); +} + +float roundf(float x) { + return round(x); +} + +long lroundf(float x) { + return round(x); +} +