1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | #include "utils.h" |
25 | #include <assert.h> |
26 | #include <stdlib.h> |
27 | #include <stdio.h> |
28 | #include <math.h> |
29 | |
30 | #ifdef HAVE_FLOAT128 |
31 | |
32 | #define pixman_fixed_to_float128(x) (((__float128)(x)) / 65536.0Q) |
33 | |
34 | typedef struct { __float128 v[3]; } pixman_vector_f128_t; |
35 | typedef struct { __float128 m[3][3]; } pixman_transform_f128_t; |
36 | |
37 | pixman_bool_t |
38 | pixman_transform_point_f128 (const pixman_transform_f128_t *t, |
39 | const pixman_vector_f128_t *v, |
40 | pixman_vector_f128_t *result) |
41 | { |
42 | int i; |
43 | for (i = 0; i < 3; i++) |
44 | { |
45 | result->v[i] = t->m[i][0] * v->v[0] + |
46 | t->m[i][1] * v->v[1] + |
47 | t->m[i][2] * v->v[2]; |
48 | } |
49 | if (result->v[2] != 0) |
50 | { |
51 | result->v[0] /= result->v[2]; |
52 | result->v[1] /= result->v[2]; |
53 | result->v[2] = 1; |
54 | return TRUE1; |
55 | } |
56 | else |
57 | { |
58 | return FALSE0; |
59 | } |
60 | } |
61 | |
62 | pixman_bool_t does_it_fit_fixed_48_16 (__float128 x) |
63 | { |
64 | if (x >= 65536.0Q * 65536.0Q * 32768.0Q) |
65 | return FALSE0; |
66 | if (x <= -65536.0Q * 65536.0Q * 32768.0Q) |
67 | return FALSE0; |
68 | return TRUE1; |
69 | } |
70 | |
71 | #endif |
72 | |
73 | static inline__inline__ uint32_t |
74 | byteswap32 (uint32_t x) |
75 | { |
76 | return ((x & ((uint32_t)0xFF << 24)) >> 24) | |
77 | ((x & ((uint32_t)0xFF << 16)) >> 8) | |
78 | ((x & ((uint32_t)0xFF << 8)) << 8) | |
79 | ((x & ((uint32_t)0xFF << 0)) << 24); |
80 | } |
81 | |
82 | static inline__inline__ uint64_t |
83 | byteswap64 (uint64_t x) |
84 | { |
85 | return ((x & ((uint64_t)0xFF << 56)) >> 56) | |
86 | ((x & ((uint64_t)0xFF << 48)) >> 40) | |
87 | ((x & ((uint64_t)0xFF << 40)) >> 24) | |
88 | ((x & ((uint64_t)0xFF << 32)) >> 8) | |
89 | ((x & ((uint64_t)0xFF << 24)) << 8) | |
90 | ((x & ((uint64_t)0xFF << 16)) << 24) | |
91 | ((x & ((uint64_t)0xFF << 8)) << 40) | |
92 | ((x & ((uint64_t)0xFF << 0)) << 56); |
93 | } |
94 | |
95 | static void |
96 | byteswap_transform (pixman_transform_t *t) |
97 | { |
98 | int i, j; |
99 | |
100 | if (is_little_endian ()) |
101 | return; |
102 | |
103 | for (i = 0; i < 3; i++) |
104 | for (j = 0; j < 3; j++) |
105 | t->matrix[i][j] = byteswap32 (t->matrix[i][j]); |
106 | } |
107 | |
108 | static void |
109 | byteswap_vector_48_16 (pixman_vector_48_16_t *v) |
110 | { |
111 | int i; |
112 | |
113 | if (is_little_endian ()) |
114 | return; |
115 | |
116 | for (i = 0; i < 3; i++) |
117 | v->v[i] = byteswap64 (v->v[i]); |
118 | } |
119 | |
120 | uint32_t |
121 | test_matrix (int testnum, int verbose) |
122 | { |
123 | uint32_t crc32 = 0; |
124 | int i, j, k; |
125 | pixman_bool_t is_affine; |
126 | |
127 | prng_srand (testnum); |
128 | |
129 | for (i = 0; i < 100; i++) |
130 | { |
131 | pixman_bool_t transform_ok; |
132 | pixman_transform_t ti; |
133 | pixman_vector_48_16_t vi, result_i; |
134 | #ifdef HAVE_FLOAT128 |
135 | pixman_transform_f128_t tf; |
136 | pixman_vector_f128_t vf, result_f; |
137 | #endif |
138 | prng_randmemset (&ti, sizeof(ti), 0); |
139 | prng_randmemset (&vi, sizeof(vi), 0); |
140 | byteswap_transform (&ti); |
141 | byteswap_vector_48_16 (&vi); |
142 | |
143 | for (j = 0; j < 3; j++) |
144 | { |
145 | |
146 | vi.v[j] >>= 17; |
147 | |
148 | if (prng_rand_n (3) == 0) |
149 | vi.v[j] >>= prng_rand_n (46); |
150 | } |
151 | |
152 | if (prng_rand_n (2)) |
153 | { |
154 | |
155 | for (j = 0; j < 3; j++) |
156 | for (k = 0; k < 3; k++) |
157 | ti.matrix[j][k] >>= prng_rand_n (30); |
158 | } |
159 | |
160 | if (prng_rand_n (2)) |
161 | { |
162 | |
163 | ti.matrix[2][0] = 0; |
164 | ti.matrix[2][1] = 0; |
165 | ti.matrix[2][2] = pixman_fixed_1(((pixman_fixed_t) ((1) << 16))); |
166 | } |
167 | |
168 | if (prng_rand_n (2)) |
169 | { |
170 | |
171 | vi.v[2] = pixman_fixed_1(((pixman_fixed_t) ((1) << 16))); |
172 | } |
173 | |
174 | is_affine = (ti.matrix[2][0] == 0 && ti.matrix[2][1] == 0 && |
175 | ti.matrix[2][2] == pixman_fixed_1(((pixman_fixed_t) ((1) << 16))) && |
176 | vi.v[2] == pixman_fixed_1(((pixman_fixed_t) ((1) << 16)))); |
177 | |
178 | transform_ok = TRUE1; |
| Value stored to 'transform_ok' is never read |
179 | if (is_affine && prng_rand_n (2)) |
180 | pixman_transform_point_31_16_affine (&ti, &vi, &result_i); |
181 | else |
182 | transform_ok = pixman_transform_point_31_16 (&ti, &vi, &result_i); |
183 | |
184 | #ifdef HAVE_FLOAT128 |
185 | |
186 | for (j = 0; j < 3; j++) |
187 | { |
188 | vf.v[j] = pixman_fixed_to_float128 (vi.v[j]); |
189 | for (k = 0; k < 3; k++) |
190 | { |
191 | tf.m[j][k] = pixman_fixed_to_float128 (ti.matrix[j][k]); |
192 | } |
193 | } |
194 | |
195 | if (pixman_transform_point_f128 (&tf, &vf, &result_f)) |
196 | { |
197 | if (transform_ok || |
198 | (does_it_fit_fixed_48_16 (result_f.v[0]) && |
199 | does_it_fit_fixed_48_16 (result_f.v[1]) && |
200 | does_it_fit_fixed_48_16 (result_f.v[2]))) |
201 | { |
202 | for (j = 0; j < 3; j++) |
203 | { |
204 | double diff = fabs (result_f.v[j] - |
205 | pixman_fixed_to_float128 (result_i.v[j])); |
206 | |
207 | if (is_affine && diff > (0.51 / 65536.0)) |
208 | { |
209 | printf ("%d:%d: bad precision for affine (%.12f)\n", |
210 | testnum, i, diff); |
211 | abort (); |
212 | } |
213 | else if (diff > (0.71 / 65536.0)) |
214 | { |
215 | printf ("%d:%d: bad precision for projective (%.12f)\n", |
216 | testnum, i, diff); |
217 | abort (); |
218 | } |
219 | } |
220 | } |
221 | } |
222 | #endif |
223 | byteswap_vector_48_16 (&result_i); |
224 | crc32 = compute_crc32 (crc32, &result_i, sizeof (result_i)); |
225 | } |
226 | return crc32; |
227 | } |
228 | |
229 | int |
230 | main (int argc, const char *argv[]) |
231 | { |
232 | return fuzzer_test_main ("matrix", 20000, |
233 | 0xBEBF98C3, |
234 | test_matrix, argc, argv); |
235 | } |