tests: add signature checks
[gnulib.git] / tests / test-frexpl.c
1 /* Test of splitting a 'long double' into fraction and mantissa.
2    Copyright (C) 2007-2009 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 3 of the License, or
7    (at your option) 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, see <http://www.gnu.org/licenses/>.  */
16
17 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
18
19 #include <config.h>
20
21 #include <math.h>
22
23 #include "signature.h"
24 SIGNATURE_CHECK (frexpl, long double, (long double, int *));
25
26 #include <float.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29
30 #include "fpucw.h"
31 #include "isnanl-nolibm.h"
32 #include "nan.h"
33
34 /* Avoid some warnings from "gcc -Wshadow".
35    This file doesn't use the exp() function.  */
36 #undef exp
37 #define exp exponent
38
39 #define ASSERT(expr) \
40   do                                                                         \
41     {                                                                        \
42       if (!(expr))                                                           \
43         {                                                                    \
44           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
45           fflush (stderr);                                                   \
46           abort ();                                                          \
47         }                                                                    \
48     }                                                                        \
49   while (0)
50
51 /* On MIPS IRIX machines, LDBL_MIN_EXP is -1021, but the smallest reliable
52    exponent for 'long double' is -964.  Similarly, on PowerPC machines,
53    LDBL_MIN_EXP is -1021, but the smallest reliable exponent for 'long double'
54    is -968.  For exponents below that, the precision may be truncated to the
55    precision used for 'double'.  */
56 #ifdef __sgi
57 # define MIN_NORMAL_EXP (LDBL_MIN_EXP + 57)
58 #elif defined __ppc || defined __ppc__ || defined __powerpc || defined __powerpc__
59 # define MIN_NORMAL_EXP (LDBL_MIN_EXP + 53)
60 #else
61 # define MIN_NORMAL_EXP LDBL_MIN_EXP
62 #endif
63
64 /* On HP-UX 10.20, negating 0.0L does not yield -0.0L.
65    So we use minus_zero instead.
66    IRIX cc can't put -0.0L into .data, but can compute at runtime.
67    Note that the expression -LDBL_MIN * LDBL_MIN does not work on other
68    platforms, such as when cross-compiling to PowerPC on MacOS X 10.5.  */
69 #if defined __hpux || defined __sgi
70 static long double
71 compute_minus_zero (void)
72 {
73   return -LDBL_MIN * LDBL_MIN;
74 }
75 # define minus_zero compute_minus_zero ()
76 #else
77 long double minus_zero = -0.0L;
78 #endif
79
80 static long double
81 my_ldexp (long double x, int d)
82 {
83   for (; d > 0; d--)
84     x *= 2.0L;
85   for (; d < 0; d++)
86     x *= 0.5L;
87   return x;
88 }
89
90 int
91 main ()
92 {
93   int i;
94   long double x;
95   DECL_LONG_DOUBLE_ROUNDING
96
97   BEGIN_LONG_DOUBLE_ROUNDING ();
98
99   { /* NaN.  */
100     int exp = -9999;
101     long double mantissa;
102     x = NaNl ();
103     mantissa = frexpl (x, &exp);
104     ASSERT (isnanl (mantissa));
105   }
106
107   { /* Positive infinity.  */
108     int exp = -9999;
109     long double mantissa;
110     x = 1.0L / 0.0L;
111     mantissa = frexpl (x, &exp);
112     ASSERT (mantissa == x);
113   }
114
115   { /* Negative infinity.  */
116     int exp = -9999;
117     long double mantissa;
118     x = -1.0L / 0.0L;
119     mantissa = frexpl (x, &exp);
120     ASSERT (mantissa == x);
121   }
122
123   { /* Positive zero.  */
124     int exp = -9999;
125     long double mantissa;
126     x = 0.0L;
127     mantissa = frexpl (x, &exp);
128     ASSERT (exp == 0);
129     ASSERT (mantissa == x);
130     ASSERT (!signbit (mantissa));
131   }
132
133   { /* Negative zero.  */
134     int exp = -9999;
135     long double mantissa;
136     x = minus_zero;
137     mantissa = frexpl (x, &exp);
138     ASSERT (exp == 0);
139     ASSERT (mantissa == x);
140     ASSERT (signbit (mantissa));
141   }
142
143   for (i = 1, x = 1.0L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
144     {
145       int exp = -9999;
146       long double mantissa = frexpl (x, &exp);
147       ASSERT (exp == i);
148       ASSERT (mantissa == 0.5L);
149     }
150   for (i = 1, x = 1.0L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
151     {
152       int exp = -9999;
153       long double mantissa = frexpl (x, &exp);
154       ASSERT (exp == i);
155       ASSERT (mantissa == 0.5L);
156     }
157   for (; i >= LDBL_MIN_EXP - 100 && x > 0.0L; i--, x *= 0.5L)
158     {
159       int exp = -9999;
160       long double mantissa = frexpl (x, &exp);
161       ASSERT (exp == i);
162       ASSERT (mantissa == 0.5L);
163     }
164
165   for (i = 1, x = -1.0L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
166     {
167       int exp = -9999;
168       long double mantissa = frexpl (x, &exp);
169       ASSERT (exp == i);
170       ASSERT (mantissa == -0.5L);
171     }
172   for (i = 1, x = -1.0L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
173     {
174       int exp = -9999;
175       long double mantissa = frexpl (x, &exp);
176       ASSERT (exp == i);
177       ASSERT (mantissa == -0.5L);
178     }
179   for (; i >= LDBL_MIN_EXP - 100 && x < 0.0L; i--, x *= 0.5L)
180     {
181       int exp = -9999;
182       long double mantissa = frexpl (x, &exp);
183       ASSERT (exp == i);
184       ASSERT (mantissa == -0.5L);
185     }
186
187   for (i = 1, x = 1.01L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
188     {
189       int exp = -9999;
190       long double mantissa = frexpl (x, &exp);
191       ASSERT (exp == i);
192       ASSERT (mantissa == 0.505L);
193     }
194   for (i = 1, x = 1.01L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
195     {
196       int exp = -9999;
197       long double mantissa = frexpl (x, &exp);
198       ASSERT (exp == i);
199       ASSERT (mantissa == 0.505L);
200     }
201   for (; i >= LDBL_MIN_EXP - 100 && x > 0.0L; i--, x *= 0.5L)
202     {
203       int exp = -9999;
204       long double mantissa = frexpl (x, &exp);
205       ASSERT (exp == i);
206       ASSERT (mantissa >= 0.5L);
207       ASSERT (mantissa < 1.0L);
208       ASSERT (mantissa == my_ldexp (x, - exp));
209     }
210
211   for (i = 1, x = 1.73205L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
212     {
213       int exp = -9999;
214       long double mantissa = frexpl (x, &exp);
215       ASSERT (exp == i);
216       ASSERT (mantissa == 0.866025L);
217     }
218   for (i = 1, x = 1.73205L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
219     {
220       int exp = -9999;
221       long double mantissa = frexpl (x, &exp);
222       ASSERT (exp == i);
223       ASSERT (mantissa == 0.866025L);
224     }
225   for (; i >= LDBL_MIN_EXP - 100 && x > 0.0L; i--, x *= 0.5L)
226     {
227       int exp = -9999;
228       long double mantissa = frexpl (x, &exp);
229       ASSERT (exp == i || exp == i + 1);
230       ASSERT (mantissa >= 0.5L);
231       ASSERT (mantissa < 1.0L);
232       ASSERT (mantissa == my_ldexp (x, - exp));
233     }
234
235   return 0;
236 }