template<typename MatrixType> void block(const MatrixType& m) { typedef typename MatrixType::Index Index; typedef typename MatrixType::Scalar Scalar; typedef typename MatrixType::RealScalar RealScalar; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType; typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType; typedef Matrix<Scalar, Dynamic, Dynamic> DynamicMatrixType; typedef Matrix<Scalar, Dynamic, 1> DynamicVectorType; Index rows = m.rows(); Index cols = m.cols(); MatrixType m1 = MatrixType::Random(rows, cols), m1_copy = m1, m2 = MatrixType::Random(rows, cols), m3(rows, cols), ones = MatrixType::Ones(rows, cols); VectorType v1 = VectorType::Random(rows); Scalar s1 = internal::random<Scalar>(); Index r1 = internal::random<Index>(0,rows-1); Index r2 = internal::random<Index>(r1,rows-1); Index c1 = internal::random<Index>(0,cols-1); Index c2 = internal::random<Index>(c1,cols-1); //check row() and col() VERIFY_IS_EQUAL(m1.col(c1).transpose(), m1.transpose().row(c1)); //check operator(), both constant and non-constant, on row() and col() m1 = m1_copy; m1.row(r1) += s1 * m1_copy.row(r2); VERIFY_IS_APPROX(m1.row(r1), m1_copy.row(r1) + s1 * m1_copy.row(r2)); // check nested block xpr on lhs m1.row(r1).row(0) += s1 * m1_copy.row(r2); VERIFY_IS_APPROX(m1.row(r1), m1_copy.row(r1) + Scalar(2) * s1 * m1_copy.row(r2)); m1 = m1_copy; m1.col(c1) += s1 * m1_copy.col(c2); VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + s1 * m1_copy.col(c2)); m1.col(c1).col(0) += s1 * m1_copy.col(c2); VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + Scalar(2) * s1 * m1_copy.col(c2)); //check block() Matrix<Scalar,Dynamic,Dynamic> b1(1,1); b1(0,0) = m1(r1,c1); RowVectorType br1(m1.block(r1,0,1,cols)); VectorType bc1(m1.block(0,c1,rows,1)); VERIFY_IS_EQUAL(b1, m1.block(r1,c1,1,1)); VERIFY_IS_EQUAL(m1.row(r1), br1); VERIFY_IS_EQUAL(m1.col(c1), bc1); //check operator(), both constant and non-constant, on block() m1.block(r1,c1,r2-r1+1,c2-c1+1) = s1 * m2.block(0, 0, r2-r1+1,c2-c1+1); m1.block(r1,c1,r2-r1+1,c2-c1+1)(r2-r1,c2-c1) = m2.block(0, 0, r2-r1+1,c2-c1+1)(0,0); enum { BlockRows = 2, BlockCols = 5 }; if (rows>=5 && cols>=8) { // test fixed block() as lvalue m1.template block<BlockRows,BlockCols>(1,1) *= s1; // test operator() on fixed block() both as constant and non-constant m1.template block<BlockRows,BlockCols>(1,1)(0, 3) = m1.template block<2,5>(1,1)(1,2); // check that fixed block() and block() agree Matrix<Scalar,Dynamic,Dynamic> b = m1.template block<BlockRows,BlockCols>(3,3); VERIFY_IS_EQUAL(b, m1.block(3,3,BlockRows,BlockCols)); // same tests with mixed fixed/dynamic size m1.template block<BlockRows,Dynamic>(1,1,BlockRows,BlockCols) *= s1; m1.template block<BlockRows,Dynamic>(1,1,BlockRows,BlockCols)(0,3) = m1.template block<2,5>(1,1)(1,2); Matrix<Scalar,Dynamic,Dynamic> b2 = m1.template block<Dynamic,BlockCols>(3,3,2,5); VERIFY_IS_EQUAL(b2, m1.block(3,3,BlockRows,BlockCols)); } if (rows>2) { // test sub vectors VERIFY_IS_EQUAL(v1.template head<2>(), v1.block(0,0,2,1)); VERIFY_IS_EQUAL(v1.template head<2>(), v1.head(2)); VERIFY_IS_EQUAL(v1.template head<2>(), v1.segment(0,2)); VERIFY_IS_EQUAL(v1.template head<2>(), v1.template segment<2>(0)); Index i = rows-2; VERIFY_IS_EQUAL(v1.template tail<2>(), v1.block(i,0,2,1)); VERIFY_IS_EQUAL(v1.template tail<2>(), v1.tail(2)); VERIFY_IS_EQUAL(v1.template tail<2>(), v1.segment(i,2)); VERIFY_IS_EQUAL(v1.template tail<2>(), v1.template segment<2>(i)); i = internal::random<Index>(0,rows-2); VERIFY_IS_EQUAL(v1.segment(i,2), v1.template segment<2>(i)); } // stress some basic stuffs with block matrices VERIFY(numext::real(ones.col(c1).sum()) == RealScalar(rows)); VERIFY(numext::real(ones.row(r1).sum()) == RealScalar(cols)); VERIFY(numext::real(ones.col(c1).dot(ones.col(c2))) == RealScalar(rows)); VERIFY(numext::real(ones.row(r1).dot(ones.row(r2))) == RealScalar(cols)); // now test some block-inside-of-block. // expressions with direct access VERIFY_IS_EQUAL( (m1.block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2)) , (m1.block(r2,c2,rows-r2,cols-c2)) ); VERIFY_IS_EQUAL( (m1.block(r1,c1,r2-r1+1,c2-c1+1).row(0)) , (m1.row(r1).segment(c1,c2-c1+1)) ); VERIFY_IS_EQUAL( (m1.block(r1,c1,r2-r1+1,c2-c1+1).col(0)) , (m1.col(c1).segment(r1,r2-r1+1)) ); VERIFY_IS_EQUAL( (m1.block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0)) , (m1.row(r1).segment(c1,c2-c1+1)).transpose() ); VERIFY_IS_EQUAL( (m1.transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0)) , (m1.row(r1).segment(c1,c2-c1+1)).transpose() ); // expressions without direct access VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2)) , ((m1+m2).block(r2,c2,rows-r2,cols-c2)) ); VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).row(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)) ); VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).col(0)) , ((m1+m2).col(c1).segment(r1,r2-r1+1)) ); VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)).transpose() ); VERIFY_IS_EQUAL( ((m1+m2).transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)).transpose() ); // evaluation into plain matrices from expressions with direct access (stress MapBase) DynamicMatrixType dm; DynamicVectorType dv; dm.setZero(); dm = m1.block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2); VERIFY_IS_EQUAL(dm, (m1.block(r2,c2,rows-r2,cols-c2))); dm.setZero(); dv.setZero(); dm = m1.block(r1,c1,r2-r1+1,c2-c1+1).row(0).transpose(); dv = m1.row(r1).segment(c1,c2-c1+1); VERIFY_IS_EQUAL(dv, dm); dm.setZero(); dv.setZero(); dm = m1.col(c1).segment(r1,r2-r1+1); dv = m1.block(r1,c1,r2-r1+1,c2-c1+1).col(0); VERIFY_IS_EQUAL(dv, dm); dm.setZero(); dv.setZero(); dm = m1.block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0); dv = m1.row(r1).segment(c1,c2-c1+1); VERIFY_IS_EQUAL(dv, dm); dm.setZero(); dv.setZero(); dm = m1.row(r1).segment(c1,c2-c1+1).transpose(); dv = m1.transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0); VERIFY_IS_EQUAL(dv, dm); }
template<typename MatrixType> void product_extra(const MatrixType& m) { typedef typename MatrixType::Index Index; typedef typename MatrixType::Scalar Scalar; typedef Matrix<Scalar, 1, Dynamic> RowVectorType; typedef Matrix<Scalar, Dynamic, 1> ColVectorType; typedef Matrix<Scalar, Dynamic, Dynamic, MatrixType::Flags&RowMajorBit> OtherMajorMatrixType; Index rows = m.rows(); Index cols = m.cols(); MatrixType m1 = MatrixType::Random(rows, cols), m2 = MatrixType::Random(rows, cols), m3(rows, cols), mzero = MatrixType::Zero(rows, cols), identity = MatrixType::Identity(rows, rows), square = MatrixType::Random(rows, rows), res = MatrixType::Random(rows, rows), square2 = MatrixType::Random(cols, cols), res2 = MatrixType::Random(cols, cols); RowVectorType v1 = RowVectorType::Random(rows), vrres(rows); ColVectorType vc2 = ColVectorType::Random(cols), vcres(cols); OtherMajorMatrixType tm1 = m1; Scalar s1 = internal::random<Scalar>(), s2 = internal::random<Scalar>(), s3 = internal::random<Scalar>(); VERIFY_IS_APPROX(m3.noalias() = m1 * m2.adjoint(), m1 * m2.adjoint().eval()); VERIFY_IS_APPROX(m3.noalias() = m1.adjoint() * square.adjoint(), m1.adjoint().eval() * square.adjoint().eval()); VERIFY_IS_APPROX(m3.noalias() = m1.adjoint() * m2, m1.adjoint().eval() * m2); VERIFY_IS_APPROX(m3.noalias() = (s1 * m1.adjoint()) * m2, (s1 * m1.adjoint()).eval() * m2); VERIFY_IS_APPROX(m3.noalias() = ((s1 * m1).adjoint()) * m2, (numext::conj(s1) * m1.adjoint()).eval() * m2); VERIFY_IS_APPROX(m3.noalias() = (- m1.adjoint() * s1) * (s3 * m2), (- m1.adjoint() * s1).eval() * (s3 * m2).eval()); VERIFY_IS_APPROX(m3.noalias() = (s2 * m1.adjoint() * s1) * m2, (s2 * m1.adjoint() * s1).eval() * m2); VERIFY_IS_APPROX(m3.noalias() = (-m1*s2) * s1*m2.adjoint(), (-m1*s2).eval() * (s1*m2.adjoint()).eval()); // a very tricky case where a scale factor has to be automatically conjugated: VERIFY_IS_APPROX( m1.adjoint() * (s1*m2).conjugate(), (m1.adjoint()).eval() * ((s1*m2).conjugate()).eval()); // test all possible conjugate combinations for the four matrix-vector product cases: VERIFY_IS_APPROX((-m1.conjugate() * s2) * (s1 * vc2), (-m1.conjugate()*s2).eval() * (s1 * vc2).eval()); VERIFY_IS_APPROX((-m1 * s2) * (s1 * vc2.conjugate()), (-m1*s2).eval() * (s1 * vc2.conjugate()).eval()); VERIFY_IS_APPROX((-m1.conjugate() * s2) * (s1 * vc2.conjugate()), (-m1.conjugate()*s2).eval() * (s1 * vc2.conjugate()).eval()); VERIFY_IS_APPROX((s1 * vc2.transpose()) * (-m1.adjoint() * s2), (s1 * vc2.transpose()).eval() * (-m1.adjoint()*s2).eval()); VERIFY_IS_APPROX((s1 * vc2.adjoint()) * (-m1.transpose() * s2), (s1 * vc2.adjoint()).eval() * (-m1.transpose()*s2).eval()); VERIFY_IS_APPROX((s1 * vc2.adjoint()) * (-m1.adjoint() * s2), (s1 * vc2.adjoint()).eval() * (-m1.adjoint()*s2).eval()); VERIFY_IS_APPROX((-m1.adjoint() * s2) * (s1 * v1.transpose()), (-m1.adjoint()*s2).eval() * (s1 * v1.transpose()).eval()); VERIFY_IS_APPROX((-m1.transpose() * s2) * (s1 * v1.adjoint()), (-m1.transpose()*s2).eval() * (s1 * v1.adjoint()).eval()); VERIFY_IS_APPROX((-m1.adjoint() * s2) * (s1 * v1.adjoint()), (-m1.adjoint()*s2).eval() * (s1 * v1.adjoint()).eval()); VERIFY_IS_APPROX((s1 * v1) * (-m1.conjugate() * s2), (s1 * v1).eval() * (-m1.conjugate()*s2).eval()); VERIFY_IS_APPROX((s1 * v1.conjugate()) * (-m1 * s2), (s1 * v1.conjugate()).eval() * (-m1*s2).eval()); VERIFY_IS_APPROX((s1 * v1.conjugate()) * (-m1.conjugate() * s2), (s1 * v1.conjugate()).eval() * (-m1.conjugate()*s2).eval()); VERIFY_IS_APPROX((-m1.adjoint() * s2) * (s1 * v1.adjoint()), (-m1.adjoint()*s2).eval() * (s1 * v1.adjoint()).eval()); // test the vector-matrix product with non aligned starts Index i = internal::random<Index>(0,m1.rows()-2); Index j = internal::random<Index>(0,m1.cols()-2); Index r = internal::random<Index>(1,m1.rows()-i); Index c = internal::random<Index>(1,m1.cols()-j); Index i2 = internal::random<Index>(0,m1.rows()-1); Index j2 = internal::random<Index>(0,m1.cols()-1); VERIFY_IS_APPROX(m1.col(j2).adjoint() * m1.block(0,j,m1.rows(),c), m1.col(j2).adjoint().eval() * m1.block(0,j,m1.rows(),c).eval()); VERIFY_IS_APPROX(m1.block(i,0,r,m1.cols()) * m1.row(i2).adjoint(), m1.block(i,0,r,m1.cols()).eval() * m1.row(i2).adjoint().eval()); // regression test MatrixType tmp = m1 * m1.adjoint() * s1; VERIFY_IS_APPROX(tmp, m1 * m1.adjoint() * s1); }
template<typename MatrixType> void product_notemporary(const MatrixType& m) { /* This test checks the number of temporaries created * during the evaluation of a complex expression */ typedef typename MatrixType::Index Index; typedef typename MatrixType::Scalar Scalar; typedef typename MatrixType::RealScalar RealScalar; typedef Matrix<Scalar, 1, Dynamic> RowVectorType; typedef Matrix<Scalar, Dynamic, 1> ColVectorType; typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> ColMajorMatrixType; typedef Matrix<Scalar, Dynamic, Dynamic, RowMajor> RowMajorMatrixType; Index rows = m.rows(); Index cols = m.cols(); ColMajorMatrixType m1 = MatrixType::Random(rows, cols), m2 = MatrixType::Random(rows, cols), m3(rows, cols); RowVectorType rv1 = RowVectorType::Random(rows), rvres(rows); ColVectorType cv1 = ColVectorType::Random(cols), cvres(cols); RowMajorMatrixType rm3(rows, cols); Scalar s1 = internal::random<Scalar>(), s2 = internal::random<Scalar>(), s3 = internal::random<Scalar>(); Index c0 = internal::random<Index>(4,cols-8), c1 = internal::random<Index>(8,cols-c0), r0 = internal::random<Index>(4,cols-8), r1 = internal::random<Index>(8,rows-r0); VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()), 1); VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()).transpose(), 1); VERIFY_EVALUATION_COUNT( m3.noalias() = m1 * m2.adjoint(), 0); VERIFY_EVALUATION_COUNT( m3 = s1 * (m1 * m2.transpose()), 1); // VERIFY_EVALUATION_COUNT( m3 = m3 + s1 * (m1 * m2.transpose()), 1); VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * (m1 * m2.transpose()), 0); VERIFY_EVALUATION_COUNT( m3 = m3 + (m1 * m2.adjoint()), 1); VERIFY_EVALUATION_COUNT( m3 = m3 + (m1 * m2.adjoint()).transpose(), 1); VERIFY_EVALUATION_COUNT( m3.noalias() = m3 + m1 * m2.transpose(), 0); VERIFY_EVALUATION_COUNT( m3.noalias() += m3 + m1 * m2.transpose(), 0); VERIFY_EVALUATION_COUNT( m3.noalias() -= m3 + m1 * m2.transpose(), 0); VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * m2.adjoint(), 0); VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * (m1*s3+m2*s2).adjoint(), 1); VERIFY_EVALUATION_COUNT( m3.noalias() = (s1 * m1).adjoint() * s2 * m2, 0); VERIFY_EVALUATION_COUNT( m3.noalias() += s1 * (-m1*s3).adjoint() * (s2 * m2 * s3), 0); VERIFY_EVALUATION_COUNT( m3.noalias() -= s1 * (m1.transpose() * m2), 0); VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() += -m1.block(r0,c0,r1,c1) * (s2*m2.block(r0,c0,r1,c1)).adjoint() ), 0); VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() -= s1 * m1.block(r0,c0,r1,c1) * m2.block(c0,r0,c1,r1) ), 0); // NOTE this is because the Block expression is not handled yet by our expression analyser VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() = s1 * m1.block(r0,c0,r1,c1) * (s1*m2).block(c0,r0,c1,r1) ), 1); VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).template triangularView<Lower>() * m2, 0); VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<Upper>() * (m2+m2), 1); VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * m2.adjoint(), 0); VERIFY_EVALUATION_COUNT( m3.template triangularView<Upper>() = (m1 * m2.adjoint()), 0); VERIFY_EVALUATION_COUNT( m3.template triangularView<Upper>() -= (m1 * m2.adjoint()), 0); // NOTE this is because the blas_traits require innerstride==1 to avoid a temporary, but that doesn't seem to be actually needed for the triangular products VERIFY_EVALUATION_COUNT( rm3.col(c0).noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * (s2*m2.row(c0)).adjoint(), 1); VERIFY_EVALUATION_COUNT( m1.template triangularView<Lower>().solveInPlace(m3), 0); VERIFY_EVALUATION_COUNT( m1.adjoint().template triangularView<Lower>().solveInPlace(m3.transpose()), 0); VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).adjoint().template selfadjointView<Lower>() * (-m2*s3).adjoint(), 0); VERIFY_EVALUATION_COUNT( m3.noalias() = s2 * m2.adjoint() * (s1 * m1.adjoint()).template selfadjointView<Upper>(), 0); VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template selfadjointView<Lower>() * m2.adjoint(), 0); // NOTE this is because the blas_traits require innerstride==1 to avoid a temporary, but that doesn't seem to be actually needed for the triangular products VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() = (s1 * m1).adjoint().template selfadjointView<Lower>() * (-m2.row(c0)*s3).adjoint(), 1); VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() -= (s1 * m1).adjoint().template selfadjointView<Upper>() * (-m2.row(c0)*s3).adjoint(), 1); VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() += m1.block(r0,r0,r1,r1).template selfadjointView<Upper>() * (s1*m2.block(r0,c0,r1,c1)), 0); VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<Upper>() * m2.block(r0,c0,r1,c1), 0); VERIFY_EVALUATION_COUNT( m3.template selfadjointView<Lower>().rankUpdate(m2.adjoint()), 0); // Here we will get 1 temporary for each resize operation of the lhs operator; resize(r1,c1) would lead to zero temporaries m3.resize(1,1); VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<Lower>() * m2.block(r0,c0,r1,c1), 1); m3.resize(1,1); VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template triangularView<UnitUpper>() * m2.block(r0,c0,r1,c1), 1); // Zero temporaries for lazy products ... VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) / (m3.transpose().lazyProduct(m3)).diagonal().sum(), 0 ); // ... and even no temporary for even deeply (>=2) nested products VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) / (m3.transpose() * m3).diagonal().sum(), 0 ); VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) / (m3.transpose() * m3).diagonal().array().abs().sum(), 0 ); // Zero temporaries for ... CoeffBasedProductMode VERIFY_EVALUATION_COUNT( m3.col(0).template head<5>() * m3.col(0).transpose() + m3.col(0).template head<5>() * m3.col(0).transpose(), 0 ); // Check matrix * vectors VERIFY_EVALUATION_COUNT( cvres.noalias() = m1 * cv1, 0 ); VERIFY_EVALUATION_COUNT( cvres.noalias() -= m1 * cv1, 0 ); VERIFY_EVALUATION_COUNT( cvres.noalias() -= m1 * m2.col(0), 0 ); VERIFY_EVALUATION_COUNT( cvres.noalias() -= m1 * rv1.adjoint(), 0 ); VERIFY_EVALUATION_COUNT( cvres.noalias() -= m1 * m2.row(0).transpose(), 0 ); VERIFY_EVALUATION_COUNT( cvres.noalias() = (m1+m1) * cv1, 0 ); VERIFY_EVALUATION_COUNT( cvres.noalias() = (rm3+rm3) * cv1, 0 ); VERIFY_EVALUATION_COUNT( cvres.noalias() = (m1+m1) * (m1*cv1), 1 ); VERIFY_EVALUATION_COUNT( cvres.noalias() = (rm3+rm3) * (m1*cv1), 1 ); // Check outer products m3 = cv1 * rv1; VERIFY_EVALUATION_COUNT( m3.noalias() = cv1 * rv1, 0 ); VERIFY_EVALUATION_COUNT( m3.noalias() = (cv1+cv1) * (rv1+rv1), 1 ); VERIFY_EVALUATION_COUNT( m3.noalias() = (m1*cv1) * (rv1), 1 ); VERIFY_EVALUATION_COUNT( m3.noalias() += (m1*cv1) * (rv1), 1 ); VERIFY_EVALUATION_COUNT( rm3.noalias() = (cv1) * (rv1 * m1), 1 ); VERIFY_EVALUATION_COUNT( rm3.noalias() -= (cv1) * (rv1 * m1), 1 ); VERIFY_EVALUATION_COUNT( rm3.noalias() = (m1*cv1) * (rv1 * m1), 2 ); VERIFY_EVALUATION_COUNT( rm3.noalias() += (m1*cv1) * (rv1 * m1), 2 ); }
void fixedSizeMatrixConstruction() { Scalar raw[4]; for(int k=0; k<4; ++k) raw[k] = internal::random<Scalar>(); { Matrix<Scalar,4,1> m(raw); Array<Scalar,4,1> a(raw); for(int k=0; k<4; ++k) VERIFY(m(k) == raw[k]); for(int k=0; k<4; ++k) VERIFY(a(k) == raw[k]); VERIFY_IS_EQUAL(m,(Matrix<Scalar,4,1>(raw[0],raw[1],raw[2],raw[3]))); VERIFY((a==(Array<Scalar,4,1>(raw[0],raw[1],raw[2],raw[3]))).all()); } { Matrix<Scalar,3,1> m(raw); Array<Scalar,3,1> a(raw); for(int k=0; k<3; ++k) VERIFY(m(k) == raw[k]); for(int k=0; k<3; ++k) VERIFY(a(k) == raw[k]); VERIFY_IS_EQUAL(m,(Matrix<Scalar,3,1>(raw[0],raw[1],raw[2]))); VERIFY((a==Array<Scalar,3,1>(raw[0],raw[1],raw[2])).all()); } { Matrix<Scalar,2,1> m(raw), m2( (DenseIndex(raw[0])), (DenseIndex(raw[1])) ); Array<Scalar,2,1> a(raw), a2( (DenseIndex(raw[0])), (DenseIndex(raw[1])) ); for(int k=0; k<2; ++k) VERIFY(m(k) == raw[k]); for(int k=0; k<2; ++k) VERIFY(a(k) == raw[k]); VERIFY_IS_EQUAL(m,(Matrix<Scalar,2,1>(raw[0],raw[1]))); VERIFY((a==Array<Scalar,2,1>(raw[0],raw[1])).all()); for(int k=0; k<2; ++k) VERIFY(m2(k) == DenseIndex(raw[k])); for(int k=0; k<2; ++k) VERIFY(a2(k) == DenseIndex(raw[k])); } { Matrix<Scalar,1,2> m(raw), m2( (DenseIndex(raw[0])), (DenseIndex(raw[1])) ), m3( (int(raw[0])), (int(raw[1])) ), m4( (float(raw[0])), (float(raw[1])) ); Array<Scalar,1,2> a(raw), a2( (DenseIndex(raw[0])), (DenseIndex(raw[1])) ); for(int k=0; k<2; ++k) VERIFY(m(k) == raw[k]); for(int k=0; k<2; ++k) VERIFY(a(k) == raw[k]); VERIFY_IS_EQUAL(m,(Matrix<Scalar,1,2>(raw[0],raw[1]))); VERIFY((a==Array<Scalar,1,2>(raw[0],raw[1])).all()); for(int k=0; k<2; ++k) VERIFY(m2(k) == DenseIndex(raw[k])); for(int k=0; k<2; ++k) VERIFY(a2(k) == DenseIndex(raw[k])); for(int k=0; k<2; ++k) VERIFY(m3(k) == int(raw[k])); for(int k=0; k<2; ++k) VERIFY((m4(k)) == Scalar(float(raw[k]))); } { Matrix<Scalar,1,1> m(raw), m1(raw[0]), m2( (DenseIndex(raw[0])) ), m3( (int(raw[0])) ); Array<Scalar,1,1> a(raw), a1(raw[0]), a2( (DenseIndex(raw[0])) ); VERIFY(m(0) == raw[0]); VERIFY(a(0) == raw[0]); VERIFY(m1(0) == raw[0]); VERIFY(a1(0) == raw[0]); VERIFY(m2(0) == DenseIndex(raw[0])); VERIFY(a2(0) == DenseIndex(raw[0])); VERIFY(m3(0) == int(raw[0])); VERIFY_IS_EQUAL(m,(Matrix<Scalar,1,1>(raw[0]))); VERIFY((a==Array<Scalar,1,1>(raw[0])).all()); } }
template<typename ArrayType> void vectorwiseop_array(const ArrayType& m) { typedef typename ArrayType::Index Index; typedef typename ArrayType::Scalar Scalar; typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType; typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType; Index rows = m.rows(); Index cols = m.cols(); Index r = internal::random<Index>(0, rows-1), c = internal::random<Index>(0, cols-1); ArrayType m1 = ArrayType::Random(rows, cols), m2(rows, cols), m3(rows, cols); ColVectorType colvec = ColVectorType::Random(rows); RowVectorType rowvec = RowVectorType::Random(cols); // test addition m2 = m1; m2.colwise() += colvec; VERIFY_IS_APPROX(m2, m1.colwise() + colvec); VERIFY_IS_APPROX(m2.col(c), m1.col(c) + colvec); VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose()); VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose()); m2 = m1; m2.rowwise() += rowvec; VERIFY_IS_APPROX(m2, m1.rowwise() + rowvec); VERIFY_IS_APPROX(m2.row(r), m1.row(r) + rowvec); VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose()); VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose()); // test substraction m2 = m1; m2.colwise() -= colvec; VERIFY_IS_APPROX(m2, m1.colwise() - colvec); VERIFY_IS_APPROX(m2.col(c), m1.col(c) - colvec); VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose()); VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose()); m2 = m1; m2.rowwise() -= rowvec; VERIFY_IS_APPROX(m2, m1.rowwise() - rowvec); VERIFY_IS_APPROX(m2.row(r), m1.row(r) - rowvec); VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose()); VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose()); // test multiplication m2 = m1; m2.colwise() *= colvec; VERIFY_IS_APPROX(m2, m1.colwise() * colvec); VERIFY_IS_APPROX(m2.col(c), m1.col(c) * colvec); VERIFY_RAISES_ASSERT(m2.colwise() *= colvec.transpose()); VERIFY_RAISES_ASSERT(m1.colwise() * colvec.transpose()); m2 = m1; m2.rowwise() *= rowvec; VERIFY_IS_APPROX(m2, m1.rowwise() * rowvec); VERIFY_IS_APPROX(m2.row(r), m1.row(r) * rowvec); VERIFY_RAISES_ASSERT(m2.rowwise() *= rowvec.transpose()); VERIFY_RAISES_ASSERT(m1.rowwise() * rowvec.transpose()); // test quotient m2 = m1; m2.colwise() /= colvec; VERIFY_IS_APPROX(m2, m1.colwise() / colvec); VERIFY_IS_APPROX(m2.col(c), m1.col(c) / colvec); VERIFY_RAISES_ASSERT(m2.colwise() /= colvec.transpose()); VERIFY_RAISES_ASSERT(m1.colwise() / colvec.transpose()); m2 = m1; m2.rowwise() /= rowvec; VERIFY_IS_APPROX(m2, m1.rowwise() / rowvec); VERIFY_IS_APPROX(m2.row(r), m1.row(r) / rowvec); VERIFY_RAISES_ASSERT(m2.rowwise() /= rowvec.transpose()); VERIFY_RAISES_ASSERT(m1.rowwise() / rowvec.transpose()); m2 = m1; // yes, there might be an aliasing issue there but ".rowwise() /=" // is supposed to evaluate " m2.colwise().sum()" into a temporary to avoid // evaluating the reduction multiple times if(ArrayType::RowsAtCompileTime>2 || ArrayType::RowsAtCompileTime==Dynamic) { m2.rowwise() /= m2.colwise().sum(); VERIFY_IS_APPROX(m2, m1.rowwise() / m1.colwise().sum()); } // all/any Array<bool,Dynamic,Dynamic> mb(rows,cols); mb = (m1.real()<=0.7).colwise().all(); VERIFY( (mb.col(c) == (m1.real().col(c)<=0.7).all()).all() ); mb = (m1.real()<=0.7).rowwise().all(); VERIFY( (mb.row(r) == (m1.real().row(r)<=0.7).all()).all() ); mb = (m1.real()>=0.7).colwise().any(); VERIFY( (mb.col(c) == (m1.real().col(c)>=0.7).any()).all() ); mb = (m1.real()>=0.7).rowwise().any(); VERIFY( (mb.row(r) == (m1.real().row(r)>=0.7).any()).all() ); }
int main() { #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::pair<MoveOnly, MoveOnly> V; typedef std::pair<const MoveOnly, MoveOnly> VC; typedef test_compare<std::less<MoveOnly> > C; typedef test_allocator<VC> A; typedef std::multimap<MoveOnly, MoveOnly, C, A> M; typedef std::move_iterator<V*> I; V a1[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m1(I(a1), I(a1+sizeof(a1)/sizeof(a1[0])), C(5), A(7)); V a2[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m2(I(a2), I(a2+sizeof(a2)/sizeof(a2[0])), C(5), A(7)); M m3(std::move(m1), A(7)); assert(m3 == m2); assert(m3.get_allocator() == A(7)); assert(m3.key_comp() == C(5)); assert(m1.empty()); } { typedef std::pair<MoveOnly, MoveOnly> V; typedef std::pair<const MoveOnly, MoveOnly> VC; typedef test_compare<std::less<MoveOnly> > C; typedef test_allocator<VC> A; typedef std::multimap<MoveOnly, MoveOnly, C, A> M; typedef std::move_iterator<V*> I; V a1[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m1(I(a1), I(a1+sizeof(a1)/sizeof(a1[0])), C(5), A(7)); V a2[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m2(I(a2), I(a2+sizeof(a2)/sizeof(a2[0])), C(5), A(7)); M m3(std::move(m1), A(5)); assert(m3 == m2); assert(m3.get_allocator() == A(5)); assert(m3.key_comp() == C(5)); assert(m1.empty()); } { typedef std::pair<MoveOnly, MoveOnly> V; typedef std::pair<const MoveOnly, MoveOnly> VC; typedef test_compare<std::less<MoveOnly> > C; typedef other_allocator<VC> A; typedef std::multimap<MoveOnly, MoveOnly, C, A> M; typedef std::move_iterator<V*> I; V a1[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m1(I(a1), I(a1+sizeof(a1)/sizeof(a1[0])), C(5), A(7)); V a2[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m2(I(a2), I(a2+sizeof(a2)/sizeof(a2[0])), C(5), A(7)); M m3(std::move(m1), A(5)); assert(m3 == m2); assert(m3.get_allocator() == A(5)); assert(m3.key_comp() == C(5)); assert(m1.empty()); } { typedef Counter<int> T; typedef std::pair<int, T> V; typedef std::pair<const int, T> VC; typedef test_allocator<VC> A; typedef std::less<int> C; typedef std::multimap<const int, T, C, A> M; typedef V* I; Counter_base::gConstructed = 0; { V a1[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; const size_t num = sizeof(a1)/sizeof(a1[0]); assert(Counter_base::gConstructed == num); M m1(I(a1), I(a1+num), C(), A()); assert(Counter_base::gConstructed == 2*num); M m2(m1); assert(m2 == m1); assert(Counter_base::gConstructed == 3*num); M m3(std::move(m1), A()); assert(m3 == m2); assert(m1.empty()); assert(Counter_base::gConstructed == 3*num); { M m4(std::move(m2), A(5)); assert(Counter_base::gConstructed == 3*num); assert(m4 == m3); assert(m2.empty()); } assert(Counter_base::gConstructed == 2*num); } assert(Counter_base::gConstructed == 0); } #if __cplusplus >= 201103L { typedef std::pair<MoveOnly, MoveOnly> V; typedef std::pair<const MoveOnly, MoveOnly> VC; typedef test_compare<std::less<MoveOnly> > C; typedef min_allocator<VC> A; typedef std::multimap<MoveOnly, MoveOnly, C, A> M; typedef std::move_iterator<V*> I; V a1[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m1(I(a1), I(a1+sizeof(a1)/sizeof(a1[0])), C(5), A()); V a2[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m2(I(a2), I(a2+sizeof(a2)/sizeof(a2[0])), C(5), A()); M m3(std::move(m1), A()); assert(m3 == m2); assert(m3.get_allocator() == A()); assert(m3.key_comp() == C(5)); assert(m1.empty()); } #endif #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES }
template<typename MatrixType> void adjoint(const MatrixType& m) { /* this test covers the following files: Transpose.h Conjugate.h Dot.h */ typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType; int rows = m.rows(); int cols = m.cols(); RealScalar largerEps = test_precision<RealScalar>(); if (ei_is_same_type<RealScalar,float>::ret) largerEps = RealScalar(1e-3f); MatrixType m1 = MatrixType::Random(rows, cols), m2 = MatrixType::Random(rows, cols), m3(rows, cols), mzero = MatrixType::Zero(rows, cols), identity = SquareMatrixType::Identity(rows, rows), square = SquareMatrixType::Random(rows, rows); VectorType v1 = VectorType::Random(rows), v2 = VectorType::Random(rows), v3 = VectorType::Random(rows), vzero = VectorType::Zero(rows); Scalar s1 = ei_random<Scalar>(), s2 = ei_random<Scalar>(); // check basic compatibility of adjoint, transpose, conjugate VERIFY_IS_APPROX(m1.transpose().conjugate().adjoint(), m1); VERIFY_IS_APPROX(m1.adjoint().conjugate().transpose(), m1); // check multiplicative behavior VERIFY_IS_APPROX((m1.adjoint() * m2).adjoint(), m2.adjoint() * m1); VERIFY_IS_APPROX((s1 * m1).adjoint(), ei_conj(s1) * m1.adjoint()); // check basic properties of dot, norm, norm2 typedef typename NumTraits<Scalar>::Real RealScalar; VERIFY(ei_isApprox((s1 * v1 + s2 * v2).dot(v3), s1 * v1.dot(v3) + s2 * v2.dot(v3), largerEps)); VERIFY(ei_isApprox(v3.dot(s1 * v1 + s2 * v2), ei_conj(s1)*v3.dot(v1)+ei_conj(s2)*v3.dot(v2), largerEps)); VERIFY_IS_APPROX(ei_conj(v1.dot(v2)), v2.dot(v1)); VERIFY_IS_APPROX(ei_abs(v1.dot(v1)), v1.squaredNorm()); if(NumTraits<Scalar>::HasFloatingPoint) VERIFY_IS_APPROX(v1.squaredNorm(), v1.norm() * v1.norm()); VERIFY_IS_MUCH_SMALLER_THAN(ei_abs(vzero.dot(v1)), static_cast<RealScalar>(1)); if(NumTraits<Scalar>::HasFloatingPoint) VERIFY_IS_MUCH_SMALLER_THAN(vzero.norm(), static_cast<RealScalar>(1)); // check compatibility of dot and adjoint VERIFY(ei_isApprox(v1.dot(square * v2), (square.adjoint() * v1).dot(v2), largerEps)); // like in testBasicStuff, test operator() to check const-qualification int r = ei_random<int>(0, rows-1), c = ei_random<int>(0, cols-1); VERIFY_IS_APPROX(m1.conjugate()(r,c), ei_conj(m1(r,c))); VERIFY_IS_APPROX(m1.adjoint()(c,r), ei_conj(m1(r,c))); if(NumTraits<Scalar>::HasFloatingPoint) { // check that Random().normalized() works: tricky as the random xpr must be evaluated by // normalized() in order to produce a consistent result. VERIFY_IS_APPROX(VectorType::Random(rows).normalized().norm(), RealScalar(1)); } // check inplace transpose m3 = m1; m3.transposeInPlace(); VERIFY_IS_APPROX(m3,m1.transpose()); m3.transposeInPlace(); VERIFY_IS_APPROX(m3,m1); }
template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& ref) { typedef typename SparseMatrixType::Index Index; const Index rows = ref.rows(); const Index cols = ref.cols(); typedef typename SparseMatrixType::Scalar Scalar; enum { Flags = SparseMatrixType::Flags }; double density = (std::max)(8./(rows*cols), 0.01); typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix; typedef Matrix<Scalar,Dynamic,1> DenseVector; Scalar eps = 1e-6; SparseMatrixType m(rows, cols); DenseMatrix refMat = DenseMatrix::Zero(rows, cols); DenseVector vec1 = DenseVector::Random(rows); Scalar s1 = internal::random<Scalar>(); std::vector<Vector2i> zeroCoords; std::vector<Vector2i> nonzeroCoords; initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords); if (zeroCoords.size()==0 || nonzeroCoords.size()==0) return; // test coeff and coeffRef for (int i=0; i<(int)zeroCoords.size(); ++i) { VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps ); if(internal::is_same<SparseMatrixType,SparseMatrix<Scalar,Flags> >::value) VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[0].x(),zeroCoords[0].y()) = 5 ); } VERIFY_IS_APPROX(m, refMat); m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5); refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5); VERIFY_IS_APPROX(m, refMat); /* // test InnerIterators and Block expressions for (int t=0; t<10; ++t) { int j = internal::random<int>(0,cols-1); int i = internal::random<int>(0,rows-1); int w = internal::random<int>(1,cols-j-1); int h = internal::random<int>(1,rows-i-1); // VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w)); for(int c=0; c<w; c++) { VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c)); for(int r=0; r<h; r++) { // VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r)); } } // for(int r=0; r<h; r++) // { // VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r)); // for(int c=0; c<w; c++) // { // VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c)); // } // } } for(int c=0; c<cols; c++) { VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c)); VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c)); } for(int r=0; r<rows; r++) { VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r)); VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r)); } */ // test insert (inner random) { DenseMatrix m1(rows,cols); m1.setZero(); SparseMatrixType m2(rows,cols); m2.reserve(10); for (int j=0; j<cols; ++j) { for (int k=0; k<rows/2; ++k) { int i = internal::random<int>(0,rows-1); if (m1.coeff(i,j)==Scalar(0)) m2.insert(i,j) = m1(i,j) = internal::random<Scalar>(); } } m2.finalize(); VERIFY_IS_APPROX(m2,m1); } // test insert (fully random) { DenseMatrix m1(rows,cols); m1.setZero(); SparseMatrixType m2(rows,cols); m2.reserve(10); for (int k=0; k<rows*cols; ++k) { int i = internal::random<int>(0,rows-1); int j = internal::random<int>(0,cols-1); if (m1.coeff(i,j)==Scalar(0)) m2.insert(i,j) = m1(i,j) = internal::random<Scalar>(); } m2.finalize(); VERIFY_IS_APPROX(m2,m1); } // test basic computations { DenseMatrix refM1 = DenseMatrix::Zero(rows, rows); DenseMatrix refM2 = DenseMatrix::Zero(rows, rows); DenseMatrix refM3 = DenseMatrix::Zero(rows, rows); DenseMatrix refM4 = DenseMatrix::Zero(rows, rows); SparseMatrixType m1(rows, rows); SparseMatrixType m2(rows, rows); SparseMatrixType m3(rows, rows); SparseMatrixType m4(rows, rows); initSparse<Scalar>(density, refM1, m1); initSparse<Scalar>(density, refM2, m2); initSparse<Scalar>(density, refM3, m3); initSparse<Scalar>(density, refM4, m4); VERIFY_IS_APPROX(m1+m2, refM1+refM2); VERIFY_IS_APPROX(m1+m2+m3, refM1+refM2+refM3); VERIFY_IS_APPROX(m3.cwiseProduct(m1+m2), refM3.cwiseProduct(refM1+refM2)); VERIFY_IS_APPROX(m1*s1-m2, refM1*s1-refM2); VERIFY_IS_APPROX(m1*=s1, refM1*=s1); VERIFY_IS_APPROX(m1/=s1, refM1/=s1); VERIFY_IS_APPROX(m1+=m2, refM1+=refM2); VERIFY_IS_APPROX(m1-=m2, refM1-=refM2); VERIFY_IS_APPROX(m1.col(0).dot(refM2.row(0)), refM1.col(0).dot(refM2.row(0))); refM4.setRandom(); // sparse cwise* dense VERIFY_IS_APPROX(m3.cwiseProduct(refM4), refM3.cwiseProduct(refM4)); // VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4); } // test transpose { DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows); SparseMatrixType m2(rows, rows); initSparse<Scalar>(density, refMat2, m2); VERIFY_IS_APPROX(m2.transpose().eval(), refMat2.transpose().eval()); VERIFY_IS_APPROX(m2.transpose(), refMat2.transpose()); VERIFY_IS_APPROX(SparseMatrixType(m2.adjoint()), refMat2.adjoint()); } // test innerVector() { DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows); SparseMatrixType m2(rows, rows); initSparse<Scalar>(density, refMat2, m2); int j0 = internal::random(0,rows-1); int j1 = internal::random(0,rows-1); VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0)); VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1)); //m2.innerVector(j0) = 2*m2.innerVector(j1); //refMat2.col(j0) = 2*refMat2.col(j1); //VERIFY_IS_APPROX(m2, refMat2); } // test innerVectors() { DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows); SparseMatrixType m2(rows, rows); initSparse<Scalar>(density, refMat2, m2); int j0 = internal::random(0,rows-2); int j1 = internal::random(0,rows-2); int n0 = internal::random<int>(1,rows-(std::max)(j0,j1)); VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0)); VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0), refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0)); //m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0); //refMat2.block(0,j0,rows,n0) = refMat2.block(0,j0,rows,n0) + refMat2.block(0,j1,rows,n0); } // test prune { SparseMatrixType m2(rows, rows); DenseMatrix refM2(rows, rows); refM2.setZero(); int countFalseNonZero = 0; int countTrueNonZero = 0; for (int j=0; j<m2.outerSize(); ++j) { m2.startVec(j); for (int i=0; i<m2.innerSize(); ++i) { float x = internal::random<float>(0,1); if (x<0.1) { // do nothing } else if (x<0.5) { countFalseNonZero++; m2.insertBackByOuterInner(j,i) = Scalar(0); } else { countTrueNonZero++; m2.insertBackByOuterInner(j,i) = refM2(i,j) = Scalar(1); } } } m2.finalize(); VERIFY(countFalseNonZero+countTrueNonZero == m2.nonZeros()); VERIFY_IS_APPROX(m2, refM2); m2.prune(Scalar(1)); VERIFY(countTrueNonZero==m2.nonZeros()); VERIFY_IS_APPROX(m2, refM2); } // test selfadjointView { DenseMatrix refMat2(rows, rows), refMat3(rows, rows); SparseMatrixType m2(rows, rows), m3(rows, rows); initSparse<Scalar>(density, refMat2, m2); refMat3 = refMat2.template selfadjointView<Lower>(); m3 = m2.template selfadjointView<Lower>(); VERIFY_IS_APPROX(m3, refMat3); } // test sparseView { DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows); SparseMatrixType m2(rows, rows); initSparse<Scalar>(density, refMat2, m2); VERIFY_IS_APPROX(m2.eval(), refMat2.sparseView().eval()); } }
int main() { #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef MoveOnly V; typedef test_compare<std::less<MoveOnly> > C; typedef test_allocator<V> A; typedef std::multiset<MoveOnly, C, A> M; typedef std::move_iterator<V*> I; V a1[] = { V(1), V(1), V(1), V(2), V(2), V(2), V(3), V(3), V(3) }; M m1(I(a1), I(a1+sizeof(a1)/sizeof(a1[0])), C(5), A(7)); V a2[] = { V(1), V(1), V(1), V(2), V(2), V(2), V(3), V(3), V(3) }; M m2(I(a2), I(a2+sizeof(a2)/sizeof(a2[0])), C(5), A(7)); M m3(std::move(m1), A(7)); assert(m3 == m2); assert(m3.get_allocator() == A(7)); assert(m3.key_comp() == C(5)); assert(m1.empty()); } { typedef MoveOnly V; typedef test_compare<std::less<MoveOnly> > C; typedef test_allocator<V> A; typedef std::multiset<MoveOnly, C, A> M; typedef std::move_iterator<V*> I; V a1[] = { V(1), V(1), V(1), V(2), V(2), V(2), V(3), V(3), V(3) }; M m1(I(a1), I(a1+sizeof(a1)/sizeof(a1[0])), C(5), A(7)); V a2[] = { V(1), V(1), V(1), V(2), V(2), V(2), V(3), V(3), V(3) }; M m2(I(a2), I(a2+sizeof(a2)/sizeof(a2[0])), C(5), A(7)); M m3(std::move(m1), A(5)); assert(m3 == m2); assert(m3.get_allocator() == A(5)); assert(m3.key_comp() == C(5)); assert(m1.empty()); } { typedef MoveOnly V; typedef test_compare<std::less<MoveOnly> > C; typedef other_allocator<V> A; typedef std::multiset<MoveOnly, C, A> M; typedef std::move_iterator<V*> I; V a1[] = { V(1), V(1), V(1), V(2), V(2), V(2), V(3), V(3), V(3) }; M m1(I(a1), I(a1+sizeof(a1)/sizeof(a1[0])), C(5), A(7)); V a2[] = { V(1), V(1), V(1), V(2), V(2), V(2), V(3), V(3), V(3) }; M m2(I(a2), I(a2+sizeof(a2)/sizeof(a2[0])), C(5), A(7)); M m3(std::move(m1), A(5)); assert(m3 == m2); assert(m3.get_allocator() == A(5)); assert(m3.key_comp() == C(5)); assert(m1.empty()); } { typedef Counter<int> V; typedef std::less<V> C; typedef test_allocator<V> A; typedef std::multiset<V, C, A> M; typedef V* I; Counter_base::gConstructed = 0; { V a1[] = { V(1), V(1), V(1), V(2), V(2), V(2), V(3), V(3), V(3) }; const size_t num = sizeof(a1)/sizeof(a1[0]); assert(Counter_base::gConstructed == num); M m1(I(a1), I(a1+num), C(), A()); assert(Counter_base::gConstructed == 2*num); M m2(m1); assert(m2 == m1); assert(Counter_base::gConstructed == 3*num); M m3(std::move(m1), A()); assert(m3 == m2); assert(m1.empty()); assert(Counter_base::gConstructed == 3*num); { M m4(std::move(m2), A(5)); assert(Counter_base::gConstructed == 3*num); assert(m4 == m3); assert(m2.empty()); } assert(Counter_base::gConstructed == 2*num); } assert(Counter_base::gConstructed == 0); } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES }
template<typename MatrixType> void basicStuff(const MatrixType& m) { typedef typename MatrixType::Scalar Scalar; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType; int rows = m.rows(); int cols = m.cols(); // this test relies a lot on Random.h, and there's not much more that we can do // to test it, hence I consider that we will have tested Random.h MatrixType m1 = MatrixType::Random(rows, cols), m2 = MatrixType::Random(rows, cols), m3(rows, cols), mzero = MatrixType::Zero(rows, cols), identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> ::Identity(rows, rows), square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>::Random(rows, rows); VectorType v1 = VectorType::Random(rows), v2 = VectorType::Random(rows), vzero = VectorType::Zero(rows); Scalar x = ei_random<Scalar>(); int r = ei_random<int>(0, rows-1), c = ei_random<int>(0, cols-1); m1.coeffRef(r,c) = x; VERIFY_IS_APPROX(x, m1.coeff(r,c)); m1(r,c) = x; VERIFY_IS_APPROX(x, m1(r,c)); v1.coeffRef(r) = x; VERIFY_IS_APPROX(x, v1.coeff(r)); v1(r) = x; VERIFY_IS_APPROX(x, v1(r)); v1[r] = x; VERIFY_IS_APPROX(x, v1[r]); VERIFY_IS_APPROX( v1, v1); VERIFY_IS_NOT_APPROX( v1, 2*v1); VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1); if(NumTraits<Scalar>::HasFloatingPoint) VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1.norm()); VERIFY_IS_NOT_MUCH_SMALLER_THAN(v1, v1); VERIFY_IS_APPROX( vzero, v1-v1); VERIFY_IS_APPROX( m1, m1); VERIFY_IS_NOT_APPROX( m1, 2*m1); VERIFY_IS_MUCH_SMALLER_THAN( mzero, m1); VERIFY_IS_NOT_MUCH_SMALLER_THAN(m1, m1); VERIFY_IS_APPROX( mzero, m1-m1); // always test operator() on each read-only expression class, // in order to check const-qualifiers. // indeed, if an expression class (here Zero) is meant to be read-only, // hence has no _write() method, the corresponding MatrixBase method (here zero()) // should return a const-qualified object so that it is the const-qualified // operator() that gets called, which in turn calls _read(). VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows,cols)(r,c), static_cast<Scalar>(1)); // now test copying a row-vector into a (column-)vector and conversely. square.col(r) = square.row(r).eval(); Matrix<Scalar, 1, MatrixType::RowsAtCompileTime> rv(rows); Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> cv(rows); rv = square.row(r); cv = square.col(r); VERIFY_IS_APPROX(rv, cv.transpose()); if(cols!=1 && rows!=1 && MatrixType::SizeAtCompileTime!=Dynamic) { VERIFY_RAISES_ASSERT(m1 = (m2.block(0,0, rows-1, cols-1))); } VERIFY_IS_APPROX(m3 = m1,m1); MatrixType m4; VERIFY_IS_APPROX(m4 = m1,m1); // test swap m3 = m1; m1.swap(m2); VERIFY_IS_APPROX(m3, m2); if(rows*cols>=3) { VERIFY_IS_NOT_APPROX(m3, m1); } }
/****************************************************************************** One forward-backward pass through a minimum-duration HMM model with a single Gaussian in each of the states. T: totalFeatures *******************************************************************************/ double ESHMM::mdHMMLogForwardBackward(ESHMM *mdHMM, VECTOR_OF_F_VECTORS *features, double **post, int T, mat &gamma, rowvec &gamma1, mat &sumxi){ printf("forward backward algorithm calculation in progress...\n"); int i = 0, j = 0 , k = 0; /* total no of states is much larger, instead of number of pdfs we have to extend states by Min_DUR, therefore total states = Q * MD */ int Q = mdHMM->hmmStates; int Qmd = Q * MIN_DUR; mat logalpha(T, Qmd); // forward probability matrix mat logbeta(T, Qmd); // backward probability matrix mat logg(T, Qmd); // loggamma mat m(Q, 1); mat logA(Qmd, Qmd); /// transition matrix is already in logarithm mat new_logp(T, Qmd); // after replication for each substates mat logp_k(Q, T); // we have single cluster only, probability of each feature corresponding to each cluster printf("Q: %d Qmd: %d\n", Q, Qmd); for(i = 0; i < Qmd; i++){ for(j = 0; j < Qmd; j++){ logA(i, j) = mdHMM->trans[i]->array[j]; } } // minimum duration viterbi hence modify B(posterior) prob matrix for(i = 0; i < Q; i++) for(j = 0; j < T; j++){ logp_k(i, j) = post[i][j]; } for(i = 0; i < Q; i++){ m(i, 0) = 1; for(j = 0; j < T; j++) logp_k(i, j) = 0.0; // since we have only one cluster so cluster probability and // total probability is same. Hence subtracting cluster probability from total probability would make it zero. } // modifying logp matrix according to minimum duration for(i = 0; i < Q; i++){ for(j = 0; j < T; j++){ for(k = i*MIN_DUR; k < (i+1)*MIN_DUR; k++){ new_logp(j, k) = post[i][j]; } } } /* forward initialization */ // for summing log probabilties, first sum probs and then take logarithm printf("forward initialization...\n\n"); for(i = 0; i < Qmd; i++){ logalpha(0, i) = mdHMM->prior->array[i] + new_logp(0, i) ; } ///print logalpha after initialization for(i = 0; i < Qmd; i++) printf("%lf ", logalpha(0, i)); /* forward induction */ printf("forward induction in progress...\n"); int t = 0; mpfr_t summation3; mpfr_init(summation3); mpfr_t var11, var21; mpfr_init(var11); mpfr_init(var21); mpfr_set_d(var11, 0.0, MPFR_RNDN); mpfr_set_d(var21, 0.0, MPFR_RNDN); mpfr_set_d(summation3, 0.0, MPFR_RNDN); for(t = 1; t < T; t++){ //printf("%d ", t); for(j = 0; j < Qmd; j++){ vec v1(Qmd), v2(Qmd); vec v3(Qmd); //first find logalpha vector for(i = 0; i < Qmd; i++) v1(i) = logalpha(t-1, i); // if(t < 20) // v1.print("v1:\n"); // extract transition probability vector for(i = 0; i < Qmd; i++) v2(i) = logA(i, j); // if(t < 20) // v2.print("v2:\n"); // Now sum both the vectors into one for(i = 0; i < Qmd; i++) v3(i) = v1(i) + v2(i); double *temp = (double *)calloc(Qmd, sizeof(double )); for(i = 0; i < Qmd; i++) temp[i] = v3(i); // if(t < 20) // v3.print("v3:\n"); //printf("printed\n"); // now sum over whole column vector mpfr_set_d(summation3, 0.0, MPFR_RNDN); // take the exponentiation and summation in one loop // getting double from mpfr variable /// double mpfr_get_d(mpfr_t op, mpfr_rnd_t rnd); //mpfr_set_d(var1, 0.0, MPFR_RNDD); //mpfr_set_d(var2, 0.0, MPFR_RNDD); // now take the exponentiation for(i = 0; i < Qmd; i++){ double elem = temp[i]; mpfr_set_d(var21, elem, MPFR_RNDD); //mpfr_printf("var2: %lf\n", var21); mpfr_exp(var11, var21, MPFR_RNDD); ///take exp(v2) and store in v1 // take sum of all elements in total mpfr_add(summation3, summation3, var11, MPFR_RNDD); // add summation and v1 } // now take the logarithm of sum mpfr_log(summation3, summation3, MPFR_RNDD); // now convert this sum to double double sum2 = mpfr_get_d(summation3, MPFR_RNDD); // now assign this double to logalpha // now add logp(t, j) sum2 += new_logp(t, j); // if(t < 20) // printf("sum: %lf\n", sum2); logalpha(t, j) = sum2; /// clear mpfr variables } if(t < 20){ printf("logalpha:\n"); for(j = 0; j < Qmd; j++) printf("%lf ", logalpha(t, j)); printf("\n"); } } // close the forward induction loop mpfr_clear(var11); mpfr_clear(var21); mpfr_clear(summation3); /* forward termination */ double ll = 0; // total log likelihood of all observation given this HMM for(i = 0; i < Qmd; i++){ ll += logalpha(T-1, i); } ///=================================================================== // for(i = 0; i < 100; i++){ // for(j = 0; j < Qmd; j++) // printf("%lf ", logalpha(i, j)); // printf("\n"); // } printf("\nprinting last column of logalpha...\n"); for(i = 1; i < 6; i++){ for(j = 0; j < Qmd; j++) printf("%lf ", logalpha(T-i, j)); printf("\n"); } printf("total loglikelihood: %lf\n", ll); ///=================================================================== double sum = 0; /* calculate logalpha last row sum */ for(i = 0; i < Qmd; i++) sum += logalpha(T-1, i); ll = sum; printf("LL: %lf........\n", ll); /* backward initilization */ /// intialize mpfr variables mpfr_t summation; mpfr_init(summation); mpfr_t var1, var2; mpfr_init(var1); mpfr_init(var2); mpfr_set_d(summation, 0.0, MPFR_RNDN); mpfr_set_d(var1, 0.0, MPFR_RNDN); mpfr_set_d(var2, 0.0, MPFR_RNDN); printf("backward initialization...\n"); mpfr_set_d(summation, 0.0, MPFR_RNDN); double *temp = (double *)calloc(Qmd, sizeof(double )); for(i = 0; i < Qmd; i++) temp[i] = logalpha(T-1, i); for(i = 0; i < Qmd; i++){ //double elem = logalpha(T-1, i); double elem = temp[i-1]; mpfr_set_d(var2, elem, MPFR_RNDN); mpfr_exp(var1, var2, MPFR_RNDN); mpfr_add(summation, summation, var1, MPFR_RNDN); } // take logarithm mpfr_log(summation, summation, MPFR_RNDN); double sum2 = mpfr_get_d(summation, MPFR_RNDN); for(i = 0; i < Qmd; i++){ logg(T-1, i) = logalpha(T-1, i) - sum2 ; } // gamma matrix for(j = 0; j < Q; j++){ gamma(j, T-1) = exp(logp_k(j, T-1) + logg(T-1, j)); } mat lognewxi(Qmd, Qmd); // declare lognewxi matrix /* backward induction */ printf("backward induction in progress...\n"); for(t = T-2; t >= 0 ; t--){ for(j = 0; j < Qmd; j++){ vec v1(Qmd); vec v2(Qmd); vec v3(Qmd); sum = 0; for(i = 0; i < Qmd; i++) v1(i) = logA(j, i); for(i = 0; i < Qmd; i++) v2(i) = logbeta(t+1, i); for(i = 0; i < Qmd; i++) v3(i) = new_logp(t+1, i); // add all three vectors for(i = 0; i < Qmd; i++) v1(i) += v2(i) + v3(i); mpfr_set_d(summation, 0.0, MPFR_RNDN); for(i = 0; i < Qmd; i++){ double elem = v1(i); mpfr_set_d(var2, elem, MPFR_RNDN); mpfr_exp(var1, var2, MPFR_RNDN); mpfr_add(summation, summation, var1, MPFR_RNDN); } mpfr_log(summation, summation, MPFR_RNDN); sum2 = mpfr_get_d(summation, MPFR_RNDN); logbeta(t, j) = sum2; } // computation of log(gamma) is now possible called logg here for(i = 0; i < Qmd; i++){ logg(t, i) = logalpha(t, i) + logbeta(t, i); } mpfr_set_d(summation, 0.0, MPFR_RNDN); for(i = 0; i < Qmd; i++){ double elem = logg(t, i); mpfr_set_d(var2, elem, MPFR_RNDN); mpfr_exp(var1, var2, MPFR_RNDN); mpfr_add(summation, summation, var1, MPFR_RNDN); } mpfr_log(summation, summation, MPFR_RNDN); sum2 = mpfr_get_d(summation, MPFR_RNDN); for(i = 0; i < Qmd; i++) logg(t, i) = logg(t, i) - sum2; // finally the gamma_k is computed (called gamma here ) mpfr_set_d(summation, 0.0, MPFR_RNDN); for(j = 0; j < Q; j++){ // for(i = j*MIN_DUR; i < (j+1) * MIN_DUR; i++){ // sum += exp(logg(t, i)); // } gamma(j, t) = exp( logp_k(j, t) + logg(t, j) ); } /* for the EM algorithm we need the sum over xi all over t */ // replicate logalpha(t, :)' matrix along columns mat m1(Qmd, Qmd); for(i = 0; i < Qmd; i++){ for(j = 0; j < Qmd; j++){ m1(i, j) = logalpha(t, i); } } // replicate logbeta matrix vec v1(Qmd); for(i = 0; i < Qmd; i++) v1(i) = logbeta(t+1, i); vec v2(Qmd); for(i = 0; i < Qmd; i++) v2(i) = new_logp(t+1, i); vec v3(Qmd); for(i = 0; i < Qmd; i++) v3(i) = v1(i) + v2(i); // replicate v3 row vector along all rows of matrix m2 mat m2(Qmd, Qmd); for(i = 0; i < Qmd; i++){ for(j = 0; j < Qmd; j++){ m2(i, j) = v3(i); } } // add both matrices m1 and m2 mat m3(Qmd, Qmd); m3 = m1 + m2; // can do direct addition ///mat lognewxi(Qmd, Qmd); // declare lognewxi matrix lognewxi.zeros(); lognewxi = m3 + logA; // add new sum to older sumxi /// first subtract total sum from lognewxi mpfr_set_d(summation, 0.0, MPFR_RNDN); for(i = 0; i < Qmd; i++){ for(j = 0; j < Qmd; j++){ double elem = lognewxi(i, j); mpfr_set_d(var2, elem, MPFR_RNDN); mpfr_exp(var1, var2, MPFR_RNDN); mpfr_add(summation, summation, var1, MPFR_RNDN); //sum += exp(lognewxi(i, j)); } } // now take the logarithm of sum mpfr_log(summation, summation, MPFR_RNDN); sum2 = mpfr_get_d(summation, MPFR_RNDN); // subtract sum from lognewxi for(i = 0; i < Qmd; i++){ for(j = 0; j < Qmd; j++){ lognewxi(i, j) = lognewxi(i, j) - sum2; } } mat newxi(Qmd, Qmd); newxi = lognewxi; // add sumxi and newlogsumxi /// take exponential of each element for(i = 0; i < Qmd; i++){ for(j = 0; j < Qmd; j++){ newxi(i, j) = exp(newxi(i, j)); } } sumxi = sumxi + newxi; } // close the backward induction loop /* handle annoying numerics */ /// calculate sum of lognewxi along each row (lognewxi is already modified in our case) for(i = 0; i < Qmd; i++){ mpfr_set_d(summation, 0.0, MPFR_RNDN); for(j = 0; j < Qmd; j++){ //sum += lognewxi(i, j); double elem = lognewxi(i, j); mpfr_set_d(var2, elem, MPFR_RNDN); mpfr_exp(var1, var2, MPFR_RNDN); mpfr_add(summation, summation, var1, MPFR_RNDN); } sum2 = mpfr_get_d(summation, MPFR_RNDN); gamma1(i) = sum2; } // normalize gamma1 which is prior and normalize sumxi which is transition matrix sum = 0; for(i = 0; i < Qmd; i++) sum += gamma1(i); for(i = 0; i < Qmd; i++) gamma1(i) /= sum; // transition probability matrix will be normalized in train_hmm function /// clear mpfr variables mpfr_clear(summation); mpfr_clear(var1); mpfr_clear(var2); printf("forward-backward algorithm calculation is done...\n"); /* finished forward-backward algorithm */ return ll; }
template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& ref) { typedef typename SparseMatrixType::StorageIndex StorageIndex; typedef Matrix<StorageIndex,2,1> Vector2; const Index rows = ref.rows(); const Index cols = ref.cols(); //const Index inner = ref.innerSize(); //const Index outer = ref.outerSize(); typedef typename SparseMatrixType::Scalar Scalar; enum { Flags = SparseMatrixType::Flags }; double density = (std::max)(8./(rows*cols), 0.01); typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix; typedef Matrix<Scalar,Dynamic,1> DenseVector; Scalar eps = 1e-6; Scalar s1 = internal::random<Scalar>(); { SparseMatrixType m(rows, cols); DenseMatrix refMat = DenseMatrix::Zero(rows, cols); DenseVector vec1 = DenseVector::Random(rows); std::vector<Vector2> zeroCoords; std::vector<Vector2> nonzeroCoords; initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords); // test coeff and coeffRef for (std::size_t i=0; i<zeroCoords.size(); ++i) { VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps ); if(internal::is_same<SparseMatrixType,SparseMatrix<Scalar,Flags> >::value) VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[i].x(),zeroCoords[i].y()) = 5 ); } VERIFY_IS_APPROX(m, refMat); if(!nonzeroCoords.empty()) { m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5); refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5); } VERIFY_IS_APPROX(m, refMat); // test assertion VERIFY_RAISES_ASSERT( m.coeffRef(-1,1) = 0 ); VERIFY_RAISES_ASSERT( m.coeffRef(0,m.cols()) = 0 ); } // test insert (inner random) { DenseMatrix m1(rows,cols); m1.setZero(); SparseMatrixType m2(rows,cols); bool call_reserve = internal::random<int>()%2; Index nnz = internal::random<int>(1,int(rows)/2); if(call_reserve) { if(internal::random<int>()%2) m2.reserve(VectorXi::Constant(m2.outerSize(), int(nnz))); else m2.reserve(m2.outerSize() * nnz); } g_realloc_count = 0; for (Index j=0; j<cols; ++j) { for (Index k=0; k<nnz; ++k) { Index i = internal::random<Index>(0,rows-1); if (m1.coeff(i,j)==Scalar(0)) m2.insert(i,j) = m1(i,j) = internal::random<Scalar>(); } } if(call_reserve && !SparseMatrixType::IsRowMajor) { VERIFY(g_realloc_count==0); } m2.finalize(); VERIFY_IS_APPROX(m2,m1); } // test insert (fully random) { DenseMatrix m1(rows,cols); m1.setZero(); SparseMatrixType m2(rows,cols); if(internal::random<int>()%2) m2.reserve(VectorXi::Constant(m2.outerSize(), 2)); for (int k=0; k<rows*cols; ++k) { Index i = internal::random<Index>(0,rows-1); Index j = internal::random<Index>(0,cols-1); if ((m1.coeff(i,j)==Scalar(0)) && (internal::random<int>()%2)) m2.insert(i,j) = m1(i,j) = internal::random<Scalar>(); else { Scalar v = internal::random<Scalar>(); m2.coeffRef(i,j) += v; m1(i,j) += v; } } VERIFY_IS_APPROX(m2,m1); } // test insert (un-compressed) for(int mode=0;mode<4;++mode) { DenseMatrix m1(rows,cols); m1.setZero(); SparseMatrixType m2(rows,cols); VectorXi r(VectorXi::Constant(m2.outerSize(), ((mode%2)==0) ? int(m2.innerSize()) : std::max<int>(1,int(m2.innerSize())/8))); m2.reserve(r); for (Index k=0; k<rows*cols; ++k) { Index i = internal::random<Index>(0,rows-1); Index j = internal::random<Index>(0,cols-1); if (m1.coeff(i,j)==Scalar(0)) m2.insert(i,j) = m1(i,j) = internal::random<Scalar>(); if(mode==3) m2.reserve(r); } if(internal::random<int>()%2) m2.makeCompressed(); VERIFY_IS_APPROX(m2,m1); } // test basic computations { DenseMatrix refM1 = DenseMatrix::Zero(rows, cols); DenseMatrix refM2 = DenseMatrix::Zero(rows, cols); DenseMatrix refM3 = DenseMatrix::Zero(rows, cols); DenseMatrix refM4 = DenseMatrix::Zero(rows, cols); SparseMatrixType m1(rows, cols); SparseMatrixType m2(rows, cols); SparseMatrixType m3(rows, cols); SparseMatrixType m4(rows, cols); initSparse<Scalar>(density, refM1, m1); initSparse<Scalar>(density, refM2, m2); initSparse<Scalar>(density, refM3, m3); initSparse<Scalar>(density, refM4, m4); if(internal::random<bool>()) m1.makeCompressed(); VERIFY_IS_APPROX(m1*s1, refM1*s1); VERIFY_IS_APPROX(m1+m2, refM1+refM2); VERIFY_IS_APPROX(m1+m2+m3, refM1+refM2+refM3); VERIFY_IS_APPROX(m3.cwiseProduct(m1+m2), refM3.cwiseProduct(refM1+refM2)); VERIFY_IS_APPROX(m1*s1-m2, refM1*s1-refM2); if(SparseMatrixType::IsRowMajor) VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.row(0).dot(refM2.row(0))); else VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.col(0)), refM1.col(0).dot(refM2.col(0))); DenseVector rv = DenseVector::Random(m1.cols()); DenseVector cv = DenseVector::Random(m1.rows()); Index r = internal::random<Index>(0,m1.rows()-2); Index c = internal::random<Index>(0,m1.cols()-1); VERIFY_IS_APPROX(( m1.template block<1,Dynamic>(r,0,1,m1.cols()).dot(rv)) , refM1.row(r).dot(rv)); VERIFY_IS_APPROX(m1.row(r).dot(rv), refM1.row(r).dot(rv)); VERIFY_IS_APPROX(m1.col(c).dot(cv), refM1.col(c).dot(cv)); VERIFY_IS_APPROX(m1.conjugate(), refM1.conjugate()); VERIFY_IS_APPROX(m1.real(), refM1.real()); refM4.setRandom(); // sparse cwise* dense VERIFY_IS_APPROX(m3.cwiseProduct(refM4), refM3.cwiseProduct(refM4)); // dense cwise* sparse VERIFY_IS_APPROX(refM4.cwiseProduct(m3), refM4.cwiseProduct(refM3)); // VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4); VERIFY_IS_APPROX(refM4 + m3, refM4 + refM3); VERIFY_IS_APPROX(m3 + refM4, refM3 + refM4); VERIFY_IS_APPROX(refM4 - m3, refM4 - refM3); VERIFY_IS_APPROX(m3 - refM4, refM3 - refM4); VERIFY_IS_APPROX(m1.sum(), refM1.sum()); VERIFY_IS_APPROX(m1*=s1, refM1*=s1); VERIFY_IS_APPROX(m1/=s1, refM1/=s1); VERIFY_IS_APPROX(m1+=m2, refM1+=refM2); VERIFY_IS_APPROX(m1-=m2, refM1-=refM2); // test aliasing VERIFY_IS_APPROX((m1 = -m1), (refM1 = -refM1)); VERIFY_IS_APPROX((m1 = m1.transpose()), (refM1 = refM1.transpose().eval())); VERIFY_IS_APPROX((m1 = -m1.transpose()), (refM1 = -refM1.transpose().eval())); VERIFY_IS_APPROX((m1 += -m1), (refM1 += -refM1)); if(m1.isCompressed()) { VERIFY_IS_APPROX(m1.coeffs().sum(), m1.sum()); m1.coeffs() += s1; for(Index j = 0; j<m1.outerSize(); ++j) for(typename SparseMatrixType::InnerIterator it(m1,j); it; ++it) refM1(it.row(), it.col()) += s1; VERIFY_IS_APPROX(m1, refM1); } // and/or { typedef SparseMatrix<bool, SparseMatrixType::Options, typename SparseMatrixType::StorageIndex> SpBool; SpBool mb1 = m1.real().template cast<bool>(); SpBool mb2 = m2.real().template cast<bool>(); VERIFY_IS_EQUAL(mb1.template cast<int>().sum(), refM1.real().template cast<bool>().count()); VERIFY_IS_EQUAL((mb1 && mb2).template cast<int>().sum(), (refM1.real().template cast<bool>() && refM2.real().template cast<bool>()).count()); VERIFY_IS_EQUAL((mb1 || mb2).template cast<int>().sum(), (refM1.real().template cast<bool>() || refM2.real().template cast<bool>()).count()); SpBool mb3 = mb1 && mb2; if(mb1.coeffs().all() && mb2.coeffs().all()) { VERIFY_IS_EQUAL(mb3.nonZeros(), (refM1.real().template cast<bool>() && refM2.real().template cast<bool>()).count()); } } } // test reverse iterators { DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols); SparseMatrixType m2(rows, cols); initSparse<Scalar>(density, refMat2, m2); std::vector<Scalar> ref_value(m2.innerSize()); std::vector<Index> ref_index(m2.innerSize()); if(internal::random<bool>()) m2.makeCompressed(); for(Index j = 0; j<m2.outerSize(); ++j) { Index count_forward = 0; for(typename SparseMatrixType::InnerIterator it(m2,j); it; ++it) { ref_value[ref_value.size()-1-count_forward] = it.value(); ref_index[ref_index.size()-1-count_forward] = it.index(); count_forward++; } Index count_reverse = 0; for(typename SparseMatrixType::ReverseInnerIterator it(m2,j); it; --it) { VERIFY_IS_APPROX( std::abs(ref_value[ref_value.size()-count_forward+count_reverse])+1, std::abs(it.value())+1); VERIFY_IS_EQUAL( ref_index[ref_index.size()-count_forward+count_reverse] , it.index()); count_reverse++; } VERIFY_IS_EQUAL(count_forward, count_reverse); } } // test transpose { DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols); SparseMatrixType m2(rows, cols); initSparse<Scalar>(density, refMat2, m2); VERIFY_IS_APPROX(m2.transpose().eval(), refMat2.transpose().eval()); VERIFY_IS_APPROX(m2.transpose(), refMat2.transpose()); VERIFY_IS_APPROX(SparseMatrixType(m2.adjoint()), refMat2.adjoint()); // check isApprox handles opposite storage order typename Transpose<SparseMatrixType>::PlainObject m3(m2); VERIFY(m2.isApprox(m3)); } // test prune { SparseMatrixType m2(rows, cols); DenseMatrix refM2(rows, cols); refM2.setZero(); int countFalseNonZero = 0; int countTrueNonZero = 0; m2.reserve(VectorXi::Constant(m2.outerSize(), int(m2.innerSize()))); for (Index j=0; j<m2.cols(); ++j) { for (Index i=0; i<m2.rows(); ++i) { float x = internal::random<float>(0,1); if (x<0.1f) { // do nothing } else if (x<0.5f) { countFalseNonZero++; m2.insert(i,j) = Scalar(0); } else { countTrueNonZero++; m2.insert(i,j) = Scalar(1); refM2(i,j) = Scalar(1); } } } if(internal::random<bool>()) m2.makeCompressed(); VERIFY(countFalseNonZero+countTrueNonZero == m2.nonZeros()); if(countTrueNonZero>0) VERIFY_IS_APPROX(m2, refM2); m2.prune(Scalar(1)); VERIFY(countTrueNonZero==m2.nonZeros()); VERIFY_IS_APPROX(m2, refM2); } // test setFromTriplets { typedef Triplet<Scalar,StorageIndex> TripletType; std::vector<TripletType> triplets; Index ntriplets = rows*cols; triplets.reserve(ntriplets); DenseMatrix refMat_sum = DenseMatrix::Zero(rows,cols); DenseMatrix refMat_prod = DenseMatrix::Zero(rows,cols); DenseMatrix refMat_last = DenseMatrix::Zero(rows,cols); for(Index i=0;i<ntriplets;++i) { StorageIndex r = internal::random<StorageIndex>(0,StorageIndex(rows-1)); StorageIndex c = internal::random<StorageIndex>(0,StorageIndex(cols-1)); Scalar v = internal::random<Scalar>(); triplets.push_back(TripletType(r,c,v)); refMat_sum(r,c) += v; if(std::abs(refMat_prod(r,c))==0) refMat_prod(r,c) = v; else refMat_prod(r,c) *= v; refMat_last(r,c) = v; } SparseMatrixType m(rows,cols); m.setFromTriplets(triplets.begin(), triplets.end()); VERIFY_IS_APPROX(m, refMat_sum); m.setFromTriplets(triplets.begin(), triplets.end(), std::multiplies<Scalar>()); VERIFY_IS_APPROX(m, refMat_prod); #if (defined(__cplusplus) && __cplusplus >= 201103L) m.setFromTriplets(triplets.begin(), triplets.end(), [] (Scalar,Scalar b) { return b; }); VERIFY_IS_APPROX(m, refMat_last); #endif } // test Map { DenseMatrix refMat2(rows, cols), refMat3(rows, cols); SparseMatrixType m2(rows, cols), m3(rows, cols); initSparse<Scalar>(density, refMat2, m2); initSparse<Scalar>(density, refMat3, m3); { Map<SparseMatrixType> mapMat2(m2.rows(), m2.cols(), m2.nonZeros(), m2.outerIndexPtr(), m2.innerIndexPtr(), m2.valuePtr(), m2.innerNonZeroPtr()); Map<SparseMatrixType> mapMat3(m3.rows(), m3.cols(), m3.nonZeros(), m3.outerIndexPtr(), m3.innerIndexPtr(), m3.valuePtr(), m3.innerNonZeroPtr()); VERIFY_IS_APPROX(mapMat2+mapMat3, refMat2+refMat3); VERIFY_IS_APPROX(mapMat2+mapMat3, refMat2+refMat3); } { MappedSparseMatrix<Scalar,SparseMatrixType::Options,StorageIndex> mapMat2(m2.rows(), m2.cols(), m2.nonZeros(), m2.outerIndexPtr(), m2.innerIndexPtr(), m2.valuePtr(), m2.innerNonZeroPtr()); MappedSparseMatrix<Scalar,SparseMatrixType::Options,StorageIndex> mapMat3(m3.rows(), m3.cols(), m3.nonZeros(), m3.outerIndexPtr(), m3.innerIndexPtr(), m3.valuePtr(), m3.innerNonZeroPtr()); VERIFY_IS_APPROX(mapMat2+mapMat3, refMat2+refMat3); VERIFY_IS_APPROX(mapMat2+mapMat3, refMat2+refMat3); } Index i = internal::random<Index>(0,rows-1); Index j = internal::random<Index>(0,cols-1); m2.coeffRef(i,j) = 123; if(internal::random<bool>()) m2.makeCompressed(); Map<SparseMatrixType> mapMat2(rows, cols, m2.nonZeros(), m2.outerIndexPtr(), m2.innerIndexPtr(), m2.valuePtr(), m2.innerNonZeroPtr()); VERIFY_IS_EQUAL(m2.coeff(i,j),Scalar(123)); VERIFY_IS_EQUAL(mapMat2.coeff(i,j),Scalar(123)); mapMat2.coeffRef(i,j) = -123; VERIFY_IS_EQUAL(m2.coeff(i,j),Scalar(-123)); } // test triangularView { DenseMatrix refMat2(rows, cols), refMat3(rows, cols); SparseMatrixType m2(rows, cols), m3(rows, cols); initSparse<Scalar>(density, refMat2, m2); refMat3 = refMat2.template triangularView<Lower>(); m3 = m2.template triangularView<Lower>(); VERIFY_IS_APPROX(m3, refMat3); refMat3 = refMat2.template triangularView<Upper>(); m3 = m2.template triangularView<Upper>(); VERIFY_IS_APPROX(m3, refMat3); { refMat3 = refMat2.template triangularView<UnitUpper>(); m3 = m2.template triangularView<UnitUpper>(); VERIFY_IS_APPROX(m3, refMat3); refMat3 = refMat2.template triangularView<UnitLower>(); m3 = m2.template triangularView<UnitLower>(); VERIFY_IS_APPROX(m3, refMat3); } refMat3 = refMat2.template triangularView<StrictlyUpper>(); m3 = m2.template triangularView<StrictlyUpper>(); VERIFY_IS_APPROX(m3, refMat3); refMat3 = refMat2.template triangularView<StrictlyLower>(); m3 = m2.template triangularView<StrictlyLower>(); VERIFY_IS_APPROX(m3, refMat3); // check sparse-traingular to dense refMat3 = m2.template triangularView<StrictlyUpper>(); VERIFY_IS_APPROX(refMat3, DenseMatrix(refMat2.template triangularView<StrictlyUpper>())); } // test selfadjointView if(!SparseMatrixType::IsRowMajor) { DenseMatrix refMat2(rows, rows), refMat3(rows, rows); SparseMatrixType m2(rows, rows), m3(rows, rows); initSparse<Scalar>(density, refMat2, m2); refMat3 = refMat2.template selfadjointView<Lower>(); m3 = m2.template selfadjointView<Lower>(); VERIFY_IS_APPROX(m3, refMat3); refMat3 += refMat2.template selfadjointView<Lower>(); m3 += m2.template selfadjointView<Lower>(); VERIFY_IS_APPROX(m3, refMat3); refMat3 -= refMat2.template selfadjointView<Lower>(); m3 -= m2.template selfadjointView<Lower>(); VERIFY_IS_APPROX(m3, refMat3); // selfadjointView only works for square matrices: SparseMatrixType m4(rows, rows+1); VERIFY_RAISES_ASSERT(m4.template selfadjointView<Lower>()); VERIFY_RAISES_ASSERT(m4.template selfadjointView<Upper>()); } // test sparseView { DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows); SparseMatrixType m2(rows, rows); initSparse<Scalar>(density, refMat2, m2); VERIFY_IS_APPROX(m2.eval(), refMat2.sparseView().eval()); // sparse view on expressions: VERIFY_IS_APPROX((s1*m2).eval(), (s1*refMat2).sparseView().eval()); VERIFY_IS_APPROX((m2+m2).eval(), (refMat2+refMat2).sparseView().eval()); VERIFY_IS_APPROX((m2*m2).eval(), (refMat2.lazyProduct(refMat2)).sparseView().eval()); VERIFY_IS_APPROX((m2*m2).eval(), (refMat2*refMat2).sparseView().eval()); } // test diagonal { DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols); SparseMatrixType m2(rows, cols); initSparse<Scalar>(density, refMat2, m2); VERIFY_IS_APPROX(m2.diagonal(), refMat2.diagonal().eval()); VERIFY_IS_APPROX(const_cast<const SparseMatrixType&>(m2).diagonal(), refMat2.diagonal().eval()); initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag); m2.diagonal() += refMat2.diagonal(); refMat2.diagonal() += refMat2.diagonal(); VERIFY_IS_APPROX(m2, refMat2); } // test diagonal to sparse { DenseVector d = DenseVector::Random(rows); DenseMatrix refMat2 = d.asDiagonal(); SparseMatrixType m2(rows, rows); m2 = d.asDiagonal(); VERIFY_IS_APPROX(m2, refMat2); SparseMatrixType m3(d.asDiagonal()); VERIFY_IS_APPROX(m3, refMat2); refMat2 += d.asDiagonal(); m2 += d.asDiagonal(); VERIFY_IS_APPROX(m2, refMat2); } // test conservative resize { std::vector< std::pair<StorageIndex,StorageIndex> > inc; if(rows > 3 && cols > 2) inc.push_back(std::pair<StorageIndex,StorageIndex>(-3,-2)); inc.push_back(std::pair<StorageIndex,StorageIndex>(0,0)); inc.push_back(std::pair<StorageIndex,StorageIndex>(3,2)); inc.push_back(std::pair<StorageIndex,StorageIndex>(3,0)); inc.push_back(std::pair<StorageIndex,StorageIndex>(0,3)); for(size_t i = 0; i< inc.size(); i++) { StorageIndex incRows = inc[i].first; StorageIndex incCols = inc[i].second; SparseMatrixType m1(rows, cols); DenseMatrix refMat1 = DenseMatrix::Zero(rows, cols); initSparse<Scalar>(density, refMat1, m1); m1.conservativeResize(rows+incRows, cols+incCols); refMat1.conservativeResize(rows+incRows, cols+incCols); if (incRows > 0) refMat1.bottomRows(incRows).setZero(); if (incCols > 0) refMat1.rightCols(incCols).setZero(); VERIFY_IS_APPROX(m1, refMat1); // Insert new values if (incRows > 0) m1.insert(m1.rows()-1, 0) = refMat1(refMat1.rows()-1, 0) = 1; if (incCols > 0) m1.insert(0, m1.cols()-1) = refMat1(0, refMat1.cols()-1) = 1; VERIFY_IS_APPROX(m1, refMat1); } } // test Identity matrix { DenseMatrix refMat1 = DenseMatrix::Identity(rows, rows); SparseMatrixType m1(rows, rows); m1.setIdentity(); VERIFY_IS_APPROX(m1, refMat1); for(int k=0; k<rows*rows/4; ++k) { Index i = internal::random<Index>(0,rows-1); Index j = internal::random<Index>(0,rows-1); Scalar v = internal::random<Scalar>(); m1.coeffRef(i,j) = v; refMat1.coeffRef(i,j) = v; VERIFY_IS_APPROX(m1, refMat1); if(internal::random<Index>(0,10)<2) m1.makeCompressed(); } m1.setIdentity(); refMat1.setIdentity(); VERIFY_IS_APPROX(m1, refMat1); } // test array/vector of InnerIterator { typedef typename SparseMatrixType::InnerIterator IteratorType; DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols); SparseMatrixType m2(rows, cols); initSparse<Scalar>(density, refMat2, m2); IteratorType static_array[2]; static_array[0] = IteratorType(m2,0); static_array[1] = IteratorType(m2,m2.outerSize()-1); VERIFY( static_array[0] || m2.innerVector(static_array[0].outer()).nonZeros() == 0 ); VERIFY( static_array[1] || m2.innerVector(static_array[1].outer()).nonZeros() == 0 ); if(static_array[0] && static_array[1]) { ++(static_array[1]); static_array[1] = IteratorType(m2,0); VERIFY( static_array[1] ); VERIFY( static_array[1].index() == static_array[0].index() ); VERIFY( static_array[1].outer() == static_array[0].outer() ); VERIFY( static_array[1].value() == static_array[0].value() ); } std::vector<IteratorType> iters(2); iters[0] = IteratorType(m2,0); iters[1] = IteratorType(m2,m2.outerSize()-1); } }
int main(int argc, char* argv[]) { constexpr float l = -0.1f; constexpr float r = 0.1f; constexpr float b = -0.1f; constexpr float t = 0.1f; constexpr float dist = 0.1f; constexpr int SAMPLES = 64; const int SAMPLEDIM = sqrt(SAMPLES); #ifndef USE_OPENGL ppm = easyppm_create(NX, NY, IMAGETYPE_PPM); #endif // Materials Material mp(Color(0.2f, 0.2f, 0.2f), Color(1.0f, 1.0f, 1.0f), Color(0.0f, 0.0f, 0.0f), 0.0f, 0.5f); Material m1(Color(0.2f, 0.0f, 0.0f), Color(1.0f, 0.0f, 0.0f), Color(0.0f, 0.0f, 0.0f), 0.0f, 0.0f); Material m2(Color(0.0f, 0.2f, 0.0f), Color(0.0f, 0.5f, 0.0f), Color(0.5f, 0.5f, 0.5f), 32.0f, 0.0f); Material m3(Color(0.0f, 0.0f, 0.2f), Color(0.0f, 0.0f, 1.0f), Color(0.0f, 0.0f, 0.0f), 0.0f, 0.8f); // Surfaces SurfaceList surfaces; surfaces.add(std::move(std::unique_ptr<Plane>(new Plane(Eigen::Vector3f(0, -2, 0), Eigen::Vector3f(0, 1, 0), mp)))); surfaces.add(std::move(std::unique_ptr<Sphere>(new Sphere(Eigen::Vector3f(-4, 0, -7), 1, m1)))); surfaces.add(std::move(std::unique_ptr<Sphere>(new Sphere(Eigen::Vector3f( 0, 0, -7), 2, m2)))); surfaces.add(std::move(std::unique_ptr<Sphere>(new Sphere(Eigen::Vector3f( 4, 0, -7), 1, m3)))); // Light Light light(Eigen::Vector3f(-4, 4, -3), 1); // Add surfaces and light to scene Scene scene(surfaces, light); // Fill pixel buffer buffer = new Color[NX*NY]; #if defined(USE_OPENMP) #pragma omp parallel for #endif for (int k = 0; k < NX*NY; k++) { int i = k % NX; int j = k / NX; Color res(0,0,0); for (int si = 0; si < SAMPLEDIM; si++) { for (int sj = 0; sj < SAMPLEDIM; sj++) { // Uniform sampling float x = (i-0.5f) + (si)/(float)SAMPLEDIM; float y = (j-0.5f) + (sj)/(float)SAMPLEDIM; float u = l + ((r-l)*(x+0.5f)/NX); float v = b + ((t-b)*(y+0.5f)/NY); auto p = Eigen::Vector3f(0, 0, 0); auto d = Eigen::Vector3f(u, v, -dist); auto ray = Ray(p, d); auto hit = std::unique_ptr<Intersection>(scene.intersect(ray)); if (hit) res += scene.shade(ray, *hit, 2, true, false).correct(2.2f); } } #if defined(USE_OPENGL) buffer[i*NY + j] = res / SAMPLES; #else auto color = res / SAMPLES; auto r = clamp(color.r * 255, 0, 255); auto g = clamp(color.g * 255, 0, 255); auto b = clamp(color.b * 255, 0, 255); easyppm_set(&ppm, i, j, easyppm_rgb(r, g, b)); #endif } #if defined(USE_OPENGL) // Write buffer to OpenGL window glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); glutInitWindowSize(NX, NY); glutCreateWindow("Part 4"); glutDisplayFunc(gl_display); glutKeyboardFunc(gl_keyboard); glutMainLoop(); #else // Write buffer to image file const char* path = "images/part4.ppm"; easyppm_invert_y(&ppm); easyppm_write(&ppm, path); easyppm_destroy(&ppm); printf("Image written to %s\n", path); #endif delete[] buffer; return 0; }
bool AdvancedMatrixTests() { Matrix m(1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4); float trace = m.Trace(); float expectedTrace = 1 + 2 + 3 + 4; if (trace != expectedTrace) { wprintf(L"trace didn't match! %f\n", trace); return false; } float det = m.Determinant(); // that's a non-reflective, scaling matrix with a scale > 1, so we should have a pos det > 1 if (det <= 1) { wprintf(L"determinant wasn't > 1! %f\n", det); return false; } Matrix invM; // we only don't have an inverse if det(M) == 0 if (m.Inverse(&invM) != (det != 0)) { wprintf(L"inverse existence didn't match determinant! %f\n", det); return false; } // if we had an inverse, let's verify it if (det != 0) { // first, m * invM == I Matrix testForIdentity = m * invM; // quick test for identiy is trace == 4 && det = 1. Not perfect, but good enough if (testForIdentity.Trace() != 4 || testForIdentity.Determinant() != 1) { wprintf(L"M * invM != I!\n"); return false; } // second, inverting the inverse should give us the original matrix Matrix testM; if (!invM.Inverse(&testM)) { return false; } if (testM.Trace() != trace || testM.Determinant() != det) { wprintf(L"inverting the inverse didn't appear to give the original matrix!\n"); return false; } } // inverse of an orthonormal matrix (any rotation matrix) is equivelant to it's transpose Matrix m2(Matrix::CreateFromAxisAngle(Vector3(0.707f, 0.707f, 0.0f), 1.234f)); Matrix invM2; if (!m2.Inverse(&invM2)) { return false; } Matrix transM2 = m2.Transpose(); if (invM2.Trace() != transM2.Trace() || invM2.Determinant() != transM2.Determinant()) { return false; } // another inverse test Matrix m3(1, 2, 0, 0, 4, 0, 4, 0, 0, 8, 8, 0, 1, 0, 2, 1); Matrix invM3; if (!m3.Inverse(&invM3)) { return false; } DirectX::XMMATRIX xm = m3; DirectX::XMVECTOR xdet; DirectX::XMMATRIX invXM = DirectX::XMMatrixInverse(&xdet, xm); DirectX::XMFLOAT4X4 invXMF; DirectX::XMStoreFloat4x4(&invXMF, invXM); return true; }
int main() { { typedef std::pair<MoveOnly, MoveOnly> V; typedef std::pair<const MoveOnly, MoveOnly> VC; typedef test_compare<std::less<MoveOnly> > C; typedef test_allocator<VC> A; typedef std::multimap<MoveOnly, MoveOnly, C, A> M; typedef std::move_iterator<V*> I; V a1[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m1(I(a1), I(a1+sizeof(a1)/sizeof(a1[0])), C(5), A(7)); V a2[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m2(I(a2), I(a2+sizeof(a2)/sizeof(a2[0])), C(5), A(7)); M m3(C(3), A(7)); m3 = std::move(m1); assert(m3 == m2); assert(m3.get_allocator() == A(7)); assert(m3.key_comp() == C(5)); assert(m1.empty()); } { typedef std::pair<MoveOnly, MoveOnly> V; typedef std::pair<const MoveOnly, MoveOnly> VC; typedef test_compare<std::less<MoveOnly> > C; typedef test_allocator<VC> A; typedef std::multimap<MoveOnly, MoveOnly, C, A> M; typedef std::move_iterator<V*> I; V a1[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m1(I(a1), I(a1+sizeof(a1)/sizeof(a1[0])), C(5), A(7)); V a2[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m2(I(a2), I(a2+sizeof(a2)/sizeof(a2[0])), C(5), A(7)); M m3(C(3), A(5)); m3 = std::move(m1); assert(m3 == m2); assert(m3.get_allocator() == A(5)); assert(m3.key_comp() == C(5)); assert(m1.empty()); } { typedef std::pair<MoveOnly, MoveOnly> V; typedef std::pair<const MoveOnly, MoveOnly> VC; typedef test_compare<std::less<MoveOnly> > C; typedef other_allocator<VC> A; typedef std::multimap<MoveOnly, MoveOnly, C, A> M; typedef std::move_iterator<V*> I; V a1[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m1(I(a1), I(a1+sizeof(a1)/sizeof(a1[0])), C(5), A(7)); V a2[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m2(I(a2), I(a2+sizeof(a2)/sizeof(a2[0])), C(5), A(7)); M m3(C(3), A(5)); m3 = std::move(m1); assert(m3 == m2); assert(m3.get_allocator() == A(7)); assert(m3.key_comp() == C(5)); assert(m1.empty()); } { typedef std::pair<MoveOnly, MoveOnly> V; typedef std::pair<const MoveOnly, MoveOnly> VC; typedef test_compare<std::less<MoveOnly> > C; typedef min_allocator<VC> A; typedef std::multimap<MoveOnly, MoveOnly, C, A> M; typedef std::move_iterator<V*> I; V a1[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m1(I(a1), I(a1+sizeof(a1)/sizeof(a1[0])), C(5), A()); V a2[] = { V(1, 1), V(1, 2), V(1, 3), V(2, 1), V(2, 2), V(2, 3), V(3, 1), V(3, 2), V(3, 3) }; M m2(I(a2), I(a2+sizeof(a2)/sizeof(a2[0])), C(5), A()); M m3(C(3), A()); m3 = std::move(m1); assert(m3 == m2); assert(m3.get_allocator() == A()); assert(m3.key_comp() == C(5)); assert(m1.empty()); } }
template<typename ArrayType> void vectorwiseop_array(const ArrayType& m) { typedef typename ArrayType::Index Index; typedef typename ArrayType::Scalar Scalar; typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType; typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType; Index rows = m.rows(); Index cols = m.cols(); Index r = internal::random<Index>(0, rows-1), c = internal::random<Index>(0, cols-1); ArrayType m1 = ArrayType::Random(rows, cols), m2(rows, cols), m3(rows, cols); ColVectorType colvec = ColVectorType::Random(rows); RowVectorType rowvec = RowVectorType::Random(cols); // test addition m2 = m1; m2.colwise() += colvec; VERIFY_IS_APPROX(m2, m1.colwise() + colvec); VERIFY_IS_APPROX(m2.col(c), m1.col(c) + colvec); VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose()); VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose()); m2 = m1; m2.rowwise() += rowvec; VERIFY_IS_APPROX(m2, m1.rowwise() + rowvec); VERIFY_IS_APPROX(m2.row(r), m1.row(r) + rowvec); VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose()); VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose()); // test substraction m2 = m1; m2.colwise() -= colvec; VERIFY_IS_APPROX(m2, m1.colwise() - colvec); VERIFY_IS_APPROX(m2.col(c), m1.col(c) - colvec); VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose()); VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose()); m2 = m1; m2.rowwise() -= rowvec; VERIFY_IS_APPROX(m2, m1.rowwise() - rowvec); VERIFY_IS_APPROX(m2.row(r), m1.row(r) - rowvec); VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose()); VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose()); // test multiplication m2 = m1; m2.colwise() *= colvec; VERIFY_IS_APPROX(m2, m1.colwise() * colvec); VERIFY_IS_APPROX(m2.col(c), m1.col(c) * colvec); VERIFY_RAISES_ASSERT(m2.colwise() *= colvec.transpose()); VERIFY_RAISES_ASSERT(m1.colwise() * colvec.transpose()); m2 = m1; m2.rowwise() *= rowvec; VERIFY_IS_APPROX(m2, m1.rowwise() * rowvec); VERIFY_IS_APPROX(m2.row(r), m1.row(r) * rowvec); VERIFY_RAISES_ASSERT(m2.rowwise() *= rowvec.transpose()); VERIFY_RAISES_ASSERT(m1.rowwise() * rowvec.transpose()); // test quotient m2 = m1; m2.colwise() /= colvec; VERIFY_IS_APPROX(m2, m1.colwise() / colvec); VERIFY_IS_APPROX(m2.col(c), m1.col(c) / colvec); VERIFY_RAISES_ASSERT(m2.colwise() /= colvec.transpose()); VERIFY_RAISES_ASSERT(m1.colwise() / colvec.transpose()); m2 = m1; m2.rowwise() /= rowvec; VERIFY_IS_APPROX(m2, m1.rowwise() / rowvec); VERIFY_IS_APPROX(m2.row(r), m1.row(r) / rowvec); VERIFY_RAISES_ASSERT(m2.rowwise() /= rowvec.transpose()); VERIFY_RAISES_ASSERT(m1.rowwise() / rowvec.transpose()); }
template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m) { typedef typename MatrixType::Index Index; typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVectorType; typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType; typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealColVectorType; typedef Matrix<RealScalar, 1, MatrixType::ColsAtCompileTime> RealRowVectorType; Index rows = m.rows(); Index cols = m.cols(); Index r = internal::random<Index>(0, rows-1), c = internal::random<Index>(0, cols-1); MatrixType m1 = MatrixType::Random(rows, cols), m2(rows, cols), m3(rows, cols); ColVectorType colvec = ColVectorType::Random(rows); RowVectorType rowvec = RowVectorType::Random(cols); RealColVectorType rcres; RealRowVectorType rrres; // test addition m2 = m1; m2.colwise() += colvec; VERIFY_IS_APPROX(m2, m1.colwise() + colvec); VERIFY_IS_APPROX(m2.col(c), m1.col(c) + colvec); VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose()); VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose()); m2 = m1; m2.rowwise() += rowvec; VERIFY_IS_APPROX(m2, m1.rowwise() + rowvec); VERIFY_IS_APPROX(m2.row(r), m1.row(r) + rowvec); VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose()); VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose()); // test substraction m2 = m1; m2.colwise() -= colvec; VERIFY_IS_APPROX(m2, m1.colwise() - colvec); VERIFY_IS_APPROX(m2.col(c), m1.col(c) - colvec); VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose()); VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose()); m2 = m1; m2.rowwise() -= rowvec; VERIFY_IS_APPROX(m2, m1.rowwise() - rowvec); VERIFY_IS_APPROX(m2.row(r), m1.row(r) - rowvec); VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose()); VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose()); // test norm rrres = m1.colwise().norm(); VERIFY_IS_APPROX(rrres(c), m1.col(c).norm()); rcres = m1.rowwise().norm(); VERIFY_IS_APPROX(rcres(r), m1.row(r).norm()); // test normalized m2 = m1.colwise().normalized(); VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized()); m2 = m1.rowwise().normalized(); VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized()); // test normalize m2 = m1; m2.colwise().normalize(); VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized()); m2 = m1; m2.rowwise().normalize(); VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized()); }
void MatrixTest::test_constructor(void) { message += "test_constructor\n"; std::string file_name = "../data/matrix.dat"; // Default Matrix<size_t> m1; assert_true(m1.get_rows_number() == 0, LOG); assert_true(m1.get_columns_number() == 0, LOG); // Rows and columns numbers Matrix<size_t> m2(0, 0); assert_true(m2.get_rows_number() == 0, LOG); assert_true(m2.get_columns_number() == 0, LOG); Matrix<double> m3(1, 1, 1.0); assert_true(m3.get_rows_number() == 1, LOG); assert_true(m3.get_columns_number() == 1, LOG); // Rows and columns numbers and initialization Matrix<size_t> m4(0, 0, 1); assert_true(m4.get_rows_number() == 0, LOG); assert_true(m4.get_columns_number() == 0, LOG); Matrix<size_t> m5(1, 1, 1); assert_true(m5.get_rows_number() == 1, LOG); assert_true(m5.get_columns_number() == 1, LOG); assert_true(m5 == true, LOG); // File constructor m1.save(file_name); Matrix<size_t> m6(file_name); assert_true(m6.get_rows_number() == 0, LOG); assert_true(m6.get_columns_number() == 0, LOG); m2.save(file_name); Matrix<size_t> m7(file_name); assert_true(m7.get_rows_number() == 0, LOG); assert_true(m7.get_columns_number() == 0, LOG); m3.save(file_name); Matrix<double> m8(file_name); assert_true(m8.get_rows_number() == 1, LOG); assert_true(m8.get_columns_number() == 1, LOG); m4.save(file_name); Matrix<size_t> m9(file_name); assert_true(m9.get_rows_number() == 0, LOG); assert_true(m9.get_columns_number() == 0, LOG); m5.save(file_name); Matrix<size_t> m10(file_name); assert_true(m10.get_rows_number() == 1, LOG); assert_true(m10.get_columns_number() == 1, LOG); assert_true(m10 == true, LOG); // Copy constructor Matrix<double> a5; Matrix<double> b5(a5); assert_true(b5.get_rows_number() == 0, LOG); assert_true(b5.get_columns_number() == 0, LOG); Matrix<size_t> a6(1, 1, true); Matrix<size_t> b6(a6); assert_true(b6.get_rows_number() == 1, LOG); assert_true(b6.get_columns_number() == 1, LOG); assert_true(b6 == true, LOG); // Operator ++ Matrix<size_t> m11(2, 2, 0); m11(0,0)++; m11(1,1)++; assert_true(m11(0,0) == 1, LOG); assert_true(m11(0,1) == 0, LOG); assert_true(m11(1,0) == 0, LOG); assert_true(m11(1,1) == 1, LOG); }
//--------------------------------------------------------- DMat& NDG2D::ConformingHrefine2D(IMat& edgerefineflag, const DMat& Qin) //--------------------------------------------------------- { #if (0) OutputNodes(false); // volume nodes //OutputNodes(true); // face nodes #endif // function newQ = ConformingHrefine2D(edgerefineflag, Q) // Purpose: apply edge splits as requested by edgerefineflag IVec v1("v1"), v2("v2"), v3("v3"), tvi; DVec x1("x1"), x2("x2"), x3("x3"), y1("y1"), y2("y2"), y3("y3"); DVec a1("a1"), a2("a2"), a3("a3"); // count vertices assert (VX.size() == Nv); // find vertex triplets for elements to be refined v1 = EToV(All,1); v2 = EToV(All,2); v3 = EToV(All,3); x1 = VX(v1); x2 = VX(v2); x3 = VX(v3); y1 = VY(v1); y2 = VY(v2); y3 = VY(v3); // find angles at each element vertex (in radians) VertexAngles(x1,x2,x3,y1,y2,y3, a1,a2,a3); // absolute value of angle size a1.set_abs(); a2.set_abs(); a3.set_abs(); int k=0,k1=0,f1=0,k2=0,f2=0, e1=0,e2=0,e3=0, b1=0,b2=0,b3=0, ref=0; IVec m1,m2,m3; DVec mx1, my1, mx2, my2, mx3, my3; // create new vertices at edge centers of marked elements // (use unique numbering derived from unique edge number)) m1 = max(IVec(Nv*(v1-1)+v2+1), IVec(Nv*(v2-1)+v1+1)); mx1=0.5*(x1+x2); my1=0.5*(y1+y2); m2 = max(IVec(Nv*(v2-1)+v3+1), IVec(Nv*(v3-1)+v2+1)); mx2=0.5*(x2+x3); my2=0.5*(y2+y3); m3 = max(IVec(Nv*(v1-1)+v3+1), IVec(Nv*(v3-1)+v1+1)); mx3=0.5*(x3+x1); my3=0.5*(y3+y1); // ensure that both elements sharing an edge are split for (k1=1; k1<=K; ++k1) { for (f1=1; f1<=Nfaces; ++f1) { if (edgerefineflag(k1,f1)) { k2 = EToE(k1,f1); f2 = EToF(k1,f1); edgerefineflag(k2,f2) = 1; } } } // store old data IMat oldEToV = EToV; DVec oldVX = VX, oldVY = VY; // count the number of elements in the refined mesh int newK = countrefinefaces(edgerefineflag); EToV.resize(newK, Nfaces, true, 0); IMat newBCType(newK,3, "newBCType"); // kold = []; IVec kold(newK, "kold"); Index1D KI,KIo; int sk=1, skstart=0, skend=0; for (k=1; k<=K; ++k) { skstart = sk; e1 = edgerefineflag(k,1); b1 = BCType(k,1); e2 = edgerefineflag(k,2); b2 = BCType(k,2); e3 = edgerefineflag(k,3); b3 = BCType(k,3); ref = e1 + 2*e2 + 4*e3; switch (ref) { case 0: EToV(sk, All) = IVec(v1(k),v2(k),v3(k)); newBCType(sk,All) = IVec(b1, b2, b3); ++sk; break; case 1: EToV(sk, All) = IVec(v1(k),m1(k),v3(k)); newBCType(sk,All) = IVec(b1, 0, b3); ++sk; EToV(sk, All) = IVec(m1(k),v2(k),v3(k)); newBCType(sk,All) = IVec(b1, b2, 0); ++sk; break; case 2: EToV(sk, All) = IVec(v2(k),m2(k),v1(k)); newBCType(sk,All) = IVec(b2, 0, b1); ++sk; EToV(sk, All) = IVec(m2(k),v3(k),v1(k)); newBCType(sk,All) = IVec(b2, b3, 0); ++sk; break; case 4: EToV(sk, All) = IVec(v3(k),m3(k),v2(k)); newBCType(sk,All) = IVec(b3, 0, b2); ++sk; EToV(sk, All) = IVec(m3(k),v1(k),v2(k)); newBCType(sk,All) = IVec(b3, b1, 0); ++sk; break; case 3: EToV(sk, All) = IVec(m1(k),v2(k),m2(k)); newBCType(sk,All) = IVec(b1, b2, 0); ++sk; if (a1(k) > a3(k)) { // split largest angle EToV(sk, All) = IVec(v1(k),m1(k),m2(k)); newBCType(sk,All) = IVec(b1, 0, 0); ++sk; EToV(sk, All) = IVec(v1(k),m2(k),v3(k)); newBCType(sk,All) = IVec( 0, b2, b3); ++sk; } else { EToV(sk, All) = IVec(v3(k),m1(k),m2(k)); newBCType(sk,All) = IVec( 0, 0, b2); ++sk; EToV(sk, All) = IVec(v3(k),v1(k),m1(k)); newBCType(sk,All) = IVec(b3, b1, 0); ++sk; } break; case 5: EToV(sk, All) = IVec(v1(k),m1(k),m3(k)); newBCType(sk,All) = IVec(b1, 0, b3); ++sk; if (a2(k) > a3(k)) { // split largest angle EToV(sk, All) = IVec(v2(k),m3(k),m1(k)); newBCType(sk,All) = IVec( 0, 0, b1); ++sk; EToV(sk, All) = IVec(v2(k),v3(k),m3(k)); newBCType(sk,All) = IVec(b2, b3, 0); ++sk; } else { EToV(sk, All) = IVec(v3(k),m3(k),m1(k)); newBCType(sk,All) = IVec(b3, 0, 0); ++sk; EToV(sk, All) = IVec(v3(k),m1(k),v2(k)); newBCType(sk,All) = IVec( 0, b1, b2); ++sk; } break; case 6: EToV(sk, All) = IVec(v3(k),m3(k),m2(k)); newBCType(sk,All) = IVec(b3, 0, b2); ++sk; if (a1(k) > a2(k)) { // split largest angle EToV(sk, All) = IVec(v1(k),m2(k),m3(k)); newBCType(sk,All) = IVec( 0, 0, b3); ++sk; EToV(sk, All) = IVec(v1(k),v2(k),m2(k)); newBCType(sk,All) = IVec(b1, b2, 0); ++sk; } else { EToV(sk, All) = IVec(v2(k),m2(k),m3(k)); newBCType(sk,All) = IVec(b2, 0, 0); ++sk; EToV(sk, All) = IVec(v2(k),m3(k),v1(k)); newBCType(sk,All) = IVec( 0 , b3, b1); ++sk; } break; default: // split all EToV(sk, All) = IVec(m1(k),m2(k),m3(k)); newBCType(sk, All) = IVec( 0, 0, 0); ++sk; EToV(sk, All) = IVec(v1(k),m1(k),m3(k)); newBCType(sk, All) = IVec(b1, 0, b3); ++sk; EToV(sk, All) = IVec(v2(k),m2(k),m1(k)); newBCType(sk, All) = IVec(b2, 0, b1); ++sk; EToV(sk, All) = IVec(v3(k),m3(k),m2(k)); newBCType(sk, All) = IVec(b3, 0, b2); ++sk; break; } skend = sk; // kold = [kold; k*ones(skend-skstart, 1)]; // element k is to be refined into (1:4) child elements. // store parent element numbers in array "kold" to help // with accessing parent vertex data during refinement. KI.reset(skstart, skend-1); // ids of child elements kold(KI) = k; // mark as children of element k } // Finished with edgerefineflag. Delete if OBJ_temp if (edgerefineflag.get_mode() == OBJ_temp) { delete (&edgerefineflag); } // renumber new nodes contiguously // ids = unique([v1;v2;v3;m1;m2;m3]); bool unique=true; IVec IDS, ids; IDS = concat( concat(v1,v2,v3), concat(m1,m2,m3) ); ids = sort(IDS, unique); Nv = ids.size(); int max_id = EToV.max_val(); umMSG(1, "max id in EToV is %d\n", max_id); // M N nnz vals triplet CSi newids(max_id,1, Nv, 1, 1 ); // newids = sparse(max(max(EToV)),1); int i=0, j=1; for (i=1; i<=Nv; ++i) { // newids(ids)= (1:Nv); newids.set1(ids(i),j, i); // load 1-based triplets } // row col x newids.compress(); // convert to csc form // Matlab ----------------------------------------------- // v1 = newids(v1); v2 = newids(v2); v3 = newids(v3); // m1 = newids(m1); m2 = newids(m2); m3 = newids(m3); //------------------------------------------------------- int KVi=v1.size(), KMi=m1.size(); // read from copies, overwrite originals // 1. reload ids for new vertices tvi = v1; for (i=1;i<=KVi;++i) {v1(i) = newids(tvi(i), 1);} tvi = v2; for (i=1;i<=KVi;++i) {v2(i) = newids(tvi(i), 1);} tvi = v3; for (i=1;i<=KVi;++i) {v3(i) = newids(tvi(i), 1);} // 2. load ids for new (midpoint) vertices tvi = m1; for (i=1;i<=KMi;++i) {m1(i) = newids(tvi(i), 1);} tvi = m2; for (i=1;i<=KMi;++i) {m2(i) = newids(tvi(i), 1);} tvi = m3; for (i=1;i<=KMi;++i) {m3(i) = newids(tvi(i), 1);} VX.resize(Nv); VY.resize(Nv); VX(v1) = x1; VX(v2) = x2; VX(v3) = x3; VY(v1) = y1; VY(v2) = y2; VY(v3) = y3; VX(m1) = mx1; VX(m2) = mx2; VX(m3) = mx3; VY(m1) = my1; VY(m2) = my2; VY(m3) = my3; if (newK != (sk-1)) { umERROR("NDG2D::ConformingHrefine2D", "Inconsistent element count: expect %d, but sk = %d", newK, (sk-1)); } else { K = newK; // sk-1; } // dumpIMat(EToV, "EToV (before)"); // EToV = newids(EToV); for (j=1; j<=3; ++j) { for (k=1; k<=K; ++k) { EToV(k,j) = newids(EToV(k,j), 1); } } #if (0) dumpIMat(EToV, "EToV (after)"); // umERROR("Checking ids", "Nigel, check EToV"); #endif BCType = newBCType; Nv = VX.size(); // xold = x; yold = y; StartUp2D(); #if (1) OutputNodes(false); // volume nodes //OutputNodes(true); // face nodes //umERROR("Exiting early", "Check adapted {volume,face} nodes"); #endif // allocate return object int Nfields = Qin.num_cols(); DMat* tmpQ = new DMat(Np*K, Nfields, "newQ", OBJ_temp); DMat& newQ = *tmpQ; // use a reference for syntax // quick return, if no interpolation is required if (Qin.size()<1) { return newQ; } DVec rOUT(Np),sOUT(Np),xout,yout,xy1(2),xy2(2),xy3(2),tmp(2),rhs; int ko=0,kv1=0,kv2=0,kv3=0,n=0; DMat A(2,2), interp; DMat oldQ = const_cast<DMat&>(Qin); for (k=1; k<=K; ++k) { ko = kold(k); xout = x(All,k); yout = y(All,k); kv1=oldEToV(ko,1); kv2=oldEToV(ko,2); kv3=oldEToV(ko,3); xy1.set(oldVX(kv1), oldVY(kv1)); xy2.set(oldVX(kv2), oldVY(kv2)); xy3.set(oldVX(kv3), oldVY(kv3)); A.set_col(1, xy2-xy1); A.set_col(2, xy3-xy1); for (i=1; i<=Np; ++i) { tmp.set(xout(i), yout(i)); rhs = 2.0*tmp - xy2 - xy3; tmp = A|rhs; rOUT(i) = tmp(1); sOUT(i) = tmp(2); } KI.reset (Np*(k -1)+1, Np*k ); // nodes in new element k KIo.reset(Np*(ko-1)+1, Np*ko); // nodes in old element ko interp = Vandermonde2D(N, rOUT, sOUT)*invV; for (n=1; n<=Nfields; ++n) { //newQ(:,k,n)= interp* Q(:,ko,n); //DVec tm1 = interp*oldQ(KIo,n); //dumpDVec(tm1, "tm1"); newQ(KI,n) = interp*oldQ(KIo,n); } } return newQ; }
// Exec_RotateDihedral::Execute() Exec::RetType Exec_RotateDihedral::Execute(CpptrajState& State, ArgList& argIn) { // Get input COORDS set std::string setname = argIn.GetStringKey("crdset"); if (setname.empty()) { mprinterr("Error: Specify COORDS dataset name with 'crdset'.\n"); return CpptrajState::ERR; } DataSet_Coords* CRD = (DataSet_Coords*)State.DSL().FindCoordsSet( setname ); if (CRD == 0) { mprinterr("Error: Could not find COORDS set '%s'\n", setname.c_str()); return CpptrajState::ERR; } if (CRD->Size() < 1) { mprinterr("Error: COORDS set is empty.\n"); return CpptrajState::ERR; } int frame = argIn.getKeyInt("frame", 0); if (frame < 0 || frame >= (int)CRD->Size()) { mprinterr("Error: Specified frame %i is out of range.\n", frame+1); return CpptrajState::ERR; } mprintf(" ROTATEDIHEDRAL: Using COORDS '%s', frame %i\n", CRD->legend(), frame+1); // Get target frame Frame FRM = CRD->AllocateFrame(); CRD->GetFrame(frame, FRM); // Save as reference Frame refFrame = FRM; // Create output COORDS set if necessary DataSet_Coords* OUT = 0; int outframe = 0; std::string outname = argIn.GetStringKey("name"); if (outname.empty()) { // This will not work for TRAJ data sets if (CRD->Type() == DataSet::TRAJ) { mprinterr("Error: Using TRAJ as input set requires use of 'name' keyword for output.\n"); return CpptrajState::ERR; } OUT = CRD; outframe = frame; } else { // Create new output set with 1 empty frame. OUT = (DataSet_Coords*)State.DSL().AddSet( DataSet::COORDS, outname ); if (OUT == 0) return CpptrajState::ERR; OUT->Allocate( DataSet::SizeArray(1, 1) ); OUT->CoordsSetup( CRD->Top(), CRD->CoordsInfo() ); OUT->AddFrame( CRD->AllocateFrame() ); mprintf("\tOutput to set '%s'\n", OUT->legend()); } // Determine whether we are setting or incrementing. enum ModeType { SET = 0, INCREMENT }; ModeType mode = SET; if (argIn.Contains("value")) mode = SET; else if (argIn.Contains("increment")) mode = INCREMENT; else { mprinterr("Error: Specify 'value <value>' or 'increment <increment>'\n"); return CpptrajState::ERR; } double value = argIn.getKeyDouble(ModeStr[mode], 0.0); switch (mode) { case SET: mprintf("\tDihedral will be set to %g degrees.\n", value); break; case INCREMENT: mprintf("\tDihedral will be incremented by %g degrees.\n", value); break; } // Convert to radians value *= Constants::DEGRAD; // Select dihedral atoms int A1, A2, A3, A4; if (argIn.Contains("type")) { // By type ArgList typeArg = argIn.GetStringKey("type"); if (typeArg.empty()) { mprinterr("Error: No dihedral type specified after 'type'\n"); return CpptrajState::ERR; } DihedralSearch dihSearch; dihSearch.SearchForArgs( typeArg ); if (dihSearch.NoDihedralTokens()) { mprinterr("Error: Specified dihedral type not recognized.\n"); return CpptrajState::ERR; } // Get residue int res = argIn.getKeyInt("res", -1); if (res <= 0) { mprinterr("Error: If 'type' specified 'res' must be specified and > 0.\n"); return CpptrajState::ERR; } // Search for dihedrals. User residue #s start from 1. if (dihSearch.FindDihedrals(CRD->Top(), Range(res-1))) return CpptrajState::ERR; DihedralSearch::mask_it dih = dihSearch.begin(); A1 = dih->A0(); A2 = dih->A1(); A3 = dih->A2(); A4 = dih->A3(); } else { // By masks AtomMask m1( argIn.GetMaskNext() ); AtomMask m2( argIn.GetMaskNext() ); AtomMask m3( argIn.GetMaskNext() ); AtomMask m4( argIn.GetMaskNext() ); if (CRD->Top().SetupIntegerMask( m1 )) return CpptrajState::ERR; if (CRD->Top().SetupIntegerMask( m2 )) return CpptrajState::ERR; if (CRD->Top().SetupIntegerMask( m3 )) return CpptrajState::ERR; if (CRD->Top().SetupIntegerMask( m4 )) return CpptrajState::ERR; if (m1.Nselected() != 1) return MaskError( m1 ); if (m2.Nselected() != 1) return MaskError( m2 ); if (m3.Nselected() != 1) return MaskError( m3 ); if (m4.Nselected() != 1) return MaskError( m4 ); A1 = m1[0]; A2 = m2[0]; A3 = m3[0]; A4 = m4[0]; } mprintf("\tRotating dihedral defined by atoms '%s'-'%s'-'%s'-'%s'\n", CRD->Top().AtomMaskName(A1).c_str(), CRD->Top().AtomMaskName(A2).c_str(), CRD->Top().AtomMaskName(A3).c_str(), CRD->Top().AtomMaskName(A4).c_str()); // Set mask of atoms that will move during dihedral rotation AtomMask Rmask = DihedralSearch::MovingAtoms(CRD->Top(), A2, A3); // Calculate current value of dihedral double torsion = Torsion( FRM.XYZ(A1), FRM.XYZ(A2), FRM.XYZ(A3), FRM.XYZ(A4) ); // Calculate delta needed to get to target value. double delta; switch (mode) { case SET: delta = value - torsion; break; case INCREMENT: delta = value; break; } mprintf("\tOriginal torsion is %g, rotating by %g degrees.\n", torsion*Constants::RADDEG, delta*Constants::RADDEG); // Set axis of rotation Vec3 axisOfRotation = FRM.SetAxisOfRotation( A2, A3 ); // Calculate rotation matrix for delta. Matrix_3x3 rotationMatrix; rotationMatrix.CalcRotationMatrix(axisOfRotation, delta); // Rotate around axis FRM.Rotate(rotationMatrix, Rmask); // RMS-fit the non-moving part of the coords back on original AtomMask refMask = Rmask; refMask.InvertMask(); FRM.Align( refFrame, refMask ); // Update coords OUT->SetCRD( outframe, FRM ); return CpptrajState::OK; }
template<typename MatrixType> void basicStuff(const MatrixType& m) { typedef typename MatrixType::Index Index; typedef typename MatrixType::Scalar Scalar; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType; Index rows = m.rows(); Index cols = m.cols(); // this test relies a lot on Random.h, and there's not much more that we can do // to test it, hence I consider that we will have tested Random.h MatrixType m1 = MatrixType::Random(rows, cols), m2 = MatrixType::Random(rows, cols), m3(rows, cols), mzero = MatrixType::Zero(rows, cols), square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>::Random(rows, rows); VectorType v1 = VectorType::Random(rows), vzero = VectorType::Zero(rows); SquareMatrixType sm1 = SquareMatrixType::Random(rows,rows), sm2(rows,rows); Scalar x = 0; while(x == Scalar(0)) x = internal::random<Scalar>(); Index r = internal::random<Index>(0, rows-1), c = internal::random<Index>(0, cols-1); m1.coeffRef(r,c) = x; VERIFY_IS_APPROX(x, m1.coeff(r,c)); m1(r,c) = x; VERIFY_IS_APPROX(x, m1(r,c)); v1.coeffRef(r) = x; VERIFY_IS_APPROX(x, v1.coeff(r)); v1(r) = x; VERIFY_IS_APPROX(x, v1(r)); v1[r] = x; VERIFY_IS_APPROX(x, v1[r]); VERIFY_IS_APPROX( v1, v1); VERIFY_IS_NOT_APPROX( v1, 2*v1); VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1); VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1.squaredNorm()); VERIFY_IS_NOT_MUCH_SMALLER_THAN(v1, v1); VERIFY_IS_APPROX( vzero, v1-v1); VERIFY_IS_APPROX( m1, m1); VERIFY_IS_NOT_APPROX( m1, 2*m1); VERIFY_IS_MUCH_SMALLER_THAN( mzero, m1); VERIFY_IS_NOT_MUCH_SMALLER_THAN(m1, m1); VERIFY_IS_APPROX( mzero, m1-m1); // always test operator() on each read-only expression class, // in order to check const-qualifiers. // indeed, if an expression class (here Zero) is meant to be read-only, // hence has no _write() method, the corresponding MatrixBase method (here zero()) // should return a const-qualified object so that it is the const-qualified // operator() that gets called, which in turn calls _read(). VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows,cols)(r,c), static_cast<Scalar>(1)); // now test copying a row-vector into a (column-)vector and conversely. square.col(r) = square.row(r).eval(); Matrix<Scalar, 1, MatrixType::RowsAtCompileTime> rv(rows); Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> cv(rows); rv = square.row(r); cv = square.col(r); VERIFY_IS_APPROX(rv, cv.transpose()); if(cols!=1 && rows!=1 && MatrixType::SizeAtCompileTime!=Dynamic) { VERIFY_RAISES_ASSERT(m1 = (m2.block(0,0, rows-1, cols-1))); } if(cols!=1 && rows!=1) { VERIFY_RAISES_ASSERT(m1[0]); VERIFY_RAISES_ASSERT((m1+m1)[0]); } VERIFY_IS_APPROX(m3 = m1,m1); MatrixType m4; VERIFY_IS_APPROX(m4 = m1,m1); m3.real() = m1.real(); VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), static_cast<const MatrixType&>(m1).real()); VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), m1.real()); // check == / != operators VERIFY(m1==m1); VERIFY(m1!=m2); VERIFY(!(m1==m2)); VERIFY(!(m1!=m1)); m1 = m2; VERIFY(m1==m2); VERIFY(!(m1!=m2)); // check automatic transposition sm2.setZero(); for(typename MatrixType::Index i=0;i<rows;++i) sm2.col(i) = sm1.row(i); VERIFY_IS_APPROX(sm2,sm1.transpose()); sm2.setZero(); for(typename MatrixType::Index i=0;i<rows;++i) sm2.col(i).noalias() = sm1.row(i); VERIFY_IS_APPROX(sm2,sm1.transpose()); sm2.setZero(); for(typename MatrixType::Index i=0;i<rows;++i) sm2.col(i).noalias() += sm1.row(i); VERIFY_IS_APPROX(sm2,sm1.transpose()); sm2.setZero(); for(typename MatrixType::Index i=0;i<rows;++i) sm2.col(i).noalias() -= sm1.row(i); VERIFY_IS_APPROX(sm2,-sm1.transpose()); // check ternary usage { bool b = internal::random<int>(0,10)>5; m3 = b ? m1 : m2; if(b) VERIFY_IS_APPROX(m3,m1); else VERIFY_IS_APPROX(m3,m2); m3 = b ? -m1 : m2; if(b) VERIFY_IS_APPROX(m3,-m1); else VERIFY_IS_APPROX(m3,m2); m3 = b ? m1 : -m2; if(b) VERIFY_IS_APPROX(m3,m1); else VERIFY_IS_APPROX(m3,-m2); } }
/*int testMat3Implementation() { int nrOfErrors = 0; std::cout << "Testing mat3 class" << std::endl; float a1[] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f}; float a2[] = {3.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 1.0f}; float a3[] = {4.0f, 0.0f, 0.0f, 0.0f, 4.0f, 0.0f, 1.0f, 1.0f, 2.0f}; egc::mat3 m1(a1), m2(a2), m3(a3), m4; m4 = m1 + m2; if(m4 == m3) std::cout << "\tCorrect + operation" << std::endl; else { std::cout << "\tIncorrect + operation" << std::endl; nrOfErrors++; } float a5[] = {3.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 3.0f, 3.0f, 3.0f}; egc::mat3 m5(a5); m4 = m1 * 3.0f; if(m4 == m5) std::cout << "\tCorrect * (with scalar value) operation" << std::endl; else { std::cout << "\tIncorrect * (with scalar value) operation" << std::endl; nrOfErrors++; } float a6[] = {3.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 1.0f, 1.0f, 1.0f}; egc::mat3 m6(a6); m4 = m1 * m2; if(m4 == m6) std::cout << "\tCorrect * (with another matrix) operation" << std::endl; else { std::cout << "\tIncorrect * (with another matrix) operation" << std::endl; nrOfErrors++; } egc::vec3 v1(1.0f, 1.0f, 1.0f); egc::vec3 v2(4.0f, 4.0f, 1.0f); egc::vec3 v3; v3 = m4 * v1; if(v3 == v2) std::cout << "\tCorrect * (with a vec3) operation" << std::endl; else { std::cout << "\tIncorrect * (with a vec3) operation" << std::endl; nrOfErrors++; } float a7[] = {-4.0f, 0.0f, 1.0f, -3.0f, 2.0f, 4.0f, 3.0f, -2.0f, -1.0f}; egc::mat3 m7(a7); if(std::abs(m7.determinant() + 24.0f) < std::numeric_limits<float>::epsilon()) std::cout << "\tCorrect determinant operation" << std::endl; else { std::cout << "\tIncorrect determinant operation" << std::endl; nrOfErrors++; } float a8[] = {-4.0f, -3.0f, 3.0f, 0.0f, 2.0f, -2.0f, 1.0f, 4.0f, -1.0f}; egc::mat3 m8(a8); if(m7.transpose() == m8) std::cout << "\tCorrect transpose operation" << std::endl; else { std::cout << "\tIncorrect transpose operation" << std::endl; nrOfErrors++; } float a9[] = {-1.0f/4.0f, 1.0f/12.0f, 1.0f/12.0f, -3.0f/8.0f, -1.0f/24.0f, -13.00f/24.0f, 0.0f, 1.0f/3.0f, 1.0f/3.0f}; egc::mat3 m9(a9); if(m7.inverse() == m9) std::cout << "\tCorrect inverse operation" << std::endl; else { std::cout << "\tIncorrect inverse operation" << std::endl; nrOfErrors++; } return nrOfErrors; } */ int testMat4Implementation() { int nrOfErrors = 0; std::cout << "Testing mat4 class" << std::endl; float a1[] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f}; float a2[] = {3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; float a3[] = {4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.0f, 0.0f, 1.0f, 1.0f, 1.0f, 2.0f}; egc::mat4 m1(a1), m2(a2), m3(a3), m4; m4 = m1 + m2; if(m4 == m3) std::cout << "\tCorrect + operation" << std::endl; else { std::cout << "\tIncorrect + operation" << std::endl; nrOfErrors++; } float a5[] = {3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 3.0f, 3.0f, 3.0f, 3.0f}; egc::mat4 m5(a5); m4 = m1 * 3.0f; if(m4 == m5) std::cout << "\tCorrect * (with scalar value) operation" << std::endl; else { std::cout << "\tIncorrect * (with scalar value) operation" << std::endl; nrOfErrors++; } float a6[] = {3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f}; egc::mat4 m6(a6); m4 = m1 * m2; if(m4 == m6) std::cout << "\tCorrect * (with another matrix) operation" << std::endl; else { std::cout << "\tIncorrect * (with another matrix) operation" << std::endl; nrOfErrors++; } egc::vec4 v1(1.0f, 1.0f, 1.0f, 1.0f); egc::vec4 v2(4.0f, 4.0f, 4.0f, 1.0f); egc::vec4 v3; v3 = m4 * v1; if(v3 == v2) std::cout << "\tCorrect * (with a vec4) operation" << std::endl; else { std::cout << "\tIncorrect * (with a vec4) operation" << std::endl; nrOfErrors++; } float a7[] = {3.0f, 4.0f, 3.0f, 9.0f, 2.0f, 0.0f, 0.0f, 2.0f, 0.0f, 1.0f, 2.0f, 3.0f, 1.0f, 2.0f, 1.0f, 1.0f}; egc::mat4 m7(a7); if(std::abs(m7.determinant() - 24.0f) < std::numeric_limits<float>::epsilon()) std::cout << "\tCorrect determinant operation" << std::endl; else { std::cout << "\tIncorrect determinant operation" << std::endl; nrOfErrors++; } float a8[] = {3.0f, 2.0f, 0.0f, 1.0f, 4.0f, 0.0f, 1.0f, 2.0f, 3.0f, 0.0f, 2.0f, 1.0f, 9.0f, 2.0f, 3.0f, 1.0f}; egc::mat4 m8(a8); if(m7.transpose() == m8) std::cout << "\tCorrect transpose operation" << std::endl; else { std::cout << "\tIncorrect transpose operation" << std::endl; nrOfErrors++; } float a9[] = {-1.0f/4.0f, 2.0f/3.0f, 1.0f/6.0f, 5.0f/12.0f, 1.0f/4.0f, -1.0f/2.0f, -1.0/2.0f, 1.0f/4.0f, -1.0f/2.0f, 1.0f/2.0f, 1.0f, 1.0f/2.0f, 1.0f/4.0f, -1.0f/6.0f, -1.0/6.0f, -5.0f/12.0f}; egc::mat4 m9(a9); if(m7.inverse() == m9) std::cout << "\tCorrect inverse operation" << std::endl; else { std::cout << "\tIncorrect inverse operation" << std::endl; nrOfErrors++; } return nrOfErrors; }
template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m) { typedef typename MatrixType::Index Index; typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVectorType; typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType; typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealColVectorType; typedef Matrix<RealScalar, 1, MatrixType::ColsAtCompileTime> RealRowVectorType; Index rows = m.rows(); Index cols = m.cols(); Index r = internal::random<Index>(0, rows-1), c = internal::random<Index>(0, cols-1); MatrixType m1 = MatrixType::Random(rows, cols), m2(rows, cols), m3(rows, cols); ColVectorType colvec = ColVectorType::Random(rows); RowVectorType rowvec = RowVectorType::Random(cols); RealColVectorType rcres; RealRowVectorType rrres; // test addition m2 = m1; m2.colwise() += colvec; VERIFY_IS_APPROX(m2, m1.colwise() + colvec); VERIFY_IS_APPROX(m2.col(c), m1.col(c) + colvec); if(rows>1) { VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose()); VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose()); } m2 = m1; m2.rowwise() += rowvec; VERIFY_IS_APPROX(m2, m1.rowwise() + rowvec); VERIFY_IS_APPROX(m2.row(r), m1.row(r) + rowvec); if(cols>1) { VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose()); VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose()); } // test substraction m2 = m1; m2.colwise() -= colvec; VERIFY_IS_APPROX(m2, m1.colwise() - colvec); VERIFY_IS_APPROX(m2.col(c), m1.col(c) - colvec); if(rows>1) { VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose()); VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose()); } m2 = m1; m2.rowwise() -= rowvec; VERIFY_IS_APPROX(m2, m1.rowwise() - rowvec); VERIFY_IS_APPROX(m2.row(r), m1.row(r) - rowvec); if(cols>1) { VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose()); VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose()); } // test norm rrres = m1.colwise().norm(); VERIFY_IS_APPROX(rrres(c), m1.col(c).norm()); rcres = m1.rowwise().norm(); VERIFY_IS_APPROX(rcres(r), m1.row(r).norm()); VERIFY_IS_APPROX(m1.cwiseAbs().colwise().sum(), m1.colwise().template lpNorm<1>()); VERIFY_IS_APPROX(m1.cwiseAbs().rowwise().sum(), m1.rowwise().template lpNorm<1>()); VERIFY_IS_APPROX(m1.cwiseAbs().colwise().maxCoeff(), m1.colwise().template lpNorm<Infinity>()); VERIFY_IS_APPROX(m1.cwiseAbs().rowwise().maxCoeff(), m1.rowwise().template lpNorm<Infinity>()); // regression for bug 1158 VERIFY_IS_APPROX(m1.cwiseAbs().colwise().sum().x(), m1.col(0).cwiseAbs().sum()); // test normalized m2 = m1.colwise().normalized(); VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized()); m2 = m1.rowwise().normalized(); VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized()); // test normalize m2 = m1; m2.colwise().normalize(); VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized()); m2 = m1; m2.rowwise().normalize(); VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized()); // test with partial reduction of products Matrix<Scalar,MatrixType::RowsAtCompileTime,MatrixType::RowsAtCompileTime> m1m1 = m1 * m1.transpose(); VERIFY_IS_APPROX( (m1 * m1.transpose()).colwise().sum(), m1m1.colwise().sum()); Matrix<Scalar,1,MatrixType::RowsAtCompileTime> tmp(rows); VERIFY_EVALUATION_COUNT( tmp = (m1 * m1.transpose()).colwise().sum(), (MatrixType::RowsAtCompileTime==Dynamic ? 1 : 0)); m2 = m1.rowwise() - (m1.colwise().sum()/RealScalar(m1.rows())).eval(); m1 = m1.rowwise() - (m1.colwise().sum()/RealScalar(m1.rows())); VERIFY_IS_APPROX( m1, m2 ); VERIFY_EVALUATION_COUNT( m2 = (m1.rowwise() - m1.colwise().sum()/RealScalar(m1.rows())), (MatrixType::RowsAtCompileTime==Dynamic && MatrixType::ColsAtCompileTime!=1 ? 1 : 0) ); }
void operator () () const { { #ifdef USE_BANDED M m1 (N, N, 1, 1), m2 (N, N, 1, 1), m3 (N, N, 1, 1); #endif #ifdef USE_DIAGONAL M m1 (N, N), m2 (N, N), m3 (N, N); #endif test_with (m1, m2, m3); #ifdef USE_RANGE ublas::matrix_range<M> mr1 (m1, ublas::range (0, N), ublas::range (0, N)), mr2 (m2, ublas::range (0, N), ublas::range (0, N)), mr3 (m3, ublas::range (0, N), ublas::range (0, N)); test_with (mr1, mr2, mr3); #endif #ifdef USE_SLICE ublas::matrix_slice<M> ms1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), ms2 (m2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), ms3 (m3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); test_with (ms1, ms2, ms3); #endif } #ifdef USE_ADAPTOR { #ifdef USE_BANDED M m1 (N, N, 1, 1), m2 (N, N, 1, 1), m3 (N, N, 1, 1); ublas::banded_adaptor<M> bam1 (m1, 1, 1), bam2 (m2, 1, 1), bam3 (m3, 1, 1); test_with (bam1, bam2, bam3); #ifdef USE_RANGE ublas::matrix_range<ublas::banded_adaptor<M> > mr1 (bam1, ublas::range (0, N), ublas::range (0, N)), mr2 (bam2, ublas::range (0, N), ublas::range (0, N)), mr3 (bam3, ublas::range (0, N), ublas::range (0, N)); test_with (mr1, mr2, mr3); #endif #ifdef USE_SLICE ublas::matrix_slice<ublas::banded_adaptor<M> > ms1 (bam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), ms2 (bam2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), ms3 (bam3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); test_with (ms1, ms2, ms3); #endif #endif #ifdef USE_DIAGONAL M m1 (N, N), m2 (N, N), m3 (N, N); ublas::diagonal_adaptor<M> dam1 (m1), dam2 (m2), dam3 (m3); test_with (dam1, dam2, dam3); #ifdef USE_RANGE ublas::matrix_range<ublas::diagonal_adaptor<M> > mr1 (dam1, ublas::range (0, N), ublas::range (0, N)), mr2 (dam2, ublas::range (0, N), ublas::range (0, N)), mr3 (dam3, ublas::range (0, N), ublas::range (0, N)); test_with (mr1, mr2, mr3); #endif #ifdef USE_SLICE ublas::matrix_slice<ublas::diagonal_adaptor<M> > ms1 (dam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), ms2 (dam2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), ms3 (dam3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); test_with (ms1, ms2, ms3); #endif #endif } #endif }
void funclike(void) { #define stringify(x) #x expect_string("5", stringify(5)); expect_string("x", stringify(x)); expect_string("x y", stringify(x y)); expect_string("x y", stringify( x y )); expect_string("x + y", stringify( x + y )); expect_string("x + y", stringify(/**/x/**/+/**//**/ /**/y/**/)); expect_string("x+y", stringify( x+y )); expect_string("'a'", stringify('a')); expect_string("'\\''", stringify('\'')); expect_string("\"abc\"", stringify("abc")); expect_string("ZERO", stringify(ZERO)); #define m1(x) x expect(5, m1(5)); expect(7, m1((5 + 2))); expect(8, m1(plus(5, 3))); expect(10, m1() 10); expect(14, m1(2 + 2 +) 10); #define m2(x) x + x expect(10, m2(5)); #define m3(x, y) x * y expect(50, m3(5, 10)); expect(11, m3(2 + 2, 3 + 3)); #define m4(x, y) x + y + TWO expect(17, m4(5, 10)); #define m6(x, ...) x + __VA_ARGS__ expect(20, m6(2, 18)); expect(25, plus(m6(2, 18, 5))); #define plus(x, y) x * y + plus(x, y) expect(11, plus(2, 3)); #undef plus #define plus(x, y) minus(x, y) #define minus(x, y) plus(x, y) expect(31, plus(30, 1)); expect(29, minus(30, 1)); // This is not a function-like macro. #define m7 (0) + 1 expect(1, m7); #define m8(x, y) x ## y expect(2, m8(TW, O)); expect(0, m8(ZERO,)); #define m9(x, y, z) x y + z expect(8, m9(1,, 7)); #define m10(x) x ## x expect_string("a", "a" m10()); #define hash_hash # ## # #define mkstr(a) # a #define in_between(a) mkstr(a) #define join(c, d) in_between(c hash_hash d) expect_string("x ## y", join(x, y)); int m14 = 67; #define m14(x) x expect(67, m14); expect(67, m14(m14)); int a = 68; #define glue(x, y) x ## y glue(a+, +); expect(69, a); #define identity(x) stringify(x) expect_string("aa A B aa C", identity(m10(a) A B m10(a) C)); #define identity2(x) stringify(z ## x) expect_string("zA aa A B aa C", identity2(A m10(a) A B m10(a) C)); #define m15(x) x x expect_string("a a", identity(m15(a))); #define m16(x) (x,x) expect_string("(a,a)", identity(m16(a))); }
template<typename MatrixType> void nomalloc(const MatrixType& m) { /* this test check no dynamic memory allocation are issued with fixed-size matrices */ typedef typename MatrixType::Index Index; typedef typename MatrixType::Scalar Scalar; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType; Index rows = m.rows(); Index cols = m.cols(); MatrixType m1 = MatrixType::Random(rows, cols), m2 = MatrixType::Random(rows, cols), m3(rows, cols), mzero = MatrixType::Zero(rows, cols), identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> ::Identity(rows, rows), square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> ::Random(rows, rows); VectorType v1 = VectorType::Random(rows), v2 = VectorType::Random(rows), vzero = VectorType::Zero(rows); Scalar s1 = internal::random<Scalar>(); Index r = internal::random<Index>(0, rows-1), c = internal::random<Index>(0, cols-1); VERIFY_IS_APPROX((m1+m2)*s1, s1*m1+s1*m2); VERIFY_IS_APPROX((m1+m2)(r,c), (m1(r,c))+(m2(r,c))); VERIFY_IS_APPROX(m1.cwiseProduct(m1.block(0,0,rows,cols)), (m1.array()*m1.array()).matrix()); VERIFY_IS_APPROX((m1*m1.transpose())*m2, m1*(m1.transpose()*m2)); m2.col(0).noalias() = m1 * m1.col(0); m2.col(0).noalias() -= m1.adjoint() * m1.col(0); m2.col(0).noalias() -= m1 * m1.row(0).adjoint(); m2.col(0).noalias() -= m1.adjoint() * m1.row(0).adjoint(); m2.row(0).noalias() = m1.row(0) * m1; m2.row(0).noalias() -= m1.row(0) * m1.adjoint(); m2.row(0).noalias() -= m1.col(0).adjoint() * m1; m2.row(0).noalias() -= m1.col(0).adjoint() * m1.adjoint(); VERIFY_IS_APPROX(m2,m2); m2.col(0).noalias() = m1.template triangularView<Upper>() * m1.col(0); m2.col(0).noalias() -= m1.adjoint().template triangularView<Upper>() * m1.col(0); m2.col(0).noalias() -= m1.template triangularView<Upper>() * m1.row(0).adjoint(); m2.col(0).noalias() -= m1.adjoint().template triangularView<Upper>() * m1.row(0).adjoint(); m2.row(0).noalias() = m1.row(0) * m1.template triangularView<Upper>(); m2.row(0).noalias() -= m1.row(0) * m1.adjoint().template triangularView<Upper>(); m2.row(0).noalias() -= m1.col(0).adjoint() * m1.template triangularView<Upper>(); m2.row(0).noalias() -= m1.col(0).adjoint() * m1.adjoint().template triangularView<Upper>(); VERIFY_IS_APPROX(m2,m2); m2.col(0).noalias() = m1.template selfadjointView<Upper>() * m1.col(0); m2.col(0).noalias() -= m1.adjoint().template selfadjointView<Upper>() * m1.col(0); m2.col(0).noalias() -= m1.template selfadjointView<Upper>() * m1.row(0).adjoint(); m2.col(0).noalias() -= m1.adjoint().template selfadjointView<Upper>() * m1.row(0).adjoint(); m2.row(0).noalias() = m1.row(0) * m1.template selfadjointView<Upper>(); m2.row(0).noalias() -= m1.row(0) * m1.adjoint().template selfadjointView<Upper>(); m2.row(0).noalias() -= m1.col(0).adjoint() * m1.template selfadjointView<Upper>(); m2.row(0).noalias() -= m1.col(0).adjoint() * m1.adjoint().template selfadjointView<Upper>(); VERIFY_IS_APPROX(m2,m2); m2.template selfadjointView<Lower>().rankUpdate(m1.col(0),-1); m2.template selfadjointView<Lower>().rankUpdate(m1.row(0),-1); // The following fancy matrix-matrix products are not safe yet regarding static allocation // m1 += m1.template triangularView<Upper>() * m2.col(; // m1.template selfadjointView<Lower>().rankUpdate(m2); // m1 += m1.template triangularView<Upper>() * m2; // m1 += m1.template selfadjointView<Lower>() * m2; // VERIFY_IS_APPROX(m1,m1); }
double StartTraining(int&result) { double errors=0.0; vcbList eTrainVcbList, fTrainVcbList; globeTrainVcbList=&eTrainVcbList; globfTrainVcbList=&fTrainVcbList; string repFilename = Prefix + ".gizacfg" ; ofstream of2(repFilename.c_str()); writeParameters(of2,getGlobalParSet(),-1) ; cout << "reading vocabulary files \n"; eTrainVcbList.setName(SourceVocabFilename.c_str()); fTrainVcbList.setName(TargetVocabFilename.c_str()); eTrainVcbList.readVocabList(); fTrainVcbList.readVocabList(); cout << "Source vocabulary list has " << eTrainVcbList.uniqTokens() << " unique tokens \n"; cout << "Target vocabulary list has " << fTrainVcbList.uniqTokens() << " unique tokens \n"; vcbList eTestVcbList(eTrainVcbList) ; vcbList fTestVcbList(fTrainVcbList) ; corpus = new sentenceHandler(CorpusFilename.c_str(), &eTrainVcbList, &fTrainVcbList); if (TestCorpusFilename == "NONE") TestCorpusFilename = ""; if (TestCorpusFilename != ""){ cout << "Test corpus will be read from: " << TestCorpusFilename << '\n'; testCorpus= new sentenceHandler(TestCorpusFilename.c_str(), &eTestVcbList, &fTestVcbList); cout << " Test total # sentence pairs : " <<(*testCorpus).getTotalNoPairs1()<<" weighted:"<<(*testCorpus).getTotalNoPairs2() <<'\n'; cout << "Size of the source portion of test corpus: " << eTestVcbList.totalVocab() << " tokens\n"; cout << "Size of the target portion of test corpus: " << fTestVcbList.totalVocab() << " tokens \n"; cout << "In source portion of the test corpus, only " << eTestVcbList.uniqTokensInCorpus() << " unique tokens appeared\n"; cout << "In target portion of the test corpus, only " << fTestVcbList.uniqTokensInCorpus() << " unique tokens appeared\n"; cout << "ratio (target/source) : " << double(fTestVcbList.totalVocab()) / eTestVcbList.totalVocab() << '\n'; } cout << " Train total # sentence pairs (weighted): " << corpus->getTotalNoPairs2() << '\n'; cout << "Size of source portion of the training corpus: " << eTrainVcbList.totalVocab()-corpus->getTotalNoPairs2() << " tokens\n"; cout << "Size of the target portion of the training corpus: " << fTrainVcbList.totalVocab() << " tokens \n"; cout << "In source portion of the training corpus, only " << eTrainVcbList.uniqTokensInCorpus() << " unique tokens appeared\n"; cout << "In target portion of the training corpus, only " << fTrainVcbList.uniqTokensInCorpus() << " unique tokens appeared\n"; cout << "lambda for PP calculation in IBM-1,IBM-2,HMM:= " << double(fTrainVcbList.totalVocab()) << "/(" << eTrainVcbList.totalVocab() << "-" << corpus->getTotalNoPairs2() << ")="; LAMBDA = double(fTrainVcbList.totalVocab()) / (eTrainVcbList.totalVocab()-corpus->getTotalNoPairs2()); cout << "= " << LAMBDA << '\n'; // load dictionary Dictionary *dictionary; useDict = !dictionary_Filename.empty(); if (useDict) dictionary = new Dictionary(dictionary_Filename.c_str()); else dictionary = new Dictionary(""); int minIter=0; #ifdef BINARY_SEARCH_FOR_TTABLE if( CoocurrenceFile.length()==0 ) { cerr << "ERROR: NO COOCURRENCE FILE GIVEN!\n"; abort(); } //ifstream coocs(CoocurrenceFile.c_str()); tmodel<COUNT, PROB> tTable(CoocurrenceFile); #else tmodel<COUNT, PROB> tTable; #endif model1 m1(CorpusFilename.c_str(), eTrainVcbList, fTrainVcbList,tTable,trainPerp, *corpus,&testPerp, testCorpus, trainViterbiPerp, &testViterbiPerp); amodel<PROB> aTable(false); amodel<COUNT> aCountTable(false); model2 m2(m1,aTable,aCountTable); hmm h(m2); model3 m3(m2); if(ReadTablePrefix.length() ) { string number = "final"; string tfile,afilennfile,dfile,d4file,p0file,afile,nfile; //d5file tfile = ReadTablePrefix + ".t3." + number ; afile = ReadTablePrefix + ".a3." + number ; nfile = ReadTablePrefix + ".n3." + number ; dfile = ReadTablePrefix + ".d3." + number ; d4file = ReadTablePrefix + ".d4." + number ; //d5file = ReadTablePrefix + ".d5." + number ; p0file = ReadTablePrefix + ".p0_3." + number ; tTable.readProbTable(tfile.c_str()); aTable.readTable(afile.c_str()); m3.dTable.readTable(dfile.c_str()); m3.nTable.readNTable(nfile.c_str()); sentPair sent ; double p0; ifstream p0f(p0file.c_str()); p0f >> p0; d4model d4m(MAX_SENTENCE_LENGTH); d4m.makeWordClasses(m1.Elist,m1.Flist,SourceVocabFilename+".classes",TargetVocabFilename+".classes"); d4m.readProbTable(d4file.c_str()); //d5model d5m(d4m); //d5m.makeWordClasses(m1.Elist,m1.Flist,SourceVocabFilename+".classes",TargetVocabFilename+".classes"); //d5m.readProbTable(d5file.c_str()); makeSetCommand("model4smoothfactor","0.0",getGlobalParSet(),2); //makeSetCommand("model5smoothfactor","0.0",getGlobalParSet(),2); if( corpus||testCorpus ) { sentenceHandler *x=corpus; if(x==0) x=testCorpus; cout << "Text corpus exists.\n"; x->rewind(); while(x&&x->getNextSentence(sent)){ Vector<WordIndex>& es = sent.eSent; Vector<WordIndex>& fs = sent.fSent; int l=es.size()-1; int m=fs.size()-1; transpair_model4 tm4(es,fs,m1.tTable,m2.aTable,m3.dTable,m3.nTable,1-p0,p0,&d4m); alignment al(l,m); cout << "I use the alignment " << sent.sentenceNo-1 << '\n'; //convert(ReferenceAlignment[sent.sentenceNo-1],al); transpair_model3 tm3(es,fs,m1.tTable,m2.aTable,m3.dTable,m3.nTable,1-p0,p0,0); double p=tm3.prob_of_target_and_alignment_given_source(al,1); cout << "Sentence " << sent.sentenceNo << " has IBM-3 prob " << p << '\n'; p=tm4.prob_of_target_and_alignment_given_source(al,3,1); cout << "Sentence " << sent.sentenceNo << " has IBM-4 prob " << p << '\n'; //transpair_model5 tm5(es,fs,m1.tTable,m2.aTable,m3.dTable,m3.nTable,1-p0,p0,&d5m); //p=tm5.prob_of_target_and_alignment_given_source(al,3,1); //cout << "Sentence " << sent.sentenceNo << " has IBM-5 prob " << p << '\n'; } } else { cout << "No corpus exists.\n"; } }
template<typename MatrixType> void trmv(const MatrixType& m) { typedef typename MatrixType::Index Index; typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType; RealScalar largerEps = 10*test_precision<RealScalar>(); Index rows = m.rows(); Index cols = m.cols(); MatrixType m1 = MatrixType::Random(rows, cols), m3(rows, cols); VectorType v1 = VectorType::Random(rows); Scalar s1 = internal::random<Scalar>(); m1 = MatrixType::Random(rows, cols); // check with a column-major matrix m3 = m1.template triangularView<Eigen::Lower>(); VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::Lower>() * v1, largerEps)); m3 = m1.template triangularView<Eigen::Upper>(); VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::Upper>() * v1, largerEps)); m3 = m1.template triangularView<Eigen::UnitLower>(); VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::UnitLower>() * v1, largerEps)); m3 = m1.template triangularView<Eigen::UnitUpper>(); VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::UnitUpper>() * v1, largerEps)); // check conjugated and scalar multiple expressions (col-major) m3 = m1.template triangularView<Eigen::Lower>(); VERIFY(((s1*m3).conjugate() * v1).isApprox((s1*m1).conjugate().template triangularView<Eigen::Lower>() * v1, largerEps)); m3 = m1.template triangularView<Eigen::Upper>(); VERIFY((m3.conjugate() * v1.conjugate()).isApprox(m1.conjugate().template triangularView<Eigen::Upper>() * v1.conjugate(), largerEps)); // check with a row-major matrix m3 = m1.template triangularView<Eigen::Upper>(); VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::Lower>() * v1, largerEps)); m3 = m1.template triangularView<Eigen::Lower>(); VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::Upper>() * v1, largerEps)); m3 = m1.template triangularView<Eigen::UnitUpper>(); VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::UnitLower>() * v1, largerEps)); m3 = m1.template triangularView<Eigen::UnitLower>(); VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::UnitUpper>() * v1, largerEps)); // check conjugated and scalar multiple expressions (row-major) m3 = m1.template triangularView<Eigen::Upper>(); VERIFY((m3.adjoint() * v1).isApprox(m1.adjoint().template triangularView<Eigen::Lower>() * v1, largerEps)); m3 = m1.template triangularView<Eigen::Lower>(); VERIFY((m3.adjoint() * (s1*v1.conjugate())).isApprox(m1.adjoint().template triangularView<Eigen::Upper>() * (s1*v1.conjugate()), largerEps)); m3 = m1.template triangularView<Eigen::UnitUpper>(); // check transposed cases: m3 = m1.template triangularView<Eigen::Lower>(); VERIFY((v1.transpose() * m3).isApprox(v1.transpose() * m1.template triangularView<Eigen::Lower>(), largerEps)); VERIFY((v1.adjoint() * m3).isApprox(v1.adjoint() * m1.template triangularView<Eigen::Lower>(), largerEps)); VERIFY((v1.adjoint() * m3.adjoint()).isApprox(v1.adjoint() * m1.template triangularView<Eigen::Lower>().adjoint(), largerEps)); // TODO check with sub-matrices }
template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& ref) { const int rows = ref.rows(); const int cols = ref.cols(); typedef typename SparseMatrixType::Scalar Scalar; enum { Flags = SparseMatrixType::Flags }; double density = std::max(8./(rows*cols), 0.01); typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix; typedef Matrix<Scalar,Dynamic,1> DenseVector; Scalar eps = 1e-6; SparseMatrixType m(rows, cols); DenseMatrix refMat = DenseMatrix::Zero(rows, cols); DenseVector vec1 = DenseVector::Random(rows); Scalar s1 = ei_random<Scalar>(); std::vector<Vector2i> zeroCoords; std::vector<Vector2i> nonzeroCoords; initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords); if (zeroCoords.size()==0 || nonzeroCoords.size()==0) return; // test coeff and coeffRef for (int i=0; i<(int)zeroCoords.size(); ++i) { VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps ); if(ei_is_same_type<SparseMatrixType,SparseMatrix<Scalar,Flags> >::ret) VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[0].x(),zeroCoords[0].y()) = 5 ); } VERIFY_IS_APPROX(m, refMat); m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5); refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5); VERIFY_IS_APPROX(m, refMat); /* // test InnerIterators and Block expressions for (int t=0; t<10; ++t) { int j = ei_random<int>(0,cols-1); int i = ei_random<int>(0,rows-1); int w = ei_random<int>(1,cols-j-1); int h = ei_random<int>(1,rows-i-1); // VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w)); for(int c=0; c<w; c++) { VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c)); for(int r=0; r<h; r++) { // VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r)); } } // for(int r=0; r<h; r++) // { // VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r)); // for(int c=0; c<w; c++) // { // VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c)); // } // } } for(int c=0; c<cols; c++) { VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c)); VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c)); } for(int r=0; r<rows; r++) { VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r)); VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r)); } */ // test SparseSetters // coherent setter // TODO extend the MatrixSetter // { // m.setZero(); // VERIFY_IS_NOT_APPROX(m, refMat); // SparseSetter<SparseMatrixType, FullyCoherentAccessPattern> w(m); // for (int i=0; i<nonzeroCoords.size(); ++i) // { // w->coeffRef(nonzeroCoords[i].x(),nonzeroCoords[i].y()) = refMat.coeff(nonzeroCoords[i].x(),nonzeroCoords[i].y()); // } // } // VERIFY_IS_APPROX(m, refMat); // random setter // { // m.setZero(); // VERIFY_IS_NOT_APPROX(m, refMat); // SparseSetter<SparseMatrixType, RandomAccessPattern> w(m); // std::vector<Vector2i> remaining = nonzeroCoords; // while(!remaining.empty()) // { // int i = ei_random<int>(0,remaining.size()-1); // w->coeffRef(remaining[i].x(),remaining[i].y()) = refMat.coeff(remaining[i].x(),remaining[i].y()); // remaining[i] = remaining.back(); // remaining.pop_back(); // } // } // VERIFY_IS_APPROX(m, refMat); VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, StdMapTraits> >(m,refMat,nonzeroCoords) )); #ifdef EIGEN_UNORDERED_MAP_SUPPORT VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, StdUnorderedMapTraits> >(m,refMat,nonzeroCoords) )); #endif #ifdef _DENSE_HASH_MAP_H_ VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, GoogleDenseHashMapTraits> >(m,refMat,nonzeroCoords) )); #endif #ifdef _SPARSE_HASH_MAP_H_ VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, GoogleSparseHashMapTraits> >(m,refMat,nonzeroCoords) )); #endif // test fillrand { DenseMatrix m1(rows,cols); m1.setZero(); SparseMatrixType m2(rows,cols); m2.startFill(); for (int j=0; j<cols; ++j) { for (int k=0; k<rows/2; ++k) { int i = ei_random<int>(0,rows-1); if (m1.coeff(i,j)==Scalar(0)) m2.fillrand(i,j) = m1(i,j) = ei_random<Scalar>(); } } m2.endFill(); VERIFY_IS_APPROX(m2,m1); } // test RandomSetter /*{ SparseMatrixType m1(rows,cols), m2(rows,cols); DenseMatrix refM1 = DenseMatrix::Zero(rows, rows); initSparse<Scalar>(density, refM1, m1); { Eigen::RandomSetter<SparseMatrixType > setter(m2); for (int j=0; j<m1.outerSize(); ++j) for (typename SparseMatrixType::InnerIterator i(m1,j); i; ++i) setter(i.index(), j) = i.value(); } VERIFY_IS_APPROX(m1, m2); }*/ // std::cerr << m.transpose() << "\n\n" << refMat.transpose() << "\n\n"; // VERIFY_IS_APPROX(m, refMat); // test basic computations { DenseMatrix refM1 = DenseMatrix::Zero(rows, rows); DenseMatrix refM2 = DenseMatrix::Zero(rows, rows); DenseMatrix refM3 = DenseMatrix::Zero(rows, rows); DenseMatrix refM4 = DenseMatrix::Zero(rows, rows); SparseMatrixType m1(rows, rows); SparseMatrixType m2(rows, rows); SparseMatrixType m3(rows, rows); SparseMatrixType m4(rows, rows); initSparse<Scalar>(density, refM1, m1); initSparse<Scalar>(density, refM2, m2); initSparse<Scalar>(density, refM3, m3); initSparse<Scalar>(density, refM4, m4); VERIFY_IS_APPROX(m1+m2, refM1+refM2); VERIFY_IS_APPROX(m1+m2+m3, refM1+refM2+refM3); VERIFY_IS_APPROX(m3.cwise()*(m1+m2), refM3.cwise()*(refM1+refM2)); VERIFY_IS_APPROX(m1*s1-m2, refM1*s1-refM2); VERIFY_IS_APPROX(m1*=s1, refM1*=s1); VERIFY_IS_APPROX(m1/=s1, refM1/=s1); VERIFY_IS_APPROX(m1+=m2, refM1+=refM2); VERIFY_IS_APPROX(m1-=m2, refM1-=refM2); VERIFY_IS_APPROX(m1.col(0).eigen2_dot(refM2.row(0)), refM1.col(0).eigen2_dot(refM2.row(0))); refM4.setRandom(); // sparse cwise* dense VERIFY_IS_APPROX(m3.cwise()*refM4, refM3.cwise()*refM4); // VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4); } // test innerVector() { DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows); SparseMatrixType m2(rows, rows); initSparse<Scalar>(density, refMat2, m2); int j0 = ei_random(0,rows-1); int j1 = ei_random(0,rows-1); VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0)); VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1)); //m2.innerVector(j0) = 2*m2.innerVector(j1); //refMat2.col(j0) = 2*refMat2.col(j1); //VERIFY_IS_APPROX(m2, refMat2); } // test innerVectors() { DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows); SparseMatrixType m2(rows, rows); initSparse<Scalar>(density, refMat2, m2); int j0 = ei_random(0,rows-2); int j1 = ei_random(0,rows-2); int n0 = ei_random<int>(1,rows-std::max(j0,j1)); VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0)); VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0), refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0)); //m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0); //refMat2.block(0,j0,rows,n0) = refMat2.block(0,j0,rows,n0) + refMat2.block(0,j1,rows,n0); } // test transpose { DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows); SparseMatrixType m2(rows, rows); initSparse<Scalar>(density, refMat2, m2); VERIFY_IS_APPROX(m2.transpose().eval(), refMat2.transpose().eval()); VERIFY_IS_APPROX(m2.transpose(), refMat2.transpose()); } // test prune { SparseMatrixType m2(rows, rows); DenseMatrix refM2(rows, rows); refM2.setZero(); int countFalseNonZero = 0; int countTrueNonZero = 0; m2.startFill(); for (int j=0; j<m2.outerSize(); ++j) for (int i=0; i<m2.innerSize(); ++i) { float x = ei_random<float>(0,1); if (x<0.1) { // do nothing } else if (x<0.5) { countFalseNonZero++; m2.fill(i,j) = Scalar(0); } else { countTrueNonZero++; m2.fill(i,j) = refM2(i,j) = Scalar(1); } } m2.endFill(); VERIFY(countFalseNonZero+countTrueNonZero == m2.nonZeros()); VERIFY_IS_APPROX(m2, refM2); m2.prune(1); VERIFY(countTrueNonZero==m2.nonZeros()); VERIFY_IS_APPROX(m2, refM2); } }
template<typename SparseMatrixType> void sparse_product() { typedef typename SparseMatrixType::Index Index; Index n = 100; const Index rows = internal::random<int>(1,n); const Index cols = internal::random<int>(1,n); const Index depth = internal::random<int>(1,n); typedef typename SparseMatrixType::Scalar Scalar; enum { Flags = SparseMatrixType::Flags }; double density = (std::max)(8./(rows*cols), 0.1); typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix; typedef Matrix<Scalar,Dynamic,1> DenseVector; Scalar s1 = internal::random<Scalar>(); Scalar s2 = internal::random<Scalar>(); // test matrix-matrix product { DenseMatrix refMat2 = DenseMatrix::Zero(rows, depth); DenseMatrix refMat2t = DenseMatrix::Zero(depth, rows); DenseMatrix refMat3 = DenseMatrix::Zero(depth, cols); DenseMatrix refMat3t = DenseMatrix::Zero(cols, depth); DenseMatrix refMat4 = DenseMatrix::Zero(rows, cols); DenseMatrix refMat4t = DenseMatrix::Zero(cols, rows); DenseMatrix refMat5 = DenseMatrix::Random(depth, cols); DenseMatrix refMat6 = DenseMatrix::Random(rows, rows); DenseMatrix dm4 = DenseMatrix::Zero(rows, rows); // DenseVector dv1 = DenseVector::Random(rows); SparseMatrixType m2 (rows, depth); SparseMatrixType m2t(depth, rows); SparseMatrixType m3 (depth, cols); SparseMatrixType m3t(cols, depth); SparseMatrixType m4 (rows, cols); SparseMatrixType m4t(cols, rows); SparseMatrixType m6(rows, rows); initSparse(density, refMat2, m2); initSparse(density, refMat2t, m2t); initSparse(density, refMat3, m3); initSparse(density, refMat3t, m3t); initSparse(density, refMat4, m4); initSparse(density, refMat4t, m4t); initSparse(density, refMat6, m6); // int c = internal::random<int>(0,depth-1); // sparse * sparse VERIFY_IS_APPROX(m4=m2*m3, refMat4=refMat2*refMat3); VERIFY_IS_APPROX(m4=m2t.transpose()*m3, refMat4=refMat2t.transpose()*refMat3); VERIFY_IS_APPROX(m4=m2t.transpose()*m3t.transpose(), refMat4=refMat2t.transpose()*refMat3t.transpose()); VERIFY_IS_APPROX(m4=m2*m3t.transpose(), refMat4=refMat2*refMat3t.transpose()); VERIFY_IS_APPROX(m4 = m2*m3/s1, refMat4 = refMat2*refMat3/s1); VERIFY_IS_APPROX(m4 = m2*m3*s1, refMat4 = refMat2*refMat3*s1); VERIFY_IS_APPROX(m4 = s2*m2*m3*s1, refMat4 = s2*refMat2*refMat3*s1); VERIFY_IS_APPROX(m4=(m2*m3).pruned(0), refMat4=refMat2*refMat3); VERIFY_IS_APPROX(m4=(m2t.transpose()*m3).pruned(0), refMat4=refMat2t.transpose()*refMat3); VERIFY_IS_APPROX(m4=(m2t.transpose()*m3t.transpose()).pruned(0), refMat4=refMat2t.transpose()*refMat3t.transpose()); VERIFY_IS_APPROX(m4=(m2*m3t.transpose()).pruned(0), refMat4=refMat2*refMat3t.transpose()); // test aliasing m4 = m2; refMat4 = refMat2; VERIFY_IS_APPROX(m4=m4*m3, refMat4=refMat4*refMat3); // sparse * dense VERIFY_IS_APPROX(dm4=m2*refMat3, refMat4=refMat2*refMat3); VERIFY_IS_APPROX(dm4=m2*refMat3t.transpose(), refMat4=refMat2*refMat3t.transpose()); VERIFY_IS_APPROX(dm4=m2t.transpose()*refMat3, refMat4=refMat2t.transpose()*refMat3); VERIFY_IS_APPROX(dm4=m2t.transpose()*refMat3t.transpose(), refMat4=refMat2t.transpose()*refMat3t.transpose()); VERIFY_IS_APPROX(dm4=m2*(refMat3+refMat3), refMat4=refMat2*(refMat3+refMat3)); VERIFY_IS_APPROX(dm4=m2t.transpose()*(refMat3+refMat5)*0.5, refMat4=refMat2t.transpose()*(refMat3+refMat5)*0.5); // dense * sparse VERIFY_IS_APPROX(dm4=refMat2*m3, refMat4=refMat2*refMat3); VERIFY_IS_APPROX(dm4=refMat2*m3t.transpose(), refMat4=refMat2*refMat3t.transpose()); VERIFY_IS_APPROX(dm4=refMat2t.transpose()*m3, refMat4=refMat2t.transpose()*refMat3); VERIFY_IS_APPROX(dm4=refMat2t.transpose()*m3t.transpose(), refMat4=refMat2t.transpose()*refMat3t.transpose()); // sparse * dense and dense * sparse outer product test_outer<SparseMatrixType,DenseMatrix>::run(m2,m4,refMat2,refMat4); VERIFY_IS_APPROX(m6=m6*m6, refMat6=refMat6*refMat6); } // test matrix - diagonal product { DenseMatrix refM2 = DenseMatrix::Zero(rows, cols); DenseMatrix refM3 = DenseMatrix::Zero(rows, cols); DenseMatrix d3 = DenseMatrix::Zero(rows, cols); DiagonalMatrix<Scalar,Dynamic> d1(DenseVector::Random(cols)); DiagonalMatrix<Scalar,Dynamic> d2(DenseVector::Random(rows)); SparseMatrixType m2(rows, cols); SparseMatrixType m3(rows, cols); initSparse<Scalar>(density, refM2, m2); initSparse<Scalar>(density, refM3, m3); VERIFY_IS_APPROX(m3=m2*d1, refM3=refM2*d1); VERIFY_IS_APPROX(m3=m2.transpose()*d2, refM3=refM2.transpose()*d2); VERIFY_IS_APPROX(m3=d2*m2, refM3=d2*refM2); VERIFY_IS_APPROX(m3=d1*m2.transpose(), refM3=d1*refM2.transpose()); // evaluate to a dense matrix to check the .row() and .col() iterator functions VERIFY_IS_APPROX(d3=m2*d1, refM3=refM2*d1); VERIFY_IS_APPROX(d3=m2.transpose()*d2, refM3=refM2.transpose()*d2); VERIFY_IS_APPROX(d3=d2*m2, refM3=d2*refM2); VERIFY_IS_APPROX(d3=d1*m2.transpose(), refM3=d1*refM2.transpose()); } // test self adjoint products { DenseMatrix b = DenseMatrix::Random(rows, rows); DenseMatrix x = DenseMatrix::Random(rows, rows); DenseMatrix refX = DenseMatrix::Random(rows, rows); DenseMatrix refUp = DenseMatrix::Zero(rows, rows); DenseMatrix refLo = DenseMatrix::Zero(rows, rows); DenseMatrix refS = DenseMatrix::Zero(rows, rows); SparseMatrixType mUp(rows, rows); SparseMatrixType mLo(rows, rows); SparseMatrixType mS(rows, rows); do { initSparse<Scalar>(density, refUp, mUp, ForceRealDiag|/*ForceNonZeroDiag|*/MakeUpperTriangular); } while (refUp.isZero()); refLo = refUp.adjoint(); mLo = mUp.adjoint(); refS = refUp + refLo; refS.diagonal() *= 0.5; mS = mUp + mLo; // TODO be able to address the diagonal.... for (int k=0; k<mS.outerSize(); ++k) for (typename SparseMatrixType::InnerIterator it(mS,k); it; ++it) if (it.index() == k) it.valueRef() *= 0.5; VERIFY_IS_APPROX(refS.adjoint(), refS); VERIFY_IS_APPROX(mS.adjoint(), mS); VERIFY_IS_APPROX(mS, refS); VERIFY_IS_APPROX(x=mS*b, refX=refS*b); VERIFY_IS_APPROX(x=mUp.template selfadjointView<Upper>()*b, refX=refS*b); VERIFY_IS_APPROX(x=mLo.template selfadjointView<Lower>()*b, refX=refS*b); VERIFY_IS_APPROX(x=mS.template selfadjointView<Upper|Lower>()*b, refX=refS*b); } }