diff --git a/doc/example.cpp b/doc/example.cpp index ca10d077a..b5582f006 100644 --- a/doc/example.cpp +++ b/doc/example.cpp @@ -11,7 +11,7 @@ void foo(const Eigen::Object& m) } template -Eigen::ScalarProduct +Eigen::ScalarMultiple twice(const Eigen::Object& m) { return 2 * m; diff --git a/src/Core/Dot.h b/src/Core/Dot.h index 158b852eb..3bf8514ba 100644 --- a/src/Core/Dot.h +++ b/src/Core/Dot.h @@ -88,7 +88,7 @@ typename NumTraits::Real Object::norm() const } template -ScalarProduct Object::normalized() const +ScalarMultiple Object::normalized() const { return (*this) / norm(); } diff --git a/src/Core/Fuzzy.h b/src/Core/Fuzzy.h index 0334e6d96..4980de8d1 100644 --- a/src/Core/Fuzzy.h +++ b/src/Core/Fuzzy.h @@ -28,34 +28,38 @@ template template -bool Object::isApprox(const OtherDerived& other) const +bool Object::isApprox( + const OtherDerived& other, + const typename NumTraits::Real& prec +) const { if(IsVector) { - return((*this - other).norm2() - <= std::min(norm2(), other.norm2()) - * NumTraits::epsilon2()); + return((*this - other).norm2() <= std::min(norm2(), other.norm2()) * prec * prec); } else { for(int i = 0; i < cols(); i++) - if(!col(i).isApprox(other.col(i))) + if(!col(i).isApprox(other.col(i), prec)) return false; return true; } } template -bool Object::isNegligble(const Scalar& other) const +bool Object::isMuchSmallerThan( + const Scalar& other, + const typename NumTraits::Real& prec +) const { if(IsVector) { - return(norm2() <= NumTraits::abs2(other) * NumTraits::epsilon2()); + return(norm2() <= NumTraits::abs2(other) * prec * prec); } else { for(int i = 0; i < cols(); i++) - if(!col(i).isNegligible(other)) + if(!col(i).isMuchSmallerThan(other, prec)) return false; return true; } @@ -63,16 +67,19 @@ bool Object::isNegligble(const Scalar& other) const template template -bool Object::isNegligble(const Object& other) const +bool Object::isMuchSmallerThan( + const Object& other, + const typename NumTraits::Real& prec +) const { if(IsVector) { - return(norm2() <= other.norm2() * NumTraits::epsilon2()); + return(norm2() <= other.norm2() * prec * prec); } else { for(int i = 0; i < cols(); i++) - if(!col(i).isNegligible(other.col(i))) + if(!col(i).isMuchSmallerThan(other.col(i), prec)) return false; return true; } diff --git a/src/Core/MatrixOps.h b/src/Core/MatrixOps.h index a1a1f47a0..7cec76407 100644 --- a/src/Core/MatrixOps.h +++ b/src/Core/MatrixOps.h @@ -206,7 +206,7 @@ operator-(const Object &mat1, const Object & template template MatrixProduct -Object::lazyMul(const Object &other) const +Object::lazyProduct(const Object &other) const { return MatrixProduct(constRef(), other.constRef()); } @@ -215,7 +215,7 @@ template Eval > operator*(const Object &mat1, const Object &mat2) { - return mat1.lazyMul(mat2).eval(); + return mat1.lazyProduct(mat2).eval(); } template diff --git a/src/Core/Numeric.h b/src/Core/Numeric.h index 8437dfb2e..04721e019 100644 --- a/src/Core/Numeric.h +++ b/src/Core/Numeric.h @@ -38,8 +38,7 @@ template<> struct NumTraits static const bool IsComplex = false; static const bool HasFloatingPoint = false; - static int epsilon() { return 0; } - static int epsilon2() { return 0; } + static int precision() { return 0; } static int real(const int& x) { return x; } static int imag(const int& x) { EI_UNUSED(x); return 0; } static int conj(const int& x) { return x; } @@ -53,18 +52,21 @@ template<> struct NumTraits // as well, so there's no problem. return (std::rand() % 21) - 10; } - static bool negligible(const int& a, const int& b) + static bool isMuchSmallerThan(const int& a, const int& b, const int& prec = precision()) { EI_UNUSED(b); - return(a == 0); + EI_UNUSED(prec); + return a == 0; } - static bool approx(const int& a, const int& b) + static bool isApprox(const int& a, const int& b, const int& prec = precision()) { - return(a == b); + EI_UNUSED(prec); + return a == b; } - static bool lessThanOrApprox(const int& a, const int& b) + static bool isApproxOrLessThan(const int& a, const int& b, const int& prec = precision()) { - return(a <= b); + EI_UNUSED(prec); + return a <= b; } }; @@ -77,8 +79,7 @@ template<> struct NumTraits static const bool IsComplex = false; static const bool HasFloatingPoint = true; - static float epsilon() { return 1e-5f; } - static float epsilon2() { return epsilon() * epsilon(); } + static float precision() { return 1e-5f; } static float real(const float& x) { return x; } static float imag(const float& x) { EI_UNUSED(x); return 0; } static float conj(const float& x) { return x; } @@ -89,17 +90,17 @@ template<> struct NumTraits { return std::rand() / (RAND_MAX/20.0f) - 10.0f; } - static bool negligible(const float& a, const float& b) + static bool isMuchSmallerThan(const float& a, const float& b, const float& prec = precision()) { - return(abs(a) <= abs(b) * epsilon()); + return abs(a) <= abs(b) * prec; } - static bool approx(const float& a, const float& b) + static bool isApprox(const float& a, const float& b, const float& prec = precision()) { - return(abs(a - b) <= std::min(abs(a), abs(b)) * epsilon()); + return abs(a - b) <= std::min(abs(a), abs(b)) * prec; } - static bool lessThanOrApprox(const float& a, const float& b) + static bool isApproxOrLessThan(const float& a, const float& b, const float& prec = precision()) { - return(a <= b || approx(a, b)); + return a <= b || isApprox(a, b, prec); } }; @@ -112,8 +113,7 @@ template<> struct NumTraits static const bool IsComplex = false; static const bool HasFloatingPoint = true; - static double epsilon() { return 1e-11; } - static double epsilon2() { return epsilon() * epsilon(); } + static double precision() { return 1e-11; } static double real(const double& x) { return x; } static double imag(const double& x) { EI_UNUSED(x); return 0; } static double conj(const double& x) { return x; } @@ -124,17 +124,17 @@ template<> struct NumTraits { return std::rand() / (RAND_MAX/20.0) - 10.0; } - static bool negligible(const double& a, const double& b) + static bool isMuchSmallerThan(const double& a, const double& b, const double& prec = precision()) { - return(abs(a) <= abs(b) * epsilon()); + return abs(a) <= abs(b) * prec; } - static bool approx(const double& a, const double& b) + static bool isApprox(const double& a, const double& b, const double& prec = precision()) { - return(abs(a - b) <= std::min(abs(a), abs(b)) * epsilon()); + return abs(a - b) <= std::min(abs(a), abs(b)) * prec; } - static bool lessThanOrApprox(const double& a, const double& b) + static bool isApproxOrLessThan(const double& a, const double& b, const double& prec = precision()) { - return(a <= b || approx(a, b)); + return a <= b || isApprox(a, b, prec); } }; @@ -148,8 +148,7 @@ template struct NumTraits > static const bool IsComplex = true; static const bool HasFloatingPoint = NumTraits::HasFloatingPoint; - static Real epsilon() { return NumTraits::epsilon(); } - static Real epsilon2() { return epsilon() * epsilon(); } + static Real precision() { return NumTraits::precision(); } static Real real(const Complex& x) { return std::real(x); } static Real imag(const Complex& x) { return std::imag(x); } static Complex conj(const Complex& x) { return std::conj(x); } @@ -163,16 +162,16 @@ template struct NumTraits > { return Complex(NumTraits::rand(), NumTraits::rand()); } - static bool negligible(const Complex& a, const Complex& b) + static bool isMuchSmallerThan(const Complex& a, const Complex& b, const Real& prec = precision()) { - return(abs2(a) <= abs2(b) * epsilon2()); + return abs2(a) <= abs2(b) * prec * prec; } - static bool approx(const Complex& a, const Complex& b) + static bool isApprox(const Complex& a, const Complex& b, const Real& prec = precision()) { - return(NumTraits::approx(std::real(a), std::real(b)) - && NumTraits::approx(std::imag(a), std::imag(b))); + return NumTraits::isApprox(std::real(a), std::real(b), prec) + && NumTraits::isApprox(std::imag(a), std::imag(b), prec); } - // lessThanOrApprox wouldn't make sense for complex numbers + // isApproxOrLessThan wouldn't make sense for complex numbers }; #endif // EI_NUMERIC_H diff --git a/src/Core/Object.h b/src/Core/Object.h index 27e5e456a..90962c46c 100644 --- a/src/Core/Object.h +++ b/src/Core/Object.h @@ -95,19 +95,29 @@ template class Object RealScalar norm2() const; RealScalar norm() const; - ScalarProduct normalized() const; + ScalarMultiple normalized() const; static Eval > random(int rows = RowsAtCompileTime, int cols = ColsAtCompileTime); template - bool isApprox(const OtherDerived& other) const; + bool isApprox( + const OtherDerived& other, + const typename NumTraits::Real& prec = NumTraits::precision() + ) const; + bool isMuchSmallerThan( + const Scalar& other, + const typename NumTraits::Real& prec = NumTraits::precision() + ) const; template - bool isNegligible(const OtherDerived& other) const; + bool isMuchSmallerThan( + const OtherDerived& other, + const typename NumTraits::Real& prec = NumTraits::precision() + ) const; template MatrixProduct - lazyMul(const Object& other) const EI_ALWAYS_INLINE; + lazyProduct(const Object& other) const EI_ALWAYS_INLINE; template Derived& operator+=(const Object& other); diff --git a/src/Core/ScalarOps.h b/src/Core/ScalarOps.h index 4a71b403e..77c9b9342 100644 --- a/src/Core/ScalarOps.h +++ b/src/Core/ScalarOps.h @@ -26,28 +26,28 @@ #ifndef EI_SCALAROPS_H #define EI_SCALAROPS_H -template class ScalarProduct - : public Object > +template class ScalarMultiple + : public Object > { public: typedef typename MatrixType::Scalar Scalar; typedef typename MatrixType::ConstRef MatRef; - friend class Object >; + friend class Object >; static const int RowsAtCompileTime = MatrixType::RowsAtCompileTime, ColsAtCompileTime = MatrixType::ColsAtCompileTime; - ScalarProduct(const MatRef& matrix, Scalar scalar) + ScalarMultiple(const MatRef& matrix, Scalar scalar) : m_matrix(matrix), m_scalar(scalar) {} - ScalarProduct(const ScalarProduct& other) + ScalarMultiple(const ScalarMultiple& other) : m_matrix(other.m_matrix), m_scalar(other.m_scalar) {} - EI_INHERIT_ASSIGNMENT_OPERATORS(ScalarProduct) + EI_INHERIT_ASSIGNMENT_OPERATORS(ScalarMultiple) private: - const ScalarProduct& _ref() const { return *this; } - const ScalarProduct& _constRef() const { return *this; } + const ScalarMultiple& _ref() const { return *this; } + const ScalarMultiple& _constRef() const { return *this; } int _rows() const { return m_matrix.rows(); } int _cols() const { return m_matrix.cols(); } @@ -63,23 +63,23 @@ template class ScalarProduct #define EI_MAKE_SCALAR_OPS(OtherScalar) \ template \ -ScalarProduct \ +ScalarMultiple \ operator*(const Object& matrix, \ OtherScalar scalar) \ { \ - return ScalarProduct(matrix.constRef(), scalar); \ + return ScalarMultiple(matrix.constRef(), scalar); \ } \ \ template \ -ScalarProduct \ +ScalarMultiple \ operator*(OtherScalar scalar, \ const Object& matrix) \ { \ - return ScalarProduct(matrix.constRef(), scalar); \ + return ScalarMultiple(matrix.constRef(), scalar); \ } \ \ template \ -ScalarProduct \ +ScalarMultiple \ operator/(const Object& matrix, \ OtherScalar scalar) \ { \ diff --git a/src/Core/Util.h b/src/Core/Util.h index 54edeed50..431c008ed 100644 --- a/src/Core/Util.h +++ b/src/Core/Util.h @@ -53,7 +53,7 @@ template class Conjugate; template class Sum; template class Difference; template class MatrixProduct; -template class ScalarProduct; +template class ScalarMultiple; template class Random; template class Eval; diff --git a/test/main.h b/test/main.h index 85968134c..fcb1b23ab 100644 --- a/test/main.h +++ b/test/main.h @@ -57,32 +57,47 @@ template<> inline int TestEpsilon >() { return TestEpsilon inline float TestEpsilon >() { return TestEpsilon(); } template<> inline double TestEpsilon >() { return TestEpsilon(); } -template bool TestNegligible(const T& a, const T& b) +template bool TestMuchSmallerThan(const T& a, const T& b) { - return(Abs(a) <= Abs(b) * TestEpsilon()); + return NumTraits::isMuchSmallerThan(a, b, TestEpsilon()); } -//template -//bool TestNegligible +template +bool TestMuchSmallerThan( + const Object& a, + const Object& b) +{ + return a.isMuchSmallerThan(b, TestEpsilon()); +} template bool TestApprox(const T& a, const T& b) { - if(Eigen::NumTraits::IsFloat) - return(Abs(a - b) <= std::min(Abs(a), Abs(b)) * TestEpsilon()); - else - return(a == b); + return NumTraits::isApprox(a, b, TestEpsilon()); } -template bool TestLessThanOrApprox(const T& a, const T& b) +template +bool TestApprox( + const Object& a, + const Object& b) { - if(Eigen::NumTraits::IsFloat) - return(a < b || Approx(a, b)); - else - return(a <= b); + return a.isApprox(b, TestEpsilon()); } -#define QVERIFY_NEGLIGIBLE(a, b) QVERIFY(TestNegligible(a, b)) +template bool TestApproxOrLessThan(const T& a, const T& b) +{ + return NumTraits::isApproxOrLessThan(a, b, TestEpsilon()); +} + +template +bool TestApproxOrLessThan( + const Object& a, + const Object& b) +{ + return a.isApproxOrLessThan(b, TestEpsilon()); +} + +#define QVERIFY_MUCH_SMALLER_THAN(a, b) QVERIFY(TestMuchSmallerThan(a, b)) #define QVERIFY_APPROX(a, b) QVERIFY(TestApprox(a, b)) -#define QVERIFY_LESS_THAN_OR_APPROX(a, b) QVERIFY(TestLessThanOrApprox(a, b)) +#define QVERIFY_APPROX_OR_LESS_THAN(a, b) QVERIFY(TestApproxOrLessThan(a, b)) #endif // EI_TEST_MAIN_H diff --git a/test/matrixops.cpp b/test/matrixops.cpp index c763ff687..9c0933d89 100644 --- a/test/matrixops.cpp +++ b/test/matrixops.cpp @@ -51,7 +51,7 @@ template