Skip to content

Commit

Permalink
Added _fpclassifyf and _isnormalf
Browse files Browse the repository at this point in the history
  • Loading branch information
ZERICO2005 authored and mateoconlechuga committed Oct 25, 2024
1 parent 7eea9f9 commit 343bbf3
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
56 changes: 56 additions & 0 deletions src/libc/fpclassify.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <math.h>
#include <stdint.h>

#if 0

/* Portable version */

int _fpclassifyf(float x)
{
return
isnan(x) ? FP_NAN :
isinf(x) ? FP_INFINITE :
(x == 0.0f) ? FP_ZERO :
isnormal(x) ? FP_NORMAL :
FP_SUBNORMAL;
}

#else

/* Bitwise version */

typedef union Float32_Bitwise {
float flt_part;
uint32_t u32_part;
uint24_t u24_part;
} Float32_Bitwise;

#define Float32_Exponent_Mask INT32_C(0x7F800000)
#define Float32_Mantissa_Mask INT32_C(0x007FFFFF)

int _fpclassifyf(float x)
{
Float32_Bitwise x_bin;
x_bin.flt_part = x;

const uint32_t exp_mask = x_bin.u32_part & Float32_Exponent_Mask;

// Both of these compile to the same lto.src as of 2024-Oct-10
#if 1
uint24_t mantissa = x_bin.u24_part;
// bit 23 is part of the exponent, so it must be cleared
mantissa += mantissa;
#else
uint32_t mantissa = x_bin.u32_part & Float32_Mantissa_Mask;
#endif

return (
(exp_mask == 0) ? FP_ZERO :
(exp_mask == Float32_Exponent_Mask) ? FP_INFINITE :
FP_NORMAL
) | (mantissa != 0);
}

#endif

int _fpclassify(double) __attribute__((alias("_fpclassifyf")));
10 changes: 10 additions & 0 deletions src/libc/include/math.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ extern "C" {
#define FP_ILOGB0 (~__INT_MAX__)
#define FP_ILOGBNAN __INT_MAX__

#define FP_NORMAL 0x1
#define FP_ZERO 0x2
#define FP_SUBNORMAL (FP_NORMAL | FP_ZERO) /* 0x3 */
#define FP_INFINITE 0x4
#define FP_NAN (FP_NORMAL | FP_INFINITE) /* 0x5 */

#define signbit(x) __builtin_signbit(x)
#define isgreater(x, y) __builtin_isgreater(x, y)
#define isgreaterequal(x, y) __builtin_isgreaterequal(x, y)
Expand All @@ -41,6 +47,7 @@ int _isinff(float n);
int _isnanf(float n);
int _isnormalf(float n);
int _isfinitef(float n);
int _fpclassifyf(float n);

#define isinf(x) ( \
sizeof((x)) == sizeof(float) ? _isinff((x)) : \
Expand All @@ -54,6 +61,9 @@ int _isfinitef(float n);
#define isfinite(x) ( \
sizeof((x)) == sizeof(float) ? _isfinitef((x)) : \
1)
#define fpclassify(x) ( \
sizeof((x)) == sizeof(float) ? _fpclassifyf((x)) : \
0)

double acos(double);
float acosf(float);
Expand Down
23 changes: 23 additions & 0 deletions src/libc/isnormal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <stdint.h>
#include <math.h>

typedef union Float32_Bitwise {
float flt_part;
uint32_t u32_part;
uint24_t u24_part;
} Float32_Bitwise;

#define Float32_Exponent_Mask INT32_C(0x7F800000)

int _isnormalf(float x)
{
Float32_Bitwise x_bin;
x_bin.flt_part = x;

const int32_t exp_mask = x_bin.u32_part & Float32_Exponent_Mask;

// Check that the exponent isn't all zeros (subnormal) or all ones (nan/inf)
return (exp_mask != 0 && exp_mask != Float32_Exponent_Mask);
}

int _isnormal(double) __attribute__((alias("_isnormalf")));

0 comments on commit 343bbf3

Please sign in to comment.