xref: /llvm-project/openmp/runtime/test/worksharing/for/omp_for_reduction.c (revision 373107699709f6fb06992bf6b76274091570aaf2)
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 
test_omp_for_reduction()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, "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, "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,"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 (dt, j);
120     }
121   }
122   if (fabs (dsum - dknown_sum) > rounding_error) {
123     result++;
124     fprintf (stderr, "\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 (dt, j);
137     }
138   }
139   if (fabs (ddiff) > rounding_error) {
140     result++;
141     fprintf (stderr, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "Error in EXCLUSIV BIT OR part 2\n");
322   }
323 
324   return (result == 0);
325   free (logics);
326 }
327 
main()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