|
1 /* |
|
2 * Copyright (c) 2004 David A. Schleef <ds@schleef.org> |
|
3 * Copyright (c) 2005 Eric Anholt <anholt@FreeBSD.org> |
|
4 * All rights reserved. |
|
5 * |
|
6 * Redistribution and use in source and binary forms, with or without |
|
7 * modification, are permitted provided that the following conditions |
|
8 * are met: |
|
9 * 1. Redistributions of source code must retain the above copyright |
|
10 * notice, this list of conditions and the following disclaimer. |
|
11 * 2. Redistributions in binary form must reproduce the above copyright |
|
12 * notice, this list of conditions and the following disclaimer in the |
|
13 * documentation and/or other materials provided with the distribution. |
|
14 * |
|
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
|
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, |
|
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
|
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
|
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
25 * POSSIBILITY OF SUCH DAMAGE. |
|
26 */ |
|
27 |
|
28 /* Tests math functions against the reference, failing if they differ by more |
|
29 * than some epsilon, and printing the difference. |
|
30 */ |
|
31 #ifdef HAVE_CONFIG_H |
|
32 #include "config.h" |
|
33 #endif |
|
34 |
|
35 #include <stdio.h> |
|
36 #include <liboil/liboil.h> |
|
37 #include <ctype.h> |
|
38 #include <stdlib.h> |
|
39 #include <string.h> |
|
40 #include <math.h> |
|
41 #ifdef HAVE_INTTYPES_H |
|
42 #include <inttypes.h> |
|
43 #endif |
|
44 |
|
45 #include <liboil/liboilprototype.h> |
|
46 #include <liboil/liboiltest.h> |
|
47 #include <liboil/liboilcpu.h> |
|
48 #include <liboil/liboilparameter.h> |
|
49 |
|
50 #define LOG_FILE "c:\\logs\\testsuite_align_log.txt" |
|
51 #include "std_log_result.h" |
|
52 #define LOG_FILENAME_LINE __FILE__, __LINE__ |
|
53 |
|
54 void create_xml(int result) |
|
55 { |
|
56 if(result) |
|
57 assert_failed = 1; |
|
58 |
|
59 testResultXml("testsuite_align"); |
|
60 close_log_file(); |
|
61 } |
|
62 |
|
63 #ifndef PRIx8 |
|
64 #define PRIx8 "x" |
|
65 #define PRIx16 "x" |
|
66 #define PRIx32 "x" |
|
67 #define PRIx64 "llx" |
|
68 #define PRId8 "d" |
|
69 #define PRId16 "d" |
|
70 #define PRId32 "d" |
|
71 #define PRId64 "lld" |
|
72 #define PRIu8 "u" |
|
73 #define PRIu16 "u" |
|
74 #define PRIu32 "u" |
|
75 #define PRIu64 "llu" |
|
76 #endif |
|
77 |
|
78 |
|
79 /* Amount by which results of different types are allowed to deviate from the |
|
80 * reference. |
|
81 */ |
|
82 #define INT_EPSILON 1 |
|
83 #define FLOAT_EPSILON 0.0001 |
|
84 |
|
85 void |
|
86 dump_array (void *data, void *ref_data, OilType type, int pre_n, int stride, |
|
87 int post_n) |
|
88 { |
|
89 int i, j; |
|
90 int s2 = oil_type_sizeof (type); |
|
91 double x; |
|
92 |
|
93 #define DUMP(type, format, int) do { \ |
|
94 for(i=0;i<post_n;i++){ \ |
|
95 float epsilon = (int) ? INT_EPSILON : FLOAT_EPSILON; \ |
|
96 std_log(LOG_FILENAME_LINE," "); \ |
|
97 for(j=0;j<pre_n;j++){ \ |
|
98 x = fabs(OIL_GET(data, i*stride + j*s2, type) - \ |
|
99 OIL_GET(ref_data, i*stride + j*s2, type)); \ |
|
100 if (x > epsilon) { \ |
|
101 std_log(LOG_FILENAME_LINE,"*" format "* (" format ") ", \ |
|
102 OIL_GET(data, i*stride + j*s2, type), \ |
|
103 OIL_GET(ref_data, i*stride + j*s2, type)); \ |
|
104 } else { \ |
|
105 std_log(LOG_FILENAME_LINE," " format " ", OIL_GET(data, i*stride + j*s2, type)); \ |
|
106 } \ |
|
107 } \ |
|
108 std_log(LOG_FILENAME_LINE,"\n"); \ |
|
109 } \ |
|
110 } while(0) |
|
111 |
|
112 switch(type) { |
|
113 case OIL_TYPE_s8p: |
|
114 case OIL_TYPE_u8p: |
|
115 DUMP(int8_t, "0x%02" PRIx8, 1); |
|
116 break; |
|
117 case OIL_TYPE_s16p: |
|
118 case OIL_TYPE_u16p: |
|
119 DUMP(uint16_t, "0x%04" PRIx16, 1); |
|
120 break; |
|
121 case OIL_TYPE_s32p: |
|
122 case OIL_TYPE_u32p: |
|
123 DUMP(uint32_t, "0x%08" PRIx32, 1); |
|
124 break; |
|
125 case OIL_TYPE_f32p: |
|
126 DUMP(float, "%g", 0); |
|
127 break; |
|
128 case OIL_TYPE_s64p: |
|
129 case OIL_TYPE_u64p: |
|
130 DUMP(uint64_t, "0x%016" PRIx64, 1); |
|
131 break; |
|
132 case OIL_TYPE_f64p: |
|
133 DUMP(double, "%g", 0); |
|
134 break; |
|
135 default: |
|
136 break; |
|
137 } |
|
138 } |
|
139 |
|
140 void |
|
141 dump_source (OilTest *test) |
|
142 { |
|
143 int i; |
|
144 for(i=0;i<OIL_ARG_LAST;i++){ |
|
145 OilParameter *p = &test->params[i]; |
|
146 if (p->is_pointer) { |
|
147 if (p->direction == 'i' || p->direction == 's') { |
|
148 printf (" %s:\n", p->parameter_name); |
|
149 dump_array (p->src_data + p->test_header, |
|
150 p->src_data + p->test_header, |
|
151 p->type, p->pre_n, p->stride, p->post_n); |
|
152 } |
|
153 } |
|
154 } |
|
155 } |
|
156 |
|
157 void |
|
158 dump_dest_ref (OilTest *test) |
|
159 { |
|
160 int i; |
|
161 for(i=0;i<OIL_ARG_LAST;i++){ |
|
162 OilParameter *p = &test->params[i]; |
|
163 if (p->is_pointer) { |
|
164 if (p->direction == 'd') { |
|
165 printf (" %s:\n", p->parameter_name); |
|
166 dump_array (p->ref_data + p->test_header, |
|
167 p->ref_data + p->test_header, |
|
168 p->type, p->pre_n, p->stride, p->post_n); |
|
169 } |
|
170 } |
|
171 } |
|
172 } |
|
173 |
|
174 int |
|
175 test_difference (void *data, void *ref_data, OilType type, int pre_n, int stride, |
|
176 int post_n) |
|
177 { |
|
178 int i, j; |
|
179 int s2 = oil_type_sizeof (type); |
|
180 double x; |
|
181 |
|
182 #define CHECK(type, is_int) do { \ |
|
183 float epsilon = (is_int) ? INT_EPSILON : FLOAT_EPSILON; \ |
|
184 for(i=0;i<post_n;i++){ \ |
|
185 for(j=0;j<pre_n;j++){ \ |
|
186 x = fabs(OIL_GET(data, i*stride + j*s2, type) - \ |
|
187 OIL_GET(ref_data, i*stride + j*s2, type)); \ |
|
188 if (x > epsilon) { \ |
|
189 return 1; \ |
|
190 } \ |
|
191 } \ |
|
192 } \ |
|
193 return 0; \ |
|
194 } while(0) |
|
195 |
|
196 switch(type) { |
|
197 case OIL_TYPE_s8p: |
|
198 CHECK(int8_t, 1); |
|
199 break; |
|
200 case OIL_TYPE_u8p: |
|
201 CHECK(uint8_t, 1); |
|
202 break; |
|
203 case OIL_TYPE_s16p: |
|
204 CHECK(int16_t, 1); |
|
205 break; |
|
206 case OIL_TYPE_u16p: |
|
207 CHECK(uint16_t, 1); |
|
208 break; |
|
209 case OIL_TYPE_s32p: |
|
210 CHECK(int32_t, 1); |
|
211 break; |
|
212 case OIL_TYPE_u32p: |
|
213 CHECK(uint32_t, 1); |
|
214 break; |
|
215 case OIL_TYPE_s64p: |
|
216 CHECK(int64_t, 1); |
|
217 break; |
|
218 case OIL_TYPE_u64p: |
|
219 CHECK(uint64_t, 1); |
|
220 break; |
|
221 case OIL_TYPE_f32p: |
|
222 CHECK(float, 0); |
|
223 break; |
|
224 case OIL_TYPE_f64p: |
|
225 CHECK(double, 0); |
|
226 break; |
|
227 default: |
|
228 return 1; |
|
229 } |
|
230 } |
|
231 |
|
232 int |
|
233 check_test (OilTest *test) |
|
234 { |
|
235 int i, failed = 0; |
|
236 for(i=0;i<OIL_ARG_LAST;i++){ |
|
237 OilParameter *p = &test->params[i]; |
|
238 if (p->is_pointer) { |
|
239 if (p->direction == 'i' || p->direction == 'd') { |
|
240 if (!test_difference(p->test_data + p->test_header, |
|
241 p->ref_data + p->test_header, |
|
242 p->type, p->pre_n, p->stride, p->post_n)) |
|
243 continue; |
|
244 printf (" Failure in %s (marked by *, ref in ()):\n", |
|
245 p->parameter_name); |
|
246 dump_array (p->test_data + p->test_header, |
|
247 p->ref_data + p->test_header, |
|
248 p->type, p->pre_n, p->stride, p->post_n); |
|
249 failed = 1; |
|
250 } |
|
251 } |
|
252 } |
|
253 return failed; |
|
254 } |
|
255 |
|
256 int check_class_with_alignment (OilFunctionClass *klass, |
|
257 OilArgType arg, int n, int align) |
|
258 { |
|
259 OilParameter *p; |
|
260 int align_offset; |
|
261 int test_failed = 0; |
|
262 OilTest *test; |
|
263 OilFunctionImpl *impl; |
|
264 |
|
265 test = oil_test_new(klass); |
|
266 |
|
267 p = &test->params[arg]; |
|
268 align_offset = align * oil_type_sizeof(p->type); |
|
269 oil_test_set_test_header(test, p, OIL_TEST_HEADER + align_offset); |
|
270 |
|
271 oil_test_set_iterations(test, 1); |
|
272 test->n = n; |
|
273 test->m = n; |
|
274 |
|
275 impl = klass->reference_impl; |
|
276 oil_test_check_impl (test, impl); |
|
277 |
|
278 for (impl = klass->first_impl; impl; impl = impl->next) { |
|
279 if (impl == klass->reference_impl) |
|
280 continue; |
|
281 if (oil_impl_is_runnable (impl)) { |
|
282 if (!oil_test_check_impl (test, impl)) { |
|
283 printf ("impl %s with arg %d offset %d, n=%d\n", impl->name, arg, |
|
284 align_offset, n); |
|
285 std_log(LOG_FILENAME_LINE,"dests for %s:\n", klass->name); |
|
286 dump_dest_ref(test); |
|
287 std_log(LOG_FILENAME_LINE,"sources for %s:\n", klass->name); |
|
288 dump_source(test); |
|
289 } |
|
290 } |
|
291 } |
|
292 oil_test_free(test); |
|
293 |
|
294 if (test_failed) |
|
295 std_log(LOG_FILENAME_LINE,"Failed in class %s", klass->name); |
|
296 return test_failed; |
|
297 } |
|
298 |
|
299 /* Check a function class for all implementations matching the reference when |
|
300 * each parameter is varied in its offset from malloc's alignment by 0 - 3 units |
|
301 * times size of the type, and with the number of elements varying between 8 and |
|
302 * 11. |
|
303 */ |
|
304 int check_class(OilFunctionClass *klass) |
|
305 { |
|
306 OilTest *test; |
|
307 int failed = 0; |
|
308 int i, n; |
|
309 |
|
310 oil_class_optimize (klass); |
|
311 |
|
312 std_log(LOG_FILENAME_LINE,"checking class %s\n", klass->name); |
|
313 |
|
314 test = oil_test_new(klass); |
|
315 for (i=0; i < OIL_ARG_LAST; i++) { |
|
316 OilParameter *p; |
|
317 int align; |
|
318 |
|
319 p = &test->params[i]; |
|
320 if (!p->is_pointer) { |
|
321 continue; |
|
322 } |
|
323 |
|
324 for (n = 8; n <= 11; n++) { |
|
325 for (align = 0; align <= 3; align++) { |
|
326 failed |= check_class_with_alignment (klass, i, n, align); |
|
327 } |
|
328 } |
|
329 } |
|
330 oil_test_free (test); |
|
331 |
|
332 return failed; |
|
333 } |
|
334 |
|
335 int main (int argc, char *argv[]) |
|
336 { |
|
337 int failed = 0; |
|
338 int i, n; |
|
339 |
|
340 std_log(LOG_FILENAME_LINE,"Test started testsuite_align"); |
|
341 oil_init (); |
|
342 |
|
343 n = oil_class_get_n_classes (); |
|
344 for (i = 0; i < n; i++) { |
|
345 OilFunctionClass *klass = oil_class_get_by_index(i); |
|
346 failed |= check_class(klass); |
|
347 } |
|
348 |
|
349 if(failed) |
|
350 assert_failed = failed; |
|
351 if(assert_failed) |
|
352 std_log(LOG_FILENAME_LINE,"Test Fail"); |
|
353 else |
|
354 std_log(LOG_FILENAME_LINE,"Test Successful"); |
|
355 create_xml(0); |
|
356 return 0; |
|
357 } |