[glib/gnulib.msvc.fixes: 2/3] build: Check for more math.h functions in gnulib



commit c40c6c0bae86dfdaa5baf652f0d7e237c6b0d905
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Thu Mar 28 18:27:33 2019 +0800

    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.

 glib/gnulib/isinf.c         | 39 +++++++++++++++++++++++++++
 glib/gnulib/isnanf-nolibm.h | 40 ++++++++++++++++++++++++++++
 glib/gnulib/isnanf.c        | 20 ++++++++++++++
 glib/gnulib/meson.build     | 27 ++++++++++++++-----
 glib/gnulib/signbitd.c      | 64 +++++++++++++++++++++++++++++++++++++++++++++
 glib/gnulib/signbitf.c      | 64 +++++++++++++++++++++++++++++++++++++++++++++
 glib/gnulib/signbitl.c      | 64 +++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 312 insertions(+), 6 deletions(-)
---
diff --git a/glib/gnulib/isinf.c b/glib/gnulib/isinf.c
new file mode 100644
index 000000000..fb4f2a808
--- /dev/null
+++ b/glib/gnulib/isinf.c
@@ -0,0 +1,39 @@
+/* Test for positive or negative infinity.
+   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 General Public License as published by
+   the Free Software Foundation; either version 2, 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Ben Pfaff <blp gnu org>, 2008. */
+
+#include <config.h>
+
+#include <float.h>
+
+int
+gl_isinff (float x)
+{
+  return x < -FLT_MAX || x > FLT_MAX;
+}
+
+int
+gl_isinfd (double x)
+{
+  return x < -DBL_MAX || x > DBL_MAX;
+}
+
+int
+gl_isinfl (long double x)
+{
+  return x < -LDBL_MAX || x > LDBL_MAX;
+}
diff --git a/glib/gnulib/isnanf-nolibm.h b/glib/gnulib/isnanf-nolibm.h
new file mode 100644
index 000000000..73937a2c3
--- /dev/null
+++ b/glib/gnulib/isnanf-nolibm.h
@@ -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 General Public License as published by
+   the Free Software Foundation; either version 3 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   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
diff --git a/glib/gnulib/isnanf.c b/glib/gnulib/isnanf.c
new file mode 100644
index 000000000..8bc58eb58
--- /dev/null
+++ b/glib/gnulib/isnanf.c
@@ -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 General Public License as published by
+   the Free Software Foundation; either version 3 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   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"
diff --git a/glib/gnulib/meson.build b/glib/gnulib/meson.build
index 2d369a6ef..2eb7f731f 100644
--- a/glib/gnulib/meson.build
+++ b/glib/gnulib/meson.build
@@ -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
@@ -240,6 +240,21 @@ math_h_config.set ('HAVE_FREXPL', links ? 1 : 0)
 math_h_config.set ('HAVE_FREXPL_IN_LIBC', links ? 1 : 0)
 set_variable ('have_frexpl', links)
 
+inf_tmpl = '''#include <math.h>
+              double x;
+              int main () {return @0@ (x);}
+           '''
+
+# Some compilers may not have isfinite, isinf available
+foreach f: ['isfinite', 'isinf', 'isnan', 'isnanf', 'signbit']
+  links = cc.links (inf_tmpl.format('isfinite'),
+                    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)
+endforeach
+
 math_h_config.set ('INCLUDE_NEXT_AS_FIRST_DIRECTIVE', 'include')
 math_h_config.set ('NEXT_AS_FIRST_DIRECTIVE_MATH_H', '<math.h>')
 math_h_config.set ('PRAGMA_COLUMNS', '')
@@ -300,7 +315,7 @@ math_h = configure_file (input: 'gnulib_math.h.in',
                          output: 'gnulib_math.h',
                          configuration: math_h_config)
 
-gnulib_sources = ['asnprintf.c', 'printf.c', 'printf-args.c', 'printf-parse.c', 'printf-frexp.c', 
'printf-frexpl.c', 'isnand.c', 'isnanl.c', 'vasnprintf.c']
+gnulib_sources = ['asnprintf.c', 'printf.c', 'printf-args.c', 'printf-parse.c', 'printf-frexp.c', 
'printf-frexpl.c', 'isnand.c', 'isnanf.c', 'isnanl.c', 'isinf.c', 'signbitd.c', 'signbitf.c', 'signbitl.c', 
'vasnprintf.c']
 
 if not gl_cv_func_frexp_works
   gnulib_sources += ['frexp.c']
diff --git a/glib/gnulib/signbitd.c b/glib/gnulib/signbitd.c
new file mode 100644
index 000000000..9eb7d3a80
--- /dev/null
+++ b/glib/gnulib/signbitd.c
@@ -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 General Public License as published by
+   the Free Software Foundation; either version 3 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   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
+}
diff --git a/glib/gnulib/signbitf.c b/glib/gnulib/signbitf.c
new file mode 100644
index 000000000..86595e5ac
--- /dev/null
+++ b/glib/gnulib/signbitf.c
@@ -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 General Public License as published by
+   the Free Software Foundation; either version 3 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   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
+}
diff --git a/glib/gnulib/signbitl.c b/glib/gnulib/signbitl.c
new file mode 100644
index 000000000..79f4992a8
--- /dev/null
+++ b/glib/gnulib/signbitl.c
@@ -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 General Public License as published by
+   the Free Software Foundation; either version 3 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   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
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]