Mercurial > gnulib
annotate tests/test-float.c @ 40231:9b3c79fdfe0b
strtod: fix clash with strtold
Problem reported for RHEL 5 by Jesse Caldwell (Bug#34817).
* lib/strtod.c (compute_minus_zero, minus_zero):
Simplify by remving the macro / external variable,
and having just a function. User changed. This avoids
the need for an external variable that might clash.
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Mon, 11 Mar 2019 16:40:29 -0700 |
parents | b06060465f09 |
children |
rev | line source |
---|---|
15300 | 1 /* Test of <float.h> substitute. |
40057
b06060465f09
maint: Run 'make update-copyright'
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
2 Copyright (C) 2011-2019 Free Software Foundation, Inc. |
15300 | 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 | |
19190 | 15 along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
15300 | 16 |
17 /* Written by Bruno Haible <bruno@clisp.org>, 2011. */ | |
18 | |
19 #include <config.h> | |
20 | |
21 #include <float.h> | |
22 | |
23 #include "fpucw.h" | |
24 #include "macros.h" | |
25 | |
26 /* Check that FLT_RADIX is a constant expression. */ | |
27 int a[] = { FLT_RADIX }; | |
28 | |
29 #if FLT_RADIX == 2 | |
30 | |
31 /* Return 2^n. */ | |
32 static float | |
33 pow2f (int n) | |
34 { | |
35 int k = n; | |
36 volatile float x = 1; | |
37 volatile float y = 2; | |
38 /* Invariant: 2^n == x * y^k. */ | |
39 if (k < 0) | |
40 { | |
41 y = 0.5f; | |
42 k = - k; | |
43 } | |
44 while (k > 0) | |
45 { | |
46 if (k != 2 * (k / 2)) | |
47 { | |
48 x = x * y; | |
49 k = k - 1; | |
50 } | |
51 if (k == 0) | |
52 break; | |
53 y = y * y; | |
54 k = k / 2; | |
55 } | |
56 /* Now k == 0, hence x == 2^n. */ | |
57 return x; | |
58 } | |
59 | |
60 /* Return 2^n. */ | |
61 static double | |
62 pow2d (int n) | |
63 { | |
64 int k = n; | |
65 volatile double x = 1; | |
66 volatile double y = 2; | |
67 /* Invariant: 2^n == x * y^k. */ | |
68 if (k < 0) | |
69 { | |
70 y = 0.5; | |
71 k = - k; | |
72 } | |
73 while (k > 0) | |
74 { | |
75 if (k != 2 * (k / 2)) | |
76 { | |
77 x = x * y; | |
78 k = k - 1; | |
79 } | |
80 if (k == 0) | |
81 break; | |
82 y = y * y; | |
83 k = k / 2; | |
84 } | |
85 /* Now k == 0, hence x == 2^n. */ | |
86 return x; | |
87 } | |
88 | |
89 /* Return 2^n. */ | |
90 static long double | |
91 pow2l (int n) | |
92 { | |
93 int k = n; | |
94 volatile long double x = 1; | |
95 volatile long double y = 2; | |
96 /* Invariant: 2^n == x * y^k. */ | |
97 if (k < 0) | |
98 { | |
99 y = 0.5L; | |
100 k = - k; | |
101 } | |
102 while (k > 0) | |
103 { | |
104 if (k != 2 * (k / 2)) | |
105 { | |
106 x = x * y; | |
107 k = k - 1; | |
108 } | |
109 if (k == 0) | |
110 break; | |
111 y = y * y; | |
112 k = k / 2; | |
113 } | |
114 /* Now k == 0, hence x == 2^n. */ | |
115 return x; | |
116 } | |
117 | |
118 /* ----------------------- Check macros for 'float' ----------------------- */ | |
119 | |
120 /* Check that the FLT_* macros expand to constant expressions. */ | |
121 int fb[] = | |
122 { | |
123 FLT_MANT_DIG, FLT_MIN_EXP, FLT_MAX_EXP, | |
124 FLT_DIG, FLT_MIN_10_EXP, FLT_MAX_10_EXP | |
125 }; | |
126 float fc[] = { FLT_EPSILON, FLT_MIN, FLT_MAX }; | |
127 | |
128 static void | |
129 test_float (void) | |
130 { | |
131 /* Check that the value of FLT_MIN_EXP is well parenthesized. */ | |
132 ASSERT ((FLT_MIN_EXP % 101111) == (FLT_MIN_EXP) % 101111); | |
133 | |
134 /* Check that the value of DBL_MIN_10_EXP is well parenthesized. */ | |
135 ASSERT ((FLT_MIN_10_EXP % 101111) == (FLT_MIN_10_EXP) % 101111); | |
136 | |
137 /* Check that 'float' is as specified in IEEE 754. */ | |
138 ASSERT (FLT_MANT_DIG == 24); | |
139 ASSERT (FLT_MIN_EXP == -125); | |
140 ASSERT (FLT_MAX_EXP == 128); | |
141 | |
142 /* Check the value of FLT_MIN_10_EXP. */ | |
143 ASSERT (FLT_MIN_10_EXP == - (int) (- (FLT_MIN_EXP - 1) * 0.30103)); | |
144 | |
145 /* Check the value of FLT_DIG. */ | |
146 ASSERT (FLT_DIG == (int) ((FLT_MANT_DIG - 1) * 0.30103)); | |
147 | |
148 /* Check the value of FLT_MIN_10_EXP. */ | |
149 ASSERT (FLT_MIN_10_EXP == - (int) (- (FLT_MIN_EXP - 1) * 0.30103)); | |
150 | |
151 /* Check the value of FLT_MAX_10_EXP. */ | |
152 ASSERT (FLT_MAX_10_EXP == (int) (FLT_MAX_EXP * 0.30103)); | |
153 | |
154 /* Check the value of FLT_MAX. */ | |
155 { | |
156 volatile float m = FLT_MAX; | |
157 int n; | |
158 | |
159 ASSERT (m + m > m); | |
160 for (n = 0; n <= 2 * FLT_MANT_DIG; n++) | |
161 { | |
162 volatile float pow2_n = pow2f (n); /* 2^n */ | |
163 volatile float x = m + (m / pow2_n); | |
164 if (x > m) | |
165 ASSERT (x + x == x); | |
166 else | |
167 ASSERT (!(x + x == x)); | |
168 } | |
169 } | |
170 | |
171 /* Check the value of FLT_MIN. */ | |
172 { | |
173 volatile float m = FLT_MIN; | |
174 volatile float x = pow2f (FLT_MIN_EXP - 1); | |
175 ASSERT (m == x); | |
176 } | |
177 | |
178 /* Check the value of FLT_EPSILON. */ | |
179 { | |
180 volatile float e = FLT_EPSILON; | |
181 volatile float me; | |
182 int n; | |
183 | |
184 me = 1.0f + e; | |
185 ASSERT (me > 1.0f); | |
186 ASSERT (me - 1.0f == e); | |
187 for (n = 0; n <= 2 * FLT_MANT_DIG; n++) | |
188 { | |
189 volatile float half_n = pow2f (- n); /* 2^-n */ | |
190 volatile float x = me - half_n; | |
191 if (x < me) | |
192 ASSERT (x <= 1.0f); | |
193 } | |
194 } | |
195 } | |
196 | |
197 /* ----------------------- Check macros for 'double' ----------------------- */ | |
198 | |
199 /* Check that the DBL_* macros expand to constant expressions. */ | |
200 int db[] = | |
201 { | |
202 DBL_MANT_DIG, DBL_MIN_EXP, DBL_MAX_EXP, | |
203 DBL_DIG, DBL_MIN_10_EXP, DBL_MAX_10_EXP | |
204 }; | |
205 double dc[] = { DBL_EPSILON, DBL_MIN, DBL_MAX }; | |
206 | |
207 static void | |
208 test_double (void) | |
209 { | |
210 /* Check that the value of DBL_MIN_EXP is well parenthesized. */ | |
211 ASSERT ((DBL_MIN_EXP % 101111) == (DBL_MIN_EXP) % 101111); | |
212 | |
213 /* Check that the value of DBL_MIN_10_EXP is well parenthesized. */ | |
214 ASSERT ((DBL_MIN_10_EXP % 101111) == (DBL_MIN_10_EXP) % 101111); | |
215 | |
216 /* Check that 'double' is as specified in IEEE 754. */ | |
217 ASSERT (DBL_MANT_DIG == 53); | |
218 ASSERT (DBL_MIN_EXP == -1021); | |
219 ASSERT (DBL_MAX_EXP == 1024); | |
220 | |
221 /* Check the value of DBL_MIN_10_EXP. */ | |
222 ASSERT (DBL_MIN_10_EXP == - (int) (- (DBL_MIN_EXP - 1) * 0.30103)); | |
223 | |
224 /* Check the value of DBL_DIG. */ | |
225 ASSERT (DBL_DIG == (int) ((DBL_MANT_DIG - 1) * 0.30103)); | |
226 | |
227 /* Check the value of DBL_MIN_10_EXP. */ | |
228 ASSERT (DBL_MIN_10_EXP == - (int) (- (DBL_MIN_EXP - 1) * 0.30103)); | |
229 | |
230 /* Check the value of DBL_MAX_10_EXP. */ | |
231 ASSERT (DBL_MAX_10_EXP == (int) (DBL_MAX_EXP * 0.30103)); | |
232 | |
233 /* Check the value of DBL_MAX. */ | |
234 { | |
235 volatile double m = DBL_MAX; | |
236 int n; | |
237 | |
238 ASSERT (m + m > m); | |
239 for (n = 0; n <= 2 * DBL_MANT_DIG; n++) | |
240 { | |
241 volatile double pow2_n = pow2d (n); /* 2^n */ | |
242 volatile double x = m + (m / pow2_n); | |
243 if (x > m) | |
244 ASSERT (x + x == x); | |
245 else | |
246 ASSERT (!(x + x == x)); | |
247 } | |
248 } | |
249 | |
250 /* Check the value of DBL_MIN. */ | |
251 { | |
252 volatile double m = DBL_MIN; | |
253 volatile double x = pow2d (DBL_MIN_EXP - 1); | |
254 ASSERT (m == x); | |
255 } | |
256 | |
257 /* Check the value of DBL_EPSILON. */ | |
258 { | |
259 volatile double e = DBL_EPSILON; | |
260 volatile double me; | |
261 int n; | |
262 | |
263 me = 1.0 + e; | |
264 ASSERT (me > 1.0); | |
265 ASSERT (me - 1.0 == e); | |
266 for (n = 0; n <= 2 * DBL_MANT_DIG; n++) | |
267 { | |
268 volatile double half_n = pow2d (- n); /* 2^-n */ | |
269 volatile double x = me - half_n; | |
270 if (x < me) | |
271 ASSERT (x <= 1.0); | |
272 } | |
273 } | |
274 } | |
275 | |
276 /* -------------------- Check macros for 'long double' -------------------- */ | |
277 | |
278 /* Check that the LDBL_* macros expand to constant expressions. */ | |
279 int lb[] = | |
280 { | |
281 LDBL_MANT_DIG, LDBL_MIN_EXP, LDBL_MAX_EXP, | |
282 LDBL_DIG, LDBL_MIN_10_EXP, LDBL_MAX_10_EXP | |
283 }; | |
284 long double lc1 = LDBL_EPSILON; | |
285 long double lc2 = LDBL_MIN; | |
286 #if 0 /* LDBL_MAX is not a constant expression on some platforms. */ | |
287 long double lc3 = LDBL_MAX; | |
288 #endif | |
289 | |
290 static void | |
291 test_long_double (void) | |
292 { | |
293 /* Check that the value of LDBL_MIN_EXP is well parenthesized. */ | |
294 ASSERT ((LDBL_MIN_EXP % 101111) == (LDBL_MIN_EXP) % 101111); | |
295 | |
296 /* Check that the value of LDBL_MIN_10_EXP is well parenthesized. */ | |
297 ASSERT ((LDBL_MIN_10_EXP % 101111) == (LDBL_MIN_10_EXP) % 101111); | |
298 | |
299 /* Check that 'long double' is at least as wide as 'double'. */ | |
300 ASSERT (LDBL_MANT_DIG >= DBL_MANT_DIG); | |
16136
fd0796dd37e2
float tests: Correct and re-enable assertion about LDBL_MIN_EXP.
Paolo Bonzini <bonzini@gnu.org>
parents:
15545
diff
changeset
|
301 ASSERT (LDBL_MIN_EXP - LDBL_MANT_DIG <= DBL_MIN_EXP - DBL_MANT_DIG); |
15300 | 302 ASSERT (LDBL_MAX_EXP >= DBL_MAX_EXP); |
303 | |
304 /* Check the value of LDBL_DIG. */ | |
305 ASSERT (LDBL_DIG == (int)((LDBL_MANT_DIG - 1) * 0.30103)); | |
306 | |
307 /* Check the value of LDBL_MIN_10_EXP. */ | |
308 ASSERT (LDBL_MIN_10_EXP == - (int) (- (LDBL_MIN_EXP - 1) * 0.30103)); | |
309 | |
310 /* Check the value of LDBL_MAX_10_EXP. */ | |
311 ASSERT (LDBL_MAX_10_EXP == (int) (LDBL_MAX_EXP * 0.30103)); | |
312 | |
313 /* Check the value of LDBL_MAX. */ | |
314 { | |
315 volatile long double m = LDBL_MAX; | |
316 int n; | |
317 | |
318 ASSERT (m + m > m); | |
319 for (n = 0; n <= 2 * LDBL_MANT_DIG; n++) | |
320 { | |
321 volatile long double pow2_n = pow2l (n); /* 2^n */ | |
322 volatile long double x = m + (m / pow2_n); | |
323 if (x > m) | |
324 ASSERT (x + x == x); | |
325 else | |
326 ASSERT (!(x + x == x)); | |
327 } | |
328 } | |
329 | |
330 /* Check the value of LDBL_MIN. */ | |
331 { | |
332 volatile long double m = LDBL_MIN; | |
333 volatile long double x = pow2l (LDBL_MIN_EXP - 1); | |
334 ASSERT (m == x); | |
335 } | |
336 | |
337 /* Check the value of LDBL_EPSILON. */ | |
338 { | |
339 volatile long double e = LDBL_EPSILON; | |
340 volatile long double me; | |
341 int n; | |
342 | |
343 me = 1.0L + e; | |
344 ASSERT (me > 1.0L); | |
345 ASSERT (me - 1.0L == e); | |
346 for (n = 0; n <= 2 * LDBL_MANT_DIG; n++) | |
347 { | |
348 volatile long double half_n = pow2l (- n); /* 2^-n */ | |
349 volatile long double x = me - half_n; | |
350 if (x < me) | |
351 ASSERT (x <= 1.0L); | |
352 } | |
353 } | |
354 } | |
355 | |
356 int | |
357 main () | |
358 { | |
359 test_float (); | |
360 test_double (); | |
361 | |
362 { | |
363 DECL_LONG_DOUBLE_ROUNDING | |
364 | |
365 BEGIN_LONG_DOUBLE_ROUNDING (); | |
366 | |
367 test_long_double (); | |
368 | |
369 END_LONG_DOUBLE_ROUNDING (); | |
370 } | |
371 | |
372 return 0; | |
373 } | |
374 | |
375 #else | |
376 | |
377 int | |
378 main () | |
379 { | |
15361 | 380 fprintf (stderr, "Skipping test: FLT_RADIX is not 2.\n"); |
15300 | 381 return 77; |
382 } | |
383 | |
384 #endif |