Beispiel #1
0
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());
  }
}
Beispiel #5
0
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() );
}
Beispiel #6
0
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
}
Beispiel #7
0
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);

}
Beispiel #8
0
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
}
Beispiel #10
0
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;
}
Beispiel #12
0
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);
  }
}
Beispiel #13
0
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;
}
Beispiel #14
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;
        }
Beispiel #15
0
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());
    }
}
Beispiel #16
0
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());
}
Beispiel #17
0
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);
  }
}
Beispiel #22
0
/*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;
}
Beispiel #23
0
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) );
}
Beispiel #24
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

    }
Beispiel #25
0
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)));
}
Beispiel #26
0
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);
}
Beispiel #27
0
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";
	 }
    }
Beispiel #28
0
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);
  }
}
Beispiel #30
0
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);
  }
}