Recognize non-IEEE numbers on i386, x86_64, ia64.
[gnulib.git] / tests / test-isnanl.h
1 /* Test of isnanl() substitute.
2    Copyright (C) 2007 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
19
20 #include <float.h>
21 #include <limits.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #define ASSERT(expr) \
26   do                                                                         \
27     {                                                                        \
28       if (!(expr))                                                           \
29         {                                                                    \
30           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
31           abort ();                                                          \
32         }                                                                    \
33     }                                                                        \
34   while (0)
35
36 int
37 main ()
38 {
39   #define NWORDS \
40     ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
41   typedef union { unsigned int word[NWORDS]; long double value; }
42           memory_long_double;
43
44   /* Finite values.  */
45   ASSERT (!isnanl (3.141L));
46   ASSERT (!isnanl (3.141e30L));
47   ASSERT (!isnanl (3.141e-30L));
48   ASSERT (!isnanl (-2.718L));
49   ASSERT (!isnanl (-2.718e30L));
50   ASSERT (!isnanl (-2.718e-30L));
51   /* Infinite values.  */
52   ASSERT (!isnanl (1.0L / 0.0L));
53   ASSERT (!isnanl (-1.0L / 0.0L));
54   /* Quiet NaN.  */
55   ASSERT (isnanl (0.0L / 0.0L));
56
57 #if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT
58   /* A bit pattern that is different from a Quiet NaN.  With a bit of luck,
59      it's a Signalling NaN.  */
60   {
61     memory_long_double m;
62     m.value = 0.0L / 0.0L;
63 # if LDBL_EXPBIT0_BIT > 0
64     m.word[LDBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (LDBL_EXPBIT0_BIT - 1);
65 # else
66     m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
67       ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
68 # endif
69     m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
70       |= (unsigned int) 1 << LDBL_EXPBIT0_BIT;
71     ASSERT (isnanl (m.value));
72   }
73 #endif
74
75 #if ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
76 /* Representation of an 80-bit 'long double' as an initializer for a sequence
77    of 'unsigned int' words.  */
78 # ifdef WORDS_BIGENDIAN
79 #  define LDBL80_WORDS(exponent,manthi,mantlo) \
80      { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \
81        ((unsigned int) (manthi) << 16) | (unsigned int) (mantlo) >> 16),    \
82        (unsigned int) (mantlo) << 16                                        \
83      }
84 # else
85 #  define LDBL80_WORDS(exponent,manthi,mantlo) \
86      { mantlo, manthi, exponent }
87 # endif
88   { /* Quiet NaN.  */
89     static memory_long_double x =
90       { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
91     ASSERT (isnanl (x.value));
92   }
93   {
94     /* Signalling NaN.  */
95     static memory_long_double x =
96       { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
97     ASSERT (isnanl (x.value));
98   }
99   /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
100      Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
101        Intel IA-64 Architecture Software Developer's Manual, Volume 1:
102        Application Architecture.
103        Table 5-2 "Floating-Point Register Encodings"
104        Figure 5-6 "Memory to Floating-Point Register Data Translation"
105    */
106   { /* Pseudo-NaN.  */
107     static memory_long_double x =
108       { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
109     ASSERT (isnanl (x.value));
110   }
111   { /* Pseudo-Infinity.  */
112     static memory_long_double x =
113       { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
114     ASSERT (isnanl (x.value));
115   }
116   { /* Pseudo-Zero.  */
117     static memory_long_double x =
118       { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
119     ASSERT (isnanl (x.value));
120   }
121   { /* Unnormalized number.  */
122     static memory_long_double x =
123       { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
124     ASSERT (isnanl (x.value));
125   }
126   { /* Pseudo-Denormal.  */
127     static memory_long_double x =
128       { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
129     ASSERT (isnanl (x.value));
130   }
131 #endif
132
133   return 0;
134 }