Commit | Line | Data |
---|---|---|
005de2e8 LC |
1 | # round.m4 serial 16 |
2 | dnl Copyright (C) 2007, 2009-2012 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_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> | |
39 | extern | |
40 | #ifdef __cplusplus | |
41 | "C" | |
42 | #endif | |
43 | double round (double); | |
44 | #ifdef _MSC_VER | |
45 | # pragma fenv_access (off) | |
46 | #endif | |
47 | int 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 | exit (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 | *) gl_cv_func_round_works="guessing yes";; | |
65 | esac | |
66 | ]) | |
67 | LIBS="$save_LIBS" | |
68 | ]) | |
69 | case "$gl_cv_func_round_works" in | |
70 | *no) REPLACE_ROUND=1 ;; | |
71 | esac | |
72 | ||
73 | m4_ifdef([gl_FUNC_ROUND_IEEE], [ | |
74 | if test $gl_round_required = ieee && test $REPLACE_ROUND = 0; then | |
75 | AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles | |
76 | AC_CACHE_CHECK([whether round works according to ISO C 99 with IEC 60559], | |
77 | [gl_cv_func_round_ieee], | |
78 | [ | |
79 | save_LIBS="$LIBS" | |
80 | LIBS="$LIBS $ROUND_LIBM" | |
81 | AC_RUN_IFELSE( | |
82 | [AC_LANG_SOURCE([[ | |
83 | #ifndef __NO_MATH_INLINES | |
84 | # define __NO_MATH_INLINES 1 /* for glibc */ | |
85 | #endif | |
86 | #include <math.h> | |
87 | extern | |
88 | #ifdef __cplusplus | |
89 | "C" | |
90 | #endif | |
91 | double round (double); | |
92 | ]gl_DOUBLE_MINUS_ZERO_CODE[ | |
93 | ]gl_DOUBLE_SIGNBIT_CODE[ | |
94 | static double dummy (double f) { return 0; } | |
95 | int main (int argc, char *argv[]) | |
96 | { | |
97 | double (*my_round) (double) = argc ? round : dummy; | |
98 | /* Test whether round (-0.0) is -0.0. */ | |
99 | if (signbitd (minus_zerod) && !signbitd (my_round (minus_zerod))) | |
100 | return 1; | |
101 | return 0; | |
102 | } | |
103 | ]])], | |
104 | [gl_cv_func_round_ieee=yes], | |
105 | [gl_cv_func_round_ieee=no], | |
106 | [case "$host_os" in | |
107 | # Guess yes on glibc systems. | |
108 | *-gnu*) gl_cv_func_round_ieee="guessing yes" ;; | |
109 | # If we don't know, assume the worst. | |
110 | *) gl_cv_func_round_ieee="guessing no" ;; | |
111 | esac | |
112 | ]) | |
113 | LIBS="$save_LIBS" | |
114 | ]) | |
115 | case "$gl_cv_func_round_ieee" in | |
116 | *yes) ;; | |
117 | *) REPLACE_ROUND=1 ;; | |
118 | esac | |
119 | fi | |
120 | ]) | |
121 | else | |
122 | HAVE_ROUND=0 | |
123 | HAVE_DECL_ROUND=0 | |
124 | fi | |
125 | if test $HAVE_ROUND = 0 || test $REPLACE_ROUND = 1; then | |
126 | dnl Find libraries needed to link lib/round.c. | |
127 | gl_FUNC_FLOOR_LIBS | |
128 | gl_FUNC_CEIL_LIBS | |
129 | ROUND_LIBM= | |
130 | dnl Append $FLOOR_LIBM to ROUND_LIBM, avoiding gratuitous duplicates. | |
131 | case " $ROUND_LIBM " in | |
132 | *" $FLOOR_LIBM "*) ;; | |
133 | *) ROUND_LIBM="$ROUND_LIBM $FLOOR_LIBM" ;; | |
134 | esac | |
135 | dnl Append $CEIL_LIBM to ROUND_LIBM, avoiding gratuitous duplicates. | |
136 | case " $ROUND_LIBM " in | |
137 | *" $CEIL_LIBM "*) ;; | |
138 | *) ROUND_LIBM="$ROUND_LIBM $CEIL_LIBM" ;; | |
139 | esac | |
140 | fi | |
141 | AC_SUBST([ROUND_LIBM]) | |
142 | ]) |