Rename isnan, applicable to 'double' only, to isnand.
[gnulib.git] / m4 / isnand.m4
1 # isnand.m4 serial 1
2 dnl Copyright (C) 2007-2008 Free Software Foundation, Inc.
3 dnl This file is free software; the Free Software Foundation
4 dnl gives unlimited permission to copy and/or distribute it,
5 dnl with or without modifications, as long as this notice is preserved.
6
7 dnl Check how to get or define isnand() without linking with libm.
8
9 AC_DEFUN([gl_FUNC_ISNAND_NO_LIBM],
10 [
11   AC_CACHE_CHECK([whether isnan(double) can be used without linking with libm],
12     [gl_cv_func_isnand_no_libm],
13     [
14       AC_TRY_LINK([#include <math.h>
15                    double x;],
16                   [return isnan (x);],
17         [gl_cv_func_isnand_no_libm=yes],
18         [gl_cv_func_isnand_no_libm=no])
19     ])
20   if test $gl_cv_func_isnand_no_libm = yes; then
21     AC_DEFINE([HAVE_ISNAND_IN_LIBC], 1,
22       [Define if the isnan(double) function is available in libc.])
23   else
24     AC_LIBOBJ([isnand])
25     gl_DOUBLE_EXPONENT_LOCATION
26   fi
27 ])
28
29 AC_DEFUN([gl_DOUBLE_EXPONENT_LOCATION],
30 [
31   AC_CACHE_CHECK([where to find the exponent in a 'double'],
32     [gl_cv_cc_double_expbit0],
33     [
34       AC_TRY_RUN([
35 #include <float.h>
36 #include <stddef.h>
37 #include <stdio.h>
38 #include <string.h>
39 #define NWORDS \
40   ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
41 typedef union { double value; unsigned int word[NWORDS]; } memory_double;
42 static unsigned int ored_words[NWORDS];
43 static unsigned int anded_words[NWORDS];
44 static void add_to_ored_words (double x)
45 {
46   memory_double m;
47   size_t i;
48   /* Clear it first, in case sizeof (double) < sizeof (memory_double).  */
49   memset (&m, 0, sizeof (memory_double));
50   m.value = x;
51   for (i = 0; i < NWORDS; i++)
52     {
53       ored_words[i] |= m.word[i];
54       anded_words[i] &= m.word[i];
55     }
56 }
57 int main ()
58 {
59   size_t j;
60   FILE *fp = fopen ("conftest.out", "w");
61   if (fp == NULL)
62     return 1;
63   for (j = 0; j < NWORDS; j++)
64     anded_words[j] = ~ (unsigned int) 0;
65   add_to_ored_words (0.25);
66   add_to_ored_words (0.5);
67   add_to_ored_words (1.0);
68   add_to_ored_words (2.0);
69   add_to_ored_words (4.0);
70   /* Remove bits that are common (e.g. if representation of the first mantissa
71      bit is explicit).  */
72   for (j = 0; j < NWORDS; j++)
73     ored_words[j] &= ~anded_words[j];
74   /* Now find the nonzero word.  */
75   for (j = 0; j < NWORDS; j++)
76     if (ored_words[j] != 0)
77       break;
78   if (j < NWORDS)
79     {
80       size_t i;
81       for (i = j + 1; i < NWORDS; i++)
82         if (ored_words[i] != 0)
83           {
84             fprintf (fp, "unknown");
85             return (fclose (fp) != 0);
86           }
87       for (i = 0; ; i++)
88         if ((ored_words[j] >> i) & 1)
89           {
90             fprintf (fp, "word %d bit %d", (int) j, (int) i);
91             return (fclose (fp) != 0);
92           }
93     }
94   fprintf (fp, "unknown");
95   return (fclose (fp) != 0);
96 }
97         ],
98         [gl_cv_cc_double_expbit0=`cat conftest.out`],
99         [gl_cv_cc_double_expbit0="unknown"],
100         [
101           dnl On ARM, there are two 'double' floating-point formats, used by
102           dnl different sets of instructions: The older FPA instructions assume
103           dnl that they are stored in big-endian word order, while the words
104           dnl (like integer types) are stored in little-endian byte order.
105           dnl The newer VFP instructions assume little-endian order consistenly.
106           AC_EGREP_CPP([mixed_endianness], [
107 #if defined arm || defined __arm || defined __arm__
108   mixed_endianness
109 #endif
110             ],
111             [gl_cv_cc_double_expbit0="unknown"],
112             [
113               pushdef([AC_MSG_CHECKING],[:])dnl
114               pushdef([AC_MSG_RESULT],[:])dnl
115               pushdef([AC_MSG_RESULT_UNQUOTED],[:])dnl
116               AC_C_BIGENDIAN(
117                 [gl_cv_cc_double_expbit0="word 0 bit 20"],
118                 [gl_cv_cc_double_expbit0="word 1 bit 20"],
119                 [gl_cv_cc_double_expbit0="unknown"])
120               popdef([AC_MSG_RESULT_UNQUOTED])dnl
121               popdef([AC_MSG_RESULT])dnl
122               popdef([AC_MSG_CHECKING])dnl
123             ])
124         ])
125       rm -f conftest.out
126     ])
127   case "$gl_cv_cc_double_expbit0" in
128     word*bit*)
129       word=`echo "$gl_cv_cc_double_expbit0" | sed -e 's/word //' -e 's/ bit.*//'`
130       bit=`echo "$gl_cv_cc_double_expbit0" | sed -e 's/word.*bit //'`
131       AC_DEFINE_UNQUOTED([DBL_EXPBIT0_WORD], [$word],
132         [Define as the word index where to find the exponent of 'double'.])
133       AC_DEFINE_UNQUOTED([DBL_EXPBIT0_BIT], [$bit],
134         [Define as the bit index in the word where to find bit 0 of the exponent of 'double'.])
135       ;;
136   esac
137 ])