Merge branch 'upstream' into stable
[gnulib.git] / m4 / isnanl.m4
1 # isnanl.m4 serial 14
2 dnl Copyright (C) 2007-2011 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([gl_MATH_H_DEFAULTS])
10   ISNANL_LIBM=
11   gl_HAVE_ISNANL_NO_LIBM
12   if test $gl_cv_func_isnanl_no_libm = no; then
13     gl_HAVE_ISNANL_IN_LIBM
14     if test $gl_cv_func_isnanl_in_libm = yes; then
15       ISNANL_LIBM=-lm
16     fi
17   fi
18   dnl The variable gl_func_isnanl set here is used by isnan.m4.
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     HAVE_ISNANL=0
34     gl_BUILD_ISNANL
35   fi
36   AC_SUBST([ISNANL_LIBM])
37 ])
38
39 AC_DEFUN([gl_FUNC_ISNANL_NO_LIBM],
40 [
41   gl_HAVE_ISNANL_NO_LIBM
42   gl_func_isnanl_no_libm=$gl_cv_func_isnanl_no_libm
43   if test $gl_func_isnanl_no_libm = yes; then
44     gl_FUNC_ISNANL_WORKS
45     case "$gl_cv_func_isnanl_works" in
46       *yes) ;;
47       *)    gl_func_isnanl_no_libm=no ;;
48     esac
49   fi
50   if test $gl_func_isnanl_no_libm = yes; then
51     AC_DEFINE([HAVE_ISNANL_IN_LIBC], [1],
52       [Define if the isnan(long double) function is available in libc.])
53   else
54     gl_BUILD_ISNANL
55   fi
56 ])
57
58 dnl Pull in replacement isnanl definition. It does not need -lm.
59 AC_DEFUN([gl_BUILD_ISNANL],
60 [
61   AC_LIBOBJ([isnanl])
62   gl_LONG_DOUBLE_EXPONENT_LOCATION
63 ])
64
65 dnl Test whether isnanl() can be used without libm.
66 AC_DEFUN([gl_HAVE_ISNANL_NO_LIBM],
67 [
68   AC_CACHE_CHECK([whether isnan(long double) can be used without linking with libm],
69     [gl_cv_func_isnanl_no_libm],
70     [
71       AC_LINK_IFELSE(
72         [AC_LANG_PROGRAM(
73            [[#include <math.h>
74              #if __GNUC__ >= 4
75              # undef isnanl
76              # define isnanl(x) __builtin_isnanl ((long double)(x))
77              #elif defined isnan
78              # undef isnanl
79              # define isnanl(x) isnan ((long double)(x))
80              #endif
81              long double x;]],
82            [[return isnanl (x);]])],
83         [gl_cv_func_isnanl_no_libm=yes],
84         [gl_cv_func_isnanl_no_libm=no])
85     ])
86 ])
87
88 dnl Test whether isnanl() can be used with libm.
89 AC_DEFUN([gl_HAVE_ISNANL_IN_LIBM],
90 [
91   AC_CACHE_CHECK([whether isnan(long double) can be used with libm],
92     [gl_cv_func_isnanl_in_libm],
93     [
94       save_LIBS="$LIBS"
95       LIBS="$LIBS -lm"
96       AC_LINK_IFELSE(
97         [AC_LANG_PROGRAM(
98            [[#include <math.h>
99              #if __GNUC__ >= 4
100              # undef isnanl
101              # define isnanl(x) __builtin_isnanl ((long double)(x))
102              #elif defined isnan
103              # undef isnanl
104              # define isnanl(x) isnan ((long double)(x))
105              #endif
106              long double x;]],
107            [[return isnanl (x);]])],
108         [gl_cv_func_isnanl_in_libm=yes],
109         [gl_cv_func_isnanl_in_libm=no])
110       LIBS="$save_LIBS"
111     ])
112 ])
113
114 dnl Test whether isnanl() recognizes all numbers which are neither finite nor
115 dnl infinite. This test fails e.g. on NetBSD/i386 and on glibc/ia64.
116 dnl Also, the GCC >= 4.0 built-in __builtin_isnanl does not pass the tests
117 dnl - for pseudo-denormals on i686 and x86_64,
118 dnl - for pseudo-zeroes, unnormalized numbers, and pseudo-denormals on ia64.
119 AC_DEFUN([gl_FUNC_ISNANL_WORKS],
120 [
121   AC_REQUIRE([AC_PROG_CC])
122   AC_REQUIRE([gl_BIGENDIAN])
123   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
124   AC_CACHE_CHECK([whether isnanl works], [gl_cv_func_isnanl_works],
125     [
126       AC_RUN_IFELSE(
127         [AC_LANG_SOURCE([[
128 #include <float.h>
129 #include <limits.h>
130 #include <math.h>
131 #if __GNUC__ >= 4
132 # undef isnanl
133 # define isnanl(x) __builtin_isnanl ((long double)(x))
134 #elif defined isnan
135 # undef isnanl
136 # define isnanl(x) isnan ((long double)(x))
137 #endif
138 #define NWORDS \
139   ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
140 typedef union { unsigned int word[NWORDS]; long double value; }
141         memory_long_double;
142 /* On Irix 6.5, gcc 3.4.3 can't compute compile-time NaN, and needs the
143    runtime type conversion.  */
144 #ifdef __sgi
145 static long double NaNl ()
146 {
147   double zero = 0.0;
148   return zero / zero;
149 }
150 #else
151 # define NaNl() (0.0L / 0.0L)
152 #endif
153 int main ()
154 {
155   int result = 0;
156
157   if (!isnanl (NaNl ()))
158     result |= 1;
159
160   {
161     memory_long_double m;
162     unsigned int i;
163
164     /* The isnanl function should be immune against changes in the sign bit and
165        in the mantissa bits.  The xor operation twiddles a bit that can only be
166        a sign bit or a mantissa bit (since the exponent never extends to
167        bit 31).  */
168     m.value = NaNl ();
169     m.word[NWORDS / 2] ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
170     for (i = 0; i < NWORDS; i++)
171       m.word[i] |= 1;
172     if (!isnanl (m.value))
173       result |= 1;
174   }
175
176 #if ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
177 /* Representation of an 80-bit 'long double' as an initializer for a sequence
178    of 'unsigned int' words.  */
179 # ifdef WORDS_BIGENDIAN
180 #  define LDBL80_WORDS(exponent,manthi,mantlo) \
181      { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \
182        ((unsigned int) (manthi) << 16) | (unsigned int) (mantlo) >> 16),    \
183        (unsigned int) (mantlo) << 16                                        \
184      }
185 # else
186 #  define LDBL80_WORDS(exponent,manthi,mantlo) \
187      { mantlo, manthi, exponent }
188 # endif
189   { /* Quiet NaN.  */
190     static memory_long_double x =
191       { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
192     if (!isnanl (x.value))
193       result |= 2;
194   }
195   {
196     /* Signalling NaN.  */
197     static memory_long_double x =
198       { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
199     if (!isnanl (x.value))
200       result |= 2;
201   }
202   /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
203      Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
204        Intel IA-64 Architecture Software Developer's Manual, Volume 1:
205        Application Architecture.
206        Table 5-2 "Floating-Point Register Encodings"
207        Figure 5-6 "Memory to Floating-Point Register Data Translation"
208    */
209   { /* Pseudo-NaN.  */
210     static memory_long_double x =
211       { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
212     if (!isnanl (x.value))
213       result |= 4;
214   }
215   { /* Pseudo-Infinity.  */
216     static memory_long_double x =
217       { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
218     if (!isnanl (x.value))
219       result |= 8;
220   }
221   { /* Pseudo-Zero.  */
222     static memory_long_double x =
223       { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
224     if (!isnanl (x.value))
225       result |= 16;
226   }
227   { /* Unnormalized number.  */
228     static memory_long_double x =
229       { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
230     if (!isnanl (x.value))
231       result |= 32;
232   }
233   { /* Pseudo-Denormal.  */
234     static memory_long_double x =
235       { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
236     if (!isnanl (x.value))
237       result |= 64;
238   }
239 #endif
240
241   return result;
242 }]])],
243         [gl_cv_func_isnanl_works=yes],
244         [gl_cv_func_isnanl_works=no],
245         [case "$host_cpu" in
246                                  # Guess no on ia64, x86_64, i386.
247            ia64 | x86_64 | i*86) gl_cv_func_isnanl_works="guessing no";;
248            *)
249              case "$host_os" in
250                netbsd*) gl_cv_func_isnanl_works="guessing no";;
251                *)       gl_cv_func_isnanl_works="guessing yes";;
252              esac
253              ;;
254          esac
255         ])
256     ])
257 ])