This source file includes following definitions.
- truncf_reference
- equal
- correct_result_p
- check
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <config.h>
23
24 #include <math.h>
25
26 #include <float.h>
27 #include <stdbool.h>
28 #include <stdint.h>
29 #include <stdio.h>
30
31 #include "isnanf-nolibm.h"
32 #include "minus-zero.h"
33 #include "macros.h"
34
35
36
37 #if defined _MSC_VER && !defined __clang__
38 # pragma fenv_access (off)
39 #endif
40
41
42
43
44 #define DOUBLE float
45 #define MANT_DIG FLT_MANT_DIG
46 #define L_(literal) literal##f
47
48
49 #define MINUS_ZERO minus_zerof
50
51
52 static const DOUBLE TWO_MANT_DIG =
53
54
55
56 (DOUBLE) (1U << ((MANT_DIG - 1) / 5))
57 * (DOUBLE) (1U << ((MANT_DIG - 1 + 1) / 5))
58 * (DOUBLE) (1U << ((MANT_DIG - 1 + 2) / 5))
59 * (DOUBLE) (1U << ((MANT_DIG - 1 + 3) / 5))
60 * (DOUBLE) (1U << ((MANT_DIG - 1 + 4) / 5));
61
62 DOUBLE
63 truncf_reference (DOUBLE x)
64 {
65
66
67
68
69
70
71 volatile DOUBLE y = x;
72 volatile DOUBLE z = y;
73
74 if (z > L_(0.0))
75 {
76
77
78 if (z < L_(1.0))
79 z = L_(0.0);
80
81 else if (z < TWO_MANT_DIG)
82 {
83
84 z += TWO_MANT_DIG;
85 z -= TWO_MANT_DIG;
86
87 if (z > y)
88 z -= L_(1.0);
89 }
90 }
91 else if (z < L_(0.0))
92 {
93
94
95 if (z > L_(-1.0))
96 z = MINUS_ZERO;
97
98 else if (z > - TWO_MANT_DIG)
99 {
100
101 z -= TWO_MANT_DIG;
102 z += TWO_MANT_DIG;
103
104 if (z < y)
105 z += L_(1.0);
106 }
107 }
108 return z;
109 }
110
111
112
113 static int
114 equal (DOUBLE x, DOUBLE y)
115 {
116 return (isnanf (x) ? isnanf (y) : x == y);
117 }
118
119
120 static bool
121 correct_result_p (DOUBLE x, DOUBLE result)
122 {
123 return
124 (x >= 0
125 ? (x < 1 ? result == L_(0.0) :
126 x - 1 < x ? result <= x && result >= x - 1 && x - result < 1 :
127 equal (result, x))
128 : (x > -1 ? result == L_(0.0) :
129 x + 1 > x ? result >= x && result <= x + 1 && result - x < 1 :
130 equal (result, x)));
131 }
132
133
134 static int
135 check (float x)
136 {
137
138 float reference = truncf_reference (x);
139 ASSERT (correct_result_p (x, reference));
140
141 {
142 float result = truncf (x);
143 if (correct_result_p (x, result))
144 return 0;
145 else
146 {
147 #if GNULIB_TEST_FPRINTF_POSIX
148 fprintf (stderr, "truncf %g(%a) = %g(%a) or %g(%a)?\n",
149 x, x, reference, reference, result, result);
150 #endif
151 return 1;
152 }
153 }
154 }
155
156 #define NUM_HIGHBITS 12
157 #define NUM_LOWBITS 4
158
159 int
160 main ()
161 {
162 unsigned int highbits;
163 unsigned int lowbits;
164 int error = 0;
165 for (highbits = 0; highbits < (1 << NUM_HIGHBITS); highbits++)
166 for (lowbits = 0; lowbits < (1 << NUM_LOWBITS); lowbits++)
167 {
168
169
170 union { float f; uint32_t i; } janus;
171 janus.i = ((uint32_t) highbits << (32 - NUM_HIGHBITS))
172 | ((uint32_t) ((int32_t) ((uint32_t) lowbits << (32 - NUM_LOWBITS))
173 >> (32 - NUM_LOWBITS - NUM_HIGHBITS))
174 >> NUM_HIGHBITS);
175 error |= check (janus.f);
176 }
177 return (error ? 1 : 0);
178 }