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