1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#define EIGEN_NO_STATIC_ASSERT
11
12#include "main.h"
13
14#undef VERIFY_IS_APPROX
15#define VERIFY_IS_APPROX(a, b) VERIFY((a)==(b));
16#undef VERIFY_IS_NOT_APPROX
17#define VERIFY_IS_NOT_APPROX(a, b) VERIFY((a)!=(b));
18
19template<typename MatrixType> void signed_integer_type_tests(const MatrixType& m)
20{
21  typedef typename MatrixType::Index Index;
22  typedef typename MatrixType::Scalar Scalar;
23
24  enum { is_signed = (Scalar(-1) > Scalar(0)) ? 0 : 1 };
25  VERIFY(is_signed == 1);
26
27  Index rows = m.rows();
28  Index cols = m.cols();
29
30  MatrixType m1(rows, cols),
31             m2 = MatrixType::Random(rows, cols),
32             mzero = MatrixType::Zero(rows, cols);
33
34  do {
35    m1 = MatrixType::Random(rows, cols);
36  } while(m1 == mzero || m1 == m2);
37
38  // check linear structure
39
40  Scalar s1;
41  do {
42    s1 = internal::random<Scalar>();
43  } while(s1 == 0);
44
45  VERIFY_IS_EQUAL(-(-m1),                  m1);
46  VERIFY_IS_EQUAL(-m2+m1+m2,               m1);
47  VERIFY_IS_EQUAL((-m1+m2)*s1,             -s1*m1+s1*m2);
48}
49
50template<typename MatrixType> void integer_type_tests(const MatrixType& m)
51{
52  typedef typename MatrixType::Index Index;
53  typedef typename MatrixType::Scalar Scalar;
54
55  VERIFY(NumTraits<Scalar>::IsInteger);
56  enum { is_signed = (Scalar(-1) > Scalar(0)) ? 0 : 1 };
57  VERIFY(int(NumTraits<Scalar>::IsSigned) == is_signed);
58
59  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
60
61  Index rows = m.rows();
62  Index cols = m.cols();
63
64  // this test relies a lot on Random.h, and there's not much more that we can do
65  // to test it, hence I consider that we will have tested Random.h
66  MatrixType m1(rows, cols),
67             m2 = MatrixType::Random(rows, cols),
68             m3(rows, cols),
69             mzero = MatrixType::Zero(rows, cols);
70
71  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
72  SquareMatrixType identity = SquareMatrixType::Identity(rows, rows),
73                   square = SquareMatrixType::Random(rows, rows);
74  VectorType v1(rows),
75             v2 = VectorType::Random(rows),
76             vzero = VectorType::Zero(rows);
77
78  do {
79    m1 = MatrixType::Random(rows, cols);
80  } while(m1 == mzero || m1 == m2);
81
82  do {
83    v1 = VectorType::Random(rows);
84  } while(v1 == vzero || v1 == v2);
85
86  VERIFY_IS_APPROX(               v1,    v1);
87  VERIFY_IS_NOT_APPROX(           v1,    2*v1);
88  VERIFY_IS_APPROX(               vzero, v1-v1);
89  VERIFY_IS_APPROX(               m1,    m1);
90  VERIFY_IS_NOT_APPROX(           m1,    2*m1);
91  VERIFY_IS_APPROX(               mzero, m1-m1);
92
93  VERIFY_IS_APPROX(m3 = m1,m1);
94  MatrixType m4;
95  VERIFY_IS_APPROX(m4 = m1,m1);
96
97  m3.real() = m1.real();
98  VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), static_cast<const MatrixType&>(m1).real());
99  VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), m1.real());
100
101  // check == / != operators
102  VERIFY(m1==m1);
103  VERIFY(m1!=m2);
104  VERIFY(!(m1==m2));
105  VERIFY(!(m1!=m1));
106  m1 = m2;
107  VERIFY(m1==m2);
108  VERIFY(!(m1!=m2));
109
110  // check linear structure
111
112  Scalar s1;
113  do {
114    s1 = internal::random<Scalar>();
115  } while(s1 == 0);
116
117  VERIFY_IS_EQUAL(m1+m1,                   2*m1);
118  VERIFY_IS_EQUAL(m1+m2-m1,                m2);
119  VERIFY_IS_EQUAL(m1*s1,                   s1*m1);
120  VERIFY_IS_EQUAL((m1+m2)*s1,              s1*m1+s1*m2);
121  m3 = m2; m3 += m1;
122  VERIFY_IS_EQUAL(m3,                      m1+m2);
123  m3 = m2; m3 -= m1;
124  VERIFY_IS_EQUAL(m3,                      m2-m1);
125  m3 = m2; m3 *= s1;
126  VERIFY_IS_EQUAL(m3,                      s1*m2);
127
128  // check matrix product.
129
130  VERIFY_IS_APPROX(identity * m1, m1);
131  VERIFY_IS_APPROX(square * (m1 + m2), square * m1 + square * m2);
132  VERIFY_IS_APPROX((m1 + m2).transpose() * square, m1.transpose() * square + m2.transpose() * square);
133  VERIFY_IS_APPROX((m1 * m2.transpose()) * m1, m1 * (m2.transpose() * m1));
134}
135
136void test_integer_types()
137{
138  for(int i = 0; i < g_repeat; i++) {
139    CALL_SUBTEST_1( integer_type_tests(Matrix<unsigned int, 1, 1>()) );
140    CALL_SUBTEST_1( integer_type_tests(Matrix<unsigned long, 3, 4>()) );
141
142    CALL_SUBTEST_2( integer_type_tests(Matrix<long, 2, 2>()) );
143    CALL_SUBTEST_2( signed_integer_type_tests(Matrix<long, 2, 2>()) );
144
145    CALL_SUBTEST_3( integer_type_tests(Matrix<char, 2, Dynamic>(2, 10)) );
146    CALL_SUBTEST_3( signed_integer_type_tests(Matrix<signed char, 2, Dynamic>(2, 10)) );
147
148    CALL_SUBTEST_4( integer_type_tests(Matrix<unsigned char, 3, 3>()) );
149    CALL_SUBTEST_4( integer_type_tests(Matrix<unsigned char, Dynamic, Dynamic>(20, 20)) );
150
151    CALL_SUBTEST_5( integer_type_tests(Matrix<short, Dynamic, 4>(7, 4)) );
152    CALL_SUBTEST_5( signed_integer_type_tests(Matrix<short, Dynamic, 4>(7, 4)) );
153
154    CALL_SUBTEST_6( integer_type_tests(Matrix<unsigned short, 4, 4>()) );
155
156    CALL_SUBTEST_7( integer_type_tests(Matrix<long long, 11, 13>()) );
157    CALL_SUBTEST_7( signed_integer_type_tests(Matrix<long long, 11, 13>()) );
158
159    CALL_SUBTEST_8( integer_type_tests(Matrix<unsigned long long, Dynamic, 5>(1, 5)) );
160  }
161}
162