1# ilogbl.m4 serial 5
2dnl Copyright (C) 2010-2021 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_ILOGBL],
8[
9  AC_REQUIRE([gl_MATH_H_DEFAULTS])
10  AC_REQUIRE([gl_LONG_DOUBLE_VS_DOUBLE])
11  AC_REQUIRE([gl_FUNC_ILOGB])
12
13  dnl Persuade glibc <math.h> to declare ilogbl().
14  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
15
16  dnl Test whether ilogbl() exists. Assume that ilogbl(), if it exists, is
17  dnl defined in the same library as ilogb().
18  save_LIBS="$LIBS"
19  LIBS="$LIBS $ILOGB_LIBM"
20  AC_CACHE_CHECK([for ilogbl],
21    [gl_cv_func_ilogbl],
22    [
23      AC_LINK_IFELSE(
24        [AC_LANG_PROGRAM(
25           [[#ifndef __NO_MATH_INLINES
26             # define __NO_MATH_INLINES 1 /* for glibc */
27             #endif
28             #include <math.h>
29             int (*funcptr) (long double) = ilogbl;
30             long double x;]],
31           [[return (funcptr (x) % 2) == 0
32                    || (ilogbl (x) % 2) == 0;]])],
33        [gl_cv_func_ilogbl=yes],
34        [gl_cv_func_ilogbl=no])
35    ])
36  LIBS="$save_LIBS"
37  if test $gl_cv_func_ilogbl = yes; then
38    ILOGBL_LIBM="$ILOGB_LIBM"
39    save_LIBS="$LIBS"
40    LIBS="$LIBS $ILOGBL_LIBM"
41    gl_FUNC_ILOGBL_WORKS
42    LIBS="$save_LIBS"
43    case "$gl_cv_func_ilogbl_works" in
44      *yes) ;;
45      *) REPLACE_ILOGBL=1 ;;
46    esac
47  else
48    HAVE_ILOGBL=0
49  fi
50  if test $HAVE_ILOGBL = 0 || test $REPLACE_ILOGBL = 1; then
51    dnl Find libraries needed to link lib/ilogbl.c.
52    if test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1; then
53      ILOGBL_LIBM="$ILOGB_LIBM"
54    else
55      AC_REQUIRE([gl_FUNC_FREXPL])
56      AC_REQUIRE([gl_FUNC_ISNANL])
57      ILOGBL_LIBM=
58      dnl Append $FREXPL_LIBM to ILOGBL_LIBM, avoiding gratuitous duplicates.
59      case " $ILOGBL_LIBM " in
60        *" $FREXPL_LIBM "*) ;;
61        *) ILOGBL_LIBM="$ILOGBL_LIBM $FREXPL_LIBM" ;;
62      esac
63      dnl Append $ISNANL_LIBM to ILOGBL_LIBM, avoiding gratuitous duplicates.
64      case " $ILOGBL_LIBM " in
65        *" $ISNANL_LIBM "*) ;;
66        *) ILOGBL_LIBM="$ILOGBL_LIBM $ISNANL_LIBM" ;;
67      esac
68    fi
69  fi
70  AC_SUBST([ILOGBL_LIBM])
71])
72
73dnl Test whether ilogbl() works.
74dnl On Cygwin 2.9, ilogbl(0.0L) is wrong.
75dnl On AIX 7.1 in 64-bit mode, ilogbl(2^(LDBL_MIN_EXP-1)) is wrong.
76dnl On Haiku 2017, it returns i-2 instead of i-1 for values between
77dnl ca. 2^-16444 and ca. 2^-16382.
78AC_DEFUN([gl_FUNC_ILOGBL_WORKS],
79[
80  AC_REQUIRE([AC_PROG_CC])
81  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
82  AC_CACHE_CHECK([whether ilogbl works], [gl_cv_func_ilogbl_works],
83    [
84      AC_RUN_IFELSE(
85        [AC_LANG_SOURCE([[
86#include <float.h>
87#include <math.h>
88/* Override the values of <float.h>, like done in float.in.h.  */
89#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__)
90# undef LDBL_MIN_EXP
91# define LDBL_MIN_EXP    (-16381)
92#endif
93#if defined __i386__ && (defined __FreeBSD__ || defined __DragonFly__)
94# undef LDBL_MIN_EXP
95# define LDBL_MIN_EXP    (-16381)
96#endif
97#if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__
98# undef LDBL_MIN_EXP
99# define LDBL_MIN_EXP DBL_MIN_EXP
100#endif
101#if defined __sgi && (LDBL_MANT_DIG >= 106)
102# if defined __GNUC__
103#  undef LDBL_MIN_EXP
104#  define LDBL_MIN_EXP DBL_MIN_EXP
105# endif
106#endif
107volatile long double x;
108static int dummy (long double x) { return 0; }
109int main (int argc, char *argv[])
110{
111  int (* volatile my_ilogbl) (long double) = argc ? ilogbl : dummy;
112  int result = 0;
113  /* This test fails on Cygwin 2.9.  */
114  {
115    x = 0.0L;
116    if (my_ilogbl (x) != FP_ILOGB0)
117      result |= 1;
118  }
119  /* This test fails on AIX 7.1 in 64-bit mode.  */
120  {
121    int i;
122    x = 0.5L;
123    for (i = LDBL_MIN_EXP - 1; i < 0; i++)
124      x = x * 0.5L;
125    if (x > 0.0L && my_ilogbl (x) != LDBL_MIN_EXP - 2)
126      result |= 2;
127  }
128  /* This test fails on Haiku 2017.  */
129  {
130    int i;
131    for (i = 1, x = (long double)1.0; i >= LDBL_MIN_EXP-100 && x > (long double)0.0; i--, x *= (long double)0.5)
132      if (my_ilogbl (x) != i - 1)
133        {
134          result |= 4;
135          break;
136        }
137  }
138  return result;
139}
140]])],
141        [gl_cv_func_ilogbl_works=yes],
142        [gl_cv_func_ilogbl_works=no],
143        [case "$host_os" in
144           aix* | haiku*)
145                   gl_cv_func_ilogbl_works="guessing no" ;;
146                   # Guess yes on native Windows.
147           mingw*) gl_cv_func_ilogbl_works="guessing yes" ;;
148           *)      gl_cv_func_ilogbl_works="guessing yes" ;;
149         esac
150        ])
151    ])
152])
153