d035c07cbdc88388599083cb4650e79387277685
[gnulib.git] / m4 / isnanl.m4
1 # isnanl.m4 serial 2
2 dnl Copyright (C) 2007 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 AC_DEFUN([gl_FUNC_ISNANL],
8 [
9   AC_REQUIRE([gt_TYPE_LONGDOUBLE])
10   ISNANL_LIBM=
11   if test $gt_cv_c_long_double = yes; then
12     gl_HAVE_ISNANL_NO_LIBM
13     if test $gl_cv_func_isnanl_no_libm = no; then
14       gl_HAVE_ISNANL_IN_LIBM
15       if test $gl_cv_func_isnanl_in_libm = yes; then
16         ISNANL_LIBM=-lm
17       fi
18     fi
19     if test $gl_cv_func_isnanl_no_libm = yes \
20        || test $gl_cv_func_isnanl_in_libm = yes; then
21       save_LIBS="$LIBS"
22       LIBS="$LIBS $ISNANL_LIBM"
23       gl_FUNC_ISNANL_WORKS
24       LIBS="$save_LIBS"
25       case "$gl_cv_func_isnanl_works" in
26         *yes) gl_func_isnanl=yes ;;
27         *)    gl_func_isnanl=no; ISNANL_LIBM= ;;
28       esac
29     else
30       gl_func_isnanl=no
31     fi
32     if test $gl_func_isnanl = yes; then
33       AC_DEFINE([HAVE_ISNANL], 1,
34         [Define if the isnan(long double) function is available.])
35     else
36       AC_LIBOBJ([isnanl])
37       gl_LONG_DOUBLE_EXPONENT_LOCATION
38     fi
39   fi
40   AC_SUBST([ISNANL_LIBM])
41 ])
42
43 AC_DEFUN([gl_FUNC_ISNANL_NO_LIBM],
44 [
45   AC_REQUIRE([gt_TYPE_LONGDOUBLE])
46   if test $gt_cv_c_long_double = yes; then
47     gl_HAVE_ISNANL_NO_LIBM
48     gl_func_isnanl_no_libm=$gl_cv_func_isnanl_no_libm
49     if test $gl_func_isnanl_no_libm = yes; then
50       gl_FUNC_ISNANL_WORKS
51       case "$gl_cv_func_isnanl_works" in
52         *yes) ;;
53         *)    gl_func_isnanl_no_libm=no ;;
54       esac
55     fi
56     if test $gl_func_isnanl_no_libm = yes; then
57       AC_DEFINE([HAVE_ISNANL_IN_LIBC], 1,
58         [Define if the isnan(long double) function is available in libc.])
59     else
60       AC_LIBOBJ([isnanl])
61       gl_LONG_DOUBLE_EXPONENT_LOCATION
62     fi
63   fi
64 ])
65
66 dnl Test whether isnanl() can be used without libm.
67 AC_DEFUN([gl_HAVE_ISNANL_NO_LIBM],
68 [
69   AC_CACHE_CHECK([whether isnan(long double) can be used without linking with libm],
70     [gl_cv_func_isnanl_no_libm],
71     [
72       AC_TRY_LINK([#include <math.h>
73                    #ifdef isnan
74                    # undef isnanl
75                    # define isnanl(x) isnan ((long double)(x))
76                    #endif
77                    long double x;],
78                   [return isnanl (x);],
79         [gl_cv_func_isnanl_no_libm=yes],
80         [gl_cv_func_isnanl_no_libm=no])
81     ])
82 ])
83
84 dnl Test whether isnanl() can be used with libm.
85 AC_DEFUN([gl_HAVE_ISNANL_IN_LIBM],
86 [
87   AC_CACHE_CHECK([whether isnan(long double) can be used with libm],
88     [gl_cv_func_isnanl_in_libm],
89     [
90       save_LIBS="$LIBS"
91       LIBS="$LIBS -lm"
92       AC_TRY_LINK([#include <math.h>
93                    #ifdef isnan
94                    # undef isnanl
95                    # define isnanl(x) isnan ((long double)(x))
96                    #endif
97                    long double x;],
98                   [return isnanl (x);],
99         [gl_cv_func_isnanl_in_libm=yes],
100         [gl_cv_func_isnanl_in_libm=no])
101       LIBS="$save_LIBS"
102     ])
103 ])
104
105 dnl Test whether isnanl() recognizes all numbers which are neither finite nor
106 dnl infinite. This test fails e.g. on NetBSD/i386.
107 AC_DEFUN([gl_FUNC_ISNANL_WORKS],
108 [
109   AC_REQUIRE([AC_PROG_CC])
110   AC_REQUIRE([gt_TYPE_LONGDOUBLE])
111   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
112   AC_CACHE_CHECK([whether isnanl works], [gl_cv_func_isnanl_works],
113     [
114       AC_TRY_RUN([
115 #include <limits.h>
116 #include <math.h>
117 #ifdef isnan
118 # undef isnanl
119 # define isnanl(x) isnan ((long double)(x))
120 #endif
121 #define NWORDS \
122   ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
123 typedef union { long double value; unsigned int word[NWORDS]; }
124         memory_long_double;
125 int main ()
126 {
127   memory_long_double m;
128   unsigned int i;
129
130   /* The isnanl function should be immune against changes in the sign bit and
131      in the mantissa bits.  The xor operation twiddles a bit that can only be
132      a sign bit or a mantissa bit (since the exponent never extends to
133      bit 31).  */
134   m.value = 0.0L / 0.0L;
135   m.word[NWORDS / 2] ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
136   for (i = 0; i < NWORDS; i++)
137     m.word[i] |= 1;
138   if (!isnanl (m.value))
139     return 1;
140
141   return 0;
142 }], [gl_cv_func_isnanl_works=yes], [gl_cv_func_isnanl_works=no],
143       [case "$host_os" in
144          netbsd*) gl_cv_func_isnanl_works="guessing no";;
145          *)       gl_cv_func_isnanl_works="guessing yes";;
146        esac
147       ])
148     ])
149 ])
150
151 AC_DEFUN([gl_LONG_DOUBLE_EXPONENT_LOCATION],
152 [
153   AC_CACHE_CHECK([where to find the exponent in a 'long double'],
154     [gl_cv_cc_long_double_expbit0],
155     [
156       AC_TRY_RUN([
157 #include <float.h>
158 #include <stddef.h>
159 #include <stdio.h>
160 #include <string.h>
161 #define NWORDS \
162   ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
163 typedef union { long double value; unsigned int word[NWORDS]; }
164         memory_long_double;
165 static unsigned int ored_words[NWORDS];
166 static unsigned int anded_words[NWORDS];
167 static void add_to_ored_words (long double x)
168 {
169   memory_long_double m;
170   size_t i;
171   /* Clear it first, in case
172      sizeof (long double) < sizeof (memory_long_double).  */
173   memset (&m, 0, sizeof (memory_long_double));
174   m.value = x;
175   for (i = 0; i < NWORDS; i++)
176     {
177       ored_words[i] |= m.word[i];
178       anded_words[i] &= m.word[i];
179     }
180 }
181 int main ()
182 {
183   size_t j;
184   FILE *fp = fopen ("conftest.out", "w");
185   if (fp == NULL)
186     return 1;
187   for (j = 0; j < NWORDS; j++)
188     anded_words[j] = ~ (unsigned int) 0;
189   add_to_ored_words (0.25L);
190   add_to_ored_words (0.5L);
191   add_to_ored_words (1.0L);
192   add_to_ored_words (2.0L);
193   add_to_ored_words (4.0L);
194   /* Remove bits that are common (e.g. if representation of the first mantissa
195      bit is explicit).  */
196   for (j = 0; j < NWORDS; j++)
197     ored_words[j] &= ~anded_words[j];
198   /* Now find the nonzero word.  */
199   for (j = 0; j < NWORDS; j++)
200     if (ored_words[j] != 0)
201       break;
202   if (j < NWORDS)
203     {
204       size_t i;
205       for (i = j + 1; i < NWORDS; i++)
206         if (ored_words[i] != 0)
207           {
208             fprintf (fp, "unknown");
209             return (fclose (fp) != 0);
210           }
211       for (i = 0; ; i++)
212         if ((ored_words[j] >> i) & 1)
213           {
214             fprintf (fp, "word %d bit %d", (int) j, (int) i);
215             return (fclose (fp) != 0);
216           }
217     }
218   fprintf (fp, "unknown");
219   return (fclose (fp) != 0);
220 }
221         ],
222         [gl_cv_cc_long_double_expbit0=`cat conftest.out`],
223         [gl_cv_cc_long_double_expbit0="unknown"],
224         [
225           dnl When cross-compiling, we don't know. It depends on the
226           dnl ABI and compiler version. There are too many cases.
227           gl_cv_cc_long_double_expbit0="unknown"
228         ])
229       rm -f conftest.out
230     ])
231   case "$gl_cv_cc_long_double_expbit0" in
232     word*bit*)
233       word=`echo "$gl_cv_cc_long_double_expbit0" | sed -e 's/word //' -e 's/ bit.*//'`
234       bit=`echo "$gl_cv_cc_long_double_expbit0" | sed -e 's/word.*bit //'`
235       AC_DEFINE_UNQUOTED([LDBL_EXPBIT0_WORD], [$word],
236         [Define as the word index where to find the exponent of 'long double'.])
237       AC_DEFINE_UNQUOTED([LDBL_EXPBIT0_BIT], [$bit],
238         [Define as the bit index in the word where to find bit 0 of the exponent of 'long double'.])
239       ;;
240   esac
241 ])