1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library 2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra. 3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// 4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> 5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com> 6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// 7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla 8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed 9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// discard stack allocation as that too bypasses malloc 12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_STACK_ALLOCATION_LIMIT 0 13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_RUNTIME_NO_MALLOC 14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include "main.h" 15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <Eigen/SVD> 16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType, int QRPreconditioner> 18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid jacobisvd_check_full(const MatrixType& m, const JacobiSVD<MatrixType, QRPreconditioner>& svd) 19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename MatrixType::Index Index; 21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index rows = m.rows(); 22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index cols = m.cols(); 23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath RowsAtCompileTime = MatrixType::RowsAtCompileTime, 26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ColsAtCompileTime = MatrixType::ColsAtCompileTime 27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename MatrixType::Scalar Scalar; 30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename NumTraits<Scalar>::Real RealScalar; 31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime> MatrixUType; 32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime> MatrixVType; 33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef Matrix<Scalar, RowsAtCompileTime, 1> ColVectorType; 34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef Matrix<Scalar, ColsAtCompileTime, 1> InputVectorType; 35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath MatrixType sigma = MatrixType::Zero(rows,cols); 37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath sigma.diagonal() = svd.singularValues().template cast<Scalar>(); 38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath MatrixUType u = svd.matrixU(); 39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath MatrixVType v = svd.matrixV(); 40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(m, u * sigma * v.adjoint()); 42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_UNITARY(u); 43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_UNITARY(v); 44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType, int QRPreconditioner> 47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid jacobisvd_compare_to_full(const MatrixType& m, 48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath unsigned int computationOptions, 49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const JacobiSVD<MatrixType, QRPreconditioner>& referenceSvd) 50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename MatrixType::Index Index; 52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index rows = m.rows(); 53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index cols = m.cols(); 54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index diagSize = (std::min)(rows, cols); 55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath JacobiSVD<MatrixType, QRPreconditioner> svd(m, computationOptions); 57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(svd.singularValues(), referenceSvd.singularValues()); 59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(computationOptions & ComputeFullU) 60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(svd.matrixU(), referenceSvd.matrixU()); 61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(computationOptions & ComputeThinU) 62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(svd.matrixU(), referenceSvd.matrixU().leftCols(diagSize)); 63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(computationOptions & ComputeFullV) 64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(svd.matrixV(), referenceSvd.matrixV()); 65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(computationOptions & ComputeThinV) 66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(svd.matrixV(), referenceSvd.matrixV().leftCols(diagSize)); 67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType, int QRPreconditioner> 70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid jacobisvd_solve(const MatrixType& m, unsigned int computationOptions) 71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename MatrixType::Scalar Scalar; 73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename MatrixType::Index Index; 74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index rows = m.rows(); 75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index cols = m.cols(); 76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath RowsAtCompileTime = MatrixType::RowsAtCompileTime, 79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ColsAtCompileTime = MatrixType::ColsAtCompileTime 80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef Matrix<Scalar, RowsAtCompileTime, Dynamic> RhsType; 83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef Matrix<Scalar, ColsAtCompileTime, Dynamic> SolutionType; 84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath RhsType rhs = RhsType::Random(rows, internal::random<Index>(1, cols)); 86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath JacobiSVD<MatrixType, QRPreconditioner> svd(m, computationOptions); 87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath SolutionType x = svd.solve(rhs); 88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // evaluate normal equation which works also for least-squares solutions 89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(m.adjoint()*m*x,m.adjoint()*rhs); 90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType, int QRPreconditioner> 93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid jacobisvd_test_all_computation_options(const MatrixType& m) 94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if (QRPreconditioner == NoQRPreconditioner && m.rows() != m.cols()) 96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return; 97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath JacobiSVD<MatrixType, QRPreconditioner> fullSvd(m, ComputeFullU|ComputeFullV); 98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_check_full(m, fullSvd); 100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeFullU | ComputeFullV); 101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(QRPreconditioner == FullPivHouseholderQRPreconditioner) 103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return; 104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_compare_to_full(m, ComputeFullU, fullSvd); 106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_compare_to_full(m, ComputeFullV, fullSvd); 107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_compare_to_full(m, 0, fullSvd); 108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if (MatrixType::ColsAtCompileTime == Dynamic) { 110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // thin U/V are only available with dynamic number of columns 111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_compare_to_full(m, ComputeFullU|ComputeThinV, fullSvd); 112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_compare_to_full(m, ComputeThinV, fullSvd); 113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_compare_to_full(m, ComputeThinU|ComputeFullV, fullSvd); 114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_compare_to_full(m, ComputeThinU , fullSvd); 115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_compare_to_full(m, ComputeThinU|ComputeThinV, fullSvd); 116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeFullU | ComputeThinV); 117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeThinU | ComputeFullV); 118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeThinU | ComputeThinV); 119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // test reconstruction 121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename MatrixType::Index Index; 122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index diagSize = (std::min)(m.rows(), m.cols()); 123c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath JacobiSVD<MatrixType, QRPreconditioner> svd(m, ComputeThinU | ComputeThinV); 124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(m, svd.matrixU().leftCols(diagSize) * svd.singularValues().asDiagonal() * svd.matrixV().leftCols(diagSize).adjoint()); 125c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType> 129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid jacobisvd(const MatrixType& a = MatrixType(), bool pickrandom = true) 130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath MatrixType m = pickrandom ? MatrixType::Random(a.rows(), a.cols()) : a; 132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_test_all_computation_options<MatrixType, FullPivHouseholderQRPreconditioner>(m); 134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_test_all_computation_options<MatrixType, ColPivHouseholderQRPreconditioner>(m); 135c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_test_all_computation_options<MatrixType, HouseholderQRPreconditioner>(m); 136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jacobisvd_test_all_computation_options<MatrixType, NoQRPreconditioner>(m); 137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType> void jacobisvd_verify_assert(const MatrixType& m) 140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename MatrixType::Scalar Scalar; 142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename MatrixType::Index Index; 143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index rows = m.rows(); 144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index cols = m.cols(); 145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { 147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath RowsAtCompileTime = MatrixType::RowsAtCompileTime, 148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ColsAtCompileTime = MatrixType::ColsAtCompileTime 149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef Matrix<Scalar, RowsAtCompileTime, 1> RhsType; 152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 153c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath RhsType rhs(rows); 154c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 155c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath JacobiSVD<MatrixType> svd; 156c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.matrixU()) 157c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.singularValues()) 158c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.matrixV()) 159c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.solve(rhs)) 160c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 161c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath MatrixType a = MatrixType::Zero(rows, cols); 162c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath a.setZero(); 163c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd.compute(a, 0); 164c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.matrixU()) 165c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.matrixV()) 166c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd.singularValues(); 167c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.solve(rhs)) 168c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 169c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if (ColsAtCompileTime == Dynamic) 170c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 171c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd.compute(a, ComputeThinU); 172c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd.matrixU(); 173c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.matrixV()) 174c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.solve(rhs)) 175c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 176c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd.compute(a, ComputeThinV); 177c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd.matrixV(); 178c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.matrixU()) 179c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.solve(rhs)) 180c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 181c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner> svd_fullqr; 182c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd_fullqr.compute(a, ComputeFullU|ComputeThinV)) 183c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd_fullqr.compute(a, ComputeThinU|ComputeThinV)) 184c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd_fullqr.compute(a, ComputeThinU|ComputeFullV)) 185c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 186c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 187c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 188c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.compute(a, ComputeThinU)) 189c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd.compute(a, ComputeThinV)) 190c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 191c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 192c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 193c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType> 194c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid jacobisvd_method() 195c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 196c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { Size = MatrixType::RowsAtCompileTime }; 197c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename MatrixType::RealScalar RealScalar; 198c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef Matrix<RealScalar, Size, 1> RealVecType; 199c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath MatrixType m = MatrixType::Identity(); 200c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(m.jacobiSvd().singularValues(), RealVecType::Ones()); 201c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(m.jacobiSvd().matrixU()); 202c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(m.jacobiSvd().matrixV()); 203c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(m.jacobiSvd(ComputeFullU|ComputeFullV).solve(m), m); 204c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 205c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 206c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// work around stupid msvc error when constructing at compile time an expression that involves 207c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// a division by zero, even if the numeric type has floating point 208c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Scalar> 209c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_DONT_INLINE Scalar zero() { return Scalar(0); } 210c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 211c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// workaround aggressive optimization in ICC 212c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename T> EIGEN_DONT_INLINE T sub(T a, T b) { return a - b; } 213c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 214c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType> 215c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid jacobisvd_inf_nan() 216c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 217c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // all this function does is verify we don't iterate infinitely on nan/inf values 218c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 219c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath JacobiSVD<MatrixType> svd; 220c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef typename MatrixType::Scalar Scalar; 221c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Scalar some_inf = Scalar(1) / zero<Scalar>(); 222c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY(sub(some_inf, some_inf) != sub(some_inf, some_inf)); 223c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd.compute(MatrixType::Constant(10,10,some_inf), ComputeFullU | ComputeFullV); 224c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 225c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Scalar some_nan = zero<Scalar>() / zero<Scalar>(); 226c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY(some_nan != some_nan); 227c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd.compute(MatrixType::Constant(10,10,some_nan), ComputeFullU | ComputeFullV); 228c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 229c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath MatrixType m = MatrixType::Zero(10,10); 230c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m(internal::random<int>(0,9), internal::random<int>(0,9)) = some_inf; 231c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd.compute(m, ComputeFullU | ComputeFullV); 232c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 233c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m = MatrixType::Zero(10,10); 234c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m(internal::random<int>(0,9), internal::random<int>(0,9)) = some_nan; 235c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd.compute(m, ComputeFullU | ComputeFullV); 236c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 237c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 238c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Regression test for bug 286: JacobiSVD loops indefinitely with some 239c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// matrices containing denormal numbers. 240c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid jacobisvd_bug286() 241c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 242c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#if defined __INTEL_COMPILER 243c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// shut up warning #239: floating point underflow 244c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#pragma warning push 245c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#pragma warning disable 239 246c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif 247c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Matrix2d M; 248c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath M << -7.90884e-313, -4.94e-324, 249c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 0, 5.60844e-313; 250c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#if defined __INTEL_COMPILER 251c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#pragma warning pop 252c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif 253c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath JacobiSVD<Matrix2d> svd; 254c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd.compute(M); // just check we don't loop indefinitely 255c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 256c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 257c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid jacobisvd_preallocate() 258c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 259c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Vector3f v(3.f, 2.f, 1.f); 260c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath MatrixXf m = v.asDiagonal(); 261c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 262c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath internal::set_is_malloc_allowed(false); 263c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(VectorXf v(10);) 264c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath JacobiSVD<MatrixXf> svd; 265c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath internal::set_is_malloc_allowed(true); 266c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd.compute(m); 267c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(svd.singularValues(), v); 268c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 269c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath JacobiSVD<MatrixXf> svd2(3,3); 270c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath internal::set_is_malloc_allowed(false); 271c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd2.compute(m); 272c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath internal::set_is_malloc_allowed(true); 273c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(svd2.singularValues(), v); 274c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd2.matrixU()); 275c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_RAISES_ASSERT(svd2.matrixV()); 276c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd2.compute(m, ComputeFullU | ComputeFullV); 277c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(svd2.matrixU(), Matrix3f::Identity()); 278c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(svd2.matrixV(), Matrix3f::Identity()); 279c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath internal::set_is_malloc_allowed(false); 280c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd2.compute(m); 281c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath internal::set_is_malloc_allowed(true); 282c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 283c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath JacobiSVD<MatrixXf> svd3(3,3,ComputeFullU|ComputeFullV); 284c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath internal::set_is_malloc_allowed(false); 285c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd2.compute(m); 286c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath internal::set_is_malloc_allowed(true); 287c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(svd2.singularValues(), v); 288c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(svd2.matrixU(), Matrix3f::Identity()); 289c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath VERIFY_IS_APPROX(svd2.matrixV(), Matrix3f::Identity()); 290c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath internal::set_is_malloc_allowed(false); 291c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath svd2.compute(m, ComputeFullU|ComputeFullV); 292c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath internal::set_is_malloc_allowed(true); 293c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 294c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 295c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid test_jacobisvd() 296c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 297c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_3(( jacobisvd_verify_assert(Matrix3f()) )); 298c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_4(( jacobisvd_verify_assert(Matrix4d()) )); 299c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_7(( jacobisvd_verify_assert(MatrixXf(10,12)) )); 300c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_8(( jacobisvd_verify_assert(MatrixXcd(7,5)) )); 301c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 302c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(int i = 0; i < g_repeat; i++) { 303c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Matrix2cd m; 304c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m << 0, 1, 305c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 0, 1; 306c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_1(( jacobisvd(m, false) )); 307c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m << 1, 0, 308c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 1, 0; 309c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_1(( jacobisvd(m, false) )); 310c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 311c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Matrix2d n; 312c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath n << 0, 0, 313c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 0, 0; 314c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_2(( jacobisvd(n, false) )); 315c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath n << 0, 0, 316c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 0, 1; 317c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_2(( jacobisvd(n, false) )); 318c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 319c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_3(( jacobisvd<Matrix3f>() )); 320c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_4(( jacobisvd<Matrix4d>() )); 321c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_5(( jacobisvd<Matrix<float,3,5> >() )); 322c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_6(( jacobisvd<Matrix<double,Dynamic,2> >(Matrix<double,Dynamic,2>(10,2)) )); 323c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 324c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath int r = internal::random<int>(1, 30), 325c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath c = internal::random<int>(1, 30); 326c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_7(( jacobisvd<MatrixXf>(MatrixXf(r,c)) )); 327c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_8(( jacobisvd<MatrixXcd>(MatrixXcd(r,c)) )); 328c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath (void) r; 329c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath (void) c; 330c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 331c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // Test on inf/nan matrix 332c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_7( jacobisvd_inf_nan<MatrixXf>() ); 333c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 334c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 335c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_7(( jacobisvd<MatrixXf>(MatrixXf(internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/2), internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/2))) )); 336c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_8(( jacobisvd<MatrixXcd>(MatrixXcd(internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/3), internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/3))) )); 337c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 338c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // test matrixbase method 339c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_1(( jacobisvd_method<Matrix2cd>() )); 340c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_3(( jacobisvd_method<Matrix3f>() )); 341c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 342c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // Test problem size constructors 343c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_7( JacobiSVD<MatrixXf>(10,10) ); 344c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 345c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // Check that preallocation avoids subsequent mallocs 346c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_9( jacobisvd_preallocate() ); 347c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 348c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // Regression check for bug 286 349c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath CALL_SUBTEST_2( jacobisvd_bug286() ); 350c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 351