diff --git a/liba/Makefile b/liba/Makefile index 0a3962929..c860db2a0 100644 --- a/liba/Makefile +++ b/liba/Makefile @@ -2,7 +2,20 @@ SFLAGS += -Iliba/include liba/src/external/sqlite/mem5.o: CFLAGS += -w -objs += $(addprefix liba/src/, assert.o errno.o malloc.o memcpy.o memset.o strcmp.o strlcpy.o strlen.o external/sqlite/mem5.o) +objs += $(addprefix liba/src/, \ + assert.o \ + errno.o \ + ieee754.o \ + isnanf.o \ + isinff.o \ + malloc.o \ + memcpy.o \ + memset.o \ + strcmp.o \ + strlcpy.o \ + strlen.o \ + external/sqlite/mem5.o \ +) objs += $(addprefix liba/src/external/openbsd/, \ e_log10f.o \ @@ -25,7 +38,11 @@ objs += $(addprefix liba/src/external/openbsd/, \ liba/src/external/openbsd/%.o: CFLAGS += -Iliba/src/external/openbsd/include -Wno-parentheses -tests += $(addprefix liba/test/, stdint.c strlcpy.c) +tests += $(addprefix liba/test/, \ + ieee754.c \ + stdint.c \ + strlcpy.c \ +) # The use of aeabi-rt could be made conditional to an AEABI target. # In practice we're always using liba on such a target. diff --git a/liba/include/math.h b/liba/include/math.h index 7ec64c08a..235eb252e 100644 --- a/liba/include/math.h +++ b/liba/include/math.h @@ -5,6 +5,9 @@ LIBA_BEGIN_DECLS +int isinff(float x); +int isnanf(float x); + float copysignf(float x, float y); float cosf(float x); float fabsf(float x); diff --git a/liba/include/private/ieee754.h b/liba/include/private/ieee754.h new file mode 100644 index 000000000..e8e567266 --- /dev/null +++ b/liba/include/private/ieee754.h @@ -0,0 +1,9 @@ +#ifndef LIBA_IEEE754_H +#define LIBA_IEEE754_H + +#include + +uint32_t ieee754man(float x); +uint8_t ieee754exp(float x); + +#endif diff --git a/liba/src/ieee754.c b/liba/src/ieee754.c new file mode 100644 index 000000000..a7904f474 --- /dev/null +++ b/liba/src/ieee754.c @@ -0,0 +1,19 @@ +#include + +uint32_t ieee754man(float x) { + union { + float f; + uint32_t i; + } u; + u.f = x; + return (u.i & ((1<<23)-1)); +} + +uint8_t ieee754exp(float x) { + union { + float f; + uint32_t i; + } u; + u.f = x; + return (u.i >> 23) & 0xFF; +} diff --git a/liba/src/isinff.c b/liba/src/isinff.c new file mode 100644 index 000000000..f184f2252 --- /dev/null +++ b/liba/src/isinff.c @@ -0,0 +1,6 @@ +#include +#include + +int isinff(float x) { + return (ieee754exp(x) == 0xFF && ieee754man(x) == 0); +} diff --git a/liba/src/isnanf.c b/liba/src/isnanf.c new file mode 100644 index 000000000..97eb74cec --- /dev/null +++ b/liba/src/isnanf.c @@ -0,0 +1,6 @@ +#include +#include + +int isnanf(float x) { + return (ieee754exp(x) == 0xFF && ieee754man(x) != 0); +} diff --git a/liba/test/ieee754.c b/liba/test/ieee754.c new file mode 100644 index 000000000..c59875ac5 --- /dev/null +++ b/liba/test/ieee754.c @@ -0,0 +1,12 @@ +#include +#include +#include + +QUIZ_CASE(liba_ieee754) { + assert(ieee754man(123.456f) == 7793017); + assert(ieee754exp(123.456f) == 133); + assert(ieee754man(555.555f) == 713605); + assert(ieee754exp(555.555f) == 136); + assert(ieee754man(0.007f) == 6643778); + assert(ieee754exp(0.007f) == 119); +}