This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH RFC] <math.h> issignaling


Hi!

In IEEE 754-1985, ÂAnnex A Recommended Functions and PredicatesÂ, 10) a
function to distinguish signaling from quiet NaNs is suggested.  This is
further elaborated in IEEE 754-2008, Â5.7.2 General operations as a
isSignaling operation.  Such a macro/function is not yet part of any
published revision of the C programming language standard, but has been
under discussion for some time alreay, see for example in
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/PostPortland2012.htm>'s
N1664 (the latest of its kind that is publically available, as far as I
know), Â14.7 Inquiry macros [...] Suggested change to C11: [...] 7.12.3.7
The issignaling macroÂ:

| Synopsis
| [1] #define __STDC_WANT_IEC_00000_EXT1__
|     #include <math.h>
|     int issignaling(real-floating x);
| 
| Description
| [2] The issignaling macro determines whether its argument value is a signaling NaN, without
|     raising a floating-point exception.
| 
| Returns
| [3] The issignaling macro returns a nonzero value if and only if its argument is a signaling NaN.


Here is the patch that I have so far (to be applied on top of those I
submitted yesterday); please comment.  Of course, later on, I can publish
this as a Git branch, but for now I'd just like a general review.


My __issignaling implementations are not as "advanced" (or "dense") as
their __isnan equivalents, but I find mine easier to understand, and
where I inspected it, GCC appears to create reasonable code for mine,
too, without jumps.  We can further optimize this later on, if there ever
turns out to be any such demand.


Currently I'm providing a __issignalingl symbol (aliased to
__issignaling) if NO_LONG_DOUBLE is defined.  The <math.h> issignaling
macro definition on the other hand adds long double support based on
__NO_LONG_DOUBLE_MATH being defined.  I don't completely understand yet
what exactly each of NO_LONG_DOUBLE, __NO_LONG_DOUBLE_MATH, and then
__LONG_DOUBLE_MATH_OPTIONAL are to achieve, and which I have to care for;
also whether I need to do anything with sysdeps/ieee754/ldbl-opt and
sysdeps/ieee754/ldbl-64-128 (don't think so)?


So far, I only tested this for 32-bit and 64-bit x86/x86_64 as well as
MIPS32 O32.  (Thus, not all issignaling functions have been tested yet.)

On 32-bit x86, the __issignalingf and __issignaling functions already
"fail" at the call site:

     804a130:       d9 05 18 e1 04 08       flds   0x804e118
     804a136:       d9 1c 24                fstps  (%esp)
     804a139:       e8 d2 eb ff ff          call   8048d10 <__issignalingf@plt>

For float and double (but not long double), per the x86 ISA, this will
load the sNaN variable (0x804e118), but then turn it into a qNaN and
raise the INVALID exception.  (Thus, the __issignalingf function will
never be able to detect a sNaN.)  I hope to get around this by adding
always_inline definitions for the __issignaling functions to the
respective mathinline.h files.  (But what about someone using <math.h>
issignaling with gcc -O0, where always_inline is not respected, I think?)
For optimization purposes, wouldn't it generally be preferable to add
always_inline definitions to the respective mathinline.h files,
duplicating the sysdeps/ieee754/*/s_issignaling*.c code?  But I take it
we cannot completely avoid the s_issignaling*.c files?

On 64-bit x86_64, the sNaN variable is directly movssed into xmm0,
avoiding this problem.  For MIPS32 O32, test results also look fine.


For brevity, I cut out all the libm.abilist changes from the following
diff; these all are:

+GLIBC_2.18
+ GLIBC_2.18 A
+ __issignaling F
+ __issignalingf F
+ __issignalingl F

 NEWS                                               |    2 +
 Versions.def                                       |    1 +
 include/math.h                                     |    3 +
 manual/arith.texi                                  |    7 +++
 math/Makefile                                      |    2 +-
 math/Versions                                      |    3 +
 math/basic-test.c                                  |   34 +++++++++++++-
 math/bits/mathcalls.h                              |    6 ++
 math/gen-libm-test.pl                              |    2 +-
 math/libm-test.inc                                 |   42 +++++++++++++++--
 math/math.h                                        |   14 ++++++
 math/test-snan.c                                   |   42 ++++++++++++++++-
 ports/sysdeps/hppa/math_private.h                  |   26 ++++++++++
 ports/sysdeps/mips/math_private.h                  |   26 ++++++++++
 .../unix/sysv/linux/aarch64/nptl/libm.abilist      |    5 ++
 .../unix/sysv/linux/alpha/nptl/libm.abilist        |    5 ++
 .../sysdeps/unix/sysv/linux/arm/nptl/libm.abilist  |    5 ++
 .../sysdeps/unix/sysv/linux/ia64/nptl/libm.abilist |    5 ++
 .../sysv/linux/m68k/coldfire/nptl/libm.abilist     |    5 ++
 .../unix/sysv/linux/m68k/m680x0/nptl/libm.abilist  |    5 ++
 .../unix/sysv/linux/mips/mips32/nptl/libm.abilist  |    5 ++
 .../sysv/linux/mips/mips64/n32/nptl/libm.abilist   |    5 ++
 .../sysv/linux/mips/mips64/n64/nptl/libm.abilist   |    5 ++
 .../powerpc/powerpc32/nofpu/nptl/libm.abilist      |    5 ++
 .../linux/tile/tilegx/tilegx32/nptl/libm.abilist   |    5 ++
 .../linux/tile/tilegx/tilegx64/nptl/libm.abilist   |    5 ++
 .../unix/sysv/linux/tile/tilepro/nptl/libm.abilist |    5 ++
 sysdeps/ieee754/dbl-64/s_issignaling.c             |   49 ++++++++++++++++++++
 sysdeps/ieee754/dbl-64/wordsize-64/s_issignaling.c |   45 ++++++++++++++++++
 sysdeps/ieee754/flt-32/s_issignalingf.c            |   42 +++++++++++++++++
 sysdeps/ieee754/ldbl-128/s_issignalingl.c          |   45 ++++++++++++++++++
 sysdeps/ieee754/ldbl-128ibm/s_issignalingl.c       |   44 ++++++++++++++++++
 sysdeps/ieee754/ldbl-96/s_issignalingl.c           |   43 +++++++++++++++++
 sysdeps/unix/sysv/linux/i386/nptl/libm.abilist     |    5 ++
 .../linux/powerpc/powerpc32/fpu/nptl/libm.abilist  |    5 ++
 .../sysv/linux/powerpc/powerpc64/nptl/libm.abilist |    5 ++
 .../unix/sysv/linux/s390/s390-32/nptl/libm.abilist |    5 ++
 .../unix/sysv/linux/s390/s390-64/nptl/libm.abilist |    5 ++
 sysdeps/unix/sysv/linux/sh/nptl/libm.abilist       |    5 ++
 .../sysv/linux/sparc/sparc32/nptl/libm.abilist     |    5 ++
 .../sysv/linux/sparc/sparc64/nptl/libm.abilist     |    5 ++
 .../unix/sysv/linux/x86_64/64/nptl/libm.abilist    |    5 ++
 .../unix/sysv/linux/x86_64/x32/nptl/libm.abilist   |    5 ++
 43 files changed, 584 insertions(+), 9 deletions(-)

diff --git NEWS NEWS
index c5e38b3..a04ffc7 100644
--- NEWS
+++ NEWS
@@ -23,6 +23,8 @@ Version 2.18
 * Support for priority inherited mutexes in pthread condition variables on
   non-x86 architectures.
 
+* New <math.h> macro named issignaling to check for a signaling NaN (sNaN).
+  This is currently GNU-specific.

 Version 2.17
 
diff --git Versions.def Versions.def
index 8651992..67e6f7a 100644
--- Versions.def
+++ Versions.def
@@ -58,6 +58,7 @@ libm {
   GLIBC_2.3.4
   GLIBC_2.4
   GLIBC_2.15
+  GLIBC_2.18
 }
 libnsl {
   GLIBC_2.0
diff --git include/math.h include/math.h
index 2b040c6..cbbce59 100644
--- include/math.h
+++ include/math.h
@@ -23,11 +23,14 @@ hidden_proto (__isnanl)
 
 libm_hidden_proto (__fpclassify)
 libm_hidden_proto (__fpclassifyf)
+libm_hidden_proto (__issignaling)
+libm_hidden_proto (__issignalingf)
 libm_hidden_proto (__exp)
 libm_hidden_proto (__expf)
 
 # ifndef __NO_LONG_DOUBLE_MATH
 libm_hidden_proto (__fpclassifyl)
+libm_hidden_proto (__issignalingl)
 libm_hidden_proto (__expl)
 libm_hidden_proto (__expm1l)
 # endif
diff --git manual/arith.texi manual/arith.texi
index faf25cc..0c0b53e 100644
--- manual/arith.texi
+++ manual/arith.texi
@@ -387,6 +387,13 @@ to
 @end smallexample
 @end deftypefn
 
+@comment math.h
+@comment GNU
+@deftypefn {Macro} int issignaling (@emph{float-type} @var{x})
+This macro returns a nonzero value if @var{x} is a signaling NaN
+(sNaN).  It is a GNU extension.
+@end deftypefn
+
 Another set of floating-point classification functions was provided by
 BSD.  @Theglibc{} also supports these functions; however, we
 recommend that you use the ISO C99 macros in new code.  Those are standard
diff --git math/Makefile math/Makefile
index e216dfb..f396ba2 100644
--- math/Makefile
+++ math/Makefile
@@ -58,7 +58,7 @@ libm-calls = e_acos e_acosh e_asin e_atan2 e_atanh e_cosh e_exp e_fmod	\
 	     s_catan s_casin s_ccos s_csin s_ctan s_ctanh s_cacos	\
 	     s_casinh s_cacosh s_catanh s_csqrt s_cpow s_cproj s_clog10 \
 	     s_fma s_lrint s_llrint s_lround s_llround e_exp10 w_log2	\
-	     s_isinf_ns $(calls:s_%=m_%) x2y2m1 k_casinh
+	     s_isinf_ns s_issignaling $(calls:s_%=m_%) x2y2m1 k_casinh
 
 include ../Makeconfig
 
diff --git math/Versions math/Versions
index 0988851..513ab14 100644
--- math/Versions
+++ math/Versions
@@ -198,4 +198,7 @@ libm {
     __gamma_r_finite; __gammaf_r_finite; __gammal_r_finite;
     __exp_finite; __expf_finite; __expl_finite;
   }
+  GLIBC_2.18 {
+    __issignaling; __issignalingf; __issignalingl;
+  }
 }
diff --git math/basic-test.c math/basic-test.c
index ffead2e..4744dc8 100644
--- math/basic-test.c
+++ math/basic-test.c
@@ -39,6 +39,9 @@ NAME (void)								      \
   /* Variables are declared volatile to forbid some compiler		      \
      optimizations.  */							      \
   volatile FLOAT Inf_var, qNaN_var, zero_var, one_var;			      \
+  /* A sNaN is only guaranteed to be representable in variables with */	      \
+  /* static (or thread-local) storage duration.  */			      \
+  static volatile FLOAT sNaN_var = __builtin_nans ## SUFFIX ("");	      \
   FLOAT x1, x2;								      \
 									      \
   zero_var = 0.0;							      \
@@ -49,6 +52,7 @@ NAME (void)								      \
   (void) &zero_var;							      \
   (void) &one_var;							      \
   (void) &qNaN_var;							      \
+  (void) &sNaN_var;							      \
   (void) &Inf_var;							      \
 									      \
 									      \
@@ -56,16 +60,28 @@ NAME (void)								      \
   check (#FLOAT " isinf (-inf) == -1", isinf (-Inf_var) == -1);		      \
   check (#FLOAT " !isinf (1)", !(isinf (one_var)));			      \
   check (#FLOAT " !isinf (qNaN)", !(isinf (qNaN_var)));			      \
+  check (#FLOAT " !isinf (sNaN)", !(isinf (sNaN_var)));			      \
 									      \
   check (#FLOAT " isnan (qNaN)", isnan (qNaN_var));			      \
+  check (#FLOAT " isnan (sNaN)", isnan (sNaN_var));			      \
   check (#FLOAT " isnan (-qNaN)", isnan (-qNaN_var));			      \
+  check (#FLOAT " isnan (-sNaN)", isnan (-sNaN_var));			      \
   check (#FLOAT " !isnan (1)", !(isnan (one_var)));			      \
   check (#FLOAT " !isnan (inf)", !(isnan (Inf_var)));			      \
 									      \
+  check (#FLOAT " !issignaling (qNaN)", !(issignaling (qNaN_var)));	      \
+  check (#FLOAT " issignaling (sNaN)", issignaling (sNaN_var));		      \
+  check (#FLOAT " !issignaling (-qNaN)", !(issignaling (-qNaN_var)));	      \
+  check (#FLOAT " issignaling (-sNaN)", issignaling (-sNaN_var));	      \
+  check (#FLOAT " !issignaling (1)", !(issignaling (one_var)));		      \
+  check (#FLOAT " !issignaling (inf)", !(issignaling (Inf_var)));	      \
+									      \
   check (#FLOAT " inf == inf", Inf_var == Inf_var);			      \
   check (#FLOAT " -inf == -inf", -Inf_var == -Inf_var);			      \
   check (#FLOAT " inf != -inf", Inf_var != -Inf_var);			      \
   check (#FLOAT " qNaN != qNaN", qNaN_var != qNaN_var);			      \
+  check (#FLOAT " sNaN != sNaN", sNaN_var != sNaN_var);			      \
+  check (#FLOAT " qNaN != sNaN", qNaN_var != sNaN_var);			      \
 									      \
   /*									      \
      the same tests but this time with NAN from <bits/nan.h>		      \
@@ -76,6 +92,8 @@ NAME (void)								      \
   check (#FLOAT " !isinf (NAN)", !(isinf (NAN)));			      \
   check (#FLOAT " !isinf (-NAN)", !(isinf (-NAN)));			      \
   check (#FLOAT " NAN != NAN", NAN != NAN);				      \
+  check (#FLOAT " NAN != qNaN", NAN != qNaN_var);			      \
+  check (#FLOAT " NAN != sNaN", NAN != sNaN_var);			      \
 									      \
   /*									      \
      And again with the value returned by the `nan' function.		      \
@@ -86,6 +104,8 @@ NAME (void)								      \
   check (#FLOAT " !isinf (-nan (\"\"))", !(isinf (-nan ## SUFFIX (""))));     \
   check (#FLOAT " nan (\"\") != nan (\"\")",				      \
 	 nan ## SUFFIX ("") != nan ## SUFFIX (""));			      \
+  check (#FLOAT " nan (\"\") != qNaN", nan ## SUFFIX ("") != qNaN_var);	      \
+  check (#FLOAT " nan (\"\") != sNaN", nan ## SUFFIX ("") != sNaN_var);	      \
 									      \
   /* test if EPSILON is ok */						      \
   x1 = 1.0;								      \
@@ -108,6 +128,9 @@ void									      \
 NAME (void)								      \
 {									      \
   volatile DOUBLE Inf_var, qNaN_var, zero_var, one_var;			      \
+  /* A sNaN is only guaranteed to be representable in variables with */	      \
+  /* static (or thread-local) storage duration.  */			      \
+  static volatile DOUBLE sNaN_var = __builtin_nans ## SUFFIX ("");	      \
   FLOAT x1, x2;								      \
 									      \
   zero_var = 0.0;							      \
@@ -116,10 +139,19 @@ NAME (void)								      \
   Inf_var = one_var / zero_var;						      \
 									      \
   (void) &qNaN_var;							      \
+  (void) &sNaN_var;							      \
   (void) &Inf_var;							      \
 									      \
   x1 = (FLOAT) qNaN_var;						      \
-  check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") qNaN", isnan (x1) != 0);	      \
+  check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") qNaN, isnan", isnan (x1));     \
+  check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") qNaN, !issignaling",	      \
+	 !issignaling (x1));						      \
+  x1 = (FLOAT) sNaN_var;						      \
+  check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") sNaN, isnan", isnan (x1));     \
+  /* Upon type conversion, a sNaN is converted into a qNaN plus an INVALID */ \
+  /* exception (not checked here).  */					      \
+  check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") sNaN, !issignaling",	      \
+	 !issignaling (x1));						      \
   x2 = (FLOAT) Inf_var;							      \
   check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") Inf", isinf (x2) != 0);	      \
 }
diff --git math/bits/mathcalls.h math/bits/mathcalls.h
index e5af507..870c54c 100644
--- math/bits/mathcalls.h
+++ math/bits/mathcalls.h
@@ -360,6 +360,12 @@ __MATHCALL (fma,, (_Mdouble_ __x, _Mdouble_ __y, _Mdouble_ __z));
 __END_NAMESPACE_C99
 #endif
 
+#ifdef __USE_GNU
+/* Test for signaling NaN.  */
+__MATHDECL_1 (int, __issignaling,, (_Mdouble_ __value))
+     __attribute__ ((__const__));
+#endif
+
 #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED
 /* Return X times (2 to the Nth power).  */
 __MATHCALL (scalb,, (_Mdouble_ __x, _Mdouble_ __n));
diff --git math/gen-libm-test.pl math/gen-libm-test.pl
index 01e0fc2..ea244ab 100755
--- math/gen-libm-test.pl
+++ math/gen-libm-test.pl
@@ -320,7 +320,7 @@ sub parse_args {
   }
   # Special handling for some macros:
   $cline .= " (\"$str\", ";
-  if ($args[0] =~ /fpclassify|isnormal|isfinite|isinf|isnan|signbit
+  if ($args[0] =~ /fpclassify|isnormal|isfinite|isinf|isnan|issignaling|signbit
       |isgreater|isgreaterequal|isless|islessequal
       |islessgreater|isunordered/x) {
     $c_call = "$args[0] (";
diff --git math/libm-test.inc math/libm-test.inc
index 19aa203..370a7a4 100644
--- math/libm-test.inc
+++ math/libm-test.inc
@@ -42,7 +42,7 @@
    cbrt, ceil, copysign, cos, cosh, erf, erfc, exp, exp10, exp2, expm1,
    fabs, fdim, finite, floor, fma, fmax, fmin, fmod, fpclassify,
    frexp, gamma, hypot,
-   ilogb, isfinite, isinf, isnan, isnormal,
+   ilogb, isfinite, isinf, isnan, isnormal, issignaling,
    isless, islessequal, isgreater, isgreaterequal, islessgreater, isunordered,
    j0, j1, jn,
    ldexp, lgamma, log, log10, log1p, log2, logb,
@@ -87,9 +87,9 @@
    aren't checked at the moment.
 
    NaN values: There exist signalling and quiet NaNs.  This implementation
-   only uses quiet NaN as parameter but does not differentiate
+   only uses quiet NaN as parameter, and does not differentiate
    between the two kinds of NaNs as result.  Where the sign of a NaN is
-   significant, this is not tested.
+   significant, this is not tested.  The payload of NaNs is not examined.
 
    Inline functions: Inlining functions should give an improvement in
    speed - but not in precission.  The inlined functions return
@@ -532,6 +532,20 @@ check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
   FLOAT ulp = 0;
 
   test_exceptions (test_name, exceptions);
+  /* We never expect a sNaN.  */
+  if (issignaling (expected))
+    {
+      printf ("internal error: %s: expecting sNaN?\n", test_name);
+      abort ();
+    }
+  /* Functions shall return qNaNs.  */
+  /* TODO: currently, many do return sNaNs (in particular for sNaN inputs), so
+     deactivate this testing for the time being.  */
+#if 0
+  if (issignaling (computed))
+    ok = 0;
+  else
+#endif
   if (isnan (computed) && isnan (expected))
     ok = 1;
   else if (isinf (computed) && isinf (expected))
@@ -546,8 +560,9 @@ check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
       else
 	ok = 1;
     }
-  /* Don't calc ulp for NaNs or infinities.  */
-  else if (isinf (computed) || isnan (computed) || isinf (expected) || isnan (expected))
+  /* Don't calculate ULPs for infinities or any kind of NaNs.  */
+  else if (isinf (computed) || isnan (computed)
+	   || isinf (expected) || isnan (expected))
     ok = 0;
   else
     {
@@ -6185,6 +6200,22 @@ isnormal_test (void)
 }
 
 static void
+issignaling_test (void)
+{
+  START (issignaling);
+
+  TEST_f_b (issignaling, 0, 0);
+  TEST_f_b (issignaling, minus_zero, 0);
+  TEST_f_b (issignaling, 10, 0);
+  TEST_f_b (issignaling, min_subnorm_value, 0);
+  TEST_f_b (issignaling, plus_infty, 0);
+  TEST_f_b (issignaling, minus_infty, 0);
+  TEST_f_b (issignaling, qnan_value, 0);
+
+  END (issignaling);
+}
+
+static void
 isunordered_test (void)
 {
   START (isunordered);
@@ -10798,6 +10829,7 @@ main (int argc, char **argv)
   isinf_test ();
   isnan_test ();
   isnormal_test ();
+  issignaling_test ();
   signbit_test ();
 
   /* Trigonometric functions:  */
diff --git math/math.h math/math.h
index 2f25c23..e3adf09 100644
--- math/math.h
+++ math/math.h
@@ -282,6 +282,20 @@ enum
 
 #endif /* Use ISO C99.  */
 
+#ifdef __USE_GNU
+/* Return nonzero value if X is a signaling NaN.  */
+# ifdef __NO_LONG_DOUBLE_MATH
+#  define issignaling(x) \
+     (sizeof (x) == sizeof (float) ? __issignalingf (x) : __issignaling (x))
+# else
+#  define issignaling(x) \
+     (sizeof (x) == sizeof (float)					      \
+      ? __issignalingf (x)						      \
+      : sizeof (x) == sizeof (double)					      \
+      ? __issignaling (x) : __issignalingl (x))
+# endif
+#endif /* Use GNU.  */
+
 #ifdef	__USE_MISC
 /* Support for various different standard error handling behaviors.  */
 typedef enum
diff --git math/test-snan.c math/test-snan.c
index 6ec9414..030d757 100644
--- math/test-snan.c
+++ math/test-snan.c
@@ -1,4 +1,4 @@
-/* Test signaling NaNs in isnan, isinf, and similar functions.
+/* Test signaling NaNs in issignaling, isnan, isinf, and similar functions.
    Copyright (C) 2008-2013 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@suse.de>, 2005.
@@ -114,6 +114,46 @@ NAME (void)								      \
   feenableexcept (FE_ALL_EXCEPT);					      \
   if (sigsetjmp(sigfpe_buf, 0))						      \
     {									      \
+      printf (#FLOAT " issignaling (qNaN) raised SIGFPE\n");		      \
+      errors++;								      \
+    } else {								      \
+      check (#FLOAT " issignaling (qNaN)", !issignaling (qNaN_var));	      \
+    }									      \
+									      \
+  feclearexcept(FE_ALL_EXCEPT);						      \
+  feenableexcept (FE_ALL_EXCEPT);					      \
+  if (sigsetjmp(sigfpe_buf, 0))						      \
+    {									      \
+      printf (#FLOAT " issignaling (-qNaN) raised SIGFPE\n");		      \
+      errors++;								      \
+    } else {								      \
+      check (#FLOAT " issignaling (-qNaN)", !issignaling (-qNaN_var));	      \
+    }									      \
+									      \
+  feclearexcept(FE_ALL_EXCEPT);						      \
+  feenableexcept (FE_ALL_EXCEPT);					      \
+  if (sigsetjmp(sigfpe_buf, 0))						      \
+    {									      \
+      printf (#FLOAT " issignaling (sNaN) raised SIGFPE\n");		      \
+      errors++;								      \
+    } else {								      \
+      check (#FLOAT " issignaling (sNaN)", issignaling (sNaN_var));	      \
+    }									      \
+									      \
+  feclearexcept(FE_ALL_EXCEPT);						      \
+  feenableexcept (FE_ALL_EXCEPT);					      \
+  if (sigsetjmp(sigfpe_buf, 0))						      \
+    {									      \
+      printf (#FLOAT " issignaling (-sNaN) raised SIGFPE\n");		      \
+      errors++;								      \
+    } else {								      \
+      check (#FLOAT " issignaling (-sNaN)", issignaling (-sNaN_var));	      \
+    }									      \
+									      \
+  feclearexcept(FE_ALL_EXCEPT);						      \
+  feenableexcept (FE_ALL_EXCEPT);					      \
+  if (sigsetjmp(sigfpe_buf, 0))						      \
+    {									      \
       printf (#FLOAT " isnan (qNaN) raised SIGFPE\n");			      \
       errors++;								      \
     } else {								      \
diff --git ports/sysdeps/hppa/math_private.h ports/sysdeps/hppa/math_private.h
new file mode 100644
index 0000000..0092b57
--- /dev/null
+++ ports/sysdeps/hppa/math_private.h
@@ -0,0 +1,26 @@
+/* Internal math stuff.  HPPA version.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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 Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _MATH_PRIVATE_H
+
+/* One of the few architectures.  */
+#define HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+
+#include_next <math_private.h>
+
+#endif
diff --git ports/sysdeps/mips/math_private.h ports/sysdeps/mips/math_private.h
new file mode 100644
index 0000000..080773d
--- /dev/null
+++ ports/sysdeps/mips/math_private.h
@@ -0,0 +1,26 @@
+/* Internal math stuff.  MIPS version.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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 Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _MATH_PRIVATE_H
+
+/* One of the few architectures.  */
+#define HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+
+#include_next <math_private.h>
+
+#endif
diff --git sysdeps/ieee754/dbl-64/s_issignaling.c sysdeps/ieee754/dbl-64/s_issignaling.c
new file mode 100644
index 0000000..3196490
--- /dev/null
+++ sysdeps/ieee754/dbl-64/s_issignaling.c
@@ -0,0 +1,49 @@
+/* Test for signaling NaN.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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 Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <math_private.h>
+
+#undef __issignaling
+int __issignaling (double x)
+{
+#ifdef HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+  u_int32_t hxi;
+  GET_HIGH_WORD (hxi, x);
+  /* We only have to care about the high-order bit of x's significand, because
+     having it set (sNaN) already makes the significand different from that
+     used to designate infinity.  */
+  return (hxi & 0x7ff80000) == 0x7ff80000;
+#else
+  u_int32_t hxi, lxi;
+  EXTRACT_WORDS (hxi, lxi, x);
+  /* To keep the following comparison simple, toggle the quiet/signaling bit,
+     so that it is set for sNaNs.  This is inverse to IEEE 754-2008 (as well as
+     common practice for IEEE 754-1985).  */
+  hxi ^= 0x00080000;
+  /* If lxi != 0, then set any suitable bit of the significand in hxi.  */
+  hxi |= (lxi | -lxi) >> 31;
+  /* We have to compare for greater (instead of greater or equal), because x's
+     significand being all-zero designates infinity not NaN.  */
+  return (hxi & 0x7fffffff) > 0x7ff80000;
+#endif
+}
+libm_hidden_def (__issignaling)
+#ifdef NO_LONG_DOUBLE
+strong_alias (__issignaling, __issignalingl)
+#endif
diff --git sysdeps/ieee754/dbl-64/wordsize-64/s_issignaling.c sysdeps/ieee754/dbl-64/wordsize-64/s_issignaling.c
new file mode 100644
index 0000000..da53725
--- /dev/null
+++ sysdeps/ieee754/dbl-64/wordsize-64/s_issignaling.c
@@ -0,0 +1,45 @@
+/* Test for signaling NaN.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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 Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <math_private.h>
+
+#undef __issignaling
+int __issignaling (double x)
+{
+  u_int64_t xi;
+  EXTRACT_WORDS64 (xi, x);
+#ifdef HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+  /* We only have to care about the high-order bit of x's significand, because
+     having it set (sNaN) already makes the significand different from that
+     used to designate infinity.  */
+  return (xi & UINT64_C (0x7ff8000000000000)) == UINT64_C (0x7ff8000000000000);
+#else
+  /* To keep the following comparison simple, toggle the quiet/signaling bit,
+     so that it is set for sNaNs.  This is inverse to IEEE 754-2008 (as well as
+     common practice for IEEE 754-1985).  */
+  xi ^= UINT64_C (0x0008000000000000);
+  /* We have to compare for greater (instead of greater or equal), because x's
+     significand being all-zero designates infinity not NaN.  */
+  return (xi & UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7ff8000000000000);
+#endif
+}
+libm_hidden_def (__issignaling)
+#ifdef NO_LONG_DOUBLE
+strong_alias (__issignaling, __issignalingl)
+#endif
diff --git sysdeps/ieee754/flt-32/s_issignalingf.c sysdeps/ieee754/flt-32/s_issignalingf.c
new file mode 100644
index 0000000..2942002
--- /dev/null
+++ sysdeps/ieee754/flt-32/s_issignalingf.c
@@ -0,0 +1,42 @@
+/* Test for signaling NaN.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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 Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <math_private.h>
+
+#undef __issignalingf
+int __issignalingf (float x)
+{
+  u_int32_t xi;
+  GET_FLOAT_WORD (xi, x);
+#ifdef HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+  /* We only have to care about the high-order bit of x's significand, because
+     having it set (sNaN) already makes the significand different from that
+     used to designate infinity.  */
+  return (xi & 0x7fc00000) == 0x7fc00000;
+#else
+  /* To keep the following comparison simple, toggle the quiet/signaling bit,
+     so that it is set for sNaNs.  This is inverse to IEEE 754-2008 (as well as
+     common practice for IEEE 754-1985).  */
+  xi ^= 0x00400000;
+  /* We have to compare for greater (instead of greater or equal), because x's
+     significand being all-zero designates infinity not NaN.  */
+  return (xi & 0x7fffffff) > 0x7fc00000;
+#endif
+}
+libm_hidden_def (__issignalingf)
diff --git sysdeps/ieee754/ldbl-128/s_issignalingl.c sysdeps/ieee754/ldbl-128/s_issignalingl.c
new file mode 100644
index 0000000..ca0a984
--- /dev/null
+++ sysdeps/ieee754/ldbl-128/s_issignalingl.c
@@ -0,0 +1,45 @@
+/* Test for signaling NaN.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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 Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <math_private.h>
+
+#undef __issignalingl
+int __issignalingl (long double x)
+{
+  u_int64_t hxi, lxi;
+  GET_LDOUBLE_WORDS64 (hxi, lxi, x);
+#ifdef HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+  /* We only have to care about the high-order bit of x's significand, because
+     having it set (sNaN) already makes the significand different from that
+     used to designate infinity.  */
+  return ((hxi & UINT64_C (0x7fff800000000000))
+          == UINT64_C (0x7fff800000000000));
+#else
+  /* To keep the following comparison simple, toggle the quiet/signaling bit,
+     so that it is set for sNaNs.  This is inverse to IEEE 754-2008 (as well as
+     common practice for IEEE 754-1985).  */
+  hxi ^= UINT64_C (0x0000800000000000);
+  /* If lxi != 0, then set any suitable bit of the significand in hxi.  */
+  hxi |= (lxi | -lxi) >> 63;
+  /* We have to compare for greater (instead of greater or equal), because x's
+     significand being all-zero designates infinity not NaN.  */
+  return (hxi & UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7fff800000000000);
+#endif
+}
+libm_hidden_def (__issignalingl)
diff --git sysdeps/ieee754/ldbl-128ibm/s_issignalingl.c sysdeps/ieee754/ldbl-128ibm/s_issignalingl.c
new file mode 100644
index 0000000..5277375
--- /dev/null
+++ sysdeps/ieee754/ldbl-128ibm/s_issignalingl.c
@@ -0,0 +1,44 @@
+/* Test for signaling NaN.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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 Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <math_private.h>
+
+#undef __issignalingl
+int __issignalingl (long double x)
+{
+  u_int64_t xi;
+  /* For inspecting NaN status, we only have to look at the first of the pair
+     of IEEE 754 64-bit precision numbers.  */
+  GET_LDOUBLE_MSW64 (xi, x);
+#ifdef HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+  /* We only have to care about the high-order bit of x's significand, because
+     having it set (sNaN) already makes the significand different from that
+     used to designate infinity.  */
+  return (xi & UINT64_C (0x7ff8000000000000)) == UINT64_C (0x7ff8000000000000);
+#else
+  /* To keep the following comparison simple, toggle the quiet/signaling bit,
+     so that it is set for sNaNs.  This is inverse to IEEE 754-2008 (as well as
+     common practice for IEEE 754-1985).  */
+  xi ^= UINT64_C (0x0008000000000000);
+  /* We have to compare for greater (instead of greater or equal), because x's
+     significand being all-zero designates infinity not NaN.  */
+  return (xi & UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7ff8000000000000);
+#endif
+}
+libm_hidden_def (__issignalingl)
diff --git sysdeps/ieee754/ldbl-96/s_issignalingl.c sysdeps/ieee754/ldbl-96/s_issignalingl.c
new file mode 100644
index 0000000..614e253
--- /dev/null
+++ sysdeps/ieee754/ldbl-96/s_issignalingl.c
@@ -0,0 +1,43 @@
+/* Test for signaling NaN.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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 Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <math_private.h>
+
+#undef __issignalingl
+int __issignalingl (long double x)
+{
+  u_int32_t exi, hxi, lxi;
+  GET_LDOUBLE_WORDS (exi, hxi, lxi, x);
+#ifdef HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+# error not implemented
+#else
+  /* To keep the following comparison simple, toggle the quiet/signaling bit,
+     so that it is set for sNaNs.  This is inverse to IEEE 754-2008 (as well as
+     common practice for IEEE 754-1985).  */
+  hxi ^= 0x40000000;
+  /* If lxi != 0, then set any suitable bit of the significand in hxi.  */
+  hxi |= (lxi | -lxi) >> 31;
+  /* We do not recognize a pseudo NaN as sNaN; they're invalid on 80387 and
+     later.  */
+  /* We have to compare for greater (instead of greater or equal), because x's
+     significand being all-zero designates infinity not NaN.  */
+  return ((exi & 0x7fff) == 0x7fff) && (hxi > 0xc0000000);
+#endif
+}
+libm_hidden_def (__issignalingl)


GrÃÃe,
 Thomas

Attachment: pgp00000.pgp
Description: PGP signature


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]