1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2009 Hauke Heibel <[email protected]>
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 #include "main.h"
11
12 #include <Eigen/Core>
13 #include "AnnoyingScalar.h"
14
15 using namespace Eigen;
16
17 template <typename Scalar, int Storage>
run_matrix_tests()18 void run_matrix_tests()
19 {
20 typedef Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Storage> MatrixType;
21
22 MatrixType m, n;
23
24 // boundary cases ...
25 m = n = MatrixType::Random(50,50);
26 m.conservativeResize(1,50);
27 VERIFY_IS_APPROX(m, n.block(0,0,1,50));
28
29 m = n = MatrixType::Random(50,50);
30 m.conservativeResize(50,1);
31 VERIFY_IS_APPROX(m, n.block(0,0,50,1));
32
33 m = n = MatrixType::Random(50,50);
34 m.conservativeResize(50,50);
35 VERIFY_IS_APPROX(m, n.block(0,0,50,50));
36
37 // random shrinking ...
38 for (int i=0; i<25; ++i)
39 {
40 const Index rows = internal::random<Index>(1,50);
41 const Index cols = internal::random<Index>(1,50);
42 m = n = MatrixType::Random(50,50);
43 m.conservativeResize(rows,cols);
44 VERIFY_IS_APPROX(m, n.block(0,0,rows,cols));
45 }
46
47 // random growing with zeroing ...
48 for (int i=0; i<25; ++i)
49 {
50 const Index rows = internal::random<Index>(50,75);
51 const Index cols = internal::random<Index>(50,75);
52 m = n = MatrixType::Random(50,50);
53 m.conservativeResizeLike(MatrixType::Zero(rows,cols));
54 VERIFY_IS_APPROX(m.block(0,0,n.rows(),n.cols()), n);
55 VERIFY( rows<=50 || m.block(50,0,rows-50,cols).sum() == Scalar(0) );
56 VERIFY( cols<=50 || m.block(0,50,rows,cols-50).sum() == Scalar(0) );
57 }
58 }
59
60 template <typename Scalar>
run_vector_tests()61 void run_vector_tests()
62 {
63 typedef Matrix<Scalar, 1, Eigen::Dynamic> VectorType;
64
65 VectorType m, n;
66
67 // boundary cases ...
68 m = n = VectorType::Random(50);
69 m.conservativeResize(1);
70 VERIFY_IS_APPROX(m, n.segment(0,1));
71
72 m = n = VectorType::Random(50);
73 m.conservativeResize(50);
74 VERIFY_IS_APPROX(m, n.segment(0,50));
75
76 m = n = VectorType::Random(50);
77 m.conservativeResize(m.rows(),1);
78 VERIFY_IS_APPROX(m, n.segment(0,1));
79
80 m = n = VectorType::Random(50);
81 m.conservativeResize(m.rows(),50);
82 VERIFY_IS_APPROX(m, n.segment(0,50));
83
84 // random shrinking ...
85 for (int i=0; i<50; ++i)
86 {
87 const int size = internal::random<int>(1,50);
88 m = n = VectorType::Random(50);
89 m.conservativeResize(size);
90 VERIFY_IS_APPROX(m, n.segment(0,size));
91
92 m = n = VectorType::Random(50);
93 m.conservativeResize(m.rows(), size);
94 VERIFY_IS_APPROX(m, n.segment(0,size));
95 }
96
97 // random growing with zeroing ...
98 for (int i=0; i<50; ++i)
99 {
100 const int size = internal::random<int>(50,100);
101 m = n = VectorType::Random(50);
102 m.conservativeResizeLike(VectorType::Zero(size));
103 VERIFY_IS_APPROX(m.segment(0,50), n);
104 VERIFY( size<=50 || m.segment(50,size-50).sum() == Scalar(0) );
105
106 m = n = VectorType::Random(50);
107 m.conservativeResizeLike(Matrix<Scalar,Dynamic,Dynamic>::Zero(1,size));
108 VERIFY_IS_APPROX(m.segment(0,50), n);
109 VERIFY( size<=50 || m.segment(50,size-50).sum() == Scalar(0) );
110 }
111 }
112
113 // Basic memory leak check with a non-copyable scalar type
noncopyable()114 template<int> void noncopyable()
115 {
116 typedef Eigen::Matrix<AnnoyingScalar,Dynamic,1> VectorType;
117 typedef Eigen::Matrix<AnnoyingScalar,Dynamic,Dynamic> MatrixType;
118
119 {
120 #ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
121 AnnoyingScalar::dont_throw = true;
122 #endif
123 int n = 50;
124 VectorType v0(n), v1(n);
125 MatrixType m0(n,n), m1(n,n), m2(n,n);
126 v0.setOnes(); v1.setOnes();
127 m0.setOnes(); m1.setOnes(); m2.setOnes();
128 VERIFY(m0==m1);
129 m0.conservativeResize(2*n,2*n);
130 VERIFY(m0.topLeftCorner(n,n) == m1);
131
132 VERIFY(v0.head(n) == v1);
133 v0.conservativeResize(2*n);
134 VERIFY(v0.head(n) == v1);
135 }
136 VERIFY(AnnoyingScalar::instances==0 && "global memory leak detected in noncopyable");
137 }
138
EIGEN_DECLARE_TEST(conservative_resize)139 EIGEN_DECLARE_TEST(conservative_resize)
140 {
141 for(int i=0; i<g_repeat; ++i)
142 {
143 CALL_SUBTEST_1((run_matrix_tests<int, Eigen::RowMajor>()));
144 CALL_SUBTEST_1((run_matrix_tests<int, Eigen::ColMajor>()));
145 CALL_SUBTEST_2((run_matrix_tests<float, Eigen::RowMajor>()));
146 CALL_SUBTEST_2((run_matrix_tests<float, Eigen::ColMajor>()));
147 CALL_SUBTEST_3((run_matrix_tests<double, Eigen::RowMajor>()));
148 CALL_SUBTEST_3((run_matrix_tests<double, Eigen::ColMajor>()));
149 CALL_SUBTEST_4((run_matrix_tests<std::complex<float>, Eigen::RowMajor>()));
150 CALL_SUBTEST_4((run_matrix_tests<std::complex<float>, Eigen::ColMajor>()));
151 CALL_SUBTEST_5((run_matrix_tests<std::complex<double>, Eigen::RowMajor>()));
152 CALL_SUBTEST_5((run_matrix_tests<std::complex<double>, Eigen::ColMajor>()));
153 CALL_SUBTEST_1((run_matrix_tests<int, Eigen::RowMajor | Eigen::DontAlign>()));
154
155 CALL_SUBTEST_1((run_vector_tests<int>()));
156 CALL_SUBTEST_2((run_vector_tests<float>()));
157 CALL_SUBTEST_3((run_vector_tests<double>()));
158 CALL_SUBTEST_4((run_vector_tests<std::complex<float> >()));
159 CALL_SUBTEST_5((run_vector_tests<std::complex<double> >()));
160
161 #ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
162 AnnoyingScalar::dont_throw = true;
163 #endif
164 CALL_SUBTEST_6(( run_vector_tests<AnnoyingScalar>() ));
165 CALL_SUBTEST_6(( noncopyable<0>() ));
166 }
167 }
168