]> granicus.if.org Git - check/commitdiff
Move infinity/not-a-number handling to lib directory
authorbel2125 <bel2125@gmail.com>
Tue, 29 Aug 2017 20:50:57 +0000 (22:50 +0200)
committerbel2125 <bel2125@gmail.com>
Tue, 29 Aug 2017 20:50:57 +0000 (22:50 +0200)
lib/CMakeLists.txt
lib/fpclassify.c [new file with mode: 0644]
lib/libcompat.h
tests/check_check_sub.c

index 64b931ea2d182b141de978d574b503b157426b3c..1eed224d3573645044a768aa3def2f00a92a4e07 100644 (file)
@@ -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 (file)
index 0000000..9c5fdfc
--- /dev/null
@@ -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 <stdint.h>
+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
+
index 8694e4fe5931131525f8fcf6840e10d3398238ac..4408774642d72507a2474db9f19e6bd82d8b31bd 100644 (file)
 /* defines exit() */
 #include <stdlib.h>
 
+/* defines NAN, INFINITY, isnan(), isinf(), isfinite() */
+#include <math.h>
+
+/* 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 <sys/time.h>
index ef0393bc8f2defab4b528fdb08365c368c38223a..a6f8f27272c0867e78512017f35fc14dfec7c0b5 100644 (file)
 
 #include "../lib/libcompat.h"
 
-#include <math.h>
 #include <sys/types.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <check.h>
 #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");