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