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