blob: d466b51dadecb1d85ba8fb5fade32547657592fe [file] [log] [blame]
Gael Guennebaud86ccd992008-11-05 13:47:55 +00001// This file is part of Eigen, a lightweight C++ template library
Benoit Jacob6347b1d2009-05-22 20:25:33 +02002// for linear algebra.
Gael Guennebaud86ccd992008-11-05 13:47:55 +00003//
Gael Guennebaud22c76092011-03-22 11:58:22 +01004// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
Gael Guennebaud86ccd992008-11-05 13:47:55 +00005// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
Desire NUENTSA4cd82452013-06-11 14:42:29 +02006// Copyright (C) 2013 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
Gael Guennebaud86ccd992008-11-05 13:47:55 +00007//
Benoit Jacob69124cf2012-07-13 14:42:47 -04008// This Source Code Form is subject to the terms of the Mozilla
9// Public License v. 2.0. If a copy of the MPL was not distributed
10// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
Gael Guennebaud86ccd992008-11-05 13:47:55 +000011
12#include "sparse.h"
13
Gael Guennebaud178858f2009-01-19 15:20:45 +000014template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& ref)
15{
Hauke Heibelf1679c72010-06-20 17:37:56 +020016 typedef typename SparseMatrixType::Index Index;
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +020017 typedef Matrix<Index,2,1> Vector2;
18
Hauke Heibelf1679c72010-06-20 17:37:56 +020019 const Index rows = ref.rows();
20 const Index cols = ref.cols();
Gael Guennebaud178858f2009-01-19 15:20:45 +000021 typedef typename SparseMatrixType::Scalar Scalar;
22 enum { Flags = SparseMatrixType::Flags };
Gael Guennebaud9f795582009-12-16 19:18:40 +010023
Gael Guennebaud42e25782011-08-19 14:18:05 +020024 double density = (std::max)(8./(rows*cols), 0.01);
Gael Guennebaud86ccd992008-11-05 13:47:55 +000025 typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
26 typedef Matrix<Scalar,Dynamic,1> DenseVector;
27 Scalar eps = 1e-6;
28
Benoit Jacob47160402010-10-25 10:15:22 -040029 Scalar s1 = internal::random<Scalar>();
Gael Guennebaud86ccd992008-11-05 13:47:55 +000030 {
Gael Guennebaudd1d7a1a2013-06-23 19:11:32 +020031 SparseMatrixType m(rows, cols);
32 DenseMatrix refMat = DenseMatrix::Zero(rows, cols);
33 DenseVector vec1 = DenseVector::Random(rows);
Gael Guennebaud86ccd992008-11-05 13:47:55 +000034
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +020035 std::vector<Vector2> zeroCoords;
36 std::vector<Vector2> nonzeroCoords;
Gael Guennebaudd1d7a1a2013-06-23 19:11:32 +020037 initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords);
Gael Guennebaud86ccd992008-11-05 13:47:55 +000038
Gael Guennebaudd1d7a1a2013-06-23 19:11:32 +020039 if (zeroCoords.size()==0 || nonzeroCoords.size()==0)
40 return;
Gael Guennebaud86ccd992008-11-05 13:47:55 +000041
Gael Guennebaudd1d7a1a2013-06-23 19:11:32 +020042 // test coeff and coeffRef
43 for (int i=0; i<(int)zeroCoords.size(); ++i)
Gael Guennebaud86ccd992008-11-05 13:47:55 +000044 {
Gael Guennebaudd1d7a1a2013-06-23 19:11:32 +020045 VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps );
46 if(internal::is_same<SparseMatrixType,SparseMatrix<Scalar,Flags> >::value)
47 VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[0].x(),zeroCoords[0].y()) = 5 );
Gael Guennebaud86ccd992008-11-05 13:47:55 +000048 }
Gael Guennebaudd1d7a1a2013-06-23 19:11:32 +020049 VERIFY_IS_APPROX(m, refMat);
Gael Guennebaud86ccd992008-11-05 13:47:55 +000050
Gael Guennebaudd1d7a1a2013-06-23 19:11:32 +020051 m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
52 refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
Gael Guennebaud86ccd992008-11-05 13:47:55 +000053
Gael Guennebaudd1d7a1a2013-06-23 19:11:32 +020054 VERIFY_IS_APPROX(m, refMat);
55 /*
56 // test InnerIterators and Block expressions
57 for (int t=0; t<10; ++t)
58 {
59 int j = internal::random<int>(0,cols-1);
60 int i = internal::random<int>(0,rows-1);
61 int w = internal::random<int>(1,cols-j-1);
62 int h = internal::random<int>(1,rows-i-1);
63
64 // VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w));
65 for(int c=0; c<w; c++)
66 {
67 VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c));
68 for(int r=0; r<h; r++)
69 {
70 // VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r));
71 }
72 }
73 // for(int r=0; r<h; r++)
74 // {
75 // VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r));
76 // for(int c=0; c<w; c++)
77 // {
78 // VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c));
79 // }
80 // }
81 }
82
83 for(int c=0; c<cols; c++)
84 {
85 VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c));
86 VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c));
87 }
88
89 for(int r=0; r<rows; r++)
90 {
91 VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r));
92 VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r));
93 }
94 */
Gael Guennebauda915f022013-06-28 16:16:02 +020095
96 // test assertion
97 VERIFY_RAISES_ASSERT( m.coeffRef(-1,1) = 0 );
98 VERIFY_RAISES_ASSERT( m.coeffRef(0,m.cols()) = 0 );
Gael Guennebaudd1d7a1a2013-06-23 19:11:32 +020099 }
Gael Guennebaud86ccd992008-11-05 13:47:55 +0000100
Gael Guennebaud28293142009-05-04 14:25:12 +0000101 // test insert (inner random)
Gael Guennebaud5015e482008-12-11 18:26:24 +0000102 {
103 DenseMatrix m1(rows,cols);
104 m1.setZero();
Gael Guennebaud178858f2009-01-19 15:20:45 +0000105 SparseMatrixType m2(rows,cols);
Gael Guennebaud4ca89f32011-12-02 19:00:16 +0100106 if(internal::random<int>()%2)
107 m2.reserve(VectorXi::Constant(m2.outerSize(), 2));
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200108 for (Index j=0; j<cols; ++j)
Gael Guennebaud5015e482008-12-11 18:26:24 +0000109 {
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200110 for (Index k=0; k<rows/2; ++k)
Gael Guennebaud5015e482008-12-11 18:26:24 +0000111 {
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200112 Index i = internal::random<Index>(0,rows-1);
Gael Guennebaud5015e482008-12-11 18:26:24 +0000113 if (m1.coeff(i,j)==Scalar(0))
Benoit Jacob47160402010-10-25 10:15:22 -0400114 m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
Gael Guennebaud5015e482008-12-11 18:26:24 +0000115 }
116 }
Gael Guennebaud28293142009-05-04 14:25:12 +0000117 m2.finalize();
118 VERIFY_IS_APPROX(m2,m1);
119 }
Gael Guennebaud9f795582009-12-16 19:18:40 +0100120
Gael Guennebaud28293142009-05-04 14:25:12 +0000121 // test insert (fully random)
122 {
123 DenseMatrix m1(rows,cols);
124 m1.setZero();
125 SparseMatrixType m2(rows,cols);
Gael Guennebaud4ca89f32011-12-02 19:00:16 +0100126 if(internal::random<int>()%2)
127 m2.reserve(VectorXi::Constant(m2.outerSize(), 2));
Gael Guennebaud28293142009-05-04 14:25:12 +0000128 for (int k=0; k<rows*cols; ++k)
129 {
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200130 Index i = internal::random<Index>(0,rows-1);
131 Index j = internal::random<Index>(0,cols-1);
Gael Guennebaud4ca89f32011-12-02 19:00:16 +0100132 if ((m1.coeff(i,j)==Scalar(0)) && (internal::random<int>()%2))
Benoit Jacob47160402010-10-25 10:15:22 -0400133 m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
Gael Guennebaud4ca89f32011-12-02 19:00:16 +0100134 else
135 {
136 Scalar v = internal::random<Scalar>();
137 m2.coeffRef(i,j) += v;
138 m1(i,j) += v;
139 }
Gael Guennebaud28293142009-05-04 14:25:12 +0000140 }
Gael Guennebaudc4c70662009-01-14 14:24:10 +0000141 VERIFY_IS_APPROX(m2,m1);
Gael Guennebaud5015e482008-12-11 18:26:24 +0000142 }
Gael Guennebaud7706baf2011-09-08 13:42:54 +0200143
144 // test insert (un-compressed)
145 for(int mode=0;mode<4;++mode)
146 {
147 DenseMatrix m1(rows,cols);
148 m1.setZero();
149 SparseMatrixType m2(rows,cols);
150 VectorXi r(VectorXi::Constant(m2.outerSize(), ((mode%2)==0) ? m2.innerSize() : std::max<int>(1,m2.innerSize()/8)));
151 m2.reserve(r);
152 for (int k=0; k<rows*cols; ++k)
153 {
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200154 Index i = internal::random<Index>(0,rows-1);
155 Index j = internal::random<Index>(0,cols-1);
Gael Guennebaud7706baf2011-09-08 13:42:54 +0200156 if (m1.coeff(i,j)==Scalar(0))
157 m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
158 if(mode==3)
159 m2.reserve(r);
160 }
Gael Guennebaud4ca89f32011-12-02 19:00:16 +0100161 if(internal::random<int>()%2)
162 m2.makeCompressed();
Gael Guennebaud7706baf2011-09-08 13:42:54 +0200163 VERIFY_IS_APPROX(m2,m1);
164 }
Gael Guennebaud9f795582009-12-16 19:18:40 +0100165
Gael Guennebaudc4c70662009-01-14 14:24:10 +0000166 // test innerVector()
167 {
168 DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
Gael Guennebaud178858f2009-01-19 15:20:45 +0000169 SparseMatrixType m2(rows, rows);
Gael Guennebaudc4c70662009-01-14 14:24:10 +0000170 initSparse<Scalar>(density, refMat2, m2);
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200171 Index j0 = internal::random<Index>(0,rows-1);
172 Index j1 = internal::random<Index>(0,rows-1);
Gael Guennebaud9353bba2011-12-04 14:39:24 +0100173 if(SparseMatrixType::IsRowMajor)
174 VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.row(j0));
175 else
176 VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0));
177
178 if(SparseMatrixType::IsRowMajor)
179 VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.row(j0)+refMat2.row(j1));
180 else
181 VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1));
Gael Guennebaud50d756b2011-12-20 18:10:02 +0100182
183 SparseMatrixType m3(rows,rows);
184 m3.reserve(VectorXi::Constant(rows,rows/2));
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200185 for(Index j=0; j<rows; ++j)
186 for(Index k=0; k<j; ++k)
Gael Guennebaud50d756b2011-12-20 18:10:02 +0100187 m3.insertByOuterInner(j,k) = k+1;
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200188 for(Index j=0; j<rows; ++j)
Gael Guennebaud50d756b2011-12-20 18:10:02 +0100189 {
Gael Guennebaud65c59302013-06-12 10:37:15 +0200190 VERIFY(j==numext::real(m3.innerVector(j).nonZeros()));
Gael Guennebaud50d756b2011-12-20 18:10:02 +0100191 if(j>0)
Gael Guennebaud65c59302013-06-12 10:37:15 +0200192 VERIFY(j==numext::real(m3.innerVector(j).lastCoeff()));
Gael Guennebaud50d756b2011-12-20 18:10:02 +0100193 }
194 m3.makeCompressed();
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200195 for(Index j=0; j<rows; ++j)
Gael Guennebaud50d756b2011-12-20 18:10:02 +0100196 {
Gael Guennebaud65c59302013-06-12 10:37:15 +0200197 VERIFY(j==numext::real(m3.innerVector(j).nonZeros()));
Gael Guennebaud50d756b2011-12-20 18:10:02 +0100198 if(j>0)
Gael Guennebaud65c59302013-06-12 10:37:15 +0200199 VERIFY(j==numext::real(m3.innerVector(j).lastCoeff()));
Gael Guennebaud50d756b2011-12-20 18:10:02 +0100200 }
201
Gael Guennebaud8ce45032009-01-27 22:48:17 +0000202 //m2.innerVector(j0) = 2*m2.innerVector(j1);
203 //refMat2.col(j0) = 2*refMat2.col(j1);
204 //VERIFY_IS_APPROX(m2, refMat2);
205 }
Gael Guennebaud9f795582009-12-16 19:18:40 +0100206
Gael Guennebaud8ce45032009-01-27 22:48:17 +0000207 // test innerVectors()
208 {
209 DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
210 SparseMatrixType m2(rows, rows);
211 initSparse<Scalar>(density, refMat2, m2);
Gael Guennebaud7450b232013-04-12 13:20:13 +0200212 if(internal::random<float>(0,1)>0.5) m2.makeCompressed();
213
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200214 Index j0 = internal::random<Index>(0,rows-2);
215 Index j1 = internal::random<Index>(0,rows-2);
216 Index n0 = internal::random<Index>(1,rows-(std::max)(j0,j1));
Gael Guennebaud9353bba2011-12-04 14:39:24 +0100217 if(SparseMatrixType::IsRowMajor)
218 VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(j0,0,n0,cols));
219 else
220 VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0));
221 if(SparseMatrixType::IsRowMajor)
222 VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
Gael Guennebaud7450b232013-04-12 13:20:13 +0200223 refMat2.middleRows(j0,n0)+refMat2.middleRows(j1,n0));
Gael Guennebaud9353bba2011-12-04 14:39:24 +0100224 else
225 VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
226 refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
Gael Guennebaud7450b232013-04-12 13:20:13 +0200227
228 VERIFY_IS_APPROX(m2, refMat2);
229
230 m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0);
231 if(SparseMatrixType::IsRowMajor)
232 refMat2.middleRows(j0,n0) = (refMat2.middleRows(j0,n0) + refMat2.middleRows(j1,n0)).eval();
233 else
234 refMat2.middleCols(j0,n0) = (refMat2.middleCols(j0,n0) + refMat2.middleCols(j1,n0)).eval();
235
236 VERIFY_IS_APPROX(m2, refMat2);
237
Gael Guennebaudc4c70662009-01-14 14:24:10 +0000238 }
Gael Guennebaud4e602832012-11-16 09:02:50 +0100239
240 // test basic computations
241 {
242 DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
243 DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
244 DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
245 DenseMatrix refM4 = DenseMatrix::Zero(rows, rows);
246 SparseMatrixType m1(rows, rows);
247 SparseMatrixType m2(rows, rows);
248 SparseMatrixType m3(rows, rows);
249 SparseMatrixType m4(rows, rows);
250 initSparse<Scalar>(density, refM1, m1);
251 initSparse<Scalar>(density, refM2, m2);
252 initSparse<Scalar>(density, refM3, m3);
253 initSparse<Scalar>(density, refM4, m4);
254
255 VERIFY_IS_APPROX(m1+m2, refM1+refM2);
256 VERIFY_IS_APPROX(m1+m2+m3, refM1+refM2+refM3);
257 VERIFY_IS_APPROX(m3.cwiseProduct(m1+m2), refM3.cwiseProduct(refM1+refM2));
258 VERIFY_IS_APPROX(m1*s1-m2, refM1*s1-refM2);
259
260 VERIFY_IS_APPROX(m1*=s1, refM1*=s1);
261 VERIFY_IS_APPROX(m1/=s1, refM1/=s1);
262
263 VERIFY_IS_APPROX(m1+=m2, refM1+=refM2);
264 VERIFY_IS_APPROX(m1-=m2, refM1-=refM2);
265
266 if(SparseMatrixType::IsRowMajor)
267 VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.row(0).dot(refM2.row(0)));
268 else
269 VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.col(0).dot(refM2.row(0)));
270
271 VERIFY_IS_APPROX(m1.conjugate(), refM1.conjugate());
272 VERIFY_IS_APPROX(m1.real(), refM1.real());
273
274 refM4.setRandom();
275 // sparse cwise* dense
276 VERIFY_IS_APPROX(m3.cwiseProduct(refM4), refM3.cwiseProduct(refM4));
277// VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4);
278
279 // test aliasing
280 VERIFY_IS_APPROX((m1 = -m1), (refM1 = -refM1));
281 VERIFY_IS_APPROX((m1 = m1.transpose()), (refM1 = refM1.transpose().eval()));
282 VERIFY_IS_APPROX((m1 = -m1.transpose()), (refM1 = -refM1.transpose().eval()));
283 VERIFY_IS_APPROX((m1 += -m1), (refM1 += -refM1));
284 }
285
286 // test transpose
287 {
288 DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
289 SparseMatrixType m2(rows, rows);
290 initSparse<Scalar>(density, refMat2, m2);
291 VERIFY_IS_APPROX(m2.transpose().eval(), refMat2.transpose().eval());
292 VERIFY_IS_APPROX(m2.transpose(), refMat2.transpose());
293
294 VERIFY_IS_APPROX(SparseMatrixType(m2.adjoint()), refMat2.adjoint());
295 }
296
297
298
299 // test generic blocks
300 {
301 DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
302 SparseMatrixType m2(rows, rows);
303 initSparse<Scalar>(density, refMat2, m2);
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200304 Index j0 = internal::random<Index>(0,rows-2);
305 Index j1 = internal::random<Index>(0,rows-2);
306 Index n0 = internal::random<Index>(1,rows-(std::max)(j0,j1));
Gael Guennebaud4e602832012-11-16 09:02:50 +0100307 if(SparseMatrixType::IsRowMajor)
308 VERIFY_IS_APPROX(m2.block(j0,0,n0,cols), refMat2.block(j0,0,n0,cols));
309 else
310 VERIFY_IS_APPROX(m2.block(0,j0,rows,n0), refMat2.block(0,j0,rows,n0));
311
312 if(SparseMatrixType::IsRowMajor)
313 VERIFY_IS_APPROX(m2.block(j0,0,n0,cols)+m2.block(j1,0,n0,cols),
314 refMat2.block(j0,0,n0,cols)+refMat2.block(j1,0,n0,cols));
315 else
316 VERIFY_IS_APPROX(m2.block(0,j0,rows,n0)+m2.block(0,j1,rows,n0),
317 refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
Gael Guennebaud5f178e52013-06-14 10:52:19 +0200318
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200319 Index i = internal::random<Index>(0,m2.outerSize()-1);
Gael Guennebaud5f178e52013-06-14 10:52:19 +0200320 if(SparseMatrixType::IsRowMajor) {
321 m2.innerVector(i) = m2.innerVector(i) * s1;
322 refMat2.row(i) = refMat2.row(i) * s1;
323 VERIFY_IS_APPROX(m2,refMat2);
324 } else {
325 m2.innerVector(i) = m2.innerVector(i) * s1;
326 refMat2.col(i) = refMat2.col(i) * s1;
327 VERIFY_IS_APPROX(m2,refMat2);
328 }
Gael Guennebaud4e602832012-11-16 09:02:50 +0100329 }
Gael Guennebaudc4c70662009-01-14 14:24:10 +0000330
Gael Guennebaud52cf07d2009-01-21 18:46:04 +0000331 // test prune
332 {
333 SparseMatrixType m2(rows, rows);
334 DenseMatrix refM2(rows, rows);
335 refM2.setZero();
336 int countFalseNonZero = 0;
337 int countTrueNonZero = 0;
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200338 for (Index j=0; j<m2.outerSize(); ++j)
Gael Guennebaud28293142009-05-04 14:25:12 +0000339 {
340 m2.startVec(j);
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200341 for (Index i=0; i<m2.innerSize(); ++i)
Gael Guennebaud52cf07d2009-01-21 18:46:04 +0000342 {
Benoit Jacob47160402010-10-25 10:15:22 -0400343 float x = internal::random<float>(0,1);
Gael Guennebaud52cf07d2009-01-21 18:46:04 +0000344 if (x<0.1)
345 {
346 // do nothing
347 }
348 else if (x<0.5)
349 {
350 countFalseNonZero++;
Gael Guennebaud8710bd22010-06-02 13:32:13 +0200351 m2.insertBackByOuterInner(j,i) = Scalar(0);
Gael Guennebaud52cf07d2009-01-21 18:46:04 +0000352 }
353 else
354 {
355 countTrueNonZero++;
Gael Guennebaud9353bba2011-12-04 14:39:24 +0100356 m2.insertBackByOuterInner(j,i) = Scalar(1);
357 if(SparseMatrixType::IsRowMajor)
358 refM2(j,i) = Scalar(1);
359 else
360 refM2(i,j) = Scalar(1);
Gael Guennebaud52cf07d2009-01-21 18:46:04 +0000361 }
362 }
Gael Guennebaud28293142009-05-04 14:25:12 +0000363 }
364 m2.finalize();
Gael Guennebaud52cf07d2009-01-21 18:46:04 +0000365 VERIFY(countFalseNonZero+countTrueNonZero == m2.nonZeros());
366 VERIFY_IS_APPROX(m2, refM2);
Hauke Heibeld204ec42010-11-02 14:33:33 +0100367 m2.prune(Scalar(1));
Gael Guennebaud52cf07d2009-01-21 18:46:04 +0000368 VERIFY(countTrueNonZero==m2.nonZeros());
369 VERIFY_IS_APPROX(m2, refM2);
370 }
Gael Guennebaud9353bba2011-12-04 14:39:24 +0100371
Gael Guennebaud87138072012-01-28 11:13:59 +0100372 // test setFromTriplets
373 {
374 typedef Triplet<Scalar,Index> TripletType;
375 std::vector<TripletType> triplets;
376 int ntriplets = rows*cols;
377 triplets.reserve(ntriplets);
378 DenseMatrix refMat(rows,cols);
379 refMat.setZero();
380 for(int i=0;i<ntriplets;++i)
381 {
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200382 Index r = internal::random<Index>(0,rows-1);
383 Index c = internal::random<Index>(0,cols-1);
Gael Guennebaud87138072012-01-28 11:13:59 +0100384 Scalar v = internal::random<Scalar>();
Gael Guennebaud18e3ac02012-01-31 09:14:01 +0100385 triplets.push_back(TripletType(r,c,v));
386 refMat(r,c) += v;
Gael Guennebaud87138072012-01-28 11:13:59 +0100387 }
388 SparseMatrixType m(rows,cols);
389 m.setFromTriplets(triplets.begin(), triplets.end());
390 VERIFY_IS_APPROX(m, refMat);
391 }
392
Gael Guennebaud9353bba2011-12-04 14:39:24 +0100393 // test triangularView
394 {
395 DenseMatrix refMat2(rows, rows), refMat3(rows, rows);
396 SparseMatrixType m2(rows, rows), m3(rows, rows);
397 initSparse<Scalar>(density, refMat2, m2);
398 refMat3 = refMat2.template triangularView<Lower>();
399 m3 = m2.template triangularView<Lower>();
400 VERIFY_IS_APPROX(m3, refMat3);
401
402 refMat3 = refMat2.template triangularView<Upper>();
403 m3 = m2.template triangularView<Upper>();
404 VERIFY_IS_APPROX(m3, refMat3);
405
406 refMat3 = refMat2.template triangularView<UnitUpper>();
407 m3 = m2.template triangularView<UnitUpper>();
408 VERIFY_IS_APPROX(m3, refMat3);
409
410 refMat3 = refMat2.template triangularView<UnitLower>();
411 m3 = m2.template triangularView<UnitLower>();
412 VERIFY_IS_APPROX(m3, refMat3);
Desire NUENTSA4cd82452013-06-11 14:42:29 +0200413
414 refMat3 = refMat2.template triangularView<StrictlyUpper>();
415 m3 = m2.template triangularView<StrictlyUpper>();
416 VERIFY_IS_APPROX(m3, refMat3);
417
418 refMat3 = refMat2.template triangularView<StrictlyLower>();
419 m3 = m2.template triangularView<StrictlyLower>();
420 VERIFY_IS_APPROX(m3, refMat3);
Gael Guennebaud9353bba2011-12-04 14:39:24 +0100421 }
Gael Guennebaudfa6d36e2010-07-22 15:57:01 +0200422
Gael Guennebaud9a3ec632010-11-15 14:14:05 +0100423 // test selfadjointView
Gael Guennebaud9353bba2011-12-04 14:39:24 +0100424 if(!SparseMatrixType::IsRowMajor)
Gael Guennebaud9a3ec632010-11-15 14:14:05 +0100425 {
426 DenseMatrix refMat2(rows, rows), refMat3(rows, rows);
427 SparseMatrixType m2(rows, rows), m3(rows, rows);
428 initSparse<Scalar>(density, refMat2, m2);
429 refMat3 = refMat2.template selfadjointView<Lower>();
430 m3 = m2.template selfadjointView<Lower>();
431 VERIFY_IS_APPROX(m3, refMat3);
432 }
433
Gael Guennebaudfa6d36e2010-07-22 15:57:01 +0200434 // test sparseView
435 {
436 DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
437 SparseMatrixType m2(rows, rows);
Gael Guennebaud9a3ec632010-11-15 14:14:05 +0100438 initSparse<Scalar>(density, refMat2, m2);
Gael Guennebaudfa6d36e2010-07-22 15:57:01 +0200439 VERIFY_IS_APPROX(m2.eval(), refMat2.sparseView().eval());
440 }
Gael Guennebaud82f9aa12011-12-04 21:49:21 +0100441
442 // test diagonal
443 {
444 DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
445 SparseMatrixType m2(rows, rows);
446 initSparse<Scalar>(density, refMat2, m2);
447 VERIFY_IS_APPROX(m2.diagonal(), refMat2.diagonal().eval());
448 }
Benjamin Piwowarski6bf49ce2012-07-19 00:07:06 +0200449
450 // test conservative resize
451 {
452 std::vector< std::pair<int,int> > inc;
453 inc.push_back(std::pair<int,int>(-3,-2));
454 inc.push_back(std::pair<int,int>(0,0));
455 inc.push_back(std::pair<int,int>(3,2));
456 inc.push_back(std::pair<int,int>(3,0));
457 inc.push_back(std::pair<int,int>(0,3));
458
459 for(size_t i = 0; i< inc.size(); i++) {
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200460 Index incRows = inc[i].first;
461 Index incCols = inc[i].second;
Benjamin Piwowarski6bf49ce2012-07-19 00:07:06 +0200462 SparseMatrixType m1(rows, cols);
463 DenseMatrix refMat1 = DenseMatrix::Zero(rows, cols);
464 initSparse<Scalar>(density, refMat1, m1);
465
466 m1.conservativeResize(rows+incRows, cols+incCols);
467 refMat1.conservativeResize(rows+incRows, cols+incCols);
468 if (incRows > 0) refMat1.bottomRows(incRows).setZero();
469 if (incCols > 0) refMat1.rightCols(incCols).setZero();
470
471 VERIFY_IS_APPROX(m1, refMat1);
472
473 // Insert new values
474 if (incRows > 0)
475 m1.insert(refMat1.rows()-1, 0) = refMat1(refMat1.rows()-1, 0) = 1;
476 if (incCols > 0)
477 m1.insert(0, refMat1.cols()-1) = refMat1(0, refMat1.cols()-1) = 1;
478
479 VERIFY_IS_APPROX(m1, refMat1);
480
481
482 }
483 }
Desire NUENTSA4cd82452013-06-11 14:42:29 +0200484
485 // test Identity matrix
486 {
487 DenseMatrix refMat1 = DenseMatrix::Identity(rows, rows);
488 SparseMatrixType m1(rows, rows);
489 m1.setIdentity();
490 VERIFY_IS_APPROX(m1, refMat1);
491 }
Gael Guennebaud86ccd992008-11-05 13:47:55 +0000492}
493
494void test_sparse_basic()
495{
496 for(int i = 0; i < g_repeat; i++) {
Gael Guennebaud91fe1502011-06-07 11:28:16 +0200497 int s = Eigen::internal::random<int>(1,50);
Gael Guennebauda1091ca2013-02-15 14:05:37 +0100498 EIGEN_UNUSED_VARIABLE(s);
Gael Guennebaud91fe1502011-06-07 11:28:16 +0200499 CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double>(8, 8)) ));
Gael Guennebaud9353bba2011-12-04 14:39:24 +0100500 CALL_SUBTEST_2(( sparse_basic(SparseMatrix<std::complex<double>, ColMajor>(s, s)) ));
501 CALL_SUBTEST_2(( sparse_basic(SparseMatrix<std::complex<double>, RowMajor>(s, s)) ));
Gael Guennebaud91fe1502011-06-07 11:28:16 +0200502 CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double>(s, s)) ));
503 CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,ColMajor,long int>(s, s)) ));
Gael Guennebaud9353bba2011-12-04 14:39:24 +0100504 CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,RowMajor,long int>(s, s)) ));
Gael Guennebaud47e89022013-06-10 10:34:03 +0200505
Gael Guennebaud6d1f5db2013-07-10 23:48:26 +0200506 CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,ColMajor,short int>(short(s), short(s))) ));
507 CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,RowMajor,short int>(short(s), short(s))) ));
Gael Guennebaud86ccd992008-11-05 13:47:55 +0000508 }
509}