1 | // RUN: %libomp-compile-and-run |
2 | #include <stdio.h> |
3 | #include <stdlib.h> |
4 | #include <math.h> |
5 | #include "omp_testsuite.h" |
6 | |
7 | #define DOUBLE_DIGITS 20 /* dt^DOUBLE_DIGITS */ |
8 | #define MAX_FACTOR 10 |
9 | #define KNOWN_PRODUCT 3628800 /* 10! */ |
10 | |
11 | int test_omp_for_reduction () |
12 | { |
13 | double dt; |
14 | int sum; |
15 | int diff; |
16 | int product = 1; |
17 | double dsum; |
18 | double dknown_sum; |
19 | double ddiff; |
20 | int logic_and; |
21 | int logic_or; |
22 | int bit_and; |
23 | int bit_or; |
24 | int exclusiv_bit_or; |
25 | int *logics; |
26 | int i; |
27 | int known_sum; |
28 | int known_product; |
29 | double rounding_error = 1.E-9; /* over all rounding error to be |
30 | ignored in the double tests */ |
31 | double dpt; |
32 | int result = 0; |
33 | int logicsArray[LOOPCOUNT]; |
34 | |
35 | /* Variables for integer tests */ |
36 | sum = 0; |
37 | product = 1; |
38 | known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2; |
39 | /* variabels for double tests */ |
40 | dt = 1. / 3.; /* base of geometric row for + and - test*/ |
41 | dsum = 0.; |
42 | /* Variabeles for logic tests */ |
43 | logics = logicsArray; |
44 | logic_and = 1; |
45 | logic_or = 0; |
46 | /* Variabeles for bit operators tests */ |
47 | bit_and = 1; |
48 | bit_or = 0; |
49 | /* Variables for exclusiv bit or */ |
50 | exclusiv_bit_or = 0; |
51 | |
52 | /************************************************************************/ |
53 | /** Tests for integers **/ |
54 | /************************************************************************/ |
55 | |
56 | /**** Testing integer addition ****/ |
57 | #pragma omp parallel |
58 | { |
59 | int j; |
60 | #pragma omp for schedule(dynamic,1) reduction(+:sum) |
61 | for (j = 1; j <= LOOPCOUNT; j++) { |
62 | sum = sum + j; |
63 | } |
64 | } |
65 | if (known_sum != sum) { |
66 | result++; |
67 | fprintf (stderr, format: "Error in sum with integers: Result was %d" |
68 | " instead of %d.\n" , sum, known_sum); |
69 | } |
70 | |
71 | /**** Testing integer subtracton ****/ |
72 | diff = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2; |
73 | #pragma omp parallel |
74 | { |
75 | int j; |
76 | #pragma omp for schedule(dynamic,1) reduction(-:diff) |
77 | for (j = 1; j <= LOOPCOUNT; j++) { |
78 | diff = diff - j; |
79 | } |
80 | } |
81 | if (diff != 0) { |
82 | result++; |
83 | fprintf (stderr, format: "Error in difference with integers: Result was %d" |
84 | " instead of 0.\n" , diff); |
85 | } |
86 | |
87 | /**** Testing integer multiplication ****/ |
88 | #pragma omp parallel |
89 | { |
90 | int j; |
91 | #pragma omp for schedule(dynamic,1) reduction(*:product) |
92 | for (j = 1; j <= MAX_FACTOR; j++) { |
93 | product *= j; |
94 | } |
95 | } |
96 | known_product = KNOWN_PRODUCT; |
97 | if(known_product != product) { |
98 | result++; |
99 | fprintf (stderr,format: "Error in Product with integers: Result was %d" |
100 | " instead of %d\n" ,product,known_product); |
101 | } |
102 | |
103 | /************************************************************************/ |
104 | /** Tests for doubles **/ |
105 | /************************************************************************/ |
106 | |
107 | /**** Testing double addition ****/ |
108 | dsum = 0.; |
109 | dpt = 1.; |
110 | for (i = 0; i < DOUBLE_DIGITS; ++i) { |
111 | dpt *= dt; |
112 | } |
113 | dknown_sum = (1 - dpt) / (1 - dt); |
114 | #pragma omp parallel |
115 | { |
116 | int j; |
117 | #pragma omp for schedule(dynamic,1) reduction(+:dsum) |
118 | for (j = 0; j < DOUBLE_DIGITS; j++) { |
119 | dsum += pow (x: dt, y: j); |
120 | } |
121 | } |
122 | if (fabs (x: dsum - dknown_sum) > rounding_error) { |
123 | result++; |
124 | fprintf (stderr, format: "\nError in sum with doubles: Result was %f" |
125 | " instead of: %f (Difference: %E)\n" , |
126 | dsum, dknown_sum, dsum-dknown_sum); |
127 | } |
128 | |
129 | /**** Testing double subtraction ****/ |
130 | ddiff = (1 - dpt) / (1 - dt); |
131 | #pragma omp parallel |
132 | { |
133 | int j; |
134 | #pragma omp for schedule(dynamic,1) reduction(-:ddiff) |
135 | for (j = 0; j < DOUBLE_DIGITS; ++j) { |
136 | ddiff -= pow (x: dt, y: j); |
137 | } |
138 | } |
139 | if (fabs (x: ddiff) > rounding_error) { |
140 | result++; |
141 | fprintf (stderr, format: "Error in Difference with doubles: Result was %E" |
142 | " instead of 0.0\n" , ddiff); |
143 | } |
144 | |
145 | |
146 | /************************************************************************/ |
147 | /** Tests for logical values **/ |
148 | /************************************************************************/ |
149 | |
150 | /**** Testing logic and ****/ |
151 | for (i = 0; i < LOOPCOUNT; i++) { |
152 | logics[i] = 1; |
153 | } |
154 | |
155 | #pragma omp parallel |
156 | { |
157 | int j; |
158 | #pragma omp for schedule(dynamic,1) reduction(&&:logic_and) |
159 | for (j = 0; j < LOOPCOUNT; ++j) { |
160 | logic_and = (logic_and && logics[j]); |
161 | } |
162 | } |
163 | if(!logic_and) { |
164 | result++; |
165 | fprintf (stderr, format: "Error in logic AND part 1\n" ); |
166 | } |
167 | |
168 | logic_and = 1; |
169 | logics[LOOPCOUNT / 2] = 0; |
170 | |
171 | #pragma omp parallel |
172 | { |
173 | int j; |
174 | #pragma omp for schedule(dynamic,1) reduction(&&:logic_and) |
175 | for (j = 0; j < LOOPCOUNT; ++j) { |
176 | logic_and = logic_and && logics[j]; |
177 | } |
178 | } |
179 | if(logic_and) { |
180 | result++; |
181 | fprintf (stderr, format: "Error in logic AND part 2\n" ); |
182 | } |
183 | |
184 | /**** Testing logic or ****/ |
185 | for (i = 0; i < LOOPCOUNT; i++) { |
186 | logics[i] = 0; |
187 | } |
188 | |
189 | #pragma omp parallel |
190 | { |
191 | int j; |
192 | #pragma omp for schedule(dynamic,1) reduction(||:logic_or) |
193 | for (j = 0; j < LOOPCOUNT; ++j) { |
194 | logic_or = logic_or || logics[j]; |
195 | } |
196 | } |
197 | if (logic_or) { |
198 | result++; |
199 | fprintf (stderr, format: "Error in logic OR part 1\n" ); |
200 | } |
201 | |
202 | logic_or = 0; |
203 | logics[LOOPCOUNT / 2] = 1; |
204 | |
205 | #pragma omp parallel |
206 | { |
207 | int j; |
208 | #pragma omp for schedule(dynamic,1) reduction(||:logic_or) |
209 | for (j = 0; j < LOOPCOUNT; ++j) { |
210 | logic_or = logic_or || logics[j]; |
211 | } |
212 | } |
213 | if(!logic_or) { |
214 | result++; |
215 | fprintf (stderr, format: "Error in logic OR part 2\n" ); |
216 | } |
217 | |
218 | /************************************************************************/ |
219 | /** Tests for bit values **/ |
220 | /************************************************************************/ |
221 | |
222 | /**** Testing bit and ****/ |
223 | for (i = 0; i < LOOPCOUNT; ++i) { |
224 | logics[i] = 1; |
225 | } |
226 | |
227 | #pragma omp parallel |
228 | { |
229 | int j; |
230 | #pragma omp for schedule(dynamic,1) reduction(&:bit_and) |
231 | for (j = 0; j < LOOPCOUNT; ++j) { |
232 | bit_and = (bit_and & logics[j]); |
233 | } |
234 | } |
235 | if (!bit_and) { |
236 | result++; |
237 | fprintf (stderr, format: "Error in BIT AND part 1\n" ); |
238 | } |
239 | |
240 | bit_and = 1; |
241 | logics[LOOPCOUNT / 2] = 0; |
242 | |
243 | #pragma omp parallel |
244 | { |
245 | int j; |
246 | #pragma omp for schedule(dynamic,1) reduction(&:bit_and) |
247 | for (j = 0; j < LOOPCOUNT; ++j) { |
248 | bit_and = bit_and & logics[j]; |
249 | } |
250 | } |
251 | if (bit_and) { |
252 | result++; |
253 | fprintf (stderr, format: "Error in BIT AND part 2\n" ); |
254 | } |
255 | |
256 | /**** Testing bit or ****/ |
257 | for (i = 0; i < LOOPCOUNT; i++) { |
258 | logics[i] = 0; |
259 | } |
260 | |
261 | #pragma omp parallel |
262 | { |
263 | int j; |
264 | #pragma omp for schedule(dynamic,1) reduction(|:bit_or) |
265 | for (j = 0; j < LOOPCOUNT; ++j) { |
266 | bit_or = bit_or | logics[j]; |
267 | } |
268 | } |
269 | if (bit_or) { |
270 | result++; |
271 | fprintf (stderr, format: "Error in BIT OR part 1\n" ); |
272 | } |
273 | |
274 | bit_or = 0; |
275 | logics[LOOPCOUNT / 2] = 1; |
276 | |
277 | #pragma omp parallel |
278 | { |
279 | int j; |
280 | #pragma omp for schedule(dynamic,1) reduction(|:bit_or) |
281 | for (j = 0; j < LOOPCOUNT; ++j) { |
282 | bit_or = bit_or | logics[j]; |
283 | } |
284 | } |
285 | if (!bit_or) { |
286 | result++; |
287 | fprintf (stderr, format: "Error in BIT OR part 2\n" ); |
288 | } |
289 | |
290 | /**** Testing exclusive bit or ****/ |
291 | for (i = 0; i < LOOPCOUNT; i++) { |
292 | logics[i] = 0; |
293 | } |
294 | |
295 | #pragma omp parallel |
296 | { |
297 | int j; |
298 | #pragma omp for schedule(dynamic,1) reduction(^:exclusiv_bit_or) |
299 | for (j = 0; j < LOOPCOUNT; ++j) { |
300 | exclusiv_bit_or = exclusiv_bit_or ^ logics[j]; |
301 | } |
302 | } |
303 | if (exclusiv_bit_or) { |
304 | result++; |
305 | fprintf (stderr, format: "Error in EXCLUSIV BIT OR part 1\n" ); |
306 | } |
307 | |
308 | exclusiv_bit_or = 0; |
309 | logics[LOOPCOUNT / 2] = 1; |
310 | |
311 | #pragma omp parallel |
312 | { |
313 | int j; |
314 | #pragma omp for schedule(dynamic,1) reduction(^:exclusiv_bit_or) |
315 | for (j = 0; j < LOOPCOUNT; ++j) { |
316 | exclusiv_bit_or = exclusiv_bit_or ^ logics[j]; |
317 | } |
318 | } |
319 | if (!exclusiv_bit_or) { |
320 | result++; |
321 | fprintf (stderr, format: "Error in EXCLUSIV BIT OR part 2\n" ); |
322 | } |
323 | |
324 | return (result == 0); |
325 | free (ptr: logics); |
326 | } |
327 | |
328 | int main() |
329 | { |
330 | int i; |
331 | int num_failed=0; |
332 | |
333 | for(i = 0; i < REPETITIONS; i++) { |
334 | if(!test_omp_for_reduction()) { |
335 | num_failed++; |
336 | } |
337 | } |
338 | return num_failed; |
339 | } |
340 | |