[Top][All Lists]
[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
- new module 'signbit',
Bruno Haible <=
- 'signbit' patch to use 'copysign' if available, Paul Eggert, 2007/04/07
- Re: 'signbit' patch to use 'copysign' if available, Bruno Haible, 2007/04/07
- Re: 'signbit' patch to use 'copysign' if available, Paul Eggert, 2007/04/09
- Re: 'signbit' patch to use 'copysign' if available, Bruno Haible, 2007/04/10
- Re: unions and aliasing (was: Re: 'signbit' patch to use 'copysign' if available), Bruno Haible, 2007/04/10
- Re: unions and aliasing, Paul Eggert, 2007/04/11
Re: 'signbit' patch to use 'copysign' if available, Bruno Haible, 2007/04/10