1# signbit.m4 serial 19 2dnl Copyright (C) 2007-2020 Free Software Foundation, Inc. 3dnl This file is free software; the Free Software Foundation 4dnl gives unlimited permission to copy and/or distribute it, 5dnl with or without modifications, as long as this notice is preserved. 6 7AC_DEFUN([gl_SIGNBIT], 8[ 9 AC_REQUIRE([gl_MATH_H_DEFAULTS]) 10 AC_REQUIRE([AC_CANONICAL_HOST]) 11 AC_CACHE_CHECK([for signbit macro], [gl_cv_func_signbit], 12 [ 13 AC_RUN_IFELSE( 14 [AC_LANG_SOURCE([[ 15#include <math.h> 16/* If signbit is defined as a function, don't use it, since calling it for 17 'float' or 'long double' arguments would involve conversions. 18 If signbit is not declared at all but exists as a library function, don't 19 use it, since the prototype may not match. 20 If signbit is not declared at all but exists as a compiler built-in, don't 21 use it, since it's preferable to use __builtin_signbit* (no warnings, 22 no conversions). */ 23#ifndef signbit 24# error "signbit should be a macro" 25#endif 26#include <string.h> 27]gl_SIGNBIT_TEST_PROGRAM 28])], 29 [gl_cv_func_signbit=yes], 30 [gl_cv_func_signbit=no], 31 [case "$host_os" in 32 # Guess yes on glibc systems. 33 *-gnu* | gnu*) gl_cv_func_signbit="guessing yes" ;; 34 # Guess yes on musl systems. 35 *-musl*) gl_cv_func_signbit="guessing yes" ;; 36 # Guess yes on native Windows. 37 mingw*) gl_cv_func_signbit="guessing yes" ;; 38 # If we don't know, obey --enable-cross-guesses. 39 *) gl_cv_func_signbit="$gl_cross_guess_normal" ;; 40 esac 41 ]) 42 ]) 43 dnl GCC 4.0 and newer provides three built-ins for signbit. 44 dnl They can be used without warnings, also in C++, regardless of <math.h>. 45 dnl But they may expand to calls to functions, which may or may not be in 46 dnl libc. 47 AC_CACHE_CHECK([for signbit compiler built-ins], [gl_cv_func_signbit_gcc], 48 [ 49 AC_RUN_IFELSE( 50 [AC_LANG_SOURCE([[ 51#if __GNUC__ >= 4 52# define signbit(x) \ 53 (sizeof (x) == sizeof (long double) ? __builtin_signbitl (x) : \ 54 sizeof (x) == sizeof (double) ? __builtin_signbit (x) : \ 55 __builtin_signbitf (x)) 56#else 57# error "signbit should be three compiler built-ins" 58#endif 59#include <string.h> 60]gl_SIGNBIT_TEST_PROGRAM 61])], 62 [gl_cv_func_signbit_gcc=yes], 63 [gl_cv_func_signbit_gcc=no], 64 [case "$host_os" in 65 # Guess yes on glibc systems. 66 *-gnu* | gnu*) gl_cv_func_signbit_gcc="guessing yes" ;; 67 # Guess yes on musl systems. 68 *-musl*) gl_cv_func_signbit_gcc="guessing yes" ;; 69 # Guess yes on mingw, no on MSVC. 70 mingw*) if test -n "$GCC"; then 71 gl_cv_func_signbit_gcc="guessing yes" 72 else 73 gl_cv_func_signbit_gcc="guessing no" 74 fi 75 ;; 76 # If we don't know, obey --enable-cross-guesses. 77 *) gl_cv_func_signbit_gcc="$gl_cross_guess_normal" ;; 78 esac 79 ]) 80 ]) 81 dnl Use the compiler built-ins whenever possible, because they are more 82 dnl efficient than the system library functions (if they exist). 83 case "$gl_cv_func_signbit_gcc" in 84 *yes) 85 REPLACE_SIGNBIT_USING_GCC=1 86 ;; 87 *) 88 case "$gl_cv_func_signbit" in 89 *yes) ;; 90 *) 91 dnl REPLACE_SIGNBIT=1 makes sure the signbit[fdl] functions get built. 92 REPLACE_SIGNBIT=1 93 ;; 94 esac 95 ;; 96 esac 97 dnl On Solaris 10, with CC in C++ mode, signbit is not available although 98 dnl is with cc in C mode. This cannot be worked around by defining 99 dnl _XOPEN_SOURCE=600, because the latter does not work in C++ mode on 100 dnl Solaris 11.0. Therefore use the replacement functions on Solaris. 101 case "$host_os" in 102 solaris*) 103 REPLACE_SIGNBIT=1 104 ;; 105 esac 106 if test $REPLACE_SIGNBIT = 1; then 107 gl_FLOAT_SIGN_LOCATION 108 gl_DOUBLE_SIGN_LOCATION 109 gl_LONG_DOUBLE_SIGN_LOCATION 110 if test "$gl_cv_cc_float_signbit" = unknown; then 111 dnl Test whether copysignf() is declared. 112 AC_CHECK_DECLS([copysignf], , , [[#include <math.h>]]) 113 if test "$ac_cv_have_decl_copysignf" = yes; then 114 dnl Test whether copysignf() can be used without libm. 115 AC_CACHE_CHECK([whether copysignf can be used without linking with libm], 116 [gl_cv_func_copysignf_no_libm], 117 [ 118 AC_LINK_IFELSE( 119 [AC_LANG_PROGRAM( 120 [[#include <math.h> 121 float x, y;]], 122 [[return copysignf (x, y) < 0;]])], 123 [gl_cv_func_copysignf_no_libm=yes], 124 [gl_cv_func_copysignf_no_libm=no]) 125 ]) 126 if test $gl_cv_func_copysignf_no_libm = yes; then 127 AC_DEFINE([HAVE_COPYSIGNF_IN_LIBC], [1], 128 [Define if the copysignf function is declared in <math.h> and available in libc.]) 129 fi 130 fi 131 fi 132 if test "$gl_cv_cc_double_signbit" = unknown; then 133 dnl Test whether copysign() is declared. 134 AC_CHECK_DECLS([copysign], , , [[#include <math.h>]]) 135 if test "$ac_cv_have_decl_copysign" = yes; then 136 dnl Test whether copysign() can be used without libm. 137 AC_CACHE_CHECK([whether copysign can be used without linking with libm], 138 [gl_cv_func_copysign_no_libm], 139 [ 140 AC_LINK_IFELSE( 141 [AC_LANG_PROGRAM( 142 [[#include <math.h> 143 double x, y;]], 144 [[return copysign (x, y) < 0;]])], 145 [gl_cv_func_copysign_no_libm=yes], 146 [gl_cv_func_copysign_no_libm=no]) 147 ]) 148 if test $gl_cv_func_copysign_no_libm = yes; then 149 AC_DEFINE([HAVE_COPYSIGN_IN_LIBC], [1], 150 [Define if the copysign function is declared in <math.h> and available in libc.]) 151 fi 152 fi 153 fi 154 if test "$gl_cv_cc_long_double_signbit" = unknown; then 155 dnl Test whether copysignl() is declared. 156 AC_CHECK_DECLS([copysignl], , , [[#include <math.h>]]) 157 if test "$ac_cv_have_decl_copysignl" = yes; then 158 dnl Test whether copysignl() can be used without libm. 159 AC_CACHE_CHECK([whether copysignl can be used without linking with libm], 160 [gl_cv_func_copysignl_no_libm], 161 [ 162 AC_LINK_IFELSE( 163 [AC_LANG_PROGRAM( 164 [[#include <math.h> 165 long double x, y;]], 166 [[return copysignl (x, y) < 0;]])], 167 [gl_cv_func_copysignl_no_libm=yes], 168 [gl_cv_func_copysignl_no_libm=no]) 169 ]) 170 if test $gl_cv_func_copysignl_no_libm = yes; then 171 AC_DEFINE([HAVE_COPYSIGNL_IN_LIBC], [1], 172 [Define if the copysignl function is declared in <math.h> and available in libc.]) 173 fi 174 fi 175 fi 176 fi 177]) 178 179AC_DEFUN([gl_SIGNBIT_TEST_PROGRAM], [[ 180/* Global variables. 181 Needed because GCC 4 constant-folds __builtin_signbitl (literal) 182 but cannot constant-fold __builtin_signbitl (variable). */ 183float vf; 184double vd; 185long double vl; 186int main () 187{ 188/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0. 189 So we use -p0f and -p0d instead. */ 190float p0f = 0.0f; 191float m0f = -p0f; 192double p0d = 0.0; 193double m0d = -p0d; 194/* On HP-UX 10.20, negating 0.0L does not yield -0.0L. 195 So we use another constant expression instead. 196 But that expression does not work on other platforms, such as when 197 cross-compiling to PowerPC on Mac OS X 10.5. */ 198long double p0l = 0.0L; 199#if defined __hpux || defined __sgi 200long double m0l = -LDBL_MIN * LDBL_MIN; 201#else 202long double m0l = -p0l; 203#endif 204 int result = 0; 205 if (signbit (vf)) /* link check */ 206 vf++; 207 { 208 float plus_inf = 1.0f / p0f; 209 float minus_inf = -1.0f / p0f; 210 if (!(!signbit (255.0f) 211 && signbit (-255.0f) 212 && !signbit (p0f) 213 && (memcmp (&m0f, &p0f, sizeof (float)) == 0 || signbit (m0f)) 214 && !signbit (plus_inf) 215 && signbit (minus_inf))) 216 result |= 1; 217 } 218 if (signbit (vd)) /* link check */ 219 vd++; 220 { 221 double plus_inf = 1.0 / p0d; 222 double minus_inf = -1.0 / p0d; 223 if (!(!signbit (255.0) 224 && signbit (-255.0) 225 && !signbit (p0d) 226 && (memcmp (&m0d, &p0d, sizeof (double)) == 0 || signbit (m0d)) 227 && !signbit (plus_inf) 228 && signbit (minus_inf))) 229 result |= 2; 230 } 231 if (signbit (vl)) /* link check */ 232 vl++; 233 { 234 long double plus_inf = 1.0L / p0l; 235 long double minus_inf = -1.0L / p0l; 236 if (signbit (255.0L)) 237 result |= 4; 238 if (!signbit (-255.0L)) 239 result |= 4; 240 if (signbit (p0l)) 241 result |= 8; 242 if (!(memcmp (&m0l, &p0l, sizeof (long double)) == 0 || signbit (m0l))) 243 result |= 16; 244 if (signbit (plus_inf)) 245 result |= 32; 246 if (!signbit (minus_inf)) 247 result |= 64; 248 } 249 return result; 250} 251]]) 252 253AC_DEFUN([gl_FLOAT_SIGN_LOCATION], 254[ 255 gl_FLOATTYPE_SIGN_LOCATION([float], [gl_cv_cc_float_signbit], [f], [FLT]) 256]) 257 258AC_DEFUN([gl_DOUBLE_SIGN_LOCATION], 259[ 260 gl_FLOATTYPE_SIGN_LOCATION([double], [gl_cv_cc_double_signbit], [], [DBL]) 261]) 262 263AC_DEFUN([gl_LONG_DOUBLE_SIGN_LOCATION], 264[ 265 gl_FLOATTYPE_SIGN_LOCATION([long double], [gl_cv_cc_long_double_signbit], [L], [LDBL]) 266]) 267 268AC_DEFUN([gl_FLOATTYPE_SIGN_LOCATION], 269[ 270 AC_CACHE_CHECK([where to find the sign bit in a '$1'], 271 [$2], 272 [ 273 AC_RUN_IFELSE( 274 [AC_LANG_SOURCE([[ 275#include <stddef.h> 276#include <stdio.h> 277#define NWORDS \ 278 ((sizeof ($1) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) 279typedef union { $1 value; unsigned int word[NWORDS]; } 280 memory_float; 281static memory_float plus = { 1.0$3 }; 282static memory_float minus = { -1.0$3 }; 283int main () 284{ 285 size_t j, k, i; 286 unsigned int m; 287 FILE *fp = fopen ("conftest.out", "w"); 288 if (fp == NULL) 289 return 1; 290 /* Find the different bit. */ 291 k = 0; m = 0; 292 for (j = 0; j < NWORDS; j++) 293 { 294 unsigned int x = plus.word[j] ^ minus.word[j]; 295 if ((x & (x - 1)) || (x && m)) 296 { 297 /* More than one bit difference. */ 298 fprintf (fp, "unknown"); 299 fclose (fp); 300 return 2; 301 } 302 if (x) 303 { 304 k = j; 305 m = x; 306 } 307 } 308 if (m == 0) 309 { 310 /* No difference. */ 311 fprintf (fp, "unknown"); 312 fclose (fp); 313 return 3; 314 } 315 /* Now m = plus.word[k] ^ ~minus.word[k]. */ 316 if (plus.word[k] & ~minus.word[k]) 317 { 318 /* Oh? The sign bit is set in the positive and cleared in the negative 319 numbers? */ 320 fprintf (fp, "unknown"); 321 fclose (fp); 322 return 4; 323 } 324 for (i = 0; ; i++) 325 if ((m >> i) & 1) 326 break; 327 fprintf (fp, "word %d bit %d", (int) k, (int) i); 328 if (fclose (fp) != 0) 329 return 5; 330 return 0; 331} 332 ]])], 333 [$2=`cat conftest.out`], 334 [$2="unknown"], 335 [ 336 dnl When cross-compiling, we don't know. It depends on the 337 dnl ABI and compiler version. There are too many cases. 338 $2="unknown" 339 ]) 340 rm -f conftest.out 341 ]) 342 case "$]$2[" in 343 word*bit*) 344 word=`echo "$]$2[" | sed -e 's/word //' -e 's/ bit.*//'` 345 bit=`echo "$]$2[" | sed -e 's/word.*bit //'` 346 AC_DEFINE_UNQUOTED([$4][_SIGNBIT_WORD], [$word], 347 [Define as the word index where to find the sign of '$1'.]) 348 AC_DEFINE_UNQUOTED([$4][_SIGNBIT_BIT], [$bit], 349 [Define as the bit index in the word where to find the sign of '$1'.]) 350 ;; 351 esac 352]) 353 354# Expands to code that defines a function signbitf(float). 355# It extracts the sign bit of a non-NaN value. 356AC_DEFUN([gl_FLOAT_SIGNBIT_CODE], 357[ 358 gl_FLOATTYPE_SIGNBIT_CODE([float], [f], [f]) 359]) 360 361# Expands to code that defines a function signbitd(double). 362# It extracts the sign bit of a non-NaN value. 363AC_DEFUN([gl_DOUBLE_SIGNBIT_CODE], 364[ 365 gl_FLOATTYPE_SIGNBIT_CODE([double], [d], []) 366]) 367 368# Expands to code that defines a function signbitl(long double). 369# It extracts the sign bit of a non-NaN value. 370AC_DEFUN([gl_LONG_DOUBLE_SIGNBIT_CODE], 371[ 372 gl_FLOATTYPE_SIGNBIT_CODE([long double], [l], [L]) 373]) 374 375AC_DEFUN([gl_FLOATTYPE_SIGNBIT_CODE], 376[[ 377static int 378signbit$2 ($1 value) 379{ 380 typedef union { $1 f; unsigned char b[sizeof ($1)]; } float_union; 381 static float_union plus_one = { 1.0$3 }; /* unused bits are zero here */ 382 static float_union minus_one = { -1.0$3 }; /* unused bits are zero here */ 383 /* Compute the sign bit mask as the XOR of plus_one and minus_one. */ 384 float_union u; 385 unsigned int i; 386 u.f = value; 387 for (i = 0; i < sizeof ($1); i++) 388 if (u.b[i] & (plus_one.b[i] ^ minus_one.b[i])) 389 return 1; 390 return 0; 391} 392]]) 393