Mercurial > gnulib
annotate tests/test-log2.h @ 40057:b06060465f09
maint: Run 'make update-copyright'
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Tue, 01 Jan 2019 00:25:11 +0100 |
parents | 10eb9086bea0 |
children |
rev | line source |
---|---|
16677 | 1 /* Test of log2*() function family. |
40057
b06060465f09
maint: Run 'make update-copyright'
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
2 Copyright (C) 2012-2019 Free Software Foundation, Inc. |
16677 | 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/>. */ |
16677 | 16 |
17 static void | |
18 test_function (void) | |
19 { | |
20 int i; | |
21 int j; | |
22 const DOUBLE TWO_MANT_DIG = | |
23 /* Assume MANT_DIG <= 5 * 31. | |
24 Use the identity | |
25 n = floor(n/5) + floor((n+1)/5) + ... + floor((n+4)/5). */ | |
26 (DOUBLE) (1U << ((MANT_DIG - 1) / 5)) | |
27 * (DOUBLE) (1U << ((MANT_DIG - 1 + 1) / 5)) | |
28 * (DOUBLE) (1U << ((MANT_DIG - 1 + 2) / 5)) | |
29 * (DOUBLE) (1U << ((MANT_DIG - 1 + 3) / 5)) | |
30 * (DOUBLE) (1U << ((MANT_DIG - 1 + 4) / 5)); | |
31 | |
32 /* Pole. */ | |
33 ASSERT (LOG2 (L_(0.0)) == - HUGEVAL); | |
34 ASSERT (LOG2 (MINUS_ZERO) == - HUGEVAL); | |
35 | |
36 /* Integral values. */ | |
37 { | |
38 DOUBLE x = L_(1.0); | |
39 DOUBLE y = LOG2 (x); | |
40 ASSERT (y == L_(0.0)); | |
41 } | |
42 { | |
43 int e; | |
44 DOUBLE x; | |
45 DOUBLE y; | |
46 for (e = 0, x = L_(0.0), y = L_(1.0); | |
47 e <= MAX_EXP - 1; | |
48 e++, x = x + L_(1.0), y = y * L_(2.0)) | |
49 { | |
50 /* Invariant: x = e, y = 2^e. */ | |
51 DOUBLE z = LOG2 (y); | |
52 ASSERT (z == x); | |
53 } | |
54 } | |
55 { | |
56 int e; | |
57 DOUBLE x; | |
58 DOUBLE y; | |
59 for (e = 0, x = L_(0.0), y = L_(1.0); | |
60 e >= MIN_EXP - 1; | |
61 e--, x = x - L_(1.0), y = y * L_(0.5)) | |
62 { | |
63 /* Invariant: x = e, y = 2^e. */ | |
64 DOUBLE z = LOG2 (y); | |
65 ASSERT (z == x); | |
66 } | |
67 } | |
68 | |
69 /* Randomized tests. */ | |
70 { | |
71 /* Error bound, in ulps. */ | |
72 const DOUBLE err_bound = | |
73 (sizeof (DOUBLE) > sizeof (double) ? | |
74 #if defined __i386__ && defined __FreeBSD__ | |
75 /* On FreeBSD/x86 6.4, the 'long double' type really has only 53 bits of | |
76 precision in the compiler but 64 bits of precision at runtime. See | |
19439
8bfc20b57265
maint: shorten https://lists.gnu.org/archive/html/... links
Jim Meyering <meyering@fb.com>
parents:
19192
diff
changeset
|
77 <https://lists.gnu.org/r/bug-gnulib/2008-07/msg00063.html>. |
16677 | 78 The compiler has truncated all 'long double' literals in log2l.c to |
79 53 bits of precision. */ | |
80 L_(8193.0) | |
81 #else | |
82 L_(5.0) | |
83 #endif | |
84 : L_(5.0)); | |
85 | |
86 for (i = 0; i < SIZEOF (RANDOM); i++) | |
87 { | |
88 DOUBLE x = L_(16.0) * RANDOM[i] + L_(1.0); /* 1.0 <= x <= 17.0 */ | |
89 DOUBLE y = LOG2 (x); | |
90 DOUBLE z = LOG2 (L_(1.0) / x); | |
91 DOUBLE err = y + z; | |
92 ASSERT (y >= L_(0.0)); | |
93 ASSERT (z <= L_(0.0)); | |
94 ASSERT (err > - err_bound / TWO_MANT_DIG | |
95 && err < err_bound / TWO_MANT_DIG); | |
96 } | |
97 } | |
98 | |
99 { | |
100 /* Error bound, in ulps. */ | |
101 const DOUBLE err_bound = | |
102 (sizeof (DOUBLE) > sizeof (double) ? | |
103 #if defined __i386__ && defined __FreeBSD__ | |
104 /* On FreeBSD/x86 6.4, the 'long double' type really has only 53 bits of | |
105 precision in the compiler but 64 bits of precision at runtime. See | |
19439
8bfc20b57265
maint: shorten https://lists.gnu.org/archive/html/... links
Jim Meyering <meyering@fb.com>
parents:
19192
diff
changeset
|
106 <https://lists.gnu.org/r/bug-gnulib/2008-07/msg00063.html>. |
16677 | 107 The compiler has truncated all 'long double' literals in log2l.c to |
108 53 bits of precision. */ | |
109 L_(8193.0) | |
110 #else | |
111 L_(9.0) | |
112 #endif | |
113 : L_(9.0)); | |
114 | |
115 for (i = 0; i < SIZEOF (RANDOM) / 5; i++) | |
116 for (j = 0; j < SIZEOF (RANDOM) / 5; j++) | |
117 { | |
118 DOUBLE x = L_(17.0) / (L_(16.0) - L_(15.0) * RANDOM[i]) - L_(1.0); | |
119 DOUBLE y = L_(17.0) / (L_(16.0) - L_(15.0) * RANDOM[j]) - L_(1.0); | |
120 /* 1/16 <= x,y <= 16 */ | |
121 DOUBLE z = L_(1.0) / (x * y); | |
122 /* Approximately x * y * z = 1. */ | |
123 DOUBLE err = LOG2 (x) + LOG2 (y) + LOG2 (z); | |
124 ASSERT (err > - err_bound / TWO_MANT_DIG | |
125 && err < err_bound / TWO_MANT_DIG); | |
126 } | |
127 } | |
128 } | |
129 | |
130 volatile DOUBLE x; | |
131 DOUBLE y; |