1# round.m4 serial 22 2dnl Copyright (C) 2007, 2009-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_ROUND], 8[ 9 m4_divert_text([DEFAULTS], [gl_round_required=plain]) 10 AC_REQUIRE([gl_MATH_H_DEFAULTS]) 11 12 dnl Persuade glibc <math.h> to declare round(). 13 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) 14 15 gl_CHECK_MATH_LIB([ROUND_LIBM], [x = round (x);], 16 [extern 17 #ifdef __cplusplus 18 "C" 19 #endif 20 double round (double); 21 ]) 22 if test "$ROUND_LIBM" != missing; then 23 HAVE_ROUND=1 24 dnl Also check whether it's declared. 25 dnl IRIX 6.5 has round() in libm but doesn't declare it in <math.h>. 26 AC_CHECK_DECLS([round], , [HAVE_DECL_ROUND=0], [[#include <math.h>]]) 27 28 dnl Test whether round() produces correct results. On NetBSD 3.0, for 29 dnl x = 1/2 - 2^-54, the system's round() returns a wrong result. 30 AC_REQUIRE([AC_PROG_CC]) 31 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles 32 AC_CACHE_CHECK([whether round works], [gl_cv_func_round_works], 33 [ 34 save_LIBS="$LIBS" 35 LIBS="$LIBS $ROUND_LIBM" 36 AC_RUN_IFELSE([AC_LANG_SOURCE([[ 37#include <float.h> 38#include <math.h> 39extern 40#ifdef __cplusplus 41"C" 42#endif 43double round (double); 44#ifdef _MSC_VER 45# pragma fenv_access (off) 46#endif 47int main() 48{ 49 /* 2^DBL_MANT_DIG. */ 50 static const double TWO_MANT_DIG = 51 /* Assume DBL_MANT_DIG <= 5 * 31. 52 Use the identity 53 n = floor(n/5) + floor((n+1)/5) + ... + floor((n+4)/5). */ 54 (double) (1U << (DBL_MANT_DIG / 5)) 55 * (double) (1U << ((DBL_MANT_DIG + 1) / 5)) 56 * (double) (1U << ((DBL_MANT_DIG + 2) / 5)) 57 * (double) (1U << ((DBL_MANT_DIG + 3) / 5)) 58 * (double) (1U << ((DBL_MANT_DIG + 4) / 5)); 59 volatile double x = 0.5 - 0.5 / TWO_MANT_DIG; 60 return (x < 0.5 && round (x) != 0.0); 61}]])], [gl_cv_func_round_works=yes], [gl_cv_func_round_works=no], 62 [case "$host_os" in 63 netbsd* | aix*) gl_cv_func_round_works="guessing no" ;; 64 # Guess yes on MSVC, no on mingw. 65 mingw*) AC_EGREP_CPP([Known], [ 66#ifdef _MSC_VER 67 Known 68#endif 69 ], 70 [gl_cv_func_round_works="guessing yes"], 71 [gl_cv_func_round_works="guessing no"]) 72 ;; 73 *) gl_cv_func_round_works="guessing yes" ;; 74 esac 75 ]) 76 LIBS="$save_LIBS" 77 ]) 78 case "$gl_cv_func_round_works" in 79 *no) REPLACE_ROUND=1 ;; 80 esac 81 82 m4_ifdef([gl_FUNC_ROUND_IEEE], [ 83 if test $gl_round_required = ieee && test $REPLACE_ROUND = 0; then 84 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles 85 AC_CACHE_CHECK([whether round works according to ISO C 99 with IEC 60559], 86 [gl_cv_func_round_ieee], 87 [ 88 save_LIBS="$LIBS" 89 LIBS="$LIBS $ROUND_LIBM" 90 AC_RUN_IFELSE( 91 [AC_LANG_SOURCE([[ 92#ifndef __NO_MATH_INLINES 93# define __NO_MATH_INLINES 1 /* for glibc */ 94#endif 95#include <math.h> 96extern 97#ifdef __cplusplus 98"C" 99#endif 100double round (double); 101]gl_DOUBLE_MINUS_ZERO_CODE[ 102]gl_DOUBLE_SIGNBIT_CODE[ 103static double dummy (double f) { return 0; } 104int main (int argc, char *argv[]) 105{ 106 double (* volatile my_round) (double) = argc ? round : dummy; 107 /* Test whether round (-0.0) is -0.0. */ 108 if (signbitd (minus_zerod) && !signbitd (my_round (minus_zerod))) 109 return 1; 110 return 0; 111} 112 ]])], 113 [gl_cv_func_round_ieee=yes], 114 [gl_cv_func_round_ieee=no], 115 [case "$host_os" in 116 # Guess yes on glibc systems. 117 *-gnu* | gnu*) gl_cv_func_round_ieee="guessing yes" ;; 118 # Guess yes on musl systems. 119 *-musl*) gl_cv_func_round_ieee="guessing yes" ;; 120 # Guess yes on MSVC, no on mingw. 121 mingw*) AC_EGREP_CPP([Known], [ 122#ifdef _MSC_VER 123 Known 124#endif 125 ], 126 [gl_cv_func_round_ieee="guessing yes"], 127 [gl_cv_func_round_ieee="guessing no"]) 128 ;; 129 # If we don't know, obey --enable-cross-guesses. 130 *) gl_cv_func_round_ieee="$gl_cross_guess_normal" ;; 131 esac 132 ]) 133 LIBS="$save_LIBS" 134 ]) 135 case "$gl_cv_func_round_ieee" in 136 *yes) ;; 137 *) REPLACE_ROUND=1 ;; 138 esac 139 fi 140 ]) 141 else 142 HAVE_ROUND=0 143 HAVE_DECL_ROUND=0 144 fi 145 if test $HAVE_ROUND = 0 || test $REPLACE_ROUND = 1; then 146 dnl Find libraries needed to link lib/round.c. 147 gl_FUNC_FLOOR_LIBS 148 gl_FUNC_CEIL_LIBS 149 ROUND_LIBM= 150 dnl Append $FLOOR_LIBM to ROUND_LIBM, avoiding gratuitous duplicates. 151 case " $ROUND_LIBM " in 152 *" $FLOOR_LIBM "*) ;; 153 *) ROUND_LIBM="$ROUND_LIBM $FLOOR_LIBM" ;; 154 esac 155 dnl Append $CEIL_LIBM to ROUND_LIBM, avoiding gratuitous duplicates. 156 case " $ROUND_LIBM " in 157 *" $CEIL_LIBM "*) ;; 158 *) ROUND_LIBM="$ROUND_LIBM $CEIL_LIBM" ;; 159 esac 160 fi 161 AC_SUBST([ROUND_LIBM]) 162]) 163