bug-gnulib
[Top][All Lists]
Advanced

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

new module 'signbit'


From: Bruno Haible
Subject: new module 'signbit'
Date: Fri, 6 Apr 2007 22:55:37 +0200
User-agent: KMail/1.5.4

Paul mentioned copysign and signbit as possible new gnulib modules. Here
is the 'signbit' module.

2007-04-06  Bruno Haible  <address@hidden>

        * modules/signbit: New file.
        * lib/signbitf.c: New file.
        * lib/signbitd.c: New file.
        * lib/signbitl.c: New file.
        * m4/signbit.m4: New file.
        * lib/math_.h (gl_signbitf, gl_signbitd, gl_signbitl): New declarations.
        (signbit): New macro.
        * m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize GNULIB_SIGNBIT and
        REPLACE_SIGNBIT.
        * modules/math (Makefile.am) Substibute also GNULIB_SIGNBIT and
        REPLACE_FREXPL into math.h.

=========================== modules/signbit ================================
Description:
signbit() macro: Determine the sign bit of a floating-point number.

Files:
lib/signbitf.c
lib/signbitd.c
lib/signbitl.c
lib/float+.h
m4/signbit.m4

Depends-on:
math
isnanf-nolibm
isnan-nolibm
isnanl-nolibm
fpieee

configure.ac:
gl_SIGNBIT
gl_MATH_MODULE_INDICATOR([signbit])

Makefile.am:

Include:
<math.h>

License:
LGPL

Maintainer:
Bruno Haible

============================ lib/signbitf.c ================================
/* signbit() macro: Determine the sign bit of a floating-point number.
   Copyright (C) 2007 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, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#include <config.h>

/* Specification.  */
#include <math.h>

#include <string.h>
#include "isnanf.h"
#include "float+.h"

#undef gl_signbitf

int
gl_signbitf (float arg)
{
#if defined FLT_SIGNBIT_WORD && defined FLT_SIGNBIT_BIT
# 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;
#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
}
============================ lib/signbitd.c ================================
/* signbit() macro: Determine the sign bit of a floating-point number.
   Copyright (C) 2007 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, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#include <config.h>

/* Specification.  */
#include <math.h>

#include <string.h>
#include "isnan.h"
#include "float+.h"

#undef gl_signbitd

int
gl_signbitd (double arg)
{
#if defined DBL_SIGNBIT_WORD && defined DBL_SIGNBIT_BIT
# 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;
#else
  /* This does not do the right thing for NaN, but this is irrelevant for
     most use cases.  */
  if (isnan (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
}
============================ lib/signbitl.c ================================
/* signbit() macro: Determine the sign bit of a floating-point number.
   Copyright (C) 2007 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, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#include <config.h>

/* Specification.  */
#include <math.h>

#include <string.h>
#include "isnanl-nolibm.h"
#include "float+.h"

#undef gl_signbitl

int
gl_signbitl (long double arg)
{
#if defined LDBL_SIGNBIT_WORD && defined LDBL_SIGNBIT_BIT
# 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;
#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
}
============================ m4/signbit.m4 =================================
# signbit.m4 serial 1
dnl Copyright (C) 2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.

AC_DEFUN([gl_SIGNBIT],
[
  AC_REQUIRE([gl_MATH_H_DEFAULTS])
  AC_CACHE_CHECK([for signbit macro], [gl_cv_func_signbit],
    [
      AC_TRY_RUN([
#include <math.h>
#include <string.h>
float p0f = 0.0f;
float m0f = -0.0f;
double p0d = 0.0;
double m0d = -0.0;
long double p0l = 0.0L;
long double m0l = -0.0L;
int main ()
{
  {
    float plus_inf = 1.0f / p0f;
    float minus_inf = -1.0f / p0f;
    if (!(!signbit (255.0f)
          && signbit (-255.0f)
          && !signbit (p0f)
          && (memcmp (&m0f, &p0f, sizeof (float)) == 0 || signbit (m0f))
          && !signbit (plus_inf)
          && signbit (minus_inf)))
      return 1;
  }
  {
    double plus_inf = 1.0 / p0d;
    double minus_inf = -1.0 / p0d;
    if (!(!signbit (255.0)
          && signbit (-255.0)
          && !signbit (p0d)
          && (memcmp (&m0d, &p0d, sizeof (double)) == 0 || signbit (m0d))
          && !signbit (plus_inf)
          && signbit (minus_inf)))
      return 1;
  }
  {
    long double plus_inf = 1.0L / p0l;
    long double minus_inf = -1.0L / p0l;
    if (!(!signbit (255.0L)
          && signbit (-255.0L)
          && !signbit (p0l)
          && (memcmp (&m0l, &p0l, sizeof (long double)) == 0 || signbit (m0l))
          && !signbit (plus_inf)
          && signbit (minus_inf)))
      return 1;
  }
  return 0;
}], [gl_cv_func_signbit=yes], [gl_cv_func_signbit=no],
        [gl_cv_func_signbit="guessing no"])
    ])
  if test "$gl_cv_func_signbit" != yes; then
    REPLACE_SIGNBIT=1
    AC_LIBOBJ([signbitf])
    AC_LIBOBJ([signbitd])
    AC_LIBOBJ([signbitl])
    gl_FLOAT_SIGN_LOCATION
    gl_DOUBLE_SIGN_LOCATION
    gl_LONG_DOUBLE_SIGN_LOCATION
  fi
])

AC_DEFUN([gl_FLOAT_SIGN_LOCATION],
[
  gl_FLOATTYPE_SIGN_LOCATION([float], [gl_cv_cc_float_signbit], [f], [FLT])
])

AC_DEFUN([gl_DOUBLE_SIGN_LOCATION],
[
  gl_FLOATTYPE_SIGN_LOCATION([double], [gl_cv_cc_double_signbit], [], [DBL])
])

AC_DEFUN([gl_LONG_DOUBLE_SIGN_LOCATION],
[
  gl_FLOATTYPE_SIGN_LOCATION([long double], [gl_cv_cc_long_double_signbit], 
[L], [LDBL])
])

AC_DEFUN([gl_FLOATTYPE_SIGN_LOCATION],
[
  AC_CACHE_CHECK([where to find the sign bit in a '$1'],
    [$2],
    [
      AC_TRY_RUN([
#include <stddef.h>
#include <stdio.h>
#define NWORDS \
  ((sizeof ($1) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
typedef union { $1 value; unsigned int word[NWORDS]; }
        memory_float;
static memory_float plus = { 1.0$3 };
static memory_float minus = { -1.0$3 };
int main ()
{
  size_t j, k, i;
  unsigned int m;
  FILE *fp = fopen ("conftest.out", "w");
  if (fp == NULL)
    return 1;
  /* Find the different bit.  */
  k = 0; m = 0;
  for (j = 0; j < NWORDS; j++)
    {
      unsigned int x = plus.word[j] ^ minus.word[j];
      if ((x & (x - 1)) || (x && m))
        {
          /* More than one bit difference.  */
          fprintf (fp, "unknown");
          return 1;
        }
      if (x)
        {
          k = j;
          m = x;
        }
    }
  if (m == 0)
    {
      /* No difference.  */
      fprintf (fp, "unknown");
      return 1;
    }
  /* Now m = plus.word[k] ^ ~minus.word[k].  */
  if (plus.word[k] & ~minus.word[k])
    {
      /* Oh? The sign bit is set in the positive and cleared in the negative
         numbers?  */
      fprintf (fp, "unknown");
      return 1;
    }
  for (i = 0; ; i++)
    if ((m >> i) & 1)
      break;
  fprintf (fp, "word %d bit %d", (int) k, (int) i);
  return (fclose (fp) != 0);
}
        ],
        [$2=`cat conftest.out`],
        [$2="unknown"],
        [
          dnl When cross-compiling, we don't know. It depends on the
          dnl ABI and compiler version. There are too many cases.
          $2="unknown"
        ])
      rm -f conftest.out
    ])
  case "$]$2[" in
    word*bit*)
      word=`echo "$]$2[" | sed -e 's/word //' -e 's/ bit.*//'`
      bit=`echo "$]$2[" | sed -e 's/word.*bit //'`
      AC_DEFINE_UNQUOTED([$4][_SIGNBIT_WORD], [$word],
        [Define as the word index where to find the sign of '$1'.])
      AC_DEFINE_UNQUOTED([$4][_SIGNBIT_BIT], [$bit],
        [Define as the bit index in the word where to find the sign of '$1'.])
      ;;
  esac
])
============================================================================
*** lib/math_.h 6 Apr 2007 12:25:54 -0000       1.9
--- lib/math_.h 6 Apr 2007 20:46:32 -0000
***************
*** 215,220 ****
--- 215,265 ----
  #endif
  
  
+ #if @GNULIB_SIGNBIT@
+ # if @REPLACE_SIGNBIT@
+ #  undef signbit
+ extern int gl_signbitf (float arg);
+ extern int gl_signbitd (double arg);
+ extern int gl_signbitl (long double arg);
+ #  if __GNUC__ >= 2 && !__STRICT_ANSI__
+ #   if defined FLT_SIGNBIT_WORD && defined FLT_SIGNBIT_BIT
+ #    define gl_signbitf(arg) \
+        ({ union { float _value;                                               
\
+                   unsigned int _word[(sizeof (float) + sizeof (unsigned int) 
- 1) / sizeof (unsigned int)]; \
+                 } _m;                                                 \
+           _m._value = (arg);                                          \
+           (_m._word[FLT_SIGNBIT_WORD] >> FLT_SIGNBIT_BIT) & 1;                
\
+         })
+ #   endif
+ #   if defined DBL_SIGNBIT_WORD && defined DBL_SIGNBIT_BIT
+ #    define gl_signbitd(arg) \
+        ({ union { double _value;                                              
\
+                   unsigned int _word[(sizeof (double) + sizeof (unsigned int) 
- 1) / sizeof (unsigned int)]; \
+                 } _m;                                                 \
+           _m._value = (arg);                                          \
+           (_m._word[DBL_SIGNBIT_WORD] >> DBL_SIGNBIT_BIT) & 1;                
\
+         })
+ #   endif
+ #   if defined LDBL_SIGNBIT_WORD && defined LDBL_SIGNBIT_BIT
+ #    define gl_signbitl(arg) \
+        ({ union { long double _value;                                 \
+                   unsigned int _word[(sizeof (long double) + sizeof (unsigned 
int) - 1) / sizeof (unsigned int)]; \
+                 } _m;                                                 \
+           _m._value = (arg);                                          \
+           (_m._word[LDBL_SIGNBIT_WORD] >> LDBL_SIGNBIT_BIT) & 1;              
\
+         })
+ #   endif
+ #  endif
+ #  define signbit(x) \
+    (sizeof (x) == sizeof (long double) ? gl_signbitl (x) : \
+     sizeof (x) == sizeof (double) ? gl_signbitd (x) : \
+     gl_signbitf (x))
+ # endif
+ #elif defined GNULIB_POSIXCHECK
+   /* How to override a macro?  */
+ #endif
+ 
+ 
  #ifdef __cplusplus
  }
  #endif
*** m4/math_h.m4        30 Mar 2007 00:13:24 -0000      1.6
--- m4/math_h.m4        6 Apr 2007 20:46:32 -0000
***************
*** 21,30 ****
  
  AC_DEFUN([gl_MATH_H_DEFAULTS],
  [
!   GNULIB_FREXP=0;  AC_SUBST([GNULIB_FREXP])
!   GNULIB_FREXPL=0; AC_SUBST([GNULIB_FREXPL])
!   GNULIB_LDEXPL=0; AC_SUBST([GNULIB_LDEXPL])
!   GNULIB_MATHL=0;  AC_SUBST([GNULIB_MATHL])
    dnl Assume proper GNU behavior unless another module says otherwise.
    HAVE_DECL_ACOSL=1;  AC_SUBST([HAVE_DECL_ACOSL])
    HAVE_DECL_ASINL=1;  AC_SUBST([HAVE_DECL_ASINL])
--- 21,31 ----
  
  AC_DEFUN([gl_MATH_H_DEFAULTS],
  [
!   GNULIB_FREXP=0;   AC_SUBST([GNULIB_FREXP])
!   GNULIB_FREXPL=0;  AC_SUBST([GNULIB_FREXPL])
!   GNULIB_LDEXPL=0;  AC_SUBST([GNULIB_LDEXPL])
!   GNULIB_MATHL=0;   AC_SUBST([GNULIB_MATHL])
!   GNULIB_SIGNBIT=0; AC_SUBST([GNULIB_SIGNBIT])
    dnl Assume proper GNU behavior unless another module says otherwise.
    HAVE_DECL_ACOSL=1;  AC_SUBST([HAVE_DECL_ACOSL])
    HAVE_DECL_ASINL=1;  AC_SUBST([HAVE_DECL_ASINL])
***************
*** 42,45 ****
--- 43,47 ----
    REPLACE_FREXP=0;    AC_SUBST([REPLACE_FREXP])
    REPLACE_FREXPL=0;   AC_SUBST([REPLACE_FREXPL])
    REPLACE_LDEXPL=0;   AC_SUBST([REPLACE_LDEXPL])
+   REPLACE_SIGNBIT=0;  AC_SUBST([REPLACE_SIGNBIT])
  ])
*** modules/math        30 Mar 2007 00:13:24 -0000      1.6
--- modules/math        6 Apr 2007 20:46:32 -0000
***************
*** 25,30 ****
--- 25,31 ----
              -e 's|@''GNULIB_FREXPL''@|$(GNULIB_FREXPL)|g' \
              -e 's|@''GNULIB_LDEXPL''@|$(GNULIB_LDEXPL)|g' \
              -e 's|@''GNULIB_MATHL''@|$(GNULIB_MATHL)|g' \
+             -e 's|@''GNULIB_SIGNBIT''@|$(GNULIB_SIGNBIT)|g' \
              -e 's|@''HAVE_DECL_ACOSL''@|$(HAVE_DECL_ACOSL)|g' \
              -e 's|@''HAVE_DECL_ASINL''@|$(HAVE_DECL_ASINL)|g' \
              -e 's|@''HAVE_DECL_ATANL''@|$(HAVE_DECL_ATANL)|g' \
***************
*** 41,46 ****
--- 42,48 ----
              -e 's|@''REPLACE_FREXP''@|$(REPLACE_FREXP)|g' \
              -e 's|@''REPLACE_FREXPL''@|$(REPLACE_FREXPL)|g' \
              -e 's|@''REPLACE_LDEXPL''@|$(REPLACE_LDEXPL)|g' \
+             -e 's|@''REPLACE_SIGNBIT''@|$(REPLACE_SIGNBIT)|g' \
              -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
              < $(srcdir)/math_.h; \
        } > address@hidden






reply via email to

[Prev in Thread] Current Thread [Next in Thread]