eigen/test/stable_norm.cpp

113 lines
4.1 KiB
C++
Raw Normal View History

2009-09-07 18:46:16 +08:00
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
2010-06-25 05:21:58 +08:00
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
2009-09-07 18:46:16 +08:00
//
// 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/.
2009-09-07 18:46:16 +08:00
#include "main.h"
template<typename T> bool isNotNaN(const T& x)
{
return x==x;
}
2011-02-21 23:17:58 +08:00
// workaround aggressive optimization in ICC
template<typename T> EIGEN_DONT_INLINE T sub(T a, T b) { return a - b; }
2010-06-08 19:29:27 +08:00
template<typename T> bool isFinite(const T& x)
{
2011-02-21 23:17:58 +08:00
return isNotNaN(sub(x,x));
}
template<typename T> EIGEN_DONT_INLINE T copy(const T& x)
{
return x;
2010-06-08 19:29:27 +08:00
}
2009-09-07 18:46:16 +08:00
template<typename MatrixType> void stable_norm(const MatrixType& m)
{
/* this test covers the following files:
StableNorm.h
*/
using std::sqrt;
using std::abs;
2010-06-20 23:37:56 +08:00
typedef typename MatrixType::Index Index;
2009-09-07 18:46:16 +08:00
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
// Check the basic machine-dependent constants.
{
int ibeta, it, iemin, iemax;
ibeta = std::numeric_limits<RealScalar>::radix; // base for floating-point numbers
it = std::numeric_limits<RealScalar>::digits; // number of base-beta digits in mantissa
iemin = std::numeric_limits<RealScalar>::min_exponent; // minimum exponent
iemax = std::numeric_limits<RealScalar>::max_exponent; // maximum exponent
VERIFY( (!(iemin > 1 - 2*it || 1+it>iemax || (it==2 && ibeta<5) || (it<=4 && ibeta <= 3 ) || it<2))
&& "the stable norm algorithm cannot be guaranteed on this computer");
}
2010-06-20 23:37:56 +08:00
Index rows = m.rows();
Index cols = m.cols();
2009-09-07 18:46:16 +08:00
Scalar big = internal::random<Scalar>() * ((std::numeric_limits<RealScalar>::max)() * RealScalar(1e-4));
Scalar small = internal::random<Scalar>() * ((std::numeric_limits<RealScalar>::min)() * RealScalar(1e4));
2009-09-07 18:46:16 +08:00
MatrixType vzero = MatrixType::Zero(rows, cols),
vrand = MatrixType::Random(rows, cols),
vbig(rows, cols),
vsmall(rows,cols);
vbig.fill(big);
vsmall.fill(small);
VERIFY_IS_MUCH_SMALLER_THAN(vzero.norm(), static_cast<RealScalar>(1));
VERIFY_IS_APPROX(vrand.stableNorm(), vrand.norm());
VERIFY_IS_APPROX(vrand.blueNorm(), vrand.norm());
VERIFY_IS_APPROX(vrand.hypotNorm(), vrand.norm());
2009-09-08 14:27:18 +08:00
RealScalar size = static_cast<RealScalar>(m.size());
2009-09-07 18:46:16 +08:00
2010-06-08 19:29:27 +08:00
// test isFinite
2010-06-09 15:48:06 +08:00
VERIFY(!isFinite( std::numeric_limits<RealScalar>::infinity()));
VERIFY(!isFinite(sqrt(-abs(big))));
2010-06-08 19:29:27 +08:00
// test overflow
VERIFY(isFinite(sqrt(size)*abs(big)));
VERIFY_IS_NOT_APPROX(sqrt(copy(vbig.squaredNorm())), abs(sqrt(size)*big)); // here the default norm must fail
VERIFY_IS_APPROX(vbig.stableNorm(), sqrt(size)*abs(big));
VERIFY_IS_APPROX(vbig.blueNorm(), sqrt(size)*abs(big));
VERIFY_IS_APPROX(vbig.hypotNorm(), sqrt(size)*abs(big));
2009-09-07 18:46:16 +08:00
// test underflow
VERIFY(isFinite(sqrt(size)*abs(small)));
VERIFY_IS_NOT_APPROX(sqrt(copy(vsmall.squaredNorm())), abs(sqrt(size)*small)); // here the default norm must fail
VERIFY_IS_APPROX(vsmall.stableNorm(), sqrt(size)*abs(small));
VERIFY_IS_APPROX(vsmall.blueNorm(), sqrt(size)*abs(small));
VERIFY_IS_APPROX(vsmall.hypotNorm(), sqrt(size)*abs(small));
// Test compilation of cwise() version
VERIFY_IS_APPROX(vrand.colwise().stableNorm(), vrand.colwise().norm());
VERIFY_IS_APPROX(vrand.colwise().blueNorm(), vrand.colwise().norm());
VERIFY_IS_APPROX(vrand.colwise().hypotNorm(), vrand.colwise().norm());
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());
2009-09-07 18:46:16 +08:00
}
void test_stable_norm()
{
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( stable_norm(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( stable_norm(Vector4d()) );
CALL_SUBTEST_3( stable_norm(VectorXd(internal::random<int>(10,2000))) );
CALL_SUBTEST_4( stable_norm(VectorXf(internal::random<int>(10,2000))) );
CALL_SUBTEST_5( stable_norm(VectorXcd(internal::random<int>(10,2000))) );
2009-09-07 18:46:16 +08:00
}
}