diff --git a/liba/Makefile b/liba/Makefile index ee0fe2d46..d74dce5ef 100644 --- a/liba/Makefile +++ b/liba/Makefile @@ -6,7 +6,9 @@ objs += $(addprefix liba/src/, \ assert.o \ errno.o \ ieee754.o \ + isnand.o \ isnanf.o \ + isinfd.o \ isinff.o \ malloc.o \ memcpy.o \ diff --git a/liba/include/math.h b/liba/include/math.h index 0f622155b..22aa89bec 100644 --- a/liba/include/math.h +++ b/liba/include/math.h @@ -13,13 +13,15 @@ LIBA_BEGIN_DECLS /* The C99 standard requires isinf and isnan to be defined as macros that can * handle arbitrary precision float numbers. The names of the functions called * by those macros (depending on the argument size) are not standardized though. - * We're chosing isinff/isnanf for single-precision functions (which is the only - * case we're actually handling). */ + * We're chosing isinff/isnanf for single-precision functions, and isinfd/isnand + * for double-precision functions. */ int isinff(float x); -#define isinf(x) isinff(x) +int isinfd(double d); +#define isinf(x) (sizeof(x) == sizeof(float) ? isinff(x) : isinfd(x)) int isnanf(float x); -#define isnan(x) isnanf(x) +int isnand(double x); +#define isnan(x) (sizeof(x) == sizeof(float) ? isnanf(x) : isnand(x)) float acosf(float x); float acoshf(float x); diff --git a/liba/include/private/ieee754.h b/liba/include/private/ieee754.h index e8e567266..4d46d2033 100644 --- a/liba/include/private/ieee754.h +++ b/liba/include/private/ieee754.h @@ -3,7 +3,10 @@ #include -uint32_t ieee754man(float x); -uint8_t ieee754exp(float x); +uint32_t ieee754man32(float x); +uint8_t ieee754exp32(float x); + +uint64_t ieee754man64(double x); +uint16_t ieee754exp64(double x); #endif diff --git a/liba/src/ieee754.c b/liba/src/ieee754.c index a7904f474..19663e662 100644 --- a/liba/src/ieee754.c +++ b/liba/src/ieee754.c @@ -1,6 +1,6 @@ #include -uint32_t ieee754man(float x) { +uint32_t ieee754man32(float x) { union { float f; uint32_t i; @@ -9,7 +9,7 @@ uint32_t ieee754man(float x) { return (u.i & ((1<<23)-1)); } -uint8_t ieee754exp(float x) { +uint8_t ieee754exp32(float x) { union { float f; uint32_t i; @@ -17,3 +17,21 @@ uint8_t ieee754exp(float x) { u.f = x; return (u.i >> 23) & 0xFF; } + +uint64_t ieee754man64(double x) { + union { + double d; + uint64_t i; + } u; + u.d = x; + return (u.i & (((uint64_t)1<<52)-1)); +} + +uint16_t ieee754exp64(double x) { + union { + double d; + uint64_t i; + } u; + u.d = x; + return (uint16_t)((u.i >> 52) & 0x7FF); +} diff --git a/liba/src/isinfd.c b/liba/src/isinfd.c new file mode 100644 index 000000000..67907bbbf --- /dev/null +++ b/liba/src/isinfd.c @@ -0,0 +1,6 @@ +#include +#include + +int isinfd(double x) { + return (ieee754exp64(x) == 0x7FF && ieee754man64(x) == 0); +} diff --git a/liba/src/isinff.c b/liba/src/isinff.c index f184f2252..07ffae6cf 100644 --- a/liba/src/isinff.c +++ b/liba/src/isinff.c @@ -2,5 +2,5 @@ #include int isinff(float x) { - return (ieee754exp(x) == 0xFF && ieee754man(x) == 0); + return (ieee754exp32(x) == 0xFF && ieee754man32(x) == 0); } diff --git a/liba/src/isnand.c b/liba/src/isnand.c new file mode 100644 index 000000000..22e3518e8 --- /dev/null +++ b/liba/src/isnand.c @@ -0,0 +1,6 @@ +#include +#include + +int isnand(double x) { + return (ieee754exp64(x) == 0x7FF && ieee754man64(x) != 0); +} diff --git a/liba/src/isnanf.c b/liba/src/isnanf.c index 97eb74cec..f524ae486 100644 --- a/liba/src/isnanf.c +++ b/liba/src/isnanf.c @@ -2,5 +2,5 @@ #include int isnanf(float x) { - return (ieee754exp(x) == 0xFF && ieee754man(x) != 0); + return (ieee754exp32(x) == 0xFF && ieee754man32(x) != 0); }