diff --git a/Eigen/src/Core/Cwise.h b/Eigen/src/Core/Cwise.h index 0f81a8a4b..c3a15e307 100644 --- a/Eigen/src/Core/Cwise.h +++ b/Eigen/src/Core/Cwise.h @@ -95,7 +95,6 @@ template class Cwise const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_sin_op) sin() const; const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_pow_op) pow(const Scalar& exponent) const; - const ScalarAddReturnType operator+(const Scalar& scalar) const; diff --git a/Eigen/src/Geometry/Transform.h b/Eigen/src/Geometry/Transform.h index 158624617..4710cc4bc 100644 --- a/Eigen/src/Geometry/Transform.h +++ b/Eigen/src/Geometry/Transform.h @@ -65,9 +65,9 @@ public: typedef _Scalar Scalar; /** type of the matrix used to represent the transformation */ typedef Matrix MatrixType; - /** type of the matrix used to represent the affine part of the transformation */ + /** type of the matrix used to represent the linear part of the transformation */ typedef Matrix AffineMatrixType; - /** type of read/write reference to the affine part of the transformation */ + /** type of read/write reference to the linear part of the transformation */ typedef Block AffinePart; /** type of a vector */ typedef Matrix VectorType; @@ -110,10 +110,10 @@ public: /** \returns a writable expression of the transformation matrix */ inline MatrixType& matrix() { return m_matrix; } - /** \returns a read-only expression of the affine (linear) part of the transformation */ - inline const AffinePart affine() const { return m_matrix.template block(0,0); } - /** \returns a writable expression of the affine (linear) part of the transformation */ - inline AffinePart affine() { return m_matrix.template block(0,0); } + /** \returns a read-only expression of the linear (linear) part of the transformation */ + inline const AffinePart linear() const { return m_matrix.template block(0,0); } + /** \returns a writable expression of the linear (linear) part of the transformation */ + inline AffinePart linear() { return m_matrix.template block(0,0); } /** \returns a read-only expression of the translation vector of the transformation */ inline const TranslationPart translation() const { return m_matrix.template block(0,Dim); } @@ -235,7 +235,7 @@ Transform& Transform::scale(const MatrixBase &other) { EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim)); - affine() = (affine() * other.asDiagonal()).lazy(); + linear() = (linear() * other.asDiagonal()).lazy(); return *this; } @@ -263,7 +263,7 @@ Transform& Transform::translate(const MatrixBase &other) { EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim)); - translation() += affine() * other; + translation() += linear() * other; return *this; } @@ -303,7 +303,7 @@ template Transform& Transform::rotate(const RotationType& rotation) { - affine() *= ToRotationMatrix::convert(rotation); + linear() *= ToRotationMatrix::convert(rotation); return *this; } @@ -334,8 +334,8 @@ Transform& Transform::shear(Scalar sx, Scalar sy) { EIGEN_STATIC_ASSERT(int(Dim)==2, you_did_a_programming_error); - VectorType tmp = affine().col(0)*sy + affine().col(1); - affine() << affine().col(0) + affine().col(1)*sx, tmp; + VectorType tmp = linear().col(0)*sy + linear().col(1); + linear() << linear().col(0) + linear().col(1)*sx, tmp; return *this; } @@ -360,18 +360,18 @@ template typename Transform::AffineMatrixType Transform::extractRotation() const { - return affine().qr().matrixQ(); + return linear().qr().matrixQ(); } /** \returns the rotation part of the transformation assuming no shear in - * the affine part. + * the linear part. * \sa extractRotation() */ template typename Transform::AffineMatrixType Transform::extractRotationNoShear() const { - return affine().cwise().abs2() + return linear().cwise().abs2() .verticalRedux(ei_scalar_sum_op()).cwise().sqrt(); } @@ -384,11 +384,11 @@ Transform& Transform::fromPositionOrientationScale(const MatrixBase &position, const OrientationType& orientation, const MatrixBase &scale) { - affine() = ToRotationMatrix::convert(orientation); + linear() = ToRotationMatrix::convert(orientation); translation() = position; m_matrix(Dim,Dim) = 1.; m_matrix.template block<1,Dim>(Dim,0).setZero(); - affine() *= scale.asDiagonal(); + linear() *= scale.asDiagonal(); return *this; } @@ -431,7 +431,7 @@ struct ei_transform_product_impl > ResultType; // FIXME should we offer an optimized version when the last row is known to be 0,0...,0,1 ? static ResultType run(const TransformType& tr, const Other& other) - { return ((tr.affine().nestByValue() * other).nestByValue() + tr.translation().nestByValue()).nestByValue() + { return ((tr.linear().nestByValue() * other).nestByValue() + tr.translation().nestByValue()).nestByValue() * (Scalar(1) / ( (tr.matrix().template block<1,Dim>(Dim,0) * other).coeff(0) + tr.matrix().coeff(Dim,Dim))); } }; diff --git a/Eigen/src/Sparse/SparseMatrix.h b/Eigen/src/Sparse/SparseMatrix.h index cc13e21c7..2504d9fd8 100644 --- a/Eigen/src/Sparse/SparseMatrix.h +++ b/Eigen/src/Sparse/SparseMatrix.h @@ -85,11 +85,15 @@ class SparseMatrix : public SparseMatrixBase > const int inner = RowMajor ? col : row; int id = m_outerIndex[outer]; - int end = m_outerIndex[outer+1]-1; - if (m_data.index(end)==inner) - return m_data.value(end); + int end = m_outerIndex[outer+1]; + // optimization: let's first check if it is the last coefficient + // (very common in high level algorithms) + if (end>0 && inner==m_data.index(end-1)) + return m_data.value(end-1); + else if (id==end) + return Scalar(0); const int* r = std::lower_bound(&m_data.index(id),&m_data.index(end),inner); - return (*r==inner) ? m_data.value(*r) : Scalar(0); + return (*r==inner) ? m_data.value(r-&m_data.index(0)) : Scalar(0); } inline Scalar& coeffRef(int row, int col) @@ -99,9 +103,11 @@ class SparseMatrix : public SparseMatrixBase > int id = m_outerIndex[outer]; int end = m_outerIndex[outer+1]; + ei_assert(end>=id && "you probably called coeffRef on a non finalized matrix"); + ei_assert(end>id && "coeffRef cannot be called on a zero coefficient"); int* r = std::lower_bound(&m_data.index(id),&m_data.index(end),inner); - ei_assert(*r==inner); - return m_data.value(*r); + ei_assert(*r==inner && "coeffRef cannot be called on a zero coefficient"); + return m_data.value(r-&m_data.index(0)); } public: diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e0f6f2664..8d217d421 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -111,5 +111,6 @@ EI_ADD_TEST(geometry) EI_ADD_TEST(regression) EI_ADD_TEST(svd) EI_ADD_TEST(ioformat) +EI_ADD_TEST(sparse) ENDIF(BUILD_TESTS) diff --git a/test/geometry.cpp b/test/geometry.cpp index a41a26c23..2aad9dda3 100644 --- a/test/geometry.cpp +++ b/test/geometry.cpp @@ -117,9 +117,9 @@ template void geometry(void) q1 = AngleAxis(a, v0.normalized()); Transform3 t0, t1, t2; t0.setIdentity(); - t0.affine() = q1.toRotationMatrix(); + t0.linear() = q1.toRotationMatrix(); t1.setIdentity(); - t1.affine() = q1.toRotationMatrix(); + t1.linear() = q1.toRotationMatrix(); v0 << 50, 2, 1;//= Vector3::Random().cwiseProduct(Vector3(10,2,0.5)); t0.scale(v0); @@ -131,10 +131,10 @@ template void geometry(void) t0.setIdentity(); t1.setIdentity(); v1 << 1, 2, 3; - t0.affine() = q1.toRotationMatrix(); + t0.linear() = q1.toRotationMatrix(); t0.pretranslate(v0); t0.scale(v1); - t1.affine() = q1.conjugate().toRotationMatrix(); + t1.linear() = q1.conjugate().toRotationMatrix(); t1.prescale(v1.cwise().inverse()); t1.translate(-v0); @@ -148,12 +148,12 @@ template void geometry(void) Vector2 v20 = Vector2::Random(); Vector2 v21 = Vector2::Random(); t21.setIdentity(); - t21.affine() = Rotation2D(a).toRotationMatrix(); + t21.linear() = Rotation2D(a).toRotationMatrix(); VERIFY_IS_APPROX(t20.fromPositionOrientationScale(v20,a,v21).matrix(), t21.pretranslate(v20).scale(v21).matrix()); t21.setIdentity(); - t21.affine() = Rotation2D(-a).toRotationMatrix(); + t21.linear() = Rotation2D(-a).toRotationMatrix(); VERIFY( (t20.fromPositionOrientationScale(v20,a,v21) * (t21.prescale(v21.cwise().inverse()).translate(-v20))).isIdentity() ); } diff --git a/test/sparse.cpp b/test/sparse.cpp new file mode 100644 index 000000000..c86697712 --- /dev/null +++ b/test/sparse.cpp @@ -0,0 +1,65 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. Eigen itself is part of the KDE project. +// +// Copyright (C) 2008 Daniel Gomez Ferro +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see . + +#include "main.h" +#include + +void test_sparse() +{ + int rows = 4, cols = 4; + SparseMatrix m(rows, cols); + + m.startFill(rows); + m.fill(0, 2) = 2; + m.fill(1, 2) = 1; + m.fill(0, 3) = 5; + m.endFill(); + + m.coeffRef(0, 2) = 3; + VERIFY_RAISES_ASSERT( m.coeffRef(0, 0) = 5 ); + VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(0, 0), 0.000001 ); + VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(0, 1), 0.000001 ); + VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(2, 1), 0.000001 ); + VERIFY_IS_APPROX( m.coeff(0, 2), 3.0 ); + VERIFY_IS_APPROX( m.coeff(1, 2), 1.0 ); + VERIFY_IS_APPROX( m.coeff(0, 3), 5.0 ); + + Matrix4d dm; + double r; + m.startFill(rows*cols); + for(int i=0; i