1// { dg-do compile }
2// { dg-options "-O3 -g" }
3
4template <typename T>
5T &max (T &a, T &b)
6{
7  if (a < b) return b; else return a;
8}
9int foo (double);
10struct S
11{
12  struct T
13  {
14    int dims, count;
15    T (int, int) : dims (), count () {}
16  };
17  T *rep;
18  S () {}
19  S (int r, int c) : rep (new T (r, c)) {}
20  ~S () { delete rep; }
21};
22template <typename T>
23struct U
24{
25  static T epsilon () throw ();
26};
27template <class T>
28struct V
29{
30  struct W
31  {
32    T * data;
33    int count;
34    W (int n) : data (new T[n]), count () {}
35  };
36  V::W *rep;
37  S dimensions;
38  int slice_len;
39  V (S s) : rep (new V <T>::W (get_size (s))) {}
40  int capacity () { return slice_len; }
41  int get_size (S);
42};
43template <class T>
44struct Z : public V <T>
45{
46  Z () : V <T> (S (0, 0)) {}
47  Z (int r, int c) : V <T> (S (r, c)) {}
48};
49template <class T>
50struct A : public Z <T>
51{
52  A () : Z <T> () {}
53  A (int n, int m) : Z <T> (n, m) {}
54};
55template <class T>
56struct B : public V <T>
57{
58};
59struct C : public A <double>
60{
61  C () : A <double> () {}
62  C (int r, int c) : A <double> (r, c) {}
63};
64struct D : public B <double>
65{
66};
67template <class T>
68struct E
69{
70};
71template <class T>
72struct G : public E <T>
73{
74};
75struct H : public G <double>
76{
77};
78template <class R>
79struct I
80{
81  R scl, sum;
82  void accum (R val)
83  {
84    R t = __builtin_fabs (val);
85    if (scl == t)
86      sum += 1;
87  }
88  operator R () { __builtin_sqrt (sum); return R (); }
89};
90template <class R>
91struct J
92{
93  template < class U > void accum (U val) {}
94  operator R () { return R (); }
95};
96template <class R>
97struct K
98{
99  R max;
100  template <class U> void accum (U val)
101  {
102    double z = __builtin_fabs (val);
103    max = ::max (max, z);
104  }
105  operator R () { return max; }
106};
107template <class R>
108struct L
109{
110  unsigned num;
111  template <class U> void accum (U) {}
112  operator R () { return num; }
113};
114template <class T, class R, class S>
115void bar (V <T> &v, R &res, S acc)
116{
117  for (int i = 0; i < v.capacity (); i++)
118    acc.accum ((i));
119  res = acc;
120}
121template <class T, class R>
122void bar (B <T> &v, R)
123{
124  R res;
125  bar (v, res, I <R> ());
126}
127template <class T, class R>
128R bar (A <T> &v, R p)
129{
130  R res;
131  if (p == 2)
132    bar (v, res, I <R> ());
133  else if (p == 1)
134    bar (v, res, J <R> ());
135  else if (p == sizeof (float) ? (p) : foo (p))
136    {
137      if (p > 0)
138	bar (v, res, K <R> ());
139    }
140  else if (p == 0)
141    bar (v, res, L <R> ());
142  return res;
143}
144template <class CT, class VectorT, class R>
145void
146baz (CT m, R p, R tol, int maxiter, VectorT)
147{
148  VectorT y (0, 0), z (0, 1);
149  R q = 0;
150  R gamma = 0, gamma1 = 0;
151  gamma = bar (y, p);
152  (void) (bar (z, q) <= (gamma1 <= gamma));
153}
154int a = 100;
155template <class CT, class VectorT, class R>
156void
157test (CT m, R p, VectorT)
158{
159  VectorT x;
160  R sqrteps (U <R>::epsilon ());
161  baz (m, p, sqrteps, a, x);
162}
163void
164fn (D x, double p)
165{
166  bar (x, p);
167}
168void
169fn (H x, double p)
170{
171  test (x, p, C ());
172}
173