# HG changeset patch # Parent cd15b09304ff115a71df02672f13ea1c0110ee4d Big 564: add hasNaN and isFinite members diff --git a/Eigen/src/Core/BooleanRedux.h b/Eigen/src/Core/BooleanRedux.h --- a/Eigen/src/Core/BooleanRedux.h +++ b/Eigen/src/Core/BooleanRedux.h @@ -124,11 +124,31 @@ inline bool DenseBase::any() co * \sa all(), any() */ template inline typename DenseBase::Index DenseBase::count() const { return derived().template cast().template cast().sum(); } +/** \returns true is \c *this contains at least one Not A Number (NaN). + * + * \sa isFinite() + */ +template +inline bool DenseBase::hasNaN() const +{ + return !((derived().array()==derived().array()).all()); +} + +/** \returns true if \c *this contains only finite numbers, i.e., no NaN and no +/-INF values. + * + * \sa hasNaN() + */ +template +inline bool DenseBase::isFinite() const +{ + return !((derived()-derived()).hasNaN()); +} + } // end namespace Eigen #endif // EIGEN_ALLANDANY_H diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -331,16 +331,19 @@ template class DenseBa template bool isMuchSmallerThan(const DenseBase& other, const RealScalar& prec = NumTraits::dummy_precision()) const; bool isApproxToConstant(const Scalar& value, const RealScalar& prec = NumTraits::dummy_precision()) const; bool isConstant(const Scalar& value, const RealScalar& prec = NumTraits::dummy_precision()) const; bool isZero(const RealScalar& prec = NumTraits::dummy_precision()) const; bool isOnes(const RealScalar& prec = NumTraits::dummy_precision()) const; + + inline bool hasNaN() const; + inline bool isFinite() const; inline Derived& operator*=(const Scalar& other); inline Derived& operator/=(const Scalar& other); typedef typename internal::add_const_on_value_type::type>::type EvalReturnType; /** \returns the matrix or vector obtained by evaluating this expression. * * Notice that in the case of a plain matrix or vector (not an expression) this function just returns @@ -410,18 +413,16 @@ template class DenseBa /** \returns the unique coefficient of a 1x1 expression */ CoeffReturnType value() const { EIGEN_STATIC_ASSERT_SIZE_1x1(Derived) eigen_assert(this->rows() == 1 && this->cols() == 1); return derived().coeff(0,0); } -/////////// Array module /////////// - bool all(void) const; bool any(void) const; Index count() const; typedef VectorwiseOp RowwiseReturnType; typedef const VectorwiseOp ConstRowwiseReturnType; typedef VectorwiseOp ColwiseReturnType; typedef const VectorwiseOp ConstColwiseReturnType; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -217,16 +217,17 @@ ei_add_test(sparse_permutations) ei_add_test(nullary) ei_add_test(nesting_ops "${CMAKE_CXX_FLAGS_DEBUG}") ei_add_test(zerosized) ei_add_test(dontalign) ei_add_test(evaluators) ei_add_test(sizeoverflow) ei_add_test(prec_inverse_4x4) ei_add_test(vectorwiseop) +ei_add_test(special_numbers) ei_add_test(simplicial_cholesky) ei_add_test(conjugate_gradient) ei_add_test(bicgstab) ei_add_test(sparselu) ei_add_test(sparseqr) # ei_add_test(denseLM) diff --git a/test/special_numbers.cpp b/test/special_numbers.cpp new file mode 100644 --- /dev/null +++ b/test/special_numbers.cpp @@ -0,0 +1,59 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2013 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "main.h" + +template void special_numbers() +{ + typedef typename NumTraits::Real RealScalar; + typedef Matrix MatType; + int rows = internal::random(1,300); + int cols = internal::random(1,300); + + Scalar nan = Scalar(0)/Scalar(0); + Scalar inf = Scalar(1)/Scalar(0); + Scalar s1 = internal::random(); + + MatType m1 = MatType::Random(rows,cols), + mnan = MatType::Random(rows,cols), + minf = MatType::Random(rows,cols), + mboth = MatType::Random(rows,cols); + + int n = internal::random(1,10); + for(int k=0; k(0,rows-1), internal::random(0,cols-1)) = nan; + minf(internal::random(0,rows-1), internal::random(0,cols-1)) = inf; + } + mboth = mnan + minf; + + VERIFY(!m1.hasNaN()); + VERIFY(m1.isFinite()); + + VERIFY(mnan.hasNaN()); + VERIFY((s1*mnan).hasNaN()); + VERIFY(!minf.hasNaN()); + VERIFY(!(2*minf).hasNaN()); + VERIFY(mboth.hasNaN()); + VERIFY(mboth.array().hasNaN()); + + VERIFY(!mnan.isFinite()); + VERIFY(!minf.isFinite()); + VERIFY(!(minf-mboth).isFinite()); + VERIFY(!mboth.isFinite()); + VERIFY(!mboth.array().isFinite()); +} + +void test_special_numbers() +{ + for(int i = 0; i < 10*g_repeat; i++) { + CALL_SUBTEST_1( special_numbers() ); + CALL_SUBTEST_1( special_numbers() ); + } +}