1// { dg-do run }
2// { dg-options "-fpic" { target fpic } }
3
4typedef __SIZE_TYPE__ size_t;
5
6template <typename NumType>
7inline
8NumType
9absolute(NumType const& x)
10{
11  if (x < NumType(0)) return -x;
12  return x;
13}
14
15class trivial_accessor
16{
17  public:
18    typedef size_t index_type;
19    struct index_value_type {};
20
21    trivial_accessor() : size_(0) {}
22
23    trivial_accessor(size_t const& n) : size_(n) {}
24
25    size_t size_1d() const { return size_; }
26
27  protected:
28    size_t size_;
29};
30
31namespace N0
32{
33  template <typename ElementType,
34            typename AccessorType = trivial_accessor>
35  class const_ref
36  {
37    public:
38      typedef ElementType value_type;
39      typedef size_t size_type;
40
41      typedef AccessorType accessor_type;
42      typedef typename accessor_type::index_type index_type;
43      typedef typename accessor_type::index_value_type index_value_type;
44
45      const_ref() {}
46
47      const_ref(const ElementType* begin, accessor_type const& accessor)
48      : begin_(begin), accessor_(accessor)
49      {
50        init();
51      }
52
53      const_ref(const ElementType* begin, index_value_type const& n0)
54      : begin_(begin), accessor_(n0)
55      {
56        init();
57      }
58
59      const_ref(const ElementType* begin, index_value_type const& n0,
60                                          index_value_type const& n1)
61      : begin_(begin), accessor_(n0, n1)
62      {
63        init();
64      }
65
66      const_ref(const ElementType* begin, index_value_type const& n0,
67                                          index_value_type const& n1,
68                                          index_value_type const& n2)
69      : begin_(begin), accessor_(n0, n1, n2)
70      {
71        init();
72      }
73
74      accessor_type const& accessor() const { return accessor_; }
75      size_type size() const { return size_; }
76
77      const ElementType* begin() const { return begin_; }
78      const ElementType* end() const { return end_; }
79
80      ElementType const&
81      operator[](size_type i) const { return begin_[i]; }
82
83      const_ref<ElementType>
84      as_1d() const
85      {
86        return const_ref<ElementType>(begin_, size_);
87      }
88
89    protected:
90      void
91      init()
92      {
93        size_ = accessor_.size_1d();
94        end_ = begin_ + size_;
95      }
96
97      const ElementType* begin_;
98      accessor_type accessor_;
99      size_type size_;
100      const ElementType* end_;
101  };
102}
103
104template <typename ElementType,
105          typename AccessorType = trivial_accessor>
106class ref : public N0::const_ref<ElementType, AccessorType>
107{
108  public:
109    typedef ElementType value_type;
110    typedef size_t size_type;
111
112    typedef N0::const_ref<ElementType, AccessorType> base_class;
113    typedef AccessorType accessor_type;
114    typedef typename accessor_type::index_type index_type;
115
116    ref() {}
117
118    ElementType*
119    begin() const { return const_cast<ElementType*>(this->begin_); }
120
121    ElementType*
122    end() const { return const_cast<ElementType*>(this->end_); }
123
124    ElementType&
125    operator[](size_type i) const { return begin()[i]; }
126};
127
128namespace N1 {
129  template <typename ElementType, size_t N>
130  class tiny_plain
131  {
132    public:
133      typedef ElementType value_type;
134      typedef size_t size_type;
135
136      static const size_t fixed_size=N;
137
138      ElementType elems[N];
139
140      tiny_plain() {}
141
142      static size_type size() { return N; }
143
144      ElementType* begin() { return elems; }
145      const ElementType* begin() const { return elems; }
146      ElementType* end() { return elems+N; }
147      const ElementType* end() const { return elems+N; }
148      ElementType& operator[](size_type i) { return elems[i]; }
149      ElementType const& operator[](size_type i) const { return elems[i]; }
150  };
151
152  template <typename ElementType, size_t N>
153  class tiny : public tiny_plain<ElementType, N>
154  {
155    public:
156      typedef ElementType value_type;
157      typedef size_t size_type;
158
159      typedef tiny_plain<ElementType, N> base_class;
160
161      tiny() {}
162  };
163}
164
165template <typename NumType>
166class mat3 : public N1::tiny_plain<NumType, 9>
167{
168  public:
169    typedef typename N1::tiny_plain<NumType, 9> base_type;
170
171    mat3() {}
172    mat3(NumType const& e00, NumType const& e01, NumType const& e02,
173         NumType const& e10, NumType const& e11, NumType const& e12,
174         NumType const& e20, NumType const& e21, NumType const& e22)
175      : base_type(e00, e01, e02, e10, e11, e12, e20, e21, e22)
176    {}
177    mat3(base_type const& a)
178      : base_type(a)
179    {}
180
181    NumType const&
182    operator()(size_t r, size_t c) const
183    {
184      return this->elems[r * 3 + c];
185    }
186    NumType&
187    operator()(size_t r, size_t c)
188    {
189      return this->elems[r * 3 + c];
190    }
191
192    NumType
193    trace() const
194    {
195      mat3 const& m = *this;
196      return m[0] + m[4] + m[8];
197    }
198
199    NumType
200    determinant() const
201    {
202      mat3 const& m = *this;
203      return   m[0] * (m[4] * m[8] - m[5] * m[7])
204             - m[1] * (m[3] * m[8] - m[5] * m[6])
205             + m[2] * (m[3] * m[7] - m[4] * m[6]);
206    }
207};
208
209template <typename NumType>
210inline
211mat3<NumType>
212operator-(mat3<NumType> const& v)
213{
214  mat3<NumType> result;
215  for(size_t i=0;i<9;i++) {
216    result[i] = -v[i];
217  }
218  return result;
219}
220
221class mat_grid : public N1::tiny<size_t, 2>
222{
223  public:
224    typedef N1::tiny<size_t, 2> index_type;
225    typedef index_type::value_type index_value_type;
226
227    mat_grid() { this->elems[0]=0; this->elems[1]=0; }
228
229    mat_grid(index_type const& n) : index_type(n) {}
230
231    mat_grid(index_value_type const& n0, index_value_type const& n1)
232    { this->elems[0]=n0; this->elems[1]=n1; }
233
234    size_t size_1d() const { return elems[0] * elems[1]; }
235
236    size_t
237    operator()(index_value_type const& r, index_value_type const& c) const
238    {
239      return r * elems[1] + c;
240    }
241};
242
243template <typename NumType, typename AccessorType = mat_grid>
244class mat_const_ref : public N0::const_ref<NumType, AccessorType>
245{
246  public:
247    typedef AccessorType accessor_type;
248    typedef typename N0::const_ref<NumType, AccessorType> base_type;
249    typedef typename accessor_type::index_value_type index_value_type;
250
251    mat_const_ref() {}
252
253    mat_const_ref(const NumType* begin, accessor_type const& grid)
254    : base_type(begin, grid)
255    {}
256
257    mat_const_ref(const NumType* begin, index_value_type const& n_rows,
258                                        index_value_type const& n_columns)
259    : base_type(begin, accessor_type(n_rows, n_columns))
260    {}
261
262    accessor_type
263    grid() const { return this->accessor(); }
264
265    index_value_type const&
266    n_rows() const { return this->accessor()[0]; }
267
268    index_value_type const&
269    n_columns() const { return this->accessor()[1]; }
270
271    NumType const&
272    operator()(index_value_type const& r, index_value_type const& c) const
273    {
274      return this->begin()[this->accessor()(r, c)];
275    }
276};
277
278template <typename NumType, typename AccessorType = mat_grid>
279class mat_ref : public mat_const_ref<NumType, AccessorType>
280{
281  public:
282    typedef AccessorType accessor_type;
283    typedef mat_const_ref<NumType, AccessorType> base_type;
284    typedef typename accessor_type::index_value_type index_value_type;
285
286    mat_ref() {}
287
288    mat_ref(NumType* begin, accessor_type const& grid)
289    : base_type(begin, grid)
290    {}
291
292    mat_ref(NumType* begin, index_value_type n_rows,
293                            index_value_type n_columns)
294    : base_type(begin, accessor_type(n_rows, n_columns))
295    {}
296
297    NumType*
298    begin() const { return const_cast<NumType*>(this->begin_); }
299
300    NumType*
301    end() const { return const_cast<NumType*>(this->end_); }
302
303    NumType&
304    operator[](index_value_type const& i) const { return begin()[i]; }
305
306    NumType&
307    operator()(index_value_type const& r, index_value_type const& c) const
308    {
309      return this->begin()[this->accessor()(r, c)];
310    }
311};
312
313  template <typename AnyType>
314  inline void
315  swap(AnyType* a, AnyType* b, size_t n)
316  {
317    for(size_t i=0;i<n;i++) {
318      AnyType t = a[i]; a[i] = b[i]; b[i] = t;
319    }
320  }
321
322template <typename IntType>
323size_t
324form_t(mat_ref<IntType>& m,
325       mat_ref<IntType> const& t)
326{
327  typedef size_t size_t;
328  size_t mr = m.n_rows();
329  size_t mc = m.n_columns();
330  size_t tc = t.n_columns();
331  if (tc) {
332  }
333  size_t i, j;
334  for (i = j = 0; i < mr && j < mc;) {
335    size_t k = i; while (k < mr && m(k,j) == 0) k++;
336    if (k == mr)
337      j++;
338    else {
339      if (i != k) {
340                swap(&m(i,0), &m(k,0), mc);
341        if (tc) swap(&t(i,0), &t(k,0), tc);
342      }
343      for (k++; k < mr; k++) {
344        IntType a = absolute(m(k, j));
345        if (a != 0 && a < absolute(m(i,j))) {
346                  swap(&m(i,0), &m(k,0), mc);
347          if (tc) swap(&t(i,0), &t(k,0), tc);
348        }
349      }
350      if (m(i,j) < 0) {
351                for(size_t ic=0;ic<mc;ic++) m(i,ic) *= -1;
352        if (tc) for(size_t ic=0;ic<tc;ic++) t(i,ic) *= -1;
353      }
354      bool cleared = true;
355      for (k = i+1; k < mr; k++) {
356        IntType a = m(k,j) / m(i,j);
357        if (a != 0) {
358                  for(size_t ic=0;ic<mc;ic++) m(k,ic) -= a * m(i,ic);
359          if (tc) for(size_t ic=0;ic<tc;ic++) t(k,ic) -= a * t(i,ic);
360        }
361        if (m(k,j) != 0) cleared = false;
362      }
363      if (cleared) { i++; j++; }
364    }
365  }
366  m = mat_ref<IntType>(m.begin(), i, mc);
367  return i;
368}
369
370template <typename IntType>
371size_t
372form(mat_ref<IntType>& m)
373{
374  mat_ref<IntType> t(0,0,0);
375  return form_t(m, t);
376}
377
378typedef mat3<int> sg_mat3;
379
380class rot_mx
381{
382  public:
383    explicit
384    rot_mx(sg_mat3 const& m, int denominator=1)
385    : num_(m), den_(denominator)
386    {}
387
388    sg_mat3 const&
389    num() const { return num_; }
390    sg_mat3&
391    num()       { return num_; }
392
393    int const&
394    operator[](size_t i) const { return num_[i]; }
395    int&
396    operator[](size_t i)       { return num_[i]; }
397
398    int
399    const& operator()(int r, int c) const { return num_(r, c); }
400    int&
401    operator()(int r, int c)       { return num_(r, c); }
402
403    int const&
404    den() const { return den_; }
405    int&
406    den()       { return den_; }
407
408    rot_mx
409    minus_unit_mx() const
410    {
411      rot_mx result(*this);
412      for (size_t i=0;i<9;i+=4) result[i] -= den_;
413      return result;
414    }
415
416    rot_mx
417    operator-() const { return rot_mx(-num_, den_); }
418
419    int
420    type() const;
421
422    int
423    order(int type=0) const;
424
425  private:
426    sg_mat3 num_;
427    int den_;
428};
429
430class rot_mx_info
431{
432  public:
433    rot_mx_info(rot_mx const& r);
434
435    int type() const { return type_; }
436
437  private:
438    int type_;
439};
440
441int rot_mx::type() const
442{
443  int det = num_.determinant();
444  if (det == -1 || det == 1) {
445    switch (num_.trace()) {
446      case -3:                return -1;
447      case -2:                return -6;
448      case -1: if (det == -1) return -4;
449               else           return  2;
450      case  0: if (det == -1) return -3;
451               else           return  3;
452      case  1: if (det == -1) return -2;
453               else           return  4;
454      case  2:                return  6;
455      case  3:                return  1;
456    }
457  }
458  return 0;
459}
460
461int rot_mx::order(int type) const
462{
463  if (type == 0) type = rot_mx::type();
464  if (type > 0) return  type;
465  if (type % 2) return -type * 2;
466                return -type;
467}
468
469rot_mx_info::rot_mx_info(rot_mx const& r)
470: type_(r.type())
471{
472  if (type_ == 0) {
473    return;
474  }
475  rot_mx proper_r = r;
476  int proper_order = type_;
477  // THE PROBLEM IS AROUND HERE
478  if (proper_order < 0) {
479    proper_order *= -1;
480    proper_r = -proper_r; // THIS FAILS ...
481  }
482  if (proper_order > 1) {
483    rot_mx rmi = proper_r.minus_unit_mx(); // ... THEREFORE WRONG HERE
484    mat_ref<int> re_mx(rmi.num().begin(), 3, 3);
485    if (form(re_mx) != 2) {
486      type_ = 0;
487    }
488  }
489}
490
491int main()
492{
493  N1::tiny<int, 9> e;
494  e[0] = 1; e[1] =  0; e[2] = 0;
495  e[3] = 0; e[4] = -1; e[5] = 0;
496  e[6] = 0; e[7] =  0; e[8] = 1;
497  rot_mx r(e);
498  rot_mx_info ri(r);
499  if (ri.type() != -2)
500    __builtin_abort ();
501  return 0;
502}
503