round.m4 5.3 KB

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