diff --git a/src/Core.h b/src/Core.h index 3ab2cf965..78d14c151 100644 --- a/src/Core.h +++ b/src/Core.h @@ -27,6 +27,8 @@ namespace Eigen { #include "Core/Trace.h" #include "Core/Dot.h" #include "Core/Random.h" +#include "Core/Zero.h" +#include "Core/Identity.h" #include "Core/Fuzzy.h" } // namespace Eigen diff --git a/src/Core/Fuzzy.h b/src/Core/Fuzzy.h index ed995dc8d..0b007329f 100644 --- a/src/Core/Fuzzy.h +++ b/src/Core/Fuzzy.h @@ -33,6 +33,7 @@ bool Object::isApprox( const typename NumTraits::Real& prec ) const { + assert(rows() == other.rows() && cols() == other.cols()); if(IsVector) { return((*this - other).norm2() <= std::min(norm2(), other.norm2()) * prec * prec); @@ -73,6 +74,7 @@ bool Object::isMuchSmallerThan( const typename NumTraits::Real& prec ) const { + assert(rows() == other.rows() && cols() == other.cols()); if(IsVector) { return(norm2() <= other.norm2() * prec * prec); diff --git a/src/Core/Identity.h b/src/Core/Identity.h new file mode 100644 index 000000000..78b380b04 --- /dev/null +++ b/src/Core/Identity.h @@ -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) 2006-2007 Benoit Jacob +// +// Eigen is free software; 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 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 General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along +// with Eigen; if not, write to the Free Software Foundation, Inc., 51 +// Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. This exception does not invalidate any other reasons why a work +// based on this file might be covered by the GNU General Public License. + +#ifndef EI_IDENTITY_H +#define EI_IDENTITY_H + +template class Identity + : public Object > +{ + public: + typedef typename MatrixType::Scalar Scalar; + friend class Object >; + + static const int RowsAtCompileTime = MatrixType::RowsAtCompileTime, + ColsAtCompileTime = MatrixType::ColsAtCompileTime; + + Identity(int rows, int cols) : m_rows(rows), m_cols(cols) + { + assert(rows > 0 && cols > 0); + } + + private: + Identity& _ref() { return *this; } + const Identity& _constRef() const { return *this; } + int _rows() const { return m_rows; } + int _cols() const { return m_cols; } + + Scalar _read(int row, int col) const + { + return static_cast(row == col); + } + + protected: + int m_rows, m_cols; +}; + +template +Identity Object::identity(int rows, int cols) +{ + return Identity(rows, cols); +} + +#endif // EI_IDENTITY_H diff --git a/src/Core/Object.h b/src/Core/Object.h index 95f540f10..5b2e34f53 100644 --- a/src/Core/Object.h +++ b/src/Core/Object.h @@ -113,6 +113,10 @@ template class Object static Eval > random(int rows = RowsAtCompileTime, int cols = ColsAtCompileTime); + static Zero + zero(int rows = RowsAtCompileTime, int cols = ColsAtCompileTime); + static Identity + identity(int rows = RowsAtCompileTime, int cols = ColsAtCompileTime); template bool isApprox( diff --git a/src/Core/Util.h b/src/Core/Util.h index 7d840828a..90840b308 100644 --- a/src/Core/Util.h +++ b/src/Core/Util.h @@ -56,6 +56,8 @@ template class Difference; template class Product; template class ScalarMultiple; template class Random; +template class Zero; +template class Identity; template class Eval; template struct ForwardDecl diff --git a/src/Core/Zero.h b/src/Core/Zero.h new file mode 100644 index 000000000..16a5747e2 --- /dev/null +++ b/src/Core/Zero.h @@ -0,0 +1,67 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. Eigen itself is part of the KDE project. +// +// Copyright (C) 2006-2007 Benoit Jacob +// +// Eigen is free software; 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 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 General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along +// with Eigen; if not, write to the Free Software Foundation, Inc., 51 +// Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. This exception does not invalidate any other reasons why a work +// based on this file might be covered by the GNU General Public License. + +#ifndef EI_ZERO_H +#define EI_ZERO_H + +template class Zero + : public Object > +{ + public: + typedef typename MatrixType::Scalar Scalar; + friend class Object >; + + static const int RowsAtCompileTime = MatrixType::RowsAtCompileTime, + ColsAtCompileTime = MatrixType::ColsAtCompileTime; + + Zero(int rows, int cols) : m_rows(rows), m_cols(cols) + { + assert(rows > 0 && cols > 0); + } + + private: + Zero& _ref() { return *this; } + const Zero& _constRef() const { return *this; } + int _rows() const { return m_rows; } + int _cols() const { return m_cols; } + + Scalar _read(int row, int col) const + { + EI_UNUSED(row); + EI_UNUSED(col); + return static_cast(0); + } + + protected: + int m_rows, m_cols; +}; + +template +Zero Object::zero(int rows, int cols) +{ + return Zero(rows, cols); +} + +#endif // EI_ZERO_H diff --git a/test/basicstuff.cpp b/test/basicstuff.cpp index 1d61b3aaa..c21a58979 100644 --- a/test/basicstuff.cpp +++ b/test/basicstuff.cpp @@ -34,26 +34,38 @@ template void basicStuff(const MatrixType& m) MatrixType m1 = MatrixType::random(rows, cols), m2 = MatrixType::random(rows, cols), - m3; - VectorType v1 = VectorType::random(rows, 1), - v2 = VectorType::random(rows, 1); + m3, + mzero = MatrixType::zero(rows, cols), + identity = Matrix + ::identity(rows, rows), + square = Matrix + ::random(rows, rows); + VectorType v1 = VectorType::random(rows), + v2 = VectorType::random(rows), + vzero = VectorType::zero(rows); Scalar s1 = NumTraits::random(), s2 = NumTraits::random(); QVERIFY(v1.isApprox(v1)); - QVERIFY((v1-v1).isMuchSmallerThan(v1)); - QVERIFY((v1-v1).isMuchSmallerThan(v1.norm())); + QVERIFY(!v1.isApprox(2*v1)); + + QVERIFY(vzero.isMuchSmallerThan(v1)); + QVERIFY(vzero.isMuchSmallerThan(v1.norm())); + QVERIFY(!v1.isMuchSmallerThan(v1)); QVERIFY(m1.isApprox(m1)); - QVERIFY((m1-m1).isMuchSmallerThan(m1)); + QVERIFY(!m1.isApprox(2*m1)); + QVERIFY(mzero.isMuchSmallerThan(m1)); + QVERIFY(!m1.isMuchSmallerThan(m1)); + + QVERIFY(vzero.isApprox(v1-v1)); + QVERIFY(mzero.isApprox(m1-m1)); QVERIFY((m1+m1).isApprox(2 * m1)); QVERIFY((m1 * s1).isApprox(s1 * m1)); QVERIFY(((m1 + m2) * s1).isApprox(s1 * m1 + s1 * m2)); QVERIFY(((s1 + s2) * m1).isApprox(m1 * s1 + m1 * s2)); - - m3 = m2; QVERIFY((m3 += m1).isApprox(m1 + m2)); m3 = m2; @@ -70,6 +82,11 @@ template void basicStuff(const MatrixType& m) m3 *= (m1.transpose() * m2); QVERIFY(m3.isApprox(m1 * (m1.transpose() * m2))); QVERIFY(m3.isApprox(m1.lazyProduct(m1.transpose() * m2))); + + QVERIFY(m1.isApprox(identity * m1)); + QVERIFY(v1.isApprox(identity * v1)); + + QVERIFY((square * (m1 + m2)).isApprox(square * m1 + square * m2)); } void EigenTest::testBasicStuff()