1 // { dg-do run }
2 // { dg-options "-fpic" { target fpic } }
3 
4 typedef __SIZE_TYPE__ size_t;
5 
6 template <typename NumType>
7 inline
8 NumType
absolute(NumType const & x)9 absolute(NumType const& x)
10 {
11   if (x < NumType(0)) return -x;
12   return x;
13 }
14 
15 class trivial_accessor
16 {
17   public:
18     typedef size_t index_type;
19     struct index_value_type {};
20 
trivial_accessor()21     trivial_accessor() : size_(0) {}
22 
trivial_accessor(size_t const & n)23     trivial_accessor(size_t const& n) : size_(n) {}
24 
size_1d()25     size_t size_1d() const { return size_; }
26 
27   protected:
28     size_t size_;
29 };
30 
31 namespace 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 
const_ref()45       const_ref() {}
46 
const_ref(const ElementType * begin,accessor_type const & accessor)47       const_ref(const ElementType* begin, accessor_type const& accessor)
48       : begin_(begin), accessor_(accessor)
49       {
50         init();
51       }
52 
const_ref(const ElementType * begin,index_value_type const & n0)53       const_ref(const ElementType* begin, index_value_type const& n0)
54       : begin_(begin), accessor_(n0)
55       {
56         init();
57       }
58 
const_ref(const ElementType * begin,index_value_type const & n0,index_value_type const & n1)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 
const_ref(const ElementType * begin,index_value_type const & n0,index_value_type const & n1,index_value_type const & n2)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 
accessor()74       accessor_type const& accessor() const { return accessor_; }
size()75       size_type size() const { return size_; }
76 
begin()77       const ElementType* begin() const { return begin_; }
end()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>
as_1d()84       as_1d() const
85       {
86         return const_ref<ElementType>(begin_, size_);
87       }
88 
89     protected:
90       void
init()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 
104 template <typename ElementType,
105           typename AccessorType = trivial_accessor>
106 class 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 
ref()116     ref() {}
117 
118     ElementType*
begin()119     begin() const { return const_cast<ElementType*>(this->begin_); }
120 
121     ElementType*
end()122     end() const { return const_cast<ElementType*>(this->end_); }
123 
124     ElementType&
125     operator[](size_type i) const { return begin()[i]; }
126 };
127 
128 namespace 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 
tiny_plain()140       tiny_plain() {}
141 
size()142       static size_type size() { return N; }
143 
begin()144       ElementType* begin() { return elems; }
begin()145       const ElementType* begin() const { return elems; }
end()146       ElementType* end() { return elems+N; }
end()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 
tiny()161       tiny() {}
162   };
163 }
164 
165 template <typename NumType>
166 class mat3 : public N1::tiny_plain<NumType, 9>
167 {
168   public:
169     typedef typename N1::tiny_plain<NumType, 9> base_type;
170 
mat3()171     mat3() {}
mat3(NumType const & e00,NumType const & e01,NumType const & e02,NumType const & e10,NumType const & e11,NumType const & e12,NumType const & e20,NumType const & e21,NumType const & e22)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     {}
mat3(base_type const & a)177     mat3(base_type const& a)
178       : base_type(a)
179     {}
180 
181     NumType const&
operator()182     operator()(size_t r, size_t c) const
183     {
184       return this->elems[r * 3 + c];
185     }
186     NumType&
operator()187     operator()(size_t r, size_t c)
188     {
189       return this->elems[r * 3 + c];
190     }
191 
192     NumType
trace()193     trace() const
194     {
195       mat3 const& m = *this;
196       return m[0] + m[4] + m[8];
197     }
198 
199     NumType
determinant()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 
209 template <typename NumType>
210 inline
211 mat3<NumType>
212 operator-(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 
221 class 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 
mat_grid()227     mat_grid() { this->elems[0]=0; this->elems[1]=0; }
228 
mat_grid(index_type const & n)229     mat_grid(index_type const& n) : index_type(n) {}
230 
mat_grid(index_value_type const & n0,index_value_type const & n1)231     mat_grid(index_value_type const& n0, index_value_type const& n1)
232     { this->elems[0]=n0; this->elems[1]=n1; }
233 
size_1d()234     size_t size_1d() const { return elems[0] * elems[1]; }
235 
236     size_t
operator()237     operator()(index_value_type const& r, index_value_type const& c) const
238     {
239       return r * elems[1] + c;
240     }
241 };
242 
243 template <typename NumType, typename AccessorType = mat_grid>
244 class 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 
mat_const_ref()251     mat_const_ref() {}
252 
mat_const_ref(const NumType * begin,accessor_type const & grid)253     mat_const_ref(const NumType* begin, accessor_type const& grid)
254     : base_type(begin, grid)
255     {}
256 
mat_const_ref(const NumType * begin,index_value_type const & n_rows,index_value_type const & n_columns)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
grid()263     grid() const { return this->accessor(); }
264 
265     index_value_type const&
n_rows()266     n_rows() const { return this->accessor()[0]; }
267 
268     index_value_type const&
n_columns()269     n_columns() const { return this->accessor()[1]; }
270 
271     NumType const&
operator()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 
278 template <typename NumType, typename AccessorType = mat_grid>
279 class 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 
mat_ref()286     mat_ref() {}
287 
mat_ref(NumType * begin,accessor_type const & grid)288     mat_ref(NumType* begin, accessor_type const& grid)
289     : base_type(begin, grid)
290     {}
291 
mat_ref(NumType * begin,index_value_type n_rows,index_value_type n_columns)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*
begin()298     begin() const { return const_cast<NumType*>(this->begin_); }
299 
300     NumType*
end()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&
operator()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
swap(AnyType * a,AnyType * b,size_t n)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 
322 template <typename IntType>
323 size_t
form_t(mat_ref<IntType> & m,mat_ref<IntType> const & t)324 form_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 
370 template <typename IntType>
371 size_t
form(mat_ref<IntType> & m)372 form(mat_ref<IntType>& m)
373 {
374   mat_ref<IntType> t(0,0,0);
375   return form_t(m, t);
376 }
377 
378 typedef mat3<int> sg_mat3;
379 
380 class rot_mx
381 {
382   public:
383     explicit
384     rot_mx(sg_mat3 const& m, int denominator=1)
num_(m)385     : num_(m), den_(denominator)
386     {}
387 
388     sg_mat3 const&
num()389     num() const { return num_; }
390     sg_mat3&
num()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
operator()399     const& operator()(int r, int c) const { return num_(r, c); }
400     int&
operator()401     operator()(int r, int c)       { return num_(r, c); }
402 
403     int const&
den()404     den() const { return den_; }
405     int&
den()406     den()       { return den_; }
407 
408     rot_mx
minus_unit_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 
430 class rot_mx_info
431 {
432   public:
433     rot_mx_info(rot_mx const& r);
434 
type()435     int type() const { return type_; }
436 
437   private:
438     int type_;
439 };
440 
type()441 int 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 
order(int type)461 int 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 
rot_mx_info(rot_mx const & r)469 rot_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 
main()491 int 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