Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "main.h"
00026
00027 template<typename T> bool isNotNaN(const T& x)
00028 {
00029 return x==x;
00030 }
00031
00032
00033 template<typename T> EIGEN_DONT_INLINE T sub(T a, T b) { return a - b; }
00034
00035 template<typename T> bool isFinite(const T& x)
00036 {
00037 return isNotNaN(sub(x,x));
00038 }
00039
00040 template<typename T> EIGEN_DONT_INLINE T copy(const T& x)
00041 {
00042 return x;
00043 }
00044
00045 template<typename MatrixType> void stable_norm(const MatrixType& m)
00046 {
00047
00048
00049
00050 typedef typename MatrixType::Index Index;
00051 typedef typename MatrixType::Scalar Scalar;
00052 typedef typename NumTraits<Scalar>::Real RealScalar;
00053
00054
00055 {
00056 int ibeta, it, iemin, iemax;
00057
00058 ibeta = std::numeric_limits<RealScalar>::radix;
00059 it = std::numeric_limits<RealScalar>::digits;
00060 iemin = std::numeric_limits<RealScalar>::min_exponent;
00061 iemax = std::numeric_limits<RealScalar>::max_exponent;
00062
00063 VERIFY( (!(iemin > 1 - 2*it || 1+it>iemax || (it==2 && ibeta<5) || (it<=4 && ibeta <= 3 ) || it<2))
00064 && "the stable norm algorithm cannot be guaranteed on this computer");
00065 }
00066
00067
00068 Index rows = m.rows();
00069 Index cols = m.cols();
00070
00071 Scalar big = internal::random<Scalar>() * (std::numeric_limits<RealScalar>::max() * RealScalar(1e-4));
00072 Scalar small = internal::random<Scalar>() * (std::numeric_limits<RealScalar>::min() * RealScalar(1e4));
00073
00074 MatrixType vzero = MatrixType::Zero(rows, cols),
00075 vrand = MatrixType::Random(rows, cols),
00076 vbig(rows, cols),
00077 vsmall(rows,cols);
00078
00079 vbig.fill(big);
00080 vsmall.fill(small);
00081
00082 VERIFY_IS_MUCH_SMALLER_THAN(vzero.norm(), static_cast<RealScalar>(1));
00083 VERIFY_IS_APPROX(vrand.stableNorm(), vrand.norm());
00084 VERIFY_IS_APPROX(vrand.blueNorm(), vrand.norm());
00085 VERIFY_IS_APPROX(vrand.hypotNorm(), vrand.norm());
00086
00087 RealScalar size = static_cast<RealScalar>(m.size());
00088
00089
00090 VERIFY(!isFinite( std::numeric_limits<RealScalar>::infinity()));
00091 VERIFY(!isFinite(internal::sqrt(-internal::abs(big))));
00092
00093
00094 VERIFY(isFinite(internal::sqrt(size)*internal::abs(big)));
00095 VERIFY_IS_NOT_APPROX(internal::sqrt(copy(vbig.squaredNorm())), internal::abs(internal::sqrt(size)*big));
00096 VERIFY_IS_APPROX(vbig.stableNorm(), internal::sqrt(size)*internal::abs(big));
00097 VERIFY_IS_APPROX(vbig.blueNorm(), internal::sqrt(size)*internal::abs(big));
00098 VERIFY_IS_APPROX(vbig.hypotNorm(), internal::sqrt(size)*internal::abs(big));
00099
00100
00101 VERIFY(isFinite(internal::sqrt(size)*internal::abs(small)));
00102 VERIFY_IS_NOT_APPROX(internal::sqrt(copy(vsmall.squaredNorm())), internal::abs(internal::sqrt(size)*small));
00103 VERIFY_IS_APPROX(vsmall.stableNorm(), internal::sqrt(size)*internal::abs(small));
00104 VERIFY_IS_APPROX(vsmall.blueNorm(), internal::sqrt(size)*internal::abs(small));
00105 VERIFY_IS_APPROX(vsmall.hypotNorm(), internal::sqrt(size)*internal::abs(small));
00106
00107
00108 VERIFY_IS_APPROX(vrand.colwise().stableNorm(), vrand.colwise().norm());
00109 VERIFY_IS_APPROX(vrand.colwise().blueNorm(), vrand.colwise().norm());
00110 VERIFY_IS_APPROX(vrand.colwise().hypotNorm(), vrand.colwise().norm());
00111 VERIFY_IS_APPROX(vrand.rowwise().stableNorm(), vrand.rowwise().norm());
00112 VERIFY_IS_APPROX(vrand.rowwise().blueNorm(), vrand.rowwise().norm());
00113 VERIFY_IS_APPROX(vrand.rowwise().hypotNorm(), vrand.rowwise().norm());
00114 }
00115
00116 void test_stable_norm()
00117 {
00118 for(int i = 0; i < g_repeat; i++) {
00119 CALL_SUBTEST_1( stable_norm(Matrix<float, 1, 1>()) );
00120 CALL_SUBTEST_2( stable_norm(Vector4d()) );
00121 CALL_SUBTEST_3( stable_norm(VectorXd(internal::random<int>(10,2000))) );
00122 CALL_SUBTEST_4( stable_norm(VectorXf(internal::random<int>(10,2000))) );
00123 CALL_SUBTEST_5( stable_norm(VectorXcd(internal::random<int>(10,2000))) );
00124 }
00125 }