Use copysign when implementing signbit, if the libc has it already.
[gnulib.git] / m4 / signbit.m4
1 # signbit.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_SIGNBIT],
8 [
9   AC_REQUIRE([gl_MATH_H_DEFAULTS])
10   AC_CACHE_CHECK([for signbit macro], [gl_cv_func_signbit],
11     [
12       AC_TRY_RUN([
13 #include <math.h>
14 #include <string.h>
15 float p0f = 0.0f;
16 float m0f = -0.0f;
17 double p0d = 0.0;
18 double m0d = -0.0;
19 long double p0l = 0.0L;
20 long double m0l = -0.0L;
21 int main ()
22 {
23   {
24     float plus_inf = 1.0f / p0f;
25     float minus_inf = -1.0f / p0f;
26     if (!(!signbit (255.0f)
27           && signbit (-255.0f)
28           && !signbit (p0f)
29           && (memcmp (&m0f, &p0f, sizeof (float)) == 0 || signbit (m0f))
30           && !signbit (plus_inf)
31           && signbit (minus_inf)))
32       return 1;
33   }
34   {
35     double plus_inf = 1.0 / p0d;
36     double minus_inf = -1.0 / p0d;
37     if (!(!signbit (255.0)
38           && signbit (-255.0)
39           && !signbit (p0d)
40           && (memcmp (&m0d, &p0d, sizeof (double)) == 0 || signbit (m0d))
41           && !signbit (plus_inf)
42           && signbit (minus_inf)))
43       return 1;
44   }
45   {
46     long double plus_inf = 1.0L / p0l;
47     long double minus_inf = -1.0L / p0l;
48     if (!(!signbit (255.0L)
49           && signbit (-255.0L)
50           && !signbit (p0l)
51           && (memcmp (&m0l, &p0l, sizeof (long double)) == 0 || signbit (m0l))
52           && !signbit (plus_inf)
53           && signbit (minus_inf)))
54       return 1;
55   }
56   return 0;
57 }], [gl_cv_func_signbit=yes], [gl_cv_func_signbit=no],
58         [gl_cv_func_signbit="guessing no"])
59     ])
60   if test "$gl_cv_func_signbit" != yes; then
61     REPLACE_SIGNBIT=1
62     AC_LIBOBJ([signbitf])
63     AC_LIBOBJ([signbitd])
64     AC_LIBOBJ([signbitl])
65     gl_FLOAT_SIGN_LOCATION
66     gl_DOUBLE_SIGN_LOCATION
67     gl_LONG_DOUBLE_SIGN_LOCATION
68     if test "$gl_cv_cc_float_signbit" = unknown; then
69       dnl Test whether copysignf() is declared.
70       AC_CHECK_DECLS([copysignf], , , [#include <math.h>])
71       if test "$ac_cv_have_decl_copysignf" = yes; then
72         dnl Test whether copysignf() can be used without libm.
73         AC_CACHE_CHECK([whether copysignf can be used without linking with libm],
74           [gl_cv_func_copysignf_no_libm],
75           [
76             AC_TRY_LINK([#include <math.h>
77                          float x, y;],
78                         [return copysignf (x, y) < 0;],
79               [gl_cv_func_copysignf_no_libm=yes],
80               [gl_cv_func_copysignf_no_libm=no])
81           ])
82         if test $gl_cv_func_copysignf_no_libm = yes; then
83           AC_DEFINE([HAVE_COPYSIGNF_IN_LIBC], 1,
84             [Define if the copysignf function is declared in <math.h> and available in libc.])
85         fi
86       fi
87     fi
88     if test "$gl_cv_cc_double_signbit" = unknown; then
89       dnl Test whether copysign() is declared.
90       AC_CHECK_DECLS([copysign], , , [#include <math.h>])
91       if test "$ac_cv_have_decl_copysign" = yes; then
92         dnl Test whether copysign() can be used without libm.
93         AC_CACHE_CHECK([whether copysign can be used without linking with libm],
94           [gl_cv_func_copysign_no_libm],
95           [
96             AC_TRY_LINK([#include <math.h>
97                          double x, y;],
98                         [return copysign (x, y) < 0;],
99               [gl_cv_func_copysign_no_libm=yes],
100               [gl_cv_func_copysign_no_libm=no])
101           ])
102         if test $gl_cv_func_copysign_no_libm = yes; then
103           AC_DEFINE([HAVE_COPYSIGN_IN_LIBC], 1,
104             [Define if the copysign function is declared in <math.h> and available in libc.])
105         fi
106       fi
107     fi
108     if test "$gl_cv_cc_long_double_signbit" = unknown; then
109       dnl Test whether copysignl() is declared.
110       AC_CHECK_DECLS([copysignl], , , [#include <math.h>])
111       if test "$ac_cv_have_decl_copysignl" = yes; then
112         dnl Test whether copysignl() can be used without libm.
113         AC_CACHE_CHECK([whether copysignl can be used without linking with libm],
114           [gl_cv_func_copysignl_no_libm],
115           [
116             AC_TRY_LINK([#include <math.h>
117                          long double x, y;],
118                         [return copysignl (x, y) < 0;],
119               [gl_cv_func_copysignl_no_libm=yes],
120               [gl_cv_func_copysignl_no_libm=no])
121           ])
122         if test $gl_cv_func_copysignl_no_libm = yes; then
123           AC_DEFINE([HAVE_COPYSIGNL_IN_LIBC], 1,
124             [Define if the copysignl function is declared in <math.h> and available in libc.])
125         fi
126       fi
127     fi
128   fi
129 ])
130
131 AC_DEFUN([gl_FLOAT_SIGN_LOCATION],
132 [
133   gl_FLOATTYPE_SIGN_LOCATION([float], [gl_cv_cc_float_signbit], [f], [FLT])
134 ])
135
136 AC_DEFUN([gl_DOUBLE_SIGN_LOCATION],
137 [
138   gl_FLOATTYPE_SIGN_LOCATION([double], [gl_cv_cc_double_signbit], [], [DBL])
139 ])
140
141 AC_DEFUN([gl_LONG_DOUBLE_SIGN_LOCATION],
142 [
143   gl_FLOATTYPE_SIGN_LOCATION([long double], [gl_cv_cc_long_double_signbit], [L], [LDBL])
144 ])
145
146 AC_DEFUN([gl_FLOATTYPE_SIGN_LOCATION],
147 [
148   AC_CACHE_CHECK([where to find the sign bit in a '$1'],
149     [$2],
150     [
151       AC_TRY_RUN([
152 #include <stddef.h>
153 #include <stdio.h>
154 #define NWORDS \
155   ((sizeof ($1) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
156 typedef union { $1 value; unsigned int word[NWORDS]; }
157         memory_float;
158 static memory_float plus = { 1.0$3 };
159 static memory_float minus = { -1.0$3 };
160 int main ()
161 {
162   size_t j, k, i;
163   unsigned int m;
164   FILE *fp = fopen ("conftest.out", "w");
165   if (fp == NULL)
166     return 1;
167   /* Find the different bit.  */
168   k = 0; m = 0;
169   for (j = 0; j < NWORDS; j++)
170     {
171       unsigned int x = plus.word[j] ^ minus.word[j];
172       if ((x & (x - 1)) || (x && m))
173         {
174           /* More than one bit difference.  */
175           fprintf (fp, "unknown");
176           return 1;
177         }
178       if (x)
179         {
180           k = j;
181           m = x;
182         }
183     }
184   if (m == 0)
185     {
186       /* No difference.  */
187       fprintf (fp, "unknown");
188       return 1;
189     }
190   /* Now m = plus.word[k] ^ ~minus.word[k].  */
191   if (plus.word[k] & ~minus.word[k])
192     {
193       /* Oh? The sign bit is set in the positive and cleared in the negative
194          numbers?  */
195       fprintf (fp, "unknown");
196       return 1;
197     }
198   for (i = 0; ; i++)
199     if ((m >> i) & 1)
200       break;
201   fprintf (fp, "word %d bit %d", (int) k, (int) i);
202   return (fclose (fp) != 0);
203 }
204         ],
205         [$2=`cat conftest.out`],
206         [$2="unknown"],
207         [
208           dnl When cross-compiling, we don't know. It depends on the
209           dnl ABI and compiler version. There are too many cases.
210           $2="unknown"
211         ])
212       rm -f conftest.out
213     ])
214   case "$]$2[" in
215     word*bit*)
216       word=`echo "$]$2[" | sed -e 's/word //' -e 's/ bit.*//'`
217       bit=`echo "$]$2[" | sed -e 's/word.*bit //'`
218       AC_DEFINE_UNQUOTED([$4][_SIGNBIT_WORD], [$word],
219         [Define as the word index where to find the sign of '$1'.])
220       AC_DEFINE_UNQUOTED([$4][_SIGNBIT_BIT], [$bit],
221         [Define as the bit index in the word where to find the sign of '$1'.])
222       ;;
223   esac
224 ])