1// { dg-do run }
2
3#include <omp.h>
4typedef __PTRDIFF_TYPE__ ptrdiff_t;
5extern "C" void abort ();
6
7template <typename T>
8class I
9{
10public:
11  typedef ptrdiff_t difference_type;
12  I ();
13  ~I ();
14  I (T *);
15  I (const I &);
16  T &operator * ();
17  T *operator -> ();
18  T &operator [] (const difference_type &) const;
19  I &operator = (const I &);
20  I &operator ++ ();
21  I operator ++ (int);
22  I &operator -- ();
23  I operator -- (int);
24  I &operator += (const difference_type &);
25  I &operator -= (const difference_type &);
26  I operator + (const difference_type &) const;
27  I operator - (const difference_type &) const;
28  template <typename S> friend bool operator == (I<S> &, I<S> &);
29  template <typename S> friend bool operator == (const I<S> &, const I<S> &);
30  template <typename S> friend bool operator < (I<S> &, I<S> &);
31  template <typename S> friend bool operator < (const I<S> &, const I<S> &);
32  template <typename S> friend bool operator <= (I<S> &, I<S> &);
33  template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
34  template <typename S> friend bool operator > (I<S> &, I<S> &);
35  template <typename S> friend bool operator > (const I<S> &, const I<S> &);
36  template <typename S> friend bool operator >= (I<S> &, I<S> &);
37  template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
38  template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
39  template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
40  template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
41private:
42  T *p;
43};
44template <typename T> I<T>::I () : p (0) {}
45template <typename T> I<T>::~I () { p = (T *) 0; }
46template <typename T> I<T>::I (T *x) : p (x) {}
47template <typename T> I<T>::I (const I &x) : p (x.p) {}
48template <typename T> T &I<T>::operator * () { return *p; }
49template <typename T> T *I<T>::operator -> () { return p; }
50template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
51template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
52template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
53template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
54template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
55template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
56template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
57template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
58template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
59template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
60template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
61template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
62template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
63template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
64template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
65template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
66template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
67template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
68template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
69template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
70template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
71template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
72template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
73template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
74template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
75
76template <typename T>
77class J
78{
79public:
80  J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
81  const I<T> &begin ();
82  const I<T> &end ();
83private:
84  I<T> b, e;
85};
86
87template <typename T> const I<T> &J<T>::begin () { return b; }
88template <typename T> const I<T> &J<T>::end () { return e; }
89
90int results[2000];
91
92void
93f1 (J<int> x, J<int> y, J<int> z)
94{
95  I<int> i, j, k;
96  int l, f = 0, n = 0, m = 0;
97#pragma omp parallel shared (i, j, k, l) firstprivate (f) \
98		     reduction (+:n, m) num_threads (8)
99  {
100  #pragma omp for lastprivate (i, j, k, l) schedule (static, 9) \
101		  collapse (4)
102    for (i = x.begin (); i < x.end (); ++i)
103      for (j = y.begin (); j <= y.end (); j += 1)
104	for (l = 0; l < 1; l++)
105	  for (k = z.begin () + 3; k < z.end () - 3; k++)
106	    if (omp_get_num_threads () == 8
107		&& ((*i + 2) * 12 + (*j + 5) * 4 + (*k - 13)
108		    != (omp_get_thread_num () * 9 + f++)))
109	      n++;
110	    else
111	      m++;
112  }
113  if (n || i != x.end () || j != y.end () + 1 || k != z.end () - 3
114      || m != 72 || l != 1)
115    abort ();
116}
117
118void
119f2 (J<int> x, J<int> y, J<int> z)
120{
121  int f = 0, n = 0, m = 0;
122#pragma omp parallel for firstprivate (f) reduction (+:n, m) \
123			 num_threads (8) schedule (static, 9) \
124			 collapse (6 - 2)
125  for (I<int> i = x.end () - 1; i >= x.begin (); --i)
126    for (int l = -131; l >= -131; l--)
127      for (I<int> j = y.end (); j > y.begin () - 1; j -= 1)
128	{
129	  for (I<int> k = z.end () - 4; k >= z.begin () + 3; k--)
130	    if (omp_get_num_threads () == 8
131		&& ((3 - *i) * 12 + (-3 - *j) * 4 + (16 - *k)
132		    != (omp_get_thread_num () * 9 + f++)))
133	      n++;
134	    else
135	      m++;
136	}
137  if (n || m != 72)
138    abort ();
139}
140
141template <typename T>
142void
143f3 (J<int> x, J<int> y, J<int> z)
144{
145  I<int> i, j, k;
146  int l, f = 0, n = 0, m = 0;
147#pragma omp parallel shared (i, j, k, l) firstprivate (f) \
148		     reduction (+:n, m) num_threads (8)
149  {
150  #pragma omp for lastprivate (i, j, k, l) schedule (static, 9) \
151		  collapse (4)
152    for (i = x.begin (); i < x.end (); ++i)
153      for (j = y.begin (); j <= y.end (); j += 1)
154	for (k = z.begin () + 3; k < z.end () - 3; k++)
155	  for (l = 7; l <= 7; l++)
156	    if (omp_get_num_threads () == 8
157		&& ((*i + 2) * 12 + (*j + 5) * 4 + (*k - 13)
158		    != (omp_get_thread_num () * 9 + f++)))
159	      n++;
160	    else
161	      m++;
162  }
163  if (n || i != x.end () || j != y.end () + 1 || k != z.end () - 3
164      || m != 72 || l != 8)
165    abort ();
166}
167
168template <typename T>
169void
170f4 (J<int> x, J<int> y, J<int> z)
171{
172  int f = 0, n = 0, m = 0;
173#pragma omp parallel for firstprivate (f) reduction (+:n, m) \
174			 num_threads (8) schedule (static, 9) \
175			 collapse (5 - 2)
176  for (I<int> i = x.end () - 1; i >= x.begin (); --i)
177    {
178      for (I<int> j = y.end (); j > y.begin () - 1; j -= 1)
179	{
180	  for (I<int> k = z.end () - 4; k >= z.begin () + 3; k--)
181	    if (omp_get_num_threads () == 8
182		&& ((3 - *i) * 12 + (-3 - *j) * 4 + (16 - *k)
183		    != (omp_get_thread_num () * 9 + f++)))
184	      n++;
185	    else
186	      m++;
187	}
188    }
189  if (n || m != 72)
190    abort ();
191}
192
193template <typename T>
194void
195f5 (J<int> x, J<int> y, J<int> z)
196{
197  I<int> i, j, k;
198  int f = 0, n = 0, m = 0;
199#pragma omp parallel shared (i, j, k) firstprivate (f) \
200		     reduction (+:n, m) num_threads (8)
201  {
202  #pragma omp for lastprivate (i, j, k) schedule (static, 9) \
203		  collapse (3)
204    for (i = x.begin (); i < x.end (); ++i)
205      for (j = y.begin (); j <= y.end (); j += (T) 1)
206	{
207	  for (k = z.begin () + 3; k < z.end () - 3; k++)
208	    if (omp_get_num_threads () == 8
209		&& ((*i + 2) * 12 + (*j + 5) * 4 + (*k - 13)
210		    != (omp_get_thread_num () * 9 + f++)))
211	      n++;
212	    else
213	      m++;
214	}
215  }
216  if (n || i != x.end () || j != y.end () + 1 || k != z.end () - 3
217      || m != 72)
218    abort ();
219}
220
221template <typename T>
222void
223f6 (J<int> x, J<int> y, J<int> z)
224{
225  int f = 0, n = 0, m = 0;
226#pragma omp parallel for firstprivate (f) reduction (+:n, m) \
227			 num_threads (8) schedule (static, 9) \
228			 collapse (5 - 2)
229  for (I<int> i = x.end () - 1; i >= x.begin (); --i)
230    {
231      for (I<int> j = y.end (); j > y.begin () - 1; j -= 1)
232	{
233	  for (I<int> k = z.end () - 4; k >= z.begin () + (T) 3; k--)
234	    if (omp_get_num_threads () == 8
235		&& ((3 - *i) * 12 + (-3 - *j) * 4 + (16 - *k)
236		    != (omp_get_thread_num () * 9 + f++)))
237	      n++;
238	    else
239	      m++;
240	}
241    }
242  if (n || m != 72)
243    abort ();
244}
245
246template <typename T>
247void
248f7 (J<T> x, J<T> y, J<T> z)
249{
250  I<T> i, j, k, o = y.begin ();
251  T l, f = 0, n = 0, m = 0;
252#pragma omp parallel shared (i, j, k, l) firstprivate (f) \
253		     reduction (+:n, m) num_threads (8)
254  {
255  #pragma omp for lastprivate (i, j, k, l) schedule (static, 9) \
256		  collapse (4)
257    for (i = x.begin (); i < x.end (); ++i)
258      for (j = y.begin (); j <= y.end (); j += 1)
259	for (l = *o; l <= *o; l = 1 + l)
260	  for (k = z.begin () + 3; k < z.end () - 3; k++)
261	    if (omp_get_num_threads () == 8
262		&& ((*i + 2) * 12 + (*j + 5) * 4 + (*k - 13)
263		    != (omp_get_thread_num () * 9 + f++)))
264	      n++;
265	    else
266	      m++;
267  }
268  if (n || i != x.end () || j != y.end () + 1 || k != z.end () - 3
269      || m != 72 || l != *o + 1)
270    abort ();
271}
272
273template <typename T>
274void
275f8 (J<T> x, J<T> y, J<T> z)
276{
277  T f = 0, n = 0, m = 0;
278#pragma omp parallel for firstprivate (f) reduction (+:n, m) \
279			 num_threads (8) schedule (static, 9) \
280			 collapse (6 - 2)
281  for (I<T> i = x.end () - 1; i >= x.begin (); --i)
282    for (T l = 0; l < 1; l++)
283      for (I<T> j = y.end (); j > y.begin () - 1; j -= 1)
284	{
285	  for (I<T> k = z.end () - 4; k >= z.begin () + 3; k--)
286	    if (omp_get_num_threads () == 8
287		&& ((3 - *i) * 12 + (-3 - *j) * 4 + (16 - *k)
288		    != (omp_get_thread_num () * 9 + f++)))
289	      n++;
290	    else
291	      m++;
292	}
293  if (n || m != 72)
294    abort ();
295}
296
297template <typename S, typename T>
298void
299f9 (J<T> x, J<T> y, J<T> z)
300{
301  S i, j, k, o = y.begin ();
302  T l, f = 0, n = 0, m = 0;
303#pragma omp parallel shared (i, j, k, l) firstprivate (f) \
304		     reduction (+:n, m) num_threads (8)
305  {
306  #pragma omp for lastprivate (i, j, k, l) schedule (static, 9) \
307		  collapse (4)
308    for (i = x.begin (); i < x.end (); ++i)
309      for (j = y.begin (); j <= y.end (); j += 1)
310	for (l = *o; l <= *o; l = 1 + l)
311	  for (k = z.begin () + 3; k < z.end () - 3; k++)
312	    if (omp_get_num_threads () == 8
313		&& ((*i + 2) * 12 + (*j + 5) * 4 + (*k - 13)
314		    != (omp_get_thread_num () * 9 + f++)))
315	      n++;
316	    else
317	      m++;
318  }
319  if (n || i != x.end () || j != y.end () + 1 || k != z.end () - 3
320      || m != 72 || l != *o + 1)
321    abort ();
322}
323
324template <typename S, typename T>
325void
326f10 (J<T> x, J<T> y, J<T> z)
327{
328  T f = 0, n = 0, m = 0;
329#pragma omp parallel for firstprivate (f) reduction (+:n, m) \
330			 num_threads (8) schedule (static, 9) \
331			 collapse (6 - 2)
332  for (S i = x.end () - 1; i >= x.begin (); --i)
333    for (T l = 0; l < 1; l++)
334      for (S j = y.end (); j > y.begin () - 1; j -= 1)
335	{
336	  for (S k = z.end () - 4; k >= z.begin () + 3; k--)
337	    if (omp_get_num_threads () == 8
338		&& ((3 - *i) * 12 + (-3 - *j) * 4 + (16 - *k)
339		    != (omp_get_thread_num () * 9 + f++)))
340	      n++;
341	    else
342	      m++;
343	}
344  if (n || m != 72)
345    abort ();
346}
347
348int
349main ()
350{
351  int a[2000];
352  long b[2000];
353  for (int i = 0; i < 2000; i++)
354    {
355      a[i] = i - 1000;
356      b[i] = i - 1000;
357    }
358  J<int> x (&a[998], &a[1004]);
359  J<int> y (&a[995], &a[997]);
360  J<int> z (&a[1010], &a[1020]);
361  f1 (x, y, z);
362  f2 (x, y, z);
363  f3 <int> (x, y, z);
364  f4 <int> (x, y, z);
365  f5 <int> (x, y, z);
366  f6 <int> (x, y, z);
367  f7 <int> (x, y, z);
368  f8 <int> (x, y, z);
369  f9 <I<int>, int> (x, y, z);
370  f10 <I<int>, int> (x, y, z);
371}
372