build: Check for more math.h functions in gnulib

There are now C99 functions that the printf items want to use that may
not be necessarily supported by the math.h that is shipped by the
compiler, such as signbit(), isinf(), isnan() and isfinite() and their
double, long and float counterparts.

This checks for whether these functions are provided by the math.h
shipped by the compiler, and builds the gnulib implementations of them
if they cannot be found.  Currently no attempt is made to check whether
these, if available from the compiler's math.h, are compliant with the
specs.
This commit is contained in:
Chun-wei Fan 2019-03-28 18:27:33 +08:00
parent a1fbeb3e4f
commit b532b9cecf
7 changed files with 312 additions and 5 deletions

30
glib/gnulib/isinf.c Normal file
View File

@ -0,0 +1,30 @@
#ifndef _MSC_VER
#error "This implementation is currently supported for Visual Studio only!"
#endif
#include "config.h"
#include <gnulib_math.h>
#include <float.h>
#include <math.h>
int
gl_isinff (float x)
{
#if defined (_WIN64) && (defined (_M_X64) || defined (_M_AMD64))
return !_finitef (x);
#else
return !_finite (x);
#endif
}
int
gl_isinfd (double x)
{
return !_finite (x);
}
int
gl_isinfl (long double x)
{
return gl_isinfd (x);
}

View File

@ -0,0 +1,40 @@
/* Test for NaN that does not need libm.
Copyright (C) 2007-2019 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General PublicLicense as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General PublicLicense for more details.
You should have received a copy of the GNU Lesser General PublicLicense
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#if HAVE_ISNANF_IN_LIBC
/* Get declaration of isnan macro or (older) isnanf function. */
# include <math.h>
# if __GNUC__ >= 4
/* GCC 4.0 and newer provides three built-ins for isnan. */
# undef isnanf
# define isnanf(x) __builtin_isnanf ((float)(x))
# elif defined isnan
# undef isnanf
# define isnanf(x) isnan ((float)(x))
# else
/* Get declaration of isnanf(), if not declared in <math.h>. */
# if defined __sgi
/* We can't include <ieeefp.h>, because it conflicts with our definition of
isnand. Therefore declare isnanf separately. */
extern int isnanf (float x);
# endif
# endif
#else
/* Test whether X is a NaN. */
# undef isnanf
# define isnanf rpl_isnanf
extern int isnanf (float x);
#endif

20
glib/gnulib/isnanf.c Normal file
View File

@ -0,0 +1,20 @@
/* Test for NaN that does not need libm.
Copyright (C) 2007, 2009-2019 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General PublicLicense as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General PublicLicense for more details.
You should have received a copy of the GNU Lesser General PublicLicense
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>, 2007. */
#define USE_FLOAT
#include "isnan.c"

View File

@ -51,10 +51,6 @@ unneeded_funcs = [
'ILOGB',
'ILOGBF',
'ILOGBL',
'ISFINITE',
'ISINF',
'ISNAN',
'ISNANF',
'LDEXPF',
'LOG',
'LOG10',
@ -84,7 +80,6 @@ unneeded_funcs = [
'ROUND',
'ROUNDF',
'ROUNDL',
'SIGNBIT',
'SINF',
'SINHF',
'SINL',
@ -110,9 +105,14 @@ endforeach
needed_funcs = [
'FREXP',
'FREXPL',
'ISFINITE',
'ISINF',
'ISNAN',
'ISNAND',
'ISNANF',
'ISNANL',
'LDEXPL',
'SIGNBIT',
]
foreach f : needed_funcs
@ -296,6 +296,29 @@ endif
math_h_config.set ('REPLACE_LDEXPL', gl_cv_func_ldexpl_works ? 0 : 1)
math_h_config.set ('HAVE_DECL_LDEXPL', gl_cv_func_ldexpl_decl ? 0 : 1)
inf_tmpl = '''#include <math.h>
double x;
int main () {return @0@ (x);}
'''
other_needed_math_sources = []
# Some compilers may not have isfinite, isinf available
foreach f: ['isfinite', 'isinf', 'isnan', 'isnanf', 'signbit']
links = cc.links (inf_tmpl.format('@0@'.format(f)),
dependencies : [libm])
math_h_config.set ('HAVE_@0@'.format(f.to_upper()), links ? 1 : 0)
math_h_config.set ('HAVE_@0@_IN_LIBC'.format(f.to_upper()), links ? 1 : 0)
math_h_config.set ('REPLACE_@0@'.format(f.to_upper()), links ? 0 : 1)
set_variable ('have_@0@'.format(f), links)
if not links
if f == 'signbit'
other_needed_math_sources += [ 'signbitd.c', 'signbitf.c', 'signbitl.c' ]
elif f != 'isfinite' and f != 'isnan'
other_needed_math_sources += [ '@0@.c'.format(f) ]
endif
endif
endforeach
math_h = configure_file (input: 'gnulib_math.h.in',
output: 'gnulib_math.h',
configuration: math_h_config)
@ -309,6 +332,8 @@ if not gl_cv_func_frexpl_works
gnulib_sources += ['frexpl.c']
endif
gnulib_sources += other_needed_math_sources
gnulib_lib = static_library('gnulib', gnulib_sources,
dependencies : [libm],
include_directories : [configinc, glibinc, include_directories ('.')],

64
glib/gnulib/signbitd.c Normal file
View File

@ -0,0 +1,64 @@
/* signbit() macro: Determine the sign bit of a floating-point number.
Copyright (C) 2007-2019 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General PublicLicense as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General PublicLicense for more details.
You should have received a copy of the GNU Lesser General PublicLicense
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <math.h>
#include <string.h>
#include "isnand-nolibm.h"
#include "float+.h"
#ifdef gl_signbitd_OPTIMIZED_MACRO
# undef gl_signbitd
#endif
int
gl_signbitd (double arg)
{
#if defined DBL_SIGNBIT_WORD && defined DBL_SIGNBIT_BIT
/* The use of a union to extract the bits of the representation of a
'long double' is safe in practice, despite of the "aliasing rules" of
C99, because the GCC docs say
"Even with '-fstrict-aliasing', type-punning is allowed, provided the
memory is accessed through the union type."
and similarly for other compilers. */
# define NWORDS \
((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
union { double value; unsigned int word[NWORDS]; } m;
m.value = arg;
return (m.word[DBL_SIGNBIT_WORD] >> DBL_SIGNBIT_BIT) & 1;
#elif HAVE_COPYSIGN_IN_LIBC
return copysign (1.0, arg) < 0;
#else
/* This does not do the right thing for NaN, but this is irrelevant for
most use cases. */
if (isnand (arg))
return 0;
if (arg < 0.0)
return 1;
else if (arg == 0.0)
{
/* Distinguish 0.0 and -0.0. */
static double plus_zero = 0.0;
double arg_mem = arg;
return (memcmp (&plus_zero, &arg_mem, SIZEOF_DBL) != 0);
}
else
return 0;
#endif
}

64
glib/gnulib/signbitf.c Normal file
View File

@ -0,0 +1,64 @@
/* signbit() macro: Determine the sign bit of a floating-point number.
Copyright (C) 2007, 2009-2019 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General PublicLicense as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General PublicLicense for more details.
You should have received a copy of the GNU Lesser General PublicLicense
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <math.h>
#include <string.h>
#include "isnanf-nolibm.h"
#include "float+.h"
#ifdef gl_signbitf_OPTIMIZED_MACRO
# undef gl_signbitf
#endif
int
gl_signbitf (float arg)
{
#if defined FLT_SIGNBIT_WORD && defined FLT_SIGNBIT_BIT
/* The use of a union to extract the bits of the representation of a
'long double' is safe in practice, despite of the "aliasing rules" of
C99, because the GCC docs say
"Even with '-fstrict-aliasing', type-punning is allowed, provided the
memory is accessed through the union type."
and similarly for other compilers. */
# define NWORDS \
((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
union { float value; unsigned int word[NWORDS]; } m;
m.value = arg;
return (m.word[FLT_SIGNBIT_WORD] >> FLT_SIGNBIT_BIT) & 1;
#elif HAVE_COPYSIGNF_IN_LIBC
return copysignf (1.0f, arg) < 0;
#else
/* This does not do the right thing for NaN, but this is irrelevant for
most use cases. */
if (isnanf (arg))
return 0;
if (arg < 0.0f)
return 1;
else if (arg == 0.0f)
{
/* Distinguish 0.0f and -0.0f. */
static float plus_zero = 0.0f;
float arg_mem = arg;
return (memcmp (&plus_zero, &arg_mem, SIZEOF_FLT) != 0);
}
else
return 0;
#endif
}

64
glib/gnulib/signbitl.c Normal file
View File

@ -0,0 +1,64 @@
/* signbit() macro: Determine the sign bit of a floating-point number.
Copyright (C) 2007, 2009-2019 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General PublicLicense as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General PublicLicense for more details.
You should have received a copy of the GNU Lesser General PublicLicense
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <math.h>
#include <string.h>
#include "isnanl-nolibm.h"
#include "float+.h"
#ifdef gl_signbitl_OPTIMIZED_MACRO
# undef gl_signbitl
#endif
int
gl_signbitl (long double arg)
{
#if defined LDBL_SIGNBIT_WORD && defined LDBL_SIGNBIT_BIT
/* The use of a union to extract the bits of the representation of a
'long double' is safe in practice, despite of the "aliasing rules" of
C99, because the GCC docs say
"Even with '-fstrict-aliasing', type-punning is allowed, provided the
memory is accessed through the union type."
and similarly for other compilers. */
# define NWORDS \
((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
union { long double value; unsigned int word[NWORDS]; } m;
m.value = arg;
return (m.word[LDBL_SIGNBIT_WORD] >> LDBL_SIGNBIT_BIT) & 1;
#elif HAVE_COPYSIGNL_IN_LIBC
return copysignl (1.0L, arg) < 0;
#else
/* This does not do the right thing for NaN, but this is irrelevant for
most use cases. */
if (isnanl (arg))
return 0;
if (arg < 0.0L)
return 1;
else if (arg == 0.0L)
{
/* Distinguish 0.0L and -0.0L. */
static long double plus_zero = 0.0L;
long double arg_mem = arg;
return (memcmp (&plus_zero, &arg_mem, SIZEOF_LDBL) != 0);
}
else
return 0;
#endif
}