summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/torture/pr37922.C
blob: a7d05ab0fe87d59b5c037c1fb5be9b22edb43af4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
// { dg-do run }
// { dg-options "-fpic" { target fpic } }

typedef __SIZE_TYPE__ size_t;

template <typename NumType>
inline
NumType
absolute(NumType const& x)
{
  if (x < NumType(0)) return -x;
  return x;
}

class trivial_accessor
{
  public:
    typedef size_t index_type;
    struct index_value_type {};

    trivial_accessor() : size_(0) {}

    trivial_accessor(size_t const& n) : size_(n) {}

    size_t size_1d() const { return size_; }

  protected:
    size_t size_;
};

namespace N0
{
  template <typename ElementType,
            typename AccessorType = trivial_accessor>
  class const_ref
  {
    public:
      typedef ElementType value_type;
      typedef size_t size_type;

      typedef AccessorType accessor_type;
      typedef typename accessor_type::index_type index_type;
      typedef typename accessor_type::index_value_type index_value_type;

      const_ref() {}

      const_ref(const ElementType* begin, accessor_type const& accessor)
      : begin_(begin), accessor_(accessor)
      {
        init();
      }

      const_ref(const ElementType* begin, index_value_type const& n0)
      : begin_(begin), accessor_(n0)
      {
        init();
      }

      const_ref(const ElementType* begin, index_value_type const& n0,
                                          index_value_type const& n1)
      : begin_(begin), accessor_(n0, n1)
      {
        init();
      }

      const_ref(const ElementType* begin, index_value_type const& n0,
                                          index_value_type const& n1,
                                          index_value_type const& n2)
      : begin_(begin), accessor_(n0, n1, n2)
      {
        init();
      }

      accessor_type const& accessor() const { return accessor_; }
      size_type size() const { return size_; }

      const ElementType* begin() const { return begin_; }
      const ElementType* end() const { return end_; }

      ElementType const&
      operator[](size_type i) const { return begin_[i]; }

      const_ref<ElementType>
      as_1d() const
      {
        return const_ref<ElementType>(begin_, size_);
      }

    protected:
      void
      init()
      {
        size_ = accessor_.size_1d();
        end_ = begin_ + size_;
      }

      const ElementType* begin_;
      accessor_type accessor_;
      size_type size_;
      const ElementType* end_;
  };
}

template <typename ElementType,
          typename AccessorType = trivial_accessor>
class ref : public N0::const_ref<ElementType, AccessorType>
{
  public:
    typedef ElementType value_type;
    typedef size_t size_type;

    typedef N0::const_ref<ElementType, AccessorType> base_class;
    typedef AccessorType accessor_type;
    typedef typename accessor_type::index_type index_type;

    ref() {}

    ElementType*
    begin() const { return const_cast<ElementType*>(this->begin_); }

    ElementType*
    end() const { return const_cast<ElementType*>(this->end_); }

    ElementType&
    operator[](size_type i) const { return begin()[i]; }
};

namespace N1 {
  template <typename ElementType, size_t N>
  class tiny_plain
  {
    public:
      typedef ElementType value_type;
      typedef size_t size_type;

      static const size_t fixed_size=N;

      ElementType elems[N];

      tiny_plain() {}

      static size_type size() { return N; }

      ElementType* begin() { return elems; }
      const ElementType* begin() const { return elems; }
      ElementType* end() { return elems+N; }
      const ElementType* end() const { return elems+N; }
      ElementType& operator[](size_type i) { return elems[i]; }
      ElementType const& operator[](size_type i) const { return elems[i]; }
  };

  template <typename ElementType, size_t N>
  class tiny : public tiny_plain<ElementType, N>
  {
    public:
      typedef ElementType value_type;
      typedef size_t size_type;

      typedef tiny_plain<ElementType, N> base_class;

      tiny() {}
  };
}

template <typename NumType>
class mat3 : public N1::tiny_plain<NumType, 9>
{
  public:
    typedef typename N1::tiny_plain<NumType, 9> base_type;

    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)
      : base_type(e00, e01, e02, e10, e11, e12, e20, e21, e22)
    {}
    mat3(base_type const& a)
      : base_type(a)
    {}

    NumType const&
    operator()(size_t r, size_t c) const
    {
      return this->elems[r * 3 + c];
    }
    NumType&
    operator()(size_t r, size_t c)
    {
      return this->elems[r * 3 + c];
    }

    NumType
    trace() const
    {
      mat3 const& m = *this;
      return m[0] + m[4] + m[8];
    }

    NumType
    determinant() const
    {
      mat3 const& m = *this;
      return   m[0] * (m[4] * m[8] - m[5] * m[7])
             - m[1] * (m[3] * m[8] - m[5] * m[6])
             + m[2] * (m[3] * m[7] - m[4] * m[6]);
    }
};

template <typename NumType>
inline
mat3<NumType>
operator-(mat3<NumType> const& v)
{
  mat3<NumType> result;
  for(size_t i=0;i<9;i++) {
    result[i] = -v[i];
  }
  return result;
}

class mat_grid : public N1::tiny<size_t, 2>
{
  public:
    typedef N1::tiny<size_t, 2> index_type;
    typedef index_type::value_type index_value_type;

    mat_grid() { this->elems[0]=0; this->elems[1]=0; }

    mat_grid(index_type const& n) : index_type(n) {}

    mat_grid(index_value_type const& n0, index_value_type const& n1)
    { this->elems[0]=n0; this->elems[1]=n1; }

    size_t size_1d() const { return elems[0] * elems[1]; }

    size_t
    operator()(index_value_type const& r, index_value_type const& c) const
    {
      return r * elems[1] + c;
    }
};

template <typename NumType, typename AccessorType = mat_grid>
class mat_const_ref : public N0::const_ref<NumType, AccessorType>
{
  public:
    typedef AccessorType accessor_type;
    typedef typename N0::const_ref<NumType, AccessorType> base_type;
    typedef typename accessor_type::index_value_type index_value_type;

    mat_const_ref() {}

    mat_const_ref(const NumType* begin, accessor_type const& grid)
    : base_type(begin, grid)
    {}

    mat_const_ref(const NumType* begin, index_value_type const& n_rows,
                                        index_value_type const& n_columns)
    : base_type(begin, accessor_type(n_rows, n_columns))
    {}

    accessor_type
    grid() const { return this->accessor(); }

    index_value_type const&
    n_rows() const { return this->accessor()[0]; }

    index_value_type const&
    n_columns() const { return this->accessor()[1]; }

    NumType const&
    operator()(index_value_type const& r, index_value_type const& c) const
    {
      return this->begin()[this->accessor()(r, c)];
    }
};

template <typename NumType, typename AccessorType = mat_grid>
class mat_ref : public mat_const_ref<NumType, AccessorType>
{
  public:
    typedef AccessorType accessor_type;
    typedef mat_const_ref<NumType, AccessorType> base_type;
    typedef typename accessor_type::index_value_type index_value_type;

    mat_ref() {}

    mat_ref(NumType* begin, accessor_type const& grid)
    : base_type(begin, grid)
    {}

    mat_ref(NumType* begin, index_value_type n_rows,
                            index_value_type n_columns)
    : base_type(begin, accessor_type(n_rows, n_columns))
    {}

    NumType*
    begin() const { return const_cast<NumType*>(this->begin_); }

    NumType*
    end() const { return const_cast<NumType*>(this->end_); }

    NumType&
    operator[](index_value_type const& i) const { return begin()[i]; }

    NumType&
    operator()(index_value_type const& r, index_value_type const& c) const
    {
      return this->begin()[this->accessor()(r, c)];
    }
};

  template <typename AnyType>
  inline void
  swap(AnyType* a, AnyType* b, size_t n)
  {
    for(size_t i=0;i<n;i++) {
      AnyType t = a[i]; a[i] = b[i]; b[i] = t;
    }
  }

template <typename IntType>
size_t
form_t(mat_ref<IntType>& m,
       mat_ref<IntType> const& t)
{
  typedef size_t size_t;
  size_t mr = m.n_rows();
  size_t mc = m.n_columns();
  size_t tc = t.n_columns();
  if (tc) {
  }
  size_t i, j;
  for (i = j = 0; i < mr && j < mc;) {
    size_t k = i; while (k < mr && m(k,j) == 0) k++;
    if (k == mr)
      j++;
    else {
      if (i != k) {
                swap(&m(i,0), &m(k,0), mc);
        if (tc) swap(&t(i,0), &t(k,0), tc);
      }
      for (k++; k < mr; k++) {
        IntType a = absolute(m(k, j));
        if (a != 0 && a < absolute(m(i,j))) {
                  swap(&m(i,0), &m(k,0), mc);
          if (tc) swap(&t(i,0), &t(k,0), tc);
        }
      }
      if (m(i,j) < 0) {
                for(size_t ic=0;ic<mc;ic++) m(i,ic) *= -1;
        if (tc) for(size_t ic=0;ic<tc;ic++) t(i,ic) *= -1;
      }
      bool cleared = true;
      for (k = i+1; k < mr; k++) {
        IntType a = m(k,j) / m(i,j);
        if (a != 0) {
                  for(size_t ic=0;ic<mc;ic++) m(k,ic) -= a * m(i,ic);
          if (tc) for(size_t ic=0;ic<tc;ic++) t(k,ic) -= a * t(i,ic);
        }
        if (m(k,j) != 0) cleared = false;
      }
      if (cleared) { i++; j++; }
    }
  }
  m = mat_ref<IntType>(m.begin(), i, mc);
  return i;
}

template <typename IntType>
size_t
form(mat_ref<IntType>& m)
{
  mat_ref<IntType> t(0,0,0);
  return form_t(m, t);
}

typedef mat3<int> sg_mat3;

class rot_mx
{
  public:
    explicit
    rot_mx(sg_mat3 const& m, int denominator=1)
    : num_(m), den_(denominator)
    {}

    sg_mat3 const&
    num() const { return num_; }
    sg_mat3&
    num()       { return num_; }

    int const&
    operator[](size_t i) const { return num_[i]; }
    int&
    operator[](size_t i)       { return num_[i]; }

    int
    const& operator()(int r, int c) const { return num_(r, c); }
    int&
    operator()(int r, int c)       { return num_(r, c); }

    int const&
    den() const { return den_; }
    int&
    den()       { return den_; }

    rot_mx
    minus_unit_mx() const
    {
      rot_mx result(*this);
      for (size_t i=0;i<9;i+=4) result[i] -= den_;
      return result;
    }

    rot_mx
    operator-() const { return rot_mx(-num_, den_); }

    int
    type() const;

    int
    order(int type=0) const;

  private:
    sg_mat3 num_;
    int den_;
};

class rot_mx_info
{
  public:
    rot_mx_info(rot_mx const& r);

    int type() const { return type_; }

  private:
    int type_;
};

int rot_mx::type() const
{
  int det = num_.determinant();
  if (det == -1 || det == 1) {
    switch (num_.trace()) {
      case -3:                return -1;
      case -2:                return -6;
      case -1: if (det == -1) return -4;
               else           return  2;
      case  0: if (det == -1) return -3;
               else           return  3;
      case  1: if (det == -1) return -2;
               else           return  4;
      case  2:                return  6;
      case  3:                return  1;
    }
  }
  return 0;
}

int rot_mx::order(int type) const
{
  if (type == 0) type = rot_mx::type();
  if (type > 0) return  type;
  if (type % 2) return -type * 2;
                return -type;
}

rot_mx_info::rot_mx_info(rot_mx const& r)
: type_(r.type())
{
  if (type_ == 0) {
    return;
  }
  rot_mx proper_r = r;
  int proper_order = type_;
  // THE PROBLEM IS AROUND HERE
  if (proper_order < 0) {
    proper_order *= -1;
    proper_r = -proper_r; // THIS FAILS ...
  }
  if (proper_order > 1) {
    rot_mx rmi = proper_r.minus_unit_mx(); // ... THEREFORE WRONG HERE
    mat_ref<int> re_mx(rmi.num().begin(), 3, 3);
    if (form(re_mx) != 2) {
      type_ = 0;
    }
  }
}

int main()
{
  N1::tiny<int, 9> e;
  e[0] = 1; e[1] =  0; e[2] = 0;
  e[3] = 0; e[4] = -1; e[5] = 0;
  e[6] = 0; e[7] =  0; e[8] = 1;
  rot_mx r(e);
  rot_mx_info ri(r);
  if (ri.type() != -2)
    __builtin_abort ();
  return 0;
}