From 18fbe7e7d4cdb737ef5775bbb32fe62b6f8ef70e Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Tue, 2 Sep 2014 14:49:23 +0200 Subject: Fix stableNorm() with respect to NaN and inf, and add respective unit tests. blueNorm() and hypotNorm() are broken wrt to NaN/inf --- test/stable_norm.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) (limited to 'test/stable_norm.cpp') diff --git a/test/stable_norm.cpp b/test/stable_norm.cpp index 549f91fbf..88cab7aa3 100644 --- a/test/stable_norm.cpp +++ b/test/stable_norm.cpp @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2009 Gael Guennebaud +// Copyright (C) 2009-2014 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 @@ -14,6 +14,21 @@ template bool isNotNaN(const T& x) return x==x; } +template bool isNaN(const T& x) +{ + return x!=x; +} + +template bool isInf(const T& x) +{ + return x > NumTraits::highest(); +} + +template bool isMinusInf(const T& x) +{ + return x < NumTraits::lowest(); +} + // workaround aggressive optimization in ICC template EIGEN_DONT_INLINE T sub(T a, T b) { return a - b; } @@ -106,6 +121,58 @@ template void stable_norm(const MatrixType& m) VERIFY_IS_APPROX(vrand.rowwise().stableNorm(), vrand.rowwise().norm()); VERIFY_IS_APPROX(vrand.rowwise().blueNorm(), vrand.rowwise().norm()); VERIFY_IS_APPROX(vrand.rowwise().hypotNorm(), vrand.rowwise().norm()); + + // test NaN, +inf, -inf + MatrixType v; + Index i = internal::random(0,rows-1); + Index j = internal::random(0,cols-1); + + // NaN + { + v = vrand; + v(i,j) = RealScalar(0)/RealScalar(0); + VERIFY(!isFinite(v.squaredNorm())); VERIFY(isNaN(v.squaredNorm())); + VERIFY(!isFinite(v.norm())); VERIFY(isNaN(v.norm())); + VERIFY(!isFinite(v.stableNorm())); VERIFY(isNaN(v.stableNorm())); + VERIFY(!isFinite(v.blueNorm())); VERIFY(isNaN(v.blueNorm())); +// VERIFY(!isFinite(v.hypotNorm())); //VERIFY(isNaN(v.hypotNorm())); + } + + // +inf + { + v = vrand; + v(i,j) = RealScalar(1)/RealScalar(0); + VERIFY(!isFinite(v.squaredNorm())); VERIFY(isInf(v.squaredNorm())); + VERIFY(!isFinite(v.norm())); VERIFY(isInf(v.norm())); + VERIFY(!isFinite(v.stableNorm())); VERIFY(isInf(v.stableNorm())); +// VERIFY(!isFinite(v.blueNorm())); //VERIFY(isInf(v.blueNorm())); +// VERIFY(!isFinite(v.hypotNorm())); //VERIFY(isInf(v.hypotNorm())); + } + + // -inf + { + v = vrand; + v(i,j) = RealScalar(-1)/RealScalar(0); + VERIFY(!isFinite(v.squaredNorm())); VERIFY(isInf(v.squaredNorm())); + VERIFY(!isFinite(v.norm())); VERIFY(isInf(v.norm())); + VERIFY(!isFinite(v.stableNorm())); VERIFY(isInf(v.stableNorm())); +// VERIFY(!isFinite(v.blueNorm())); VERIFY(isInf(v.blueNorm())); +// VERIFY(!isFinite(v.hypotNorm())); VERIFY(isInf(v.hypotNorm())); + } + + // mix + { + Index i2 = internal::random(0,rows-1); + Index j2 = internal::random(0,cols-1); + v = vrand; + v(i,j) = RealScalar(-1)/RealScalar(0); + v(i2,j2) = RealScalar(0)/RealScalar(0); + VERIFY(!isFinite(v.squaredNorm())); VERIFY(isNaN(v.squaredNorm())); + VERIFY(!isFinite(v.norm())); VERIFY(isNaN(v.norm())); + VERIFY(!isFinite(v.stableNorm())); VERIFY(isNaN(v.stableNorm())); +// VERIFY(!isFinite(v.blueNorm())); //VERIFY(isNaN(v.blueNorm())); +// VERIFY(!isFinite(v.hypotNorm())); VERIFY(isNaN(v.hypotNorm())); + } } void test_stable_norm() -- cgit v1.2.3