From: bel2125 Date: Tue, 29 Aug 2017 20:50:57 +0000 (+0200) Subject: Move infinity/not-a-number handling to lib directory X-Git-Tag: 0.12.0~4^2~14 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=37a1188e9c23fbebec4829c3f105fdf2977f4277;p=check Move infinity/not-a-number handling to lib directory --- diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 64b931e..1eed224 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -21,6 +21,8 @@ set(SOURCES libcompat.c) +set(SOURCES fpclassify.c) + if (NOT HAVE_LIBRT) set(SOURCES ${SOURCES} clock_gettime.c) set(SOURCES ${SOURCES} timer_create.c) diff --git a/lib/fpclassify.c b/lib/fpclassify.c new file mode 100644 index 0000000..9c5fdfc --- /dev/null +++ b/lib/fpclassify.c @@ -0,0 +1,46 @@ +/* Replacement function for isnan/isinf/isfinite for processors using + * IEEE 754 floating point format. + * Copyright (C) 2017, bel2125 + * License: LGPL v2 or MIT (as you like). + */ + + +#include "libcompat.h" + +#if !defined(isnan) || !defined(isinf) || !defined(isfinite) + +#if defined(HAVE_STDINT_H) +#include +typedef uint64_t bitfield64; +#elif defined(_MSC_VER) +typedef unsigned __int64 bitfield64; +#else +typedef unsigned long long bitfield64; +#endif + +static bitfield64 ms = 0x8000000000000000; +static bitfield64 me = 0x7FF0000000000000; +static bitfield64 mf = 0x000FFFFFFFFFFFFF; + +int fpclassify(double d) +{ + bitfield64 *p = (bitfield64 *)&d; + if ((*p & me) != me) { + /* finite */ + if (*p & mf) { + /* finite and not null */ + if (*p & me) { + return FP_NORMAL; + } + return FP_SUBNORMAL; + } + return FP_ZERO; + } + if (*p & mf) { + return FP_NAN; + } + return FP_INFINITE; +} + +#endif + diff --git a/lib/libcompat.h b/lib/libcompat.h index 8694e4f..4408774 100644 --- a/lib/libcompat.h +++ b/lib/libcompat.h @@ -72,6 +72,29 @@ /* defines exit() */ #include +/* defines NAN, INFINITY, isnan(), isinf(), isfinite() */ +#include + +/* However, some older Visual Studio Versions do not */ +#if !defined(INFINITY) +double ZERO = 0.0; +double INFINITY = 1.0 / ZERO; +#endif +#if !defined(NAN) +double NAN = INFINITY * ZERO; +#endif +#if !defined(isnan) || !defined(isinf) || !defined(isfinite) +#define FP_INFINITE (1) +#define FP_NAN (2) +#define FP_ZERO (4) +#define FP_NORMAL (8) +#define FP_SUBNORMAL (16) +#define isnan(x) ((fpclassify((double)(x)) & FP_NAN) == FP_NAN) +#define isnan(x) ((fpclassify((double)(x)) & FP_INFINITE) == FP_INFINITE) +#define isfinite(x) ((fpclassify((double)(x)) & (FP_NAN|FP_INFINITE)) == 0) +#endif + + /* provides localtime and struct tm */ #ifdef HAVE_SYS_TIME_H #include diff --git a/tests/check_check_sub.c b/tests/check_check_sub.c index ef0393b..a6f8f27 100644 --- a/tests/check_check_sub.c +++ b/tests/check_check_sub.c @@ -20,57 +20,12 @@ #include "../lib/libcompat.h" -#include #include #include #include #include #include "check_check.h" -#if !defined(NAN) -/* According to POSIX, NAN and INFINITY are defined in math.h, see - * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/math.h.html - * Hovever, older Visual Studio compilers do not define these values. - */ -double NAN; -#endif -#if !defined(INFINITY) -double INFINITY; -#endif -#if !defined(isnan) -int isnan(double d) { -#ifdef _MSC_VER - unsigned __int64 *p = &d, m = 0x7FF0000000000000; -#else - unsigned long long *p = &d, m = 0x7FF0000000000000; -#endif - if ((*p & m) != m) return 0; /* finite */ - *p &= 0x000FFFFFFFFFFFFF; /* mask exponent and sign */ - return *p != 0; -} -#endif -#if !defined(isinf) -int isinf(double d) { -#ifdef _MSC_VER - unsigned __int64 *p = &d, m = 0x7FF0000000000000; -#else - unsigned long long *p = &d, m = 0x7FF0000000000000; -#endif - *p &= 0x000FFFFFFFFFFFFF; /* mask exponent and sign */ - return *p == 0; -} -#endif -#if !defined(isfinite) -int isfinite(double d) { -#ifdef _MSC_VER - unsigned __int64 *p = &d, m = 0x7FF0000000000000; -#else - unsigned long long *p = &d, m = 0x7FF0000000000000; -#endif - return (*p & m) != m; -} -#endif - START_TEST(test_lno) { @@ -3010,13 +2965,6 @@ Suite *make_sub_suite(void) TCase *tc_exit_handlers; #endif -#if !defined(NAN) - NAN /= NAN; /* division of 0 by 0 */ -#endif -#if !defined(INFINITY) - INFINITY = 1.0 / INFINITY; /* division of 1 by 0 */ -#endif - s = suite_create("Check Servant"); tc_simple = tcase_create("Simple Tests");