blob: a7d05ab0fe87d59b5c037c1fb5be9b22edb43af4 [file] [log] [blame]
// { 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;
}