xref: /llvm-project/openmp/runtime/test/worksharing/for/omp_parallel_for_reduction.c (revision 373107699709f6fb06992bf6b76274091570aaf2)
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_parallel_for_reduction()10 int test_omp_parallel_for_reduction()
11 {
12   int sum;
13   int known_sum;
14   double dsum;
15   double dknown_sum;
16   double dt=0.5;  /* base of geometric row for + and - test*/
17   double rounding_error= 1.E-9;
18   int diff;
19   double ddiff;
20   int product;
21   int known_product;
22   int logic_and;
23   int logic_or;
24   int bit_and;
25   int bit_or;
26   int exclusiv_bit_or;
27   int logics[LOOPCOUNT];
28   int i;
29   double dpt;
30   int result;
31 
32   sum =0;
33   dsum=0;
34   dt = 1./3.;
35   result = 0;
36   product = 1;
37   logic_and=1;
38   logic_or=0;
39   bit_and=1;
40   bit_or=0;
41   exclusiv_bit_or=0;
42 
43   /* Tests for integers */
44   known_sum = (LOOPCOUNT*(LOOPCOUNT+1))/2;
45   #pragma omp parallel for schedule(dynamic,1) private(i) reduction(+:sum)
46   for (i=1;i<=LOOPCOUNT;i++) {
47     sum=sum+i;
48   }
49   if(known_sum!=sum) {
50     result++;
51     fprintf(stderr,"Error in sum with integers: Result was %d"
52       " instead of %d\n",sum,known_sum);
53   }
54 
55   diff = (LOOPCOUNT*(LOOPCOUNT+1))/2;
56   #pragma omp parallel for schedule(dynamic,1) private(i) reduction(-:diff)
57   for (i=1;i<=LOOPCOUNT;++i) {
58     diff=diff-i;
59   }
60   if(diff != 0) {
61     result++;
62     fprintf(stderr,"Error in difference with integers: Result was %d"
63       " instead of 0.\n",diff);
64   }
65 
66   /* Tests for doubles */
67   dsum=0;
68   dpt=1;
69   for (i=0;i<DOUBLE_DIGITS;++i) {
70     dpt*=dt;
71   }
72   dknown_sum = (1-dpt)/(1-dt);
73   #pragma omp parallel for schedule(dynamic,1) private(i) reduction(+:dsum)
74   for (i=0;i<DOUBLE_DIGITS;++i) {
75     dsum += pow(dt,i);
76   }
77   if( fabs(dsum-dknown_sum) > rounding_error ) {
78     result++;
79     fprintf(stderr,"Error in sum with doubles: Result was %f"
80       " instead of %f (Difference: %E)\n",
81       dsum, dknown_sum, dsum-dknown_sum);
82   }
83 
84   dpt=1;
85 
86   for (i=0;i<DOUBLE_DIGITS;++i) {
87     dpt*=dt;
88   }
89   fprintf(stderr,"\n");
90   ddiff = (1-dpt)/(1-dt);
91   #pragma omp parallel for schedule(dynamic,1) private(i) reduction(-:ddiff)
92   for (i=0;i<DOUBLE_DIGITS;++i) {
93     ddiff -= pow(dt,i);
94   }
95   if( fabs(ddiff) > rounding_error) {
96     result++;
97     fprintf(stderr,"Error in Difference with doubles: Result was %E"
98       " instead of 0.0\n",ddiff);
99   }
100 
101   /* Tests for integers */
102   #pragma omp parallel for schedule(dynamic,1) private(i) reduction(*:product)
103   for(i=1;i<=MAX_FACTOR;i++) {
104     product *= i;
105   }
106   known_product = KNOWN_PRODUCT;
107   if(known_product != product) {
108     result++;
109     fprintf(stderr,"Error in Product with integers: Result was %d"
110       " instead of %d\n\n",product,known_product);
111   }
112 
113   /* Tests for logic AND */
114   for(i=0;i<LOOPCOUNT;i++) {
115     logics[i]=1;
116   }
117 
118   #pragma omp parallel for schedule(dynamic,1) private(i) \
119     reduction(&&:logic_and)
120   for(i=0;i<LOOPCOUNT;++i) {
121     logic_and = (logic_and && logics[i]);
122   }
123   if(!logic_and) {
124     result++;
125     fprintf(stderr,"Error in logic AND part 1.\n");
126   }
127 
128   logic_and = 1;
129   logics[LOOPCOUNT/2]=0;
130 
131   #pragma omp parallel for schedule(dynamic,1) private(i) \
132     reduction(&&:logic_and)
133   for(i=0;i<LOOPCOUNT;++i) {
134     logic_and = logic_and && logics[i];
135   }
136   if(logic_and) {
137     result++;
138     fprintf(stderr,"Error in logic AND part 2.\n");
139   }
140 
141   /* Tests for logic OR */
142   for(i=0;i<LOOPCOUNT;i++) {
143     logics[i]=0;
144   }
145 
146   #pragma omp parallel for schedule(dynamic,1) private(i) \
147     reduction(||:logic_or)
148   for(i=0;i<LOOPCOUNT;++i) {
149     logic_or = logic_or || logics[i];
150   }
151   if(logic_or) {
152     result++;
153     fprintf(stderr,"Error in logic OR part 1.\n");
154   }
155   logic_or = 0;
156   logics[LOOPCOUNT/2]=1;
157 
158   #pragma omp parallel for schedule(dynamic,1) private(i) \
159     reduction(||:logic_or)
160   for(i=0;i<LOOPCOUNT;++i) {
161     logic_or = logic_or || logics[i];
162   }
163   if(!logic_or) {
164     result++;
165     fprintf(stderr,"Error in logic OR part 2.\n");
166   }
167 
168   /* Tests for bitwise AND */
169   for(i=0;i<LOOPCOUNT;++i) {
170     logics[i]=1;
171   }
172 
173   #pragma omp parallel for schedule(dynamic,1) private(i) \
174     reduction(&:bit_and)
175   for(i=0;i<LOOPCOUNT;++i) {
176     bit_and = (bit_and & logics[i]);
177   }
178   if(!bit_and) {
179     result++;
180     fprintf(stderr,"Error in BIT AND part 1.\n");
181   }
182 
183   bit_and = 1;
184   logics[LOOPCOUNT/2]=0;
185 
186   #pragma omp parallel for schedule(dynamic,1) private(i) \
187     reduction(&:bit_and)
188   for(i=0;i<LOOPCOUNT;++i) {
189     bit_and = bit_and & logics[i];
190   }
191   if(bit_and) {
192     result++;
193     fprintf(stderr,"Error in BIT AND part 2.\n");
194   }
195 
196   /* Tests for bitwise OR */
197   for(i=0;i<LOOPCOUNT;i++) {
198     logics[i]=0;
199   }
200 
201   #pragma omp parallel for schedule(dynamic,1) private(i) \
202     reduction(|:bit_or)
203   for(i=0;i<LOOPCOUNT;++i) {
204     bit_or = bit_or | logics[i];
205   }
206   if(bit_or) {
207     result++;
208     fprintf(stderr,"Error in BIT OR part 1\n");
209   }
210   bit_or = 0;
211   logics[LOOPCOUNT/2]=1;
212 
213   #pragma omp parallel for schedule(dynamic,1) private(i) \
214     reduction(|:bit_or)
215   for(i=0;i<LOOPCOUNT;++i) {
216     bit_or = bit_or | logics[i];
217   }
218   if(!bit_or) {
219     result++;
220     fprintf(stderr,"Error in BIT OR part 2\n");
221   }
222 
223   /* Tests for bitwise XOR */
224   for(i=0;i<LOOPCOUNT;i++) {
225     logics[i]=0;
226   }
227 
228   #pragma omp parallel for schedule(dynamic,1) private(i) \
229     reduction(^:exclusiv_bit_or)
230   for(i=0;i<LOOPCOUNT;++i) {
231     exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
232   }
233   if(exclusiv_bit_or) {
234     result++;
235     fprintf(stderr,"Error in EXCLUSIV BIT OR part 1\n");
236   }
237 
238   exclusiv_bit_or = 0;
239   logics[LOOPCOUNT/2]=1;
240 
241   #pragma omp parallel for schedule(dynamic,1) private(i) \
242     reduction(^:exclusiv_bit_or)
243   for(i=0;i<LOOPCOUNT;++i) {
244     exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
245   }
246   if(!exclusiv_bit_or) {
247     result++;
248     fprintf(stderr,"Error in EXCLUSIV BIT OR part 2\n");
249   }
250 
251   /*printf("\nResult:%d\n",result);*/
252   return (result==0);
253 }
254 
main()255 int main()
256 {
257   int i;
258   int num_failed=0;
259 
260   for(i = 0; i < REPETITIONS; i++) {
261     if(!test_omp_parallel_for_reduction()) {
262       num_failed++;
263     }
264   }
265   return num_failed;
266 }
267