Flush the standard error stream before aborting.
[pspp] / tests / test-frexp.c
1 /* Test of splitting a 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 "isnand.h"
28 #include "nan.h"
29
30 /* Avoid some warnings from "gcc -Wshadow".
31    This file doesn't use the exp() function.  */
32 #define exp exponent
33
34 #define ASSERT(expr) \
35   do                                                                         \
36     {                                                                        \
37       if (!(expr))                                                           \
38         {                                                                    \
39           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
40           fflush (stderr);                                                   \
41           abort ();                                                          \
42         }                                                                    \
43     }                                                                        \
44   while (0)
45
46 static double
47 my_ldexp (double x, int d)
48 {
49   for (; d > 0; d--)
50     x *= 2.0;
51   for (; d < 0; d++)
52     x *= 0.5;
53   return x;
54 }
55
56 int
57 main ()
58 {
59   int i;
60   /* The use of 'volatile' guarantees that excess precision bits are dropped
61      when dealing with denormalized numbers.  It is necessary on x86 systems
62      where double-floats are not IEEE compliant by default, to avoid that the
63      results become platform and compiler option dependent.  'volatile' is a
64      portable alternative to gcc's -ffloat-store option.  */
65   volatile double x;
66
67   { /* NaN.  */
68     int exp = -9999;
69     double mantissa;
70     x = NaNd ();
71     mantissa = frexp (x, &exp);
72     ASSERT (isnand (mantissa));
73   }
74
75   { /* Positive infinity.  */
76     int exp = -9999;
77     double mantissa;
78     x = 1.0 / 0.0;
79     mantissa = frexp (x, &exp);
80     ASSERT (mantissa == x);
81   }
82
83   { /* Negative infinity.  */
84     int exp = -9999;
85     double mantissa;
86     x = -1.0 / 0.0;
87     mantissa = frexp (x, &exp);
88     ASSERT (mantissa == x);
89   }
90
91   { /* Positive zero.  */
92     int exp = -9999;
93     double mantissa;
94     x = 0.0;
95     mantissa = frexp (x, &exp);
96     ASSERT (exp == 0);
97     ASSERT (mantissa == x);
98     ASSERT (!signbit (mantissa));
99   }
100
101   { /* Negative zero.  */
102     int exp = -9999;
103     double mantissa;
104     x = -0.0;
105     mantissa = frexp (x, &exp);
106     ASSERT (exp == 0);
107     ASSERT (mantissa == x);
108     ASSERT (signbit (mantissa));
109   }
110
111   for (i = 1, x = 1.0; i <= DBL_MAX_EXP; i++, x *= 2.0)
112     {
113       int exp = -9999;
114       double mantissa = frexp (x, &exp);
115       ASSERT (exp == i);
116       ASSERT (mantissa == 0.5);
117     }
118   for (i = 1, x = 1.0; i >= DBL_MIN_EXP; i--, x *= 0.5)
119     {
120       int exp = -9999;
121       double mantissa = frexp (x, &exp);
122       ASSERT (exp == i);
123       ASSERT (mantissa == 0.5);
124     }
125   for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5)
126     {
127       int exp = -9999;
128       double mantissa = frexp (x, &exp);
129       ASSERT (exp == i);
130       ASSERT (mantissa == 0.5);
131     }
132
133   for (i = 1, x = -1.0; i <= DBL_MAX_EXP; i++, x *= 2.0)
134     {
135       int exp = -9999;
136       double mantissa = frexp (x, &exp);
137       ASSERT (exp == i);
138       ASSERT (mantissa == -0.5);
139     }
140   for (i = 1, x = -1.0; i >= DBL_MIN_EXP; i--, x *= 0.5)
141     {
142       int exp = -9999;
143       double mantissa = frexp (x, &exp);
144       ASSERT (exp == i);
145       ASSERT (mantissa == -0.5);
146     }
147   for (; i >= DBL_MIN_EXP - 100 && x < 0.0; i--, x *= 0.5)
148     {
149       int exp = -9999;
150       double mantissa = frexp (x, &exp);
151       ASSERT (exp == i);
152       ASSERT (mantissa == -0.5);
153     }
154
155   for (i = 1, x = 1.01; i <= DBL_MAX_EXP; i++, x *= 2.0)
156     {
157       int exp = -9999;
158       double mantissa = frexp (x, &exp);
159       ASSERT (exp == i);
160       ASSERT (mantissa == 0.505);
161     }
162   for (i = 1, x = 1.01; i >= DBL_MIN_EXP; i--, x *= 0.5)
163     {
164       int exp = -9999;
165       double mantissa = frexp (x, &exp);
166       ASSERT (exp == i);
167       ASSERT (mantissa == 0.505);
168     }
169   for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5)
170     {
171       int exp = -9999;
172       double mantissa = frexp (x, &exp);
173       ASSERT (exp == i);
174       ASSERT (mantissa >= 0.5);
175       ASSERT (mantissa < 1.0);
176       ASSERT (mantissa == my_ldexp (x, - exp));
177     }
178
179   for (i = 1, x = 1.73205; i <= DBL_MAX_EXP; i++, x *= 2.0)
180     {
181       int exp = -9999;
182       double mantissa = frexp (x, &exp);
183       ASSERT (exp == i);
184       ASSERT (mantissa == 0.866025);
185     }
186   for (i = 1, x = 1.73205; i >= DBL_MIN_EXP; i--, x *= 0.5)
187     {
188       int exp = -9999;
189       double mantissa = frexp (x, &exp);
190       ASSERT (exp == i);
191       ASSERT (mantissa == 0.866025);
192     }
193   for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5)
194     {
195       int exp = -9999;
196       double mantissa = frexp (x, &exp);
197       ASSERT (exp == i || exp == i + 1);
198       ASSERT (mantissa >= 0.5);
199       ASSERT (mantissa < 1.0);
200       ASSERT (mantissa == my_ldexp (x, - exp));
201     }
202
203   return 0;
204 }