Eigne Matrix Class Library

Dependents:   MPC_current_control HydraulicControlBoard_SW AHRS Test_ekf ... more

Committer:
jsoh91
Date:
Tue Sep 24 00:18:23 2019 +0000
Revision:
1:3b8049da21b8
Parent:
0:13a5d365ba16
ignore and revise some of error parts

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ykuroda 0:13a5d365ba16 1 // This file is part of Eigen, a lightweight C++ template library
ykuroda 0:13a5d365ba16 2 // for linear algebra.
ykuroda 0:13a5d365ba16 3 //
ykuroda 0:13a5d365ba16 4 // Copyright (C) 2009-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
ykuroda 0:13a5d365ba16 5 //
ykuroda 0:13a5d365ba16 6 // This Source Code Form is subject to the terms of the Mozilla
ykuroda 0:13a5d365ba16 7 // Public License v. 2.0. If a copy of the MPL was not distributed
ykuroda 0:13a5d365ba16 8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
ykuroda 0:13a5d365ba16 9
ykuroda 0:13a5d365ba16 10 #ifndef EIGEN_JACOBISVD_H
ykuroda 0:13a5d365ba16 11 #define EIGEN_JACOBISVD_H
ykuroda 0:13a5d365ba16 12
ykuroda 0:13a5d365ba16 13 namespace Eigen {
ykuroda 0:13a5d365ba16 14
ykuroda 0:13a5d365ba16 15 namespace internal {
ykuroda 0:13a5d365ba16 16 // forward declaration (needed by ICC)
ykuroda 0:13a5d365ba16 17 // the empty body is required by MSVC
ykuroda 0:13a5d365ba16 18 template<typename MatrixType, int QRPreconditioner,
ykuroda 0:13a5d365ba16 19 bool IsComplex = NumTraits<typename MatrixType::Scalar>::IsComplex>
ykuroda 0:13a5d365ba16 20 struct svd_precondition_2x2_block_to_be_real {};
ykuroda 0:13a5d365ba16 21
ykuroda 0:13a5d365ba16 22 /*** QR preconditioners (R-SVD)
ykuroda 0:13a5d365ba16 23 ***
ykuroda 0:13a5d365ba16 24 *** Their role is to reduce the problem of computing the SVD to the case of a square matrix.
ykuroda 0:13a5d365ba16 25 *** This approach, known as R-SVD, is an optimization for rectangular-enough matrices, and is a requirement for
ykuroda 0:13a5d365ba16 26 *** JacobiSVD which by itself is only able to work on square matrices.
ykuroda 0:13a5d365ba16 27 ***/
ykuroda 0:13a5d365ba16 28
ykuroda 0:13a5d365ba16 29 enum { PreconditionIfMoreColsThanRows, PreconditionIfMoreRowsThanCols };
ykuroda 0:13a5d365ba16 30
ykuroda 0:13a5d365ba16 31 template<typename MatrixType, int QRPreconditioner, int Case>
ykuroda 0:13a5d365ba16 32 struct qr_preconditioner_should_do_anything
ykuroda 0:13a5d365ba16 33 {
ykuroda 0:13a5d365ba16 34 enum { a = MatrixType::RowsAtCompileTime != Dynamic &&
ykuroda 0:13a5d365ba16 35 MatrixType::ColsAtCompileTime != Dynamic &&
ykuroda 0:13a5d365ba16 36 MatrixType::ColsAtCompileTime <= MatrixType::RowsAtCompileTime,
ykuroda 0:13a5d365ba16 37 b = MatrixType::RowsAtCompileTime != Dynamic &&
ykuroda 0:13a5d365ba16 38 MatrixType::ColsAtCompileTime != Dynamic &&
ykuroda 0:13a5d365ba16 39 MatrixType::RowsAtCompileTime <= MatrixType::ColsAtCompileTime,
ykuroda 0:13a5d365ba16 40 ret = !( (QRPreconditioner == NoQRPreconditioner) ||
ykuroda 0:13a5d365ba16 41 (Case == PreconditionIfMoreColsThanRows && bool(a)) ||
ykuroda 0:13a5d365ba16 42 (Case == PreconditionIfMoreRowsThanCols && bool(b)) )
ykuroda 0:13a5d365ba16 43 };
ykuroda 0:13a5d365ba16 44 };
ykuroda 0:13a5d365ba16 45
ykuroda 0:13a5d365ba16 46 template<typename MatrixType, int QRPreconditioner, int Case,
ykuroda 0:13a5d365ba16 47 bool DoAnything = qr_preconditioner_should_do_anything<MatrixType, QRPreconditioner, Case>::ret
ykuroda 0:13a5d365ba16 48 > struct qr_preconditioner_impl {};
ykuroda 0:13a5d365ba16 49
ykuroda 0:13a5d365ba16 50 template<typename MatrixType, int QRPreconditioner, int Case>
ykuroda 0:13a5d365ba16 51 class qr_preconditioner_impl<MatrixType, QRPreconditioner, Case, false>
ykuroda 0:13a5d365ba16 52 {
ykuroda 0:13a5d365ba16 53 public:
ykuroda 0:13a5d365ba16 54 typedef typename MatrixType::Index Index;
ykuroda 0:13a5d365ba16 55 void allocate(const JacobiSVD<MatrixType, QRPreconditioner>&) {}
ykuroda 0:13a5d365ba16 56 bool run(JacobiSVD<MatrixType, QRPreconditioner>&, const MatrixType&)
ykuroda 0:13a5d365ba16 57 {
ykuroda 0:13a5d365ba16 58 return false;
ykuroda 0:13a5d365ba16 59 }
ykuroda 0:13a5d365ba16 60 };
ykuroda 0:13a5d365ba16 61
ykuroda 0:13a5d365ba16 62 /*** preconditioner using FullPivHouseholderQR ***/
ykuroda 0:13a5d365ba16 63
ykuroda 0:13a5d365ba16 64 template<typename MatrixType>
ykuroda 0:13a5d365ba16 65 class qr_preconditioner_impl<MatrixType, FullPivHouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
ykuroda 0:13a5d365ba16 66 {
ykuroda 0:13a5d365ba16 67 public:
ykuroda 0:13a5d365ba16 68 typedef typename MatrixType::Index Index;
ykuroda 0:13a5d365ba16 69 typedef typename MatrixType::Scalar Scalar;
ykuroda 0:13a5d365ba16 70 enum
ykuroda 0:13a5d365ba16 71 {
ykuroda 0:13a5d365ba16 72 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ykuroda 0:13a5d365ba16 73 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime
ykuroda 0:13a5d365ba16 74 };
ykuroda 0:13a5d365ba16 75 typedef Matrix<Scalar, 1, RowsAtCompileTime, RowMajor, 1, MaxRowsAtCompileTime> WorkspaceType;
ykuroda 0:13a5d365ba16 76
ykuroda 0:13a5d365ba16 77 void allocate(const JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd)
ykuroda 0:13a5d365ba16 78 {
ykuroda 0:13a5d365ba16 79 if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
ykuroda 0:13a5d365ba16 80 {
ykuroda 0:13a5d365ba16 81 m_qr.~QRType();
ykuroda 0:13a5d365ba16 82 ::new (&m_qr) QRType(svd.rows(), svd.cols());
ykuroda 0:13a5d365ba16 83 }
ykuroda 0:13a5d365ba16 84 if (svd.m_computeFullU) m_workspace.resize(svd.rows());
ykuroda 0:13a5d365ba16 85 }
ykuroda 0:13a5d365ba16 86
ykuroda 0:13a5d365ba16 87 bool run(JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
ykuroda 0:13a5d365ba16 88 {
ykuroda 0:13a5d365ba16 89 if(matrix.rows() > matrix.cols())
ykuroda 0:13a5d365ba16 90 {
ykuroda 0:13a5d365ba16 91 m_qr.compute(matrix);
ykuroda 0:13a5d365ba16 92 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
ykuroda 0:13a5d365ba16 93 if(svd.m_computeFullU) m_qr.matrixQ().evalTo(svd.m_matrixU, m_workspace);
ykuroda 0:13a5d365ba16 94 if(svd.computeV()) svd.m_matrixV = m_qr.colsPermutation();
ykuroda 0:13a5d365ba16 95 return true;
ykuroda 0:13a5d365ba16 96 }
ykuroda 0:13a5d365ba16 97 return false;
ykuroda 0:13a5d365ba16 98 }
ykuroda 0:13a5d365ba16 99 private:
ykuroda 0:13a5d365ba16 100 typedef FullPivHouseholderQR<MatrixType> QRType;
ykuroda 0:13a5d365ba16 101 QRType m_qr;
ykuroda 0:13a5d365ba16 102 WorkspaceType m_workspace;
ykuroda 0:13a5d365ba16 103 };
ykuroda 0:13a5d365ba16 104
ykuroda 0:13a5d365ba16 105 template<typename MatrixType>
ykuroda 0:13a5d365ba16 106 class qr_preconditioner_impl<MatrixType, FullPivHouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
ykuroda 0:13a5d365ba16 107 {
ykuroda 0:13a5d365ba16 108 public:
ykuroda 0:13a5d365ba16 109 typedef typename MatrixType::Index Index;
ykuroda 0:13a5d365ba16 110 typedef typename MatrixType::Scalar Scalar;
ykuroda 0:13a5d365ba16 111 enum
ykuroda 0:13a5d365ba16 112 {
ykuroda 0:13a5d365ba16 113 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ykuroda 0:13a5d365ba16 114 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
ykuroda 0:13a5d365ba16 115 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
ykuroda 0:13a5d365ba16 116 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
ykuroda 0:13a5d365ba16 117 Options = MatrixType::Options
ykuroda 0:13a5d365ba16 118 };
ykuroda 0:13a5d365ba16 119 typedef Matrix<Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime>
ykuroda 0:13a5d365ba16 120 TransposeTypeWithSameStorageOrder;
ykuroda 0:13a5d365ba16 121
ykuroda 0:13a5d365ba16 122 void allocate(const JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd)
ykuroda 0:13a5d365ba16 123 {
ykuroda 0:13a5d365ba16 124 if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
ykuroda 0:13a5d365ba16 125 {
ykuroda 0:13a5d365ba16 126 m_qr.~QRType();
ykuroda 0:13a5d365ba16 127 ::new (&m_qr) QRType(svd.cols(), svd.rows());
ykuroda 0:13a5d365ba16 128 }
ykuroda 0:13a5d365ba16 129 m_adjoint.resize(svd.cols(), svd.rows());
ykuroda 0:13a5d365ba16 130 if (svd.m_computeFullV) m_workspace.resize(svd.cols());
ykuroda 0:13a5d365ba16 131 }
ykuroda 0:13a5d365ba16 132
ykuroda 0:13a5d365ba16 133 bool run(JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
ykuroda 0:13a5d365ba16 134 {
ykuroda 0:13a5d365ba16 135 if(matrix.cols() > matrix.rows())
ykuroda 0:13a5d365ba16 136 {
ykuroda 0:13a5d365ba16 137 m_adjoint = matrix.adjoint();
ykuroda 0:13a5d365ba16 138 m_qr.compute(m_adjoint);
ykuroda 0:13a5d365ba16 139 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
ykuroda 0:13a5d365ba16 140 if(svd.m_computeFullV) m_qr.matrixQ().evalTo(svd.m_matrixV, m_workspace);
ykuroda 0:13a5d365ba16 141 if(svd.computeU()) svd.m_matrixU = m_qr.colsPermutation();
ykuroda 0:13a5d365ba16 142 return true;
ykuroda 0:13a5d365ba16 143 }
ykuroda 0:13a5d365ba16 144 else return false;
ykuroda 0:13a5d365ba16 145 }
ykuroda 0:13a5d365ba16 146 private:
ykuroda 0:13a5d365ba16 147 typedef FullPivHouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
ykuroda 0:13a5d365ba16 148 QRType m_qr;
ykuroda 0:13a5d365ba16 149 TransposeTypeWithSameStorageOrder m_adjoint;
ykuroda 0:13a5d365ba16 150 typename internal::plain_row_type<MatrixType>::type m_workspace;
ykuroda 0:13a5d365ba16 151 };
ykuroda 0:13a5d365ba16 152
ykuroda 0:13a5d365ba16 153 /*** preconditioner using ColPivHouseholderQR ***/
ykuroda 0:13a5d365ba16 154
ykuroda 0:13a5d365ba16 155 template<typename MatrixType>
ykuroda 0:13a5d365ba16 156 class qr_preconditioner_impl<MatrixType, ColPivHouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
ykuroda 0:13a5d365ba16 157 {
ykuroda 0:13a5d365ba16 158 public:
ykuroda 0:13a5d365ba16 159 typedef typename MatrixType::Index Index;
ykuroda 0:13a5d365ba16 160
ykuroda 0:13a5d365ba16 161 void allocate(const JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd)
ykuroda 0:13a5d365ba16 162 {
ykuroda 0:13a5d365ba16 163 if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
ykuroda 0:13a5d365ba16 164 {
ykuroda 0:13a5d365ba16 165 m_qr.~QRType();
ykuroda 0:13a5d365ba16 166 ::new (&m_qr) QRType(svd.rows(), svd.cols());
ykuroda 0:13a5d365ba16 167 }
ykuroda 0:13a5d365ba16 168 if (svd.m_computeFullU) m_workspace.resize(svd.rows());
ykuroda 0:13a5d365ba16 169 else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
ykuroda 0:13a5d365ba16 170 }
ykuroda 0:13a5d365ba16 171
ykuroda 0:13a5d365ba16 172 bool run(JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
ykuroda 0:13a5d365ba16 173 {
ykuroda 0:13a5d365ba16 174 if(matrix.rows() > matrix.cols())
ykuroda 0:13a5d365ba16 175 {
ykuroda 0:13a5d365ba16 176 m_qr.compute(matrix);
ykuroda 0:13a5d365ba16 177 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
ykuroda 0:13a5d365ba16 178 if(svd.m_computeFullU) m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace);
ykuroda 0:13a5d365ba16 179 else if(svd.m_computeThinU)
ykuroda 0:13a5d365ba16 180 {
ykuroda 0:13a5d365ba16 181 svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
ykuroda 0:13a5d365ba16 182 m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace);
ykuroda 0:13a5d365ba16 183 }
ykuroda 0:13a5d365ba16 184 if(svd.computeV()) svd.m_matrixV = m_qr.colsPermutation();
ykuroda 0:13a5d365ba16 185 return true;
ykuroda 0:13a5d365ba16 186 }
ykuroda 0:13a5d365ba16 187 return false;
ykuroda 0:13a5d365ba16 188 }
ykuroda 0:13a5d365ba16 189
ykuroda 0:13a5d365ba16 190 private:
ykuroda 0:13a5d365ba16 191 typedef ColPivHouseholderQR<MatrixType> QRType;
ykuroda 0:13a5d365ba16 192 QRType m_qr;
ykuroda 0:13a5d365ba16 193 typename internal::plain_col_type<MatrixType>::type m_workspace;
ykuroda 0:13a5d365ba16 194 };
ykuroda 0:13a5d365ba16 195
ykuroda 0:13a5d365ba16 196 template<typename MatrixType>
ykuroda 0:13a5d365ba16 197 class qr_preconditioner_impl<MatrixType, ColPivHouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
ykuroda 0:13a5d365ba16 198 {
ykuroda 0:13a5d365ba16 199 public:
ykuroda 0:13a5d365ba16 200 typedef typename MatrixType::Index Index;
ykuroda 0:13a5d365ba16 201 typedef typename MatrixType::Scalar Scalar;
ykuroda 0:13a5d365ba16 202 enum
ykuroda 0:13a5d365ba16 203 {
ykuroda 0:13a5d365ba16 204 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ykuroda 0:13a5d365ba16 205 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
ykuroda 0:13a5d365ba16 206 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
ykuroda 0:13a5d365ba16 207 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
ykuroda 0:13a5d365ba16 208 Options = MatrixType::Options
ykuroda 0:13a5d365ba16 209 };
ykuroda 0:13a5d365ba16 210
ykuroda 0:13a5d365ba16 211 typedef Matrix<Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime>
ykuroda 0:13a5d365ba16 212 TransposeTypeWithSameStorageOrder;
ykuroda 0:13a5d365ba16 213
ykuroda 0:13a5d365ba16 214 void allocate(const JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd)
ykuroda 0:13a5d365ba16 215 {
ykuroda 0:13a5d365ba16 216 if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
ykuroda 0:13a5d365ba16 217 {
ykuroda 0:13a5d365ba16 218 m_qr.~QRType();
ykuroda 0:13a5d365ba16 219 ::new (&m_qr) QRType(svd.cols(), svd.rows());
ykuroda 0:13a5d365ba16 220 }
ykuroda 0:13a5d365ba16 221 if (svd.m_computeFullV) m_workspace.resize(svd.cols());
ykuroda 0:13a5d365ba16 222 else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
ykuroda 0:13a5d365ba16 223 m_adjoint.resize(svd.cols(), svd.rows());
ykuroda 0:13a5d365ba16 224 }
ykuroda 0:13a5d365ba16 225
ykuroda 0:13a5d365ba16 226 bool run(JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
ykuroda 0:13a5d365ba16 227 {
ykuroda 0:13a5d365ba16 228 if(matrix.cols() > matrix.rows())
ykuroda 0:13a5d365ba16 229 {
ykuroda 0:13a5d365ba16 230 m_adjoint = matrix.adjoint();
ykuroda 0:13a5d365ba16 231 m_qr.compute(m_adjoint);
ykuroda 0:13a5d365ba16 232
ykuroda 0:13a5d365ba16 233 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
ykuroda 0:13a5d365ba16 234 if(svd.m_computeFullV) m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace);
ykuroda 0:13a5d365ba16 235 else if(svd.m_computeThinV)
ykuroda 0:13a5d365ba16 236 {
ykuroda 0:13a5d365ba16 237 svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
ykuroda 0:13a5d365ba16 238 m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace);
ykuroda 0:13a5d365ba16 239 }
ykuroda 0:13a5d365ba16 240 if(svd.computeU()) svd.m_matrixU = m_qr.colsPermutation();
ykuroda 0:13a5d365ba16 241 return true;
ykuroda 0:13a5d365ba16 242 }
ykuroda 0:13a5d365ba16 243 else return false;
ykuroda 0:13a5d365ba16 244 }
ykuroda 0:13a5d365ba16 245
ykuroda 0:13a5d365ba16 246 private:
ykuroda 0:13a5d365ba16 247 typedef ColPivHouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
ykuroda 0:13a5d365ba16 248 QRType m_qr;
ykuroda 0:13a5d365ba16 249 TransposeTypeWithSameStorageOrder m_adjoint;
ykuroda 0:13a5d365ba16 250 typename internal::plain_row_type<MatrixType>::type m_workspace;
ykuroda 0:13a5d365ba16 251 };
ykuroda 0:13a5d365ba16 252
ykuroda 0:13a5d365ba16 253 /*** preconditioner using HouseholderQR ***/
ykuroda 0:13a5d365ba16 254
ykuroda 0:13a5d365ba16 255 template<typename MatrixType>
ykuroda 0:13a5d365ba16 256 class qr_preconditioner_impl<MatrixType, HouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
ykuroda 0:13a5d365ba16 257 {
ykuroda 0:13a5d365ba16 258 public:
ykuroda 0:13a5d365ba16 259 typedef typename MatrixType::Index Index;
ykuroda 0:13a5d365ba16 260
ykuroda 0:13a5d365ba16 261 void allocate(const JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd)
ykuroda 0:13a5d365ba16 262 {
ykuroda 0:13a5d365ba16 263 if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
ykuroda 0:13a5d365ba16 264 {
ykuroda 0:13a5d365ba16 265 m_qr.~QRType();
ykuroda 0:13a5d365ba16 266 ::new (&m_qr) QRType(svd.rows(), svd.cols());
ykuroda 0:13a5d365ba16 267 }
ykuroda 0:13a5d365ba16 268 if (svd.m_computeFullU) m_workspace.resize(svd.rows());
ykuroda 0:13a5d365ba16 269 else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
ykuroda 0:13a5d365ba16 270 }
ykuroda 0:13a5d365ba16 271
ykuroda 0:13a5d365ba16 272 bool run(JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd, const MatrixType& matrix)
ykuroda 0:13a5d365ba16 273 {
ykuroda 0:13a5d365ba16 274 if(matrix.rows() > matrix.cols())
ykuroda 0:13a5d365ba16 275 {
ykuroda 0:13a5d365ba16 276 m_qr.compute(matrix);
ykuroda 0:13a5d365ba16 277 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
ykuroda 0:13a5d365ba16 278 if(svd.m_computeFullU) m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace);
ykuroda 0:13a5d365ba16 279 else if(svd.m_computeThinU)
ykuroda 0:13a5d365ba16 280 {
ykuroda 0:13a5d365ba16 281 svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
ykuroda 0:13a5d365ba16 282 m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace);
ykuroda 0:13a5d365ba16 283 }
ykuroda 0:13a5d365ba16 284 if(svd.computeV()) svd.m_matrixV.setIdentity(matrix.cols(), matrix.cols());
ykuroda 0:13a5d365ba16 285 return true;
ykuroda 0:13a5d365ba16 286 }
ykuroda 0:13a5d365ba16 287 return false;
ykuroda 0:13a5d365ba16 288 }
ykuroda 0:13a5d365ba16 289 private:
ykuroda 0:13a5d365ba16 290 typedef HouseholderQR<MatrixType> QRType;
ykuroda 0:13a5d365ba16 291 QRType m_qr;
ykuroda 0:13a5d365ba16 292 typename internal::plain_col_type<MatrixType>::type m_workspace;
ykuroda 0:13a5d365ba16 293 };
ykuroda 0:13a5d365ba16 294
ykuroda 0:13a5d365ba16 295 template<typename MatrixType>
ykuroda 0:13a5d365ba16 296 class qr_preconditioner_impl<MatrixType, HouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
ykuroda 0:13a5d365ba16 297 {
ykuroda 0:13a5d365ba16 298 public:
ykuroda 0:13a5d365ba16 299 typedef typename MatrixType::Index Index;
ykuroda 0:13a5d365ba16 300 typedef typename MatrixType::Scalar Scalar;
ykuroda 0:13a5d365ba16 301 enum
ykuroda 0:13a5d365ba16 302 {
ykuroda 0:13a5d365ba16 303 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ykuroda 0:13a5d365ba16 304 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
ykuroda 0:13a5d365ba16 305 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
ykuroda 0:13a5d365ba16 306 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
ykuroda 0:13a5d365ba16 307 Options = MatrixType::Options
ykuroda 0:13a5d365ba16 308 };
ykuroda 0:13a5d365ba16 309
ykuroda 0:13a5d365ba16 310 typedef Matrix<Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime>
ykuroda 0:13a5d365ba16 311 TransposeTypeWithSameStorageOrder;
ykuroda 0:13a5d365ba16 312
ykuroda 0:13a5d365ba16 313 void allocate(const JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd)
ykuroda 0:13a5d365ba16 314 {
ykuroda 0:13a5d365ba16 315 if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
ykuroda 0:13a5d365ba16 316 {
ykuroda 0:13a5d365ba16 317 m_qr.~QRType();
ykuroda 0:13a5d365ba16 318 ::new (&m_qr) QRType(svd.cols(), svd.rows());
ykuroda 0:13a5d365ba16 319 }
ykuroda 0:13a5d365ba16 320 if (svd.m_computeFullV) m_workspace.resize(svd.cols());
ykuroda 0:13a5d365ba16 321 else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
ykuroda 0:13a5d365ba16 322 m_adjoint.resize(svd.cols(), svd.rows());
ykuroda 0:13a5d365ba16 323 }
ykuroda 0:13a5d365ba16 324
ykuroda 0:13a5d365ba16 325 bool run(JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd, const MatrixType& matrix)
ykuroda 0:13a5d365ba16 326 {
ykuroda 0:13a5d365ba16 327 if(matrix.cols() > matrix.rows())
ykuroda 0:13a5d365ba16 328 {
ykuroda 0:13a5d365ba16 329 m_adjoint = matrix.adjoint();
ykuroda 0:13a5d365ba16 330 m_qr.compute(m_adjoint);
ykuroda 0:13a5d365ba16 331
ykuroda 0:13a5d365ba16 332 svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
ykuroda 0:13a5d365ba16 333 if(svd.m_computeFullV) m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace);
ykuroda 0:13a5d365ba16 334 else if(svd.m_computeThinV)
ykuroda 0:13a5d365ba16 335 {
ykuroda 0:13a5d365ba16 336 svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
ykuroda 0:13a5d365ba16 337 m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace);
ykuroda 0:13a5d365ba16 338 }
ykuroda 0:13a5d365ba16 339 if(svd.computeU()) svd.m_matrixU.setIdentity(matrix.rows(), matrix.rows());
ykuroda 0:13a5d365ba16 340 return true;
ykuroda 0:13a5d365ba16 341 }
ykuroda 0:13a5d365ba16 342 else return false;
ykuroda 0:13a5d365ba16 343 }
ykuroda 0:13a5d365ba16 344
ykuroda 0:13a5d365ba16 345 private:
ykuroda 0:13a5d365ba16 346 typedef HouseholderQR<TransposeTypeWithSameStorageOrder> QRType;
ykuroda 0:13a5d365ba16 347 QRType m_qr;
ykuroda 0:13a5d365ba16 348 TransposeTypeWithSameStorageOrder m_adjoint;
ykuroda 0:13a5d365ba16 349 typename internal::plain_row_type<MatrixType>::type m_workspace;
ykuroda 0:13a5d365ba16 350 };
ykuroda 0:13a5d365ba16 351
ykuroda 0:13a5d365ba16 352 /*** 2x2 SVD implementation
ykuroda 0:13a5d365ba16 353 ***
ykuroda 0:13a5d365ba16 354 *** JacobiSVD consists in performing a series of 2x2 SVD subproblems
ykuroda 0:13a5d365ba16 355 ***/
ykuroda 0:13a5d365ba16 356
ykuroda 0:13a5d365ba16 357 template<typename MatrixType, int QRPreconditioner>
ykuroda 0:13a5d365ba16 358 struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, false>
ykuroda 0:13a5d365ba16 359 {
ykuroda 0:13a5d365ba16 360 typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
ykuroda 0:13a5d365ba16 361 typedef typename SVD::Index Index;
ykuroda 0:13a5d365ba16 362 static void run(typename SVD::WorkMatrixType&, SVD&, Index, Index) {}
ykuroda 0:13a5d365ba16 363 };
ykuroda 0:13a5d365ba16 364
ykuroda 0:13a5d365ba16 365 template<typename MatrixType, int QRPreconditioner>
ykuroda 0:13a5d365ba16 366 struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
ykuroda 0:13a5d365ba16 367 {
ykuroda 0:13a5d365ba16 368 typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
ykuroda 0:13a5d365ba16 369 typedef typename MatrixType::Scalar Scalar;
ykuroda 0:13a5d365ba16 370 typedef typename MatrixType::RealScalar RealScalar;
ykuroda 0:13a5d365ba16 371 typedef typename SVD::Index Index;
ykuroda 0:13a5d365ba16 372 static void run(typename SVD::WorkMatrixType& work_matrix, SVD& svd, Index p, Index q)
ykuroda 0:13a5d365ba16 373 {
ykuroda 0:13a5d365ba16 374 using std::sqrt;
ykuroda 0:13a5d365ba16 375 Scalar z;
ykuroda 0:13a5d365ba16 376 JacobiRotation<Scalar> rot;
ykuroda 0:13a5d365ba16 377 RealScalar n = sqrt(numext::abs2(work_matrix.coeff(p,p)) + numext::abs2(work_matrix.coeff(q,p)));
ykuroda 0:13a5d365ba16 378
ykuroda 0:13a5d365ba16 379 if(n==0)
ykuroda 0:13a5d365ba16 380 {
ykuroda 0:13a5d365ba16 381 z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
ykuroda 0:13a5d365ba16 382 work_matrix.row(p) *= z;
ykuroda 0:13a5d365ba16 383 if(svd.computeU()) svd.m_matrixU.col(p) *= conj(z);
ykuroda 0:13a5d365ba16 384 if(work_matrix.coeff(q,q)!=Scalar(0))
ykuroda 0:13a5d365ba16 385 {
ykuroda 0:13a5d365ba16 386 z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
ykuroda 0:13a5d365ba16 387 work_matrix.row(q) *= z;
ykuroda 0:13a5d365ba16 388 if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
ykuroda 0:13a5d365ba16 389 }
ykuroda 0:13a5d365ba16 390 // otherwise the second row is already zero, so we have nothing to do.
ykuroda 0:13a5d365ba16 391 }
ykuroda 0:13a5d365ba16 392 else
ykuroda 0:13a5d365ba16 393 {
ykuroda 0:13a5d365ba16 394 rot.c() = conj(work_matrix.coeff(p,p)) / n;
ykuroda 0:13a5d365ba16 395 rot.s() = work_matrix.coeff(q,p) / n;
ykuroda 0:13a5d365ba16 396 work_matrix.applyOnTheLeft(p,q,rot);
ykuroda 0:13a5d365ba16 397 if(svd.computeU()) svd.m_matrixU.applyOnTheRight(p,q,rot.adjoint());
ykuroda 0:13a5d365ba16 398 if(work_matrix.coeff(p,q) != Scalar(0))
ykuroda 0:13a5d365ba16 399 {
ykuroda 0:13a5d365ba16 400 Scalar z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
ykuroda 0:13a5d365ba16 401 work_matrix.col(q) *= z;
ykuroda 0:13a5d365ba16 402 if(svd.computeV()) svd.m_matrixV.col(q) *= z;
ykuroda 0:13a5d365ba16 403 }
ykuroda 0:13a5d365ba16 404 if(work_matrix.coeff(q,q) != Scalar(0))
ykuroda 0:13a5d365ba16 405 {
ykuroda 0:13a5d365ba16 406 z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
ykuroda 0:13a5d365ba16 407 work_matrix.row(q) *= z;
ykuroda 0:13a5d365ba16 408 if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
ykuroda 0:13a5d365ba16 409 }
ykuroda 0:13a5d365ba16 410 }
ykuroda 0:13a5d365ba16 411 }
ykuroda 0:13a5d365ba16 412 };
ykuroda 0:13a5d365ba16 413
ykuroda 0:13a5d365ba16 414 template<typename MatrixType, typename RealScalar, typename Index>
ykuroda 0:13a5d365ba16 415 void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q,
ykuroda 0:13a5d365ba16 416 JacobiRotation<RealScalar> *j_left,
ykuroda 0:13a5d365ba16 417 JacobiRotation<RealScalar> *j_right)
ykuroda 0:13a5d365ba16 418 {
ykuroda 0:13a5d365ba16 419 using std::sqrt;
ykuroda 0:13a5d365ba16 420 using std::abs;
ykuroda 0:13a5d365ba16 421 Matrix<RealScalar,2,2> m;
ykuroda 0:13a5d365ba16 422 m << numext::real(matrix.coeff(p,p)), numext::real(matrix.coeff(p,q)),
ykuroda 0:13a5d365ba16 423 numext::real(matrix.coeff(q,p)), numext::real(matrix.coeff(q,q));
ykuroda 0:13a5d365ba16 424 JacobiRotation<RealScalar> rot1;
ykuroda 0:13a5d365ba16 425 RealScalar t = m.coeff(0,0) + m.coeff(1,1);
ykuroda 0:13a5d365ba16 426 RealScalar d = m.coeff(1,0) - m.coeff(0,1);
ykuroda 0:13a5d365ba16 427 if(t == RealScalar(0))
ykuroda 0:13a5d365ba16 428 {
ykuroda 0:13a5d365ba16 429 rot1.c() = RealScalar(0);
ykuroda 0:13a5d365ba16 430 rot1.s() = d > RealScalar(0) ? RealScalar(1) : RealScalar(-1);
ykuroda 0:13a5d365ba16 431 }
ykuroda 0:13a5d365ba16 432 else
ykuroda 0:13a5d365ba16 433 {
ykuroda 0:13a5d365ba16 434 RealScalar t2d2 = numext::hypot(t,d);
ykuroda 0:13a5d365ba16 435 rot1.c() = abs(t)/t2d2;
ykuroda 0:13a5d365ba16 436 rot1.s() = d/t2d2;
ykuroda 0:13a5d365ba16 437 if(t<RealScalar(0))
ykuroda 0:13a5d365ba16 438 rot1.s() = -rot1.s();
ykuroda 0:13a5d365ba16 439 }
ykuroda 0:13a5d365ba16 440 m.applyOnTheLeft(0,1,rot1);
ykuroda 0:13a5d365ba16 441 j_right->makeJacobi(m,0,1);
ykuroda 0:13a5d365ba16 442 *j_left = rot1 * j_right->transpose();
ykuroda 0:13a5d365ba16 443 }
ykuroda 0:13a5d365ba16 444
ykuroda 0:13a5d365ba16 445 } // end namespace internal
ykuroda 0:13a5d365ba16 446
ykuroda 0:13a5d365ba16 447 /** \ingroup SVD_Module
ykuroda 0:13a5d365ba16 448 *
ykuroda 0:13a5d365ba16 449 *
ykuroda 0:13a5d365ba16 450 * \class JacobiSVD
ykuroda 0:13a5d365ba16 451 *
ykuroda 0:13a5d365ba16 452 * \brief Two-sided Jacobi SVD decomposition of a rectangular matrix
ykuroda 0:13a5d365ba16 453 *
ykuroda 0:13a5d365ba16 454 * \param MatrixType the type of the matrix of which we are computing the SVD decomposition
ykuroda 0:13a5d365ba16 455 * \param QRPreconditioner this optional parameter allows to specify the type of QR decomposition that will be used internally
ykuroda 0:13a5d365ba16 456 * for the R-SVD step for non-square matrices. See discussion of possible values below.
ykuroda 0:13a5d365ba16 457 *
ykuroda 0:13a5d365ba16 458 * SVD decomposition consists in decomposing any n-by-p matrix \a A as a product
ykuroda 0:13a5d365ba16 459 * \f[ A = U S V^* \f]
ykuroda 0:13a5d365ba16 460 * where \a U is a n-by-n unitary, \a V is a p-by-p unitary, and \a S is a n-by-p real positive matrix which is zero outside of its main diagonal;
ykuroda 0:13a5d365ba16 461 * the diagonal entries of S are known as the \em singular \em values of \a A and the columns of \a U and \a V are known as the left
ykuroda 0:13a5d365ba16 462 * and right \em singular \em vectors of \a A respectively.
ykuroda 0:13a5d365ba16 463 *
ykuroda 0:13a5d365ba16 464 * Singular values are always sorted in decreasing order.
ykuroda 0:13a5d365ba16 465 *
ykuroda 0:13a5d365ba16 466 * This JacobiSVD decomposition computes only the singular values by default. If you want \a U or \a V, you need to ask for them explicitly.
ykuroda 0:13a5d365ba16 467 *
ykuroda 0:13a5d365ba16 468 * You can ask for only \em thin \a U or \a V to be computed, meaning the following. In case of a rectangular n-by-p matrix, letting \a m be the
ykuroda 0:13a5d365ba16 469 * smaller value among \a n and \a p, there are only \a m singular vectors; the remaining columns of \a U and \a V do not correspond to actual
ykuroda 0:13a5d365ba16 470 * singular vectors. Asking for \em thin \a U or \a V means asking for only their \a m first columns to be formed. So \a U is then a n-by-m matrix,
ykuroda 0:13a5d365ba16 471 * and \a V is then a p-by-m matrix. Notice that thin \a U and \a V are all you need for (least squares) solving.
ykuroda 0:13a5d365ba16 472 *
ykuroda 0:13a5d365ba16 473 * Here's an example demonstrating basic usage:
ykuroda 0:13a5d365ba16 474 * \include JacobiSVD_basic.cpp
ykuroda 0:13a5d365ba16 475 * Output: \verbinclude JacobiSVD_basic.out
ykuroda 0:13a5d365ba16 476 *
ykuroda 0:13a5d365ba16 477 * This JacobiSVD class is a two-sided Jacobi R-SVD decomposition, ensuring optimal reliability and accuracy. The downside is that it's slower than
ykuroda 0:13a5d365ba16 478 * bidiagonalizing SVD algorithms for large square matrices; however its complexity is still \f$ O(n^2p) \f$ where \a n is the smaller dimension and
ykuroda 0:13a5d365ba16 479 * \a p is the greater dimension, meaning that it is still of the same order of complexity as the faster bidiagonalizing R-SVD algorithms.
ykuroda 0:13a5d365ba16 480 * In particular, like any R-SVD, it takes advantage of non-squareness in that its complexity is only linear in the greater dimension.
ykuroda 0:13a5d365ba16 481 *
ykuroda 0:13a5d365ba16 482 * If the input matrix has inf or nan coefficients, the result of the computation is undefined, but the computation is guaranteed to
ykuroda 0:13a5d365ba16 483 * terminate in finite (and reasonable) time.
ykuroda 0:13a5d365ba16 484 *
ykuroda 0:13a5d365ba16 485 * The possible values for QRPreconditioner are:
ykuroda 0:13a5d365ba16 486 * \li ColPivHouseholderQRPreconditioner is the default. In practice it's very safe. It uses column-pivoting QR.
ykuroda 0:13a5d365ba16 487 * \li FullPivHouseholderQRPreconditioner, is the safest and slowest. It uses full-pivoting QR.
ykuroda 0:13a5d365ba16 488 * Contrary to other QRs, it doesn't allow computing thin unitaries.
ykuroda 0:13a5d365ba16 489 * \li HouseholderQRPreconditioner is the fastest, and less safe and accurate than the pivoting variants. It uses non-pivoting QR.
ykuroda 0:13a5d365ba16 490 * This is very similar in safety and accuracy to the bidiagonalization process used by bidiagonalizing SVD algorithms (since bidiagonalization
ykuroda 0:13a5d365ba16 491 * is inherently non-pivoting). However the resulting SVD is still more reliable than bidiagonalizing SVDs because the Jacobi-based iterarive
ykuroda 0:13a5d365ba16 492 * process is more reliable than the optimized bidiagonal SVD iterations.
ykuroda 0:13a5d365ba16 493 * \li NoQRPreconditioner allows not to use a QR preconditioner at all. This is useful if you know that you will only be computing
ykuroda 0:13a5d365ba16 494 * JacobiSVD decompositions of square matrices. Non-square matrices require a QR preconditioner. Using this option will result in
ykuroda 0:13a5d365ba16 495 * faster compilation and smaller executable code. It won't significantly speed up computation, since JacobiSVD is always checking
ykuroda 0:13a5d365ba16 496 * if QR preconditioning is needed before applying it anyway.
ykuroda 0:13a5d365ba16 497 *
ykuroda 0:13a5d365ba16 498 * \sa MatrixBase::jacobiSvd()
ykuroda 0:13a5d365ba16 499 */
ykuroda 0:13a5d365ba16 500 template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
ykuroda 0:13a5d365ba16 501 {
ykuroda 0:13a5d365ba16 502 public:
ykuroda 0:13a5d365ba16 503
ykuroda 0:13a5d365ba16 504 typedef _MatrixType MatrixType;
ykuroda 0:13a5d365ba16 505 typedef typename MatrixType::Scalar Scalar;
ykuroda 0:13a5d365ba16 506 typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
ykuroda 0:13a5d365ba16 507 typedef typename MatrixType::Index Index;
ykuroda 0:13a5d365ba16 508 enum {
ykuroda 0:13a5d365ba16 509 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ykuroda 0:13a5d365ba16 510 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
ykuroda 0:13a5d365ba16 511 DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime,ColsAtCompileTime),
ykuroda 0:13a5d365ba16 512 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
ykuroda 0:13a5d365ba16 513 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
ykuroda 0:13a5d365ba16 514 MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime,MaxColsAtCompileTime),
ykuroda 0:13a5d365ba16 515 MatrixOptions = MatrixType::Options
ykuroda 0:13a5d365ba16 516 };
ykuroda 0:13a5d365ba16 517
ykuroda 0:13a5d365ba16 518 typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime,
ykuroda 0:13a5d365ba16 519 MatrixOptions, MaxRowsAtCompileTime, MaxRowsAtCompileTime>
ykuroda 0:13a5d365ba16 520 MatrixUType;
ykuroda 0:13a5d365ba16 521 typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime,
ykuroda 0:13a5d365ba16 522 MatrixOptions, MaxColsAtCompileTime, MaxColsAtCompileTime>
ykuroda 0:13a5d365ba16 523 MatrixVType;
ykuroda 0:13a5d365ba16 524 typedef typename internal::plain_diag_type<MatrixType, RealScalar>::type SingularValuesType;
ykuroda 0:13a5d365ba16 525 typedef typename internal::plain_row_type<MatrixType>::type RowType;
ykuroda 0:13a5d365ba16 526 typedef typename internal::plain_col_type<MatrixType>::type ColType;
ykuroda 0:13a5d365ba16 527 typedef Matrix<Scalar, DiagSizeAtCompileTime, DiagSizeAtCompileTime,
ykuroda 0:13a5d365ba16 528 MatrixOptions, MaxDiagSizeAtCompileTime, MaxDiagSizeAtCompileTime>
ykuroda 0:13a5d365ba16 529 WorkMatrixType;
ykuroda 0:13a5d365ba16 530
ykuroda 0:13a5d365ba16 531 /** \brief Default Constructor.
ykuroda 0:13a5d365ba16 532 *
ykuroda 0:13a5d365ba16 533 * The default constructor is useful in cases in which the user intends to
ykuroda 0:13a5d365ba16 534 * perform decompositions via JacobiSVD::compute(const MatrixType&).
ykuroda 0:13a5d365ba16 535 */
ykuroda 0:13a5d365ba16 536 JacobiSVD()
ykuroda 0:13a5d365ba16 537 : m_isInitialized(false),
ykuroda 0:13a5d365ba16 538 m_isAllocated(false),
ykuroda 0:13a5d365ba16 539 m_usePrescribedThreshold(false),
ykuroda 0:13a5d365ba16 540 m_computationOptions(0),
ykuroda 0:13a5d365ba16 541 m_rows(-1), m_cols(-1), m_diagSize(0)
ykuroda 0:13a5d365ba16 542 {}
ykuroda 0:13a5d365ba16 543
ykuroda 0:13a5d365ba16 544
ykuroda 0:13a5d365ba16 545 /** \brief Default Constructor with memory preallocation
ykuroda 0:13a5d365ba16 546 *
ykuroda 0:13a5d365ba16 547 * Like the default constructor but with preallocation of the internal data
ykuroda 0:13a5d365ba16 548 * according to the specified problem size.
ykuroda 0:13a5d365ba16 549 * \sa JacobiSVD()
ykuroda 0:13a5d365ba16 550 */
ykuroda 0:13a5d365ba16 551 JacobiSVD(Index rows, Index cols, unsigned int computationOptions = 0)
ykuroda 0:13a5d365ba16 552 : m_isInitialized(false),
ykuroda 0:13a5d365ba16 553 m_isAllocated(false),
ykuroda 0:13a5d365ba16 554 m_usePrescribedThreshold(false),
ykuroda 0:13a5d365ba16 555 m_computationOptions(0),
ykuroda 0:13a5d365ba16 556 m_rows(-1), m_cols(-1)
ykuroda 0:13a5d365ba16 557 {
ykuroda 0:13a5d365ba16 558 allocate(rows, cols, computationOptions);
ykuroda 0:13a5d365ba16 559 }
ykuroda 0:13a5d365ba16 560
ykuroda 0:13a5d365ba16 561 /** \brief Constructor performing the decomposition of given matrix.
ykuroda 0:13a5d365ba16 562 *
ykuroda 0:13a5d365ba16 563 * \param matrix the matrix to decompose
ykuroda 0:13a5d365ba16 564 * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
ykuroda 0:13a5d365ba16 565 * By default, none is computed. This is a bit-field, the possible bits are #ComputeFullU, #ComputeThinU,
ykuroda 0:13a5d365ba16 566 * #ComputeFullV, #ComputeThinV.
ykuroda 0:13a5d365ba16 567 *
ykuroda 0:13a5d365ba16 568 * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
ykuroda 0:13a5d365ba16 569 * available with the (non-default) FullPivHouseholderQR preconditioner.
ykuroda 0:13a5d365ba16 570 */
ykuroda 0:13a5d365ba16 571 JacobiSVD(const MatrixType& matrix, unsigned int computationOptions = 0)
ykuroda 0:13a5d365ba16 572 : m_isInitialized(false),
ykuroda 0:13a5d365ba16 573 m_isAllocated(false),
ykuroda 0:13a5d365ba16 574 m_usePrescribedThreshold(false),
ykuroda 0:13a5d365ba16 575 m_computationOptions(0),
ykuroda 0:13a5d365ba16 576 m_rows(-1), m_cols(-1)
ykuroda 0:13a5d365ba16 577 {
ykuroda 0:13a5d365ba16 578 compute(matrix, computationOptions);
ykuroda 0:13a5d365ba16 579 }
ykuroda 0:13a5d365ba16 580
ykuroda 0:13a5d365ba16 581 /** \brief Method performing the decomposition of given matrix using custom options.
ykuroda 0:13a5d365ba16 582 *
ykuroda 0:13a5d365ba16 583 * \param matrix the matrix to decompose
ykuroda 0:13a5d365ba16 584 * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
ykuroda 0:13a5d365ba16 585 * By default, none is computed. This is a bit-field, the possible bits are #ComputeFullU, #ComputeThinU,
ykuroda 0:13a5d365ba16 586 * #ComputeFullV, #ComputeThinV.
ykuroda 0:13a5d365ba16 587 *
ykuroda 0:13a5d365ba16 588 * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
ykuroda 0:13a5d365ba16 589 * available with the (non-default) FullPivHouseholderQR preconditioner.
ykuroda 0:13a5d365ba16 590 */
ykuroda 0:13a5d365ba16 591 JacobiSVD& compute(const MatrixType& matrix, unsigned int computationOptions);
ykuroda 0:13a5d365ba16 592
ykuroda 0:13a5d365ba16 593 /** \brief Method performing the decomposition of given matrix using current options.
ykuroda 0:13a5d365ba16 594 *
ykuroda 0:13a5d365ba16 595 * \param matrix the matrix to decompose
ykuroda 0:13a5d365ba16 596 *
ykuroda 0:13a5d365ba16 597 * This method uses the current \a computationOptions, as already passed to the constructor or to compute(const MatrixType&, unsigned int).
ykuroda 0:13a5d365ba16 598 */
ykuroda 0:13a5d365ba16 599 JacobiSVD& compute(const MatrixType& matrix)
ykuroda 0:13a5d365ba16 600 {
ykuroda 0:13a5d365ba16 601 return compute(matrix, m_computationOptions);
ykuroda 0:13a5d365ba16 602 }
ykuroda 0:13a5d365ba16 603
ykuroda 0:13a5d365ba16 604 /** \returns the \a U matrix.
ykuroda 0:13a5d365ba16 605 *
ykuroda 0:13a5d365ba16 606 * For the SVD decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p,
ykuroda 0:13a5d365ba16 607 * the U matrix is n-by-n if you asked for #ComputeFullU, and is n-by-m if you asked for #ComputeThinU.
ykuroda 0:13a5d365ba16 608 *
ykuroda 0:13a5d365ba16 609 * The \a m first columns of \a U are the left singular vectors of the matrix being decomposed.
ykuroda 0:13a5d365ba16 610 *
ykuroda 0:13a5d365ba16 611 * This method asserts that you asked for \a U to be computed.
ykuroda 0:13a5d365ba16 612 */
ykuroda 0:13a5d365ba16 613 const MatrixUType& matrixU() const
ykuroda 0:13a5d365ba16 614 {
ykuroda 0:13a5d365ba16 615 eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
ykuroda 0:13a5d365ba16 616 eigen_assert(computeU() && "This JacobiSVD decomposition didn't compute U. Did you ask for it?");
ykuroda 0:13a5d365ba16 617 return m_matrixU;
ykuroda 0:13a5d365ba16 618 }
ykuroda 0:13a5d365ba16 619
ykuroda 0:13a5d365ba16 620 /** \returns the \a V matrix.
ykuroda 0:13a5d365ba16 621 *
ykuroda 0:13a5d365ba16 622 * For the SVD decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p,
ykuroda 0:13a5d365ba16 623 * the V matrix is p-by-p if you asked for #ComputeFullV, and is p-by-m if you asked for ComputeThinV.
ykuroda 0:13a5d365ba16 624 *
ykuroda 0:13a5d365ba16 625 * The \a m first columns of \a V are the right singular vectors of the matrix being decomposed.
ykuroda 0:13a5d365ba16 626 *
ykuroda 0:13a5d365ba16 627 * This method asserts that you asked for \a V to be computed.
ykuroda 0:13a5d365ba16 628 */
ykuroda 0:13a5d365ba16 629 const MatrixVType& matrixV() const
ykuroda 0:13a5d365ba16 630 {
ykuroda 0:13a5d365ba16 631 eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
ykuroda 0:13a5d365ba16 632 eigen_assert(computeV() && "This JacobiSVD decomposition didn't compute V. Did you ask for it?");
ykuroda 0:13a5d365ba16 633 return m_matrixV;
ykuroda 0:13a5d365ba16 634 }
ykuroda 0:13a5d365ba16 635
ykuroda 0:13a5d365ba16 636 /** \returns the vector of singular values.
ykuroda 0:13a5d365ba16 637 *
ykuroda 0:13a5d365ba16 638 * For the SVD decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p, the
ykuroda 0:13a5d365ba16 639 * returned vector has size \a m. Singular values are always sorted in decreasing order.
ykuroda 0:13a5d365ba16 640 */
ykuroda 0:13a5d365ba16 641 const SingularValuesType& singularValues() const
ykuroda 0:13a5d365ba16 642 {
ykuroda 0:13a5d365ba16 643 eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
ykuroda 0:13a5d365ba16 644 return m_singularValues;
ykuroda 0:13a5d365ba16 645 }
ykuroda 0:13a5d365ba16 646
ykuroda 0:13a5d365ba16 647 /** \returns true if \a U (full or thin) is asked for in this SVD decomposition */
ykuroda 0:13a5d365ba16 648 inline bool computeU() const { return m_computeFullU || m_computeThinU; }
ykuroda 0:13a5d365ba16 649 /** \returns true if \a V (full or thin) is asked for in this SVD decomposition */
ykuroda 0:13a5d365ba16 650 inline bool computeV() const { return m_computeFullV || m_computeThinV; }
ykuroda 0:13a5d365ba16 651
ykuroda 0:13a5d365ba16 652 /** \returns a (least squares) solution of \f$ A x = b \f$ using the current SVD decomposition of A.
ykuroda 0:13a5d365ba16 653 *
ykuroda 0:13a5d365ba16 654 * \param b the right-hand-side of the equation to solve.
ykuroda 0:13a5d365ba16 655 *
ykuroda 0:13a5d365ba16 656 * \note Solving requires both U and V to be computed. Thin U and V are enough, there is no need for full U or V.
ykuroda 0:13a5d365ba16 657 *
ykuroda 0:13a5d365ba16 658 * \note SVD solving is implicitly least-squares. Thus, this method serves both purposes of exact solving and least-squares solving.
ykuroda 0:13a5d365ba16 659 * In other words, the returned solution is guaranteed to minimize the Euclidean norm \f$ \Vert A x - b \Vert \f$.
ykuroda 0:13a5d365ba16 660 */
ykuroda 0:13a5d365ba16 661 template<typename Rhs>
ykuroda 0:13a5d365ba16 662 inline const internal::solve_retval<JacobiSVD, Rhs>
ykuroda 0:13a5d365ba16 663 solve(const MatrixBase<Rhs>& b) const
ykuroda 0:13a5d365ba16 664 {
ykuroda 0:13a5d365ba16 665 eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
ykuroda 0:13a5d365ba16 666 eigen_assert(computeU() && computeV() && "JacobiSVD::solve() requires both unitaries U and V to be computed (thin unitaries suffice).");
ykuroda 0:13a5d365ba16 667 return internal::solve_retval<JacobiSVD, Rhs>(*this, b.derived());
ykuroda 0:13a5d365ba16 668 }
ykuroda 0:13a5d365ba16 669
ykuroda 0:13a5d365ba16 670 /** \returns the number of singular values that are not exactly 0 */
ykuroda 0:13a5d365ba16 671 Index nonzeroSingularValues() const
ykuroda 0:13a5d365ba16 672 {
ykuroda 0:13a5d365ba16 673 eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
ykuroda 0:13a5d365ba16 674 return m_nonzeroSingularValues;
ykuroda 0:13a5d365ba16 675 }
ykuroda 0:13a5d365ba16 676
ykuroda 0:13a5d365ba16 677 /** \returns the rank of the matrix of which \c *this is the SVD.
ykuroda 0:13a5d365ba16 678 *
ykuroda 0:13a5d365ba16 679 * \note This method has to determine which singular values should be considered nonzero.
ykuroda 0:13a5d365ba16 680 * For that, it uses the threshold value that you can control by calling
ykuroda 0:13a5d365ba16 681 * setThreshold(const RealScalar&).
ykuroda 0:13a5d365ba16 682 */
ykuroda 0:13a5d365ba16 683 inline Index rank() const
ykuroda 0:13a5d365ba16 684 {
ykuroda 0:13a5d365ba16 685 using std::abs;
ykuroda 0:13a5d365ba16 686 eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
ykuroda 0:13a5d365ba16 687 if(m_singularValues.size()==0) return 0;
ykuroda 0:13a5d365ba16 688 RealScalar premultiplied_threshold = m_singularValues.coeff(0) * threshold();
ykuroda 0:13a5d365ba16 689 Index i = m_nonzeroSingularValues-1;
ykuroda 0:13a5d365ba16 690 while(i>=0 && m_singularValues.coeff(i) < premultiplied_threshold) --i;
ykuroda 0:13a5d365ba16 691 return i+1;
ykuroda 0:13a5d365ba16 692 }
ykuroda 0:13a5d365ba16 693
ykuroda 0:13a5d365ba16 694 /** Allows to prescribe a threshold to be used by certain methods, such as rank() and solve(),
ykuroda 0:13a5d365ba16 695 * which need to determine when singular values are to be considered nonzero.
ykuroda 0:13a5d365ba16 696 * This is not used for the SVD decomposition itself.
ykuroda 0:13a5d365ba16 697 *
ykuroda 0:13a5d365ba16 698 * When it needs to get the threshold value, Eigen calls threshold().
ykuroda 0:13a5d365ba16 699 * The default is \c NumTraits<Scalar>::epsilon()
ykuroda 0:13a5d365ba16 700 *
ykuroda 0:13a5d365ba16 701 * \param threshold The new value to use as the threshold.
ykuroda 0:13a5d365ba16 702 *
ykuroda 0:13a5d365ba16 703 * A singular value will be considered nonzero if its value is strictly greater than
ykuroda 0:13a5d365ba16 704 * \f$ \vert singular value \vert \leqslant threshold \times \vert max singular value \vert \f$.
ykuroda 0:13a5d365ba16 705 *
ykuroda 0:13a5d365ba16 706 * If you want to come back to the default behavior, call setThreshold(Default_t)
ykuroda 0:13a5d365ba16 707 */
ykuroda 0:13a5d365ba16 708 JacobiSVD& setThreshold(const RealScalar& threshold)
ykuroda 0:13a5d365ba16 709 {
ykuroda 0:13a5d365ba16 710 m_usePrescribedThreshold = true;
ykuroda 0:13a5d365ba16 711 m_prescribedThreshold = threshold;
ykuroda 0:13a5d365ba16 712 return *this;
ykuroda 0:13a5d365ba16 713 }
ykuroda 0:13a5d365ba16 714
ykuroda 0:13a5d365ba16 715 /** Allows to come back to the default behavior, letting Eigen use its default formula for
ykuroda 0:13a5d365ba16 716 * determining the threshold.
ykuroda 0:13a5d365ba16 717 *
ykuroda 0:13a5d365ba16 718 * You should pass the special object Eigen::Default as parameter here.
ykuroda 0:13a5d365ba16 719 * \code svd.setThreshold(Eigen::Default); \endcode
ykuroda 0:13a5d365ba16 720 *
ykuroda 0:13a5d365ba16 721 * See the documentation of setThreshold(const RealScalar&).
ykuroda 0:13a5d365ba16 722 */
ykuroda 0:13a5d365ba16 723 JacobiSVD& setThreshold(Default_t)
ykuroda 0:13a5d365ba16 724 {
ykuroda 0:13a5d365ba16 725 m_usePrescribedThreshold = false;
ykuroda 0:13a5d365ba16 726 return *this;
ykuroda 0:13a5d365ba16 727 }
ykuroda 0:13a5d365ba16 728
ykuroda 0:13a5d365ba16 729 /** Returns the threshold that will be used by certain methods such as rank().
ykuroda 0:13a5d365ba16 730 *
ykuroda 0:13a5d365ba16 731 * See the documentation of setThreshold(const RealScalar&).
ykuroda 0:13a5d365ba16 732 */
ykuroda 0:13a5d365ba16 733 RealScalar threshold() const
ykuroda 0:13a5d365ba16 734 {
ykuroda 0:13a5d365ba16 735 eigen_assert(m_isInitialized || m_usePrescribedThreshold);
ykuroda 0:13a5d365ba16 736 return m_usePrescribedThreshold ? m_prescribedThreshold
ykuroda 0:13a5d365ba16 737 : (std::max<Index>)(1,m_diagSize)*NumTraits<Scalar>::epsilon();
ykuroda 0:13a5d365ba16 738 }
ykuroda 0:13a5d365ba16 739
ykuroda 0:13a5d365ba16 740 inline Index rows() const { return m_rows; }
ykuroda 0:13a5d365ba16 741 inline Index cols() const { return m_cols; }
ykuroda 0:13a5d365ba16 742
ykuroda 0:13a5d365ba16 743 private:
ykuroda 0:13a5d365ba16 744 void allocate(Index rows, Index cols, unsigned int computationOptions);
ykuroda 0:13a5d365ba16 745
ykuroda 0:13a5d365ba16 746 static void check_template_parameters()
ykuroda 0:13a5d365ba16 747 {
ykuroda 0:13a5d365ba16 748 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
ykuroda 0:13a5d365ba16 749 }
ykuroda 0:13a5d365ba16 750
ykuroda 0:13a5d365ba16 751 protected:
ykuroda 0:13a5d365ba16 752 MatrixUType m_matrixU;
ykuroda 0:13a5d365ba16 753 MatrixVType m_matrixV;
ykuroda 0:13a5d365ba16 754 SingularValuesType m_singularValues;
ykuroda 0:13a5d365ba16 755 WorkMatrixType m_workMatrix;
ykuroda 0:13a5d365ba16 756 bool m_isInitialized, m_isAllocated, m_usePrescribedThreshold;
ykuroda 0:13a5d365ba16 757 bool m_computeFullU, m_computeThinU;
ykuroda 0:13a5d365ba16 758 bool m_computeFullV, m_computeThinV;
ykuroda 0:13a5d365ba16 759 unsigned int m_computationOptions;
ykuroda 0:13a5d365ba16 760 Index m_nonzeroSingularValues, m_rows, m_cols, m_diagSize;
ykuroda 0:13a5d365ba16 761 RealScalar m_prescribedThreshold;
ykuroda 0:13a5d365ba16 762
ykuroda 0:13a5d365ba16 763 template<typename __MatrixType, int _QRPreconditioner, bool _IsComplex>
ykuroda 0:13a5d365ba16 764 friend struct internal::svd_precondition_2x2_block_to_be_real;
ykuroda 0:13a5d365ba16 765 template<typename __MatrixType, int _QRPreconditioner, int _Case, bool _DoAnything>
ykuroda 0:13a5d365ba16 766 friend struct internal::qr_preconditioner_impl;
ykuroda 0:13a5d365ba16 767
ykuroda 0:13a5d365ba16 768 internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreColsThanRows> m_qr_precond_morecols;
ykuroda 0:13a5d365ba16 769 internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreRowsThanCols> m_qr_precond_morerows;
ykuroda 0:13a5d365ba16 770 MatrixType m_scaledMatrix;
ykuroda 0:13a5d365ba16 771 };
ykuroda 0:13a5d365ba16 772
ykuroda 0:13a5d365ba16 773 template<typename MatrixType, int QRPreconditioner>
ykuroda 0:13a5d365ba16 774 void JacobiSVD<MatrixType, QRPreconditioner>::allocate(Index rows, Index cols, unsigned int computationOptions)
ykuroda 0:13a5d365ba16 775 {
ykuroda 0:13a5d365ba16 776 eigen_assert(rows >= 0 && cols >= 0);
ykuroda 0:13a5d365ba16 777
ykuroda 0:13a5d365ba16 778 if (m_isAllocated &&
ykuroda 0:13a5d365ba16 779 rows == m_rows &&
ykuroda 0:13a5d365ba16 780 cols == m_cols &&
ykuroda 0:13a5d365ba16 781 computationOptions == m_computationOptions)
ykuroda 0:13a5d365ba16 782 {
ykuroda 0:13a5d365ba16 783 return;
ykuroda 0:13a5d365ba16 784 }
ykuroda 0:13a5d365ba16 785
ykuroda 0:13a5d365ba16 786 m_rows = rows;
ykuroda 0:13a5d365ba16 787 m_cols = cols;
ykuroda 0:13a5d365ba16 788 m_isInitialized = false;
ykuroda 0:13a5d365ba16 789 m_isAllocated = true;
ykuroda 0:13a5d365ba16 790 m_computationOptions = computationOptions;
ykuroda 0:13a5d365ba16 791 m_computeFullU = (computationOptions & ComputeFullU) != 0;
ykuroda 0:13a5d365ba16 792 m_computeThinU = (computationOptions & ComputeThinU) != 0;
ykuroda 0:13a5d365ba16 793 m_computeFullV = (computationOptions & ComputeFullV) != 0;
ykuroda 0:13a5d365ba16 794 m_computeThinV = (computationOptions & ComputeThinV) != 0;
ykuroda 0:13a5d365ba16 795 eigen_assert(!(m_computeFullU && m_computeThinU) && "JacobiSVD: you can't ask for both full and thin U");
ykuroda 0:13a5d365ba16 796 eigen_assert(!(m_computeFullV && m_computeThinV) && "JacobiSVD: you can't ask for both full and thin V");
ykuroda 0:13a5d365ba16 797 eigen_assert(EIGEN_IMPLIES(m_computeThinU || m_computeThinV, MatrixType::ColsAtCompileTime==Dynamic) &&
ykuroda 0:13a5d365ba16 798 "JacobiSVD: thin U and V are only available when your matrix has a dynamic number of columns.");
ykuroda 0:13a5d365ba16 799 if (QRPreconditioner == FullPivHouseholderQRPreconditioner)
ykuroda 0:13a5d365ba16 800 {
ykuroda 0:13a5d365ba16 801 eigen_assert(!(m_computeThinU || m_computeThinV) &&
ykuroda 0:13a5d365ba16 802 "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. "
ykuroda 0:13a5d365ba16 803 "Use the ColPivHouseholderQR preconditioner instead.");
ykuroda 0:13a5d365ba16 804 }
ykuroda 0:13a5d365ba16 805 m_diagSize = (std::min)(m_rows, m_cols);
ykuroda 0:13a5d365ba16 806 m_singularValues.resize(m_diagSize);
ykuroda 0:13a5d365ba16 807 if(RowsAtCompileTime==Dynamic)
ykuroda 0:13a5d365ba16 808 m_matrixU.resize(m_rows, m_computeFullU ? m_rows
ykuroda 0:13a5d365ba16 809 : m_computeThinU ? m_diagSize
ykuroda 0:13a5d365ba16 810 : 0);
ykuroda 0:13a5d365ba16 811 if(ColsAtCompileTime==Dynamic)
ykuroda 0:13a5d365ba16 812 m_matrixV.resize(m_cols, m_computeFullV ? m_cols
ykuroda 0:13a5d365ba16 813 : m_computeThinV ? m_diagSize
ykuroda 0:13a5d365ba16 814 : 0);
ykuroda 0:13a5d365ba16 815 m_workMatrix.resize(m_diagSize, m_diagSize);
ykuroda 0:13a5d365ba16 816
ykuroda 0:13a5d365ba16 817 if(m_cols>m_rows) m_qr_precond_morecols.allocate(*this);
ykuroda 0:13a5d365ba16 818 if(m_rows>m_cols) m_qr_precond_morerows.allocate(*this);
ykuroda 0:13a5d365ba16 819 if(m_rows!=m_cols) m_scaledMatrix.resize(rows,cols);
ykuroda 0:13a5d365ba16 820 }
ykuroda 0:13a5d365ba16 821
ykuroda 0:13a5d365ba16 822 template<typename MatrixType, int QRPreconditioner>
ykuroda 0:13a5d365ba16 823 JacobiSVD<MatrixType, QRPreconditioner>&
ykuroda 0:13a5d365ba16 824 JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsigned int computationOptions)
ykuroda 0:13a5d365ba16 825 {
ykuroda 0:13a5d365ba16 826 check_template_parameters();
ykuroda 0:13a5d365ba16 827
ykuroda 0:13a5d365ba16 828 using std::abs;
ykuroda 0:13a5d365ba16 829 allocate(matrix.rows(), matrix.cols(), computationOptions);
ykuroda 0:13a5d365ba16 830
ykuroda 0:13a5d365ba16 831 // currently we stop when we reach precision 2*epsilon as the last bit of precision can require an unreasonable number of iterations,
ykuroda 0:13a5d365ba16 832 // only worsening the precision of U and V as we accumulate more rotations
ykuroda 0:13a5d365ba16 833 const RealScalar precision = RealScalar(2) * NumTraits<Scalar>::epsilon();
ykuroda 0:13a5d365ba16 834
ykuroda 0:13a5d365ba16 835 // limit for very small denormal numbers to be considered zero in order to avoid infinite loops (see bug 286)
ykuroda 0:13a5d365ba16 836 const RealScalar considerAsZero = RealScalar(2) * std::numeric_limits<RealScalar>::denorm_min();
ykuroda 0:13a5d365ba16 837
ykuroda 0:13a5d365ba16 838 // Scaling factor to reduce over/under-flows
ykuroda 0:13a5d365ba16 839 RealScalar scale = matrix.cwiseAbs().maxCoeff();
ykuroda 0:13a5d365ba16 840 if(scale==RealScalar(0)) scale = RealScalar(1);
ykuroda 0:13a5d365ba16 841
ykuroda 0:13a5d365ba16 842 /*** step 1. The R-SVD step: we use a QR decomposition to reduce to the case of a square matrix */
ykuroda 0:13a5d365ba16 843
ykuroda 0:13a5d365ba16 844 if(m_rows!=m_cols)
ykuroda 0:13a5d365ba16 845 {
ykuroda 0:13a5d365ba16 846 m_scaledMatrix = matrix / scale;
ykuroda 0:13a5d365ba16 847 m_qr_precond_morecols.run(*this, m_scaledMatrix);
ykuroda 0:13a5d365ba16 848 m_qr_precond_morerows.run(*this, m_scaledMatrix);
ykuroda 0:13a5d365ba16 849 }
ykuroda 0:13a5d365ba16 850 else
ykuroda 0:13a5d365ba16 851 {
ykuroda 0:13a5d365ba16 852 m_workMatrix = matrix.block(0,0,m_diagSize,m_diagSize) / scale;
ykuroda 0:13a5d365ba16 853 if(m_computeFullU) m_matrixU.setIdentity(m_rows,m_rows);
ykuroda 0:13a5d365ba16 854 if(m_computeThinU) m_matrixU.setIdentity(m_rows,m_diagSize);
ykuroda 0:13a5d365ba16 855 if(m_computeFullV) m_matrixV.setIdentity(m_cols,m_cols);
ykuroda 0:13a5d365ba16 856 if(m_computeThinV) m_matrixV.setIdentity(m_cols, m_diagSize);
ykuroda 0:13a5d365ba16 857 }
ykuroda 0:13a5d365ba16 858
ykuroda 0:13a5d365ba16 859 /*** step 2. The main Jacobi SVD iteration. ***/
ykuroda 0:13a5d365ba16 860
ykuroda 0:13a5d365ba16 861 bool finished = false;
ykuroda 0:13a5d365ba16 862 while(!finished)
ykuroda 0:13a5d365ba16 863 {
ykuroda 0:13a5d365ba16 864 finished = true;
ykuroda 0:13a5d365ba16 865
ykuroda 0:13a5d365ba16 866 // do a sweep: for all index pairs (p,q), perform SVD of the corresponding 2x2 sub-matrix
ykuroda 0:13a5d365ba16 867
ykuroda 0:13a5d365ba16 868 for(Index p = 1; p < m_diagSize; ++p)
ykuroda 0:13a5d365ba16 869 {
ykuroda 0:13a5d365ba16 870 for(Index q = 0; q < p; ++q)
ykuroda 0:13a5d365ba16 871 {
ykuroda 0:13a5d365ba16 872 // if this 2x2 sub-matrix is not diagonal already...
ykuroda 0:13a5d365ba16 873 // notice that this comparison will evaluate to false if any NaN is involved, ensuring that NaN's don't
ykuroda 0:13a5d365ba16 874 // keep us iterating forever. Similarly, small denormal numbers are considered zero.
ykuroda 0:13a5d365ba16 875 using std::max;
ykuroda 0:13a5d365ba16 876 RealScalar threshold = (max)(considerAsZero, precision * (max)(abs(m_workMatrix.coeff(p,p)),
ykuroda 0:13a5d365ba16 877 abs(m_workMatrix.coeff(q,q))));
ykuroda 0:13a5d365ba16 878 // We compare both values to threshold instead of calling max to be robust to NaN (See bug 791)
ykuroda 0:13a5d365ba16 879 if(abs(m_workMatrix.coeff(p,q))>threshold || abs(m_workMatrix.coeff(q,p)) > threshold)
ykuroda 0:13a5d365ba16 880 {
ykuroda 0:13a5d365ba16 881 finished = false;
ykuroda 0:13a5d365ba16 882
ykuroda 0:13a5d365ba16 883 // perform SVD decomposition of 2x2 sub-matrix corresponding to indices p,q to make it diagonal
ykuroda 0:13a5d365ba16 884 internal::svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner>::run(m_workMatrix, *this, p, q);
ykuroda 0:13a5d365ba16 885 JacobiRotation<RealScalar> j_left, j_right;
ykuroda 0:13a5d365ba16 886 internal::real_2x2_jacobi_svd(m_workMatrix, p, q, &j_left, &j_right);
ykuroda 0:13a5d365ba16 887
ykuroda 0:13a5d365ba16 888 // accumulate resulting Jacobi rotations
ykuroda 0:13a5d365ba16 889 m_workMatrix.applyOnTheLeft(p,q,j_left);
ykuroda 0:13a5d365ba16 890 if(computeU()) m_matrixU.applyOnTheRight(p,q,j_left.transpose());
ykuroda 0:13a5d365ba16 891
ykuroda 0:13a5d365ba16 892 m_workMatrix.applyOnTheRight(p,q,j_right);
ykuroda 0:13a5d365ba16 893 if(computeV()) m_matrixV.applyOnTheRight(p,q,j_right);
ykuroda 0:13a5d365ba16 894 }
ykuroda 0:13a5d365ba16 895 }
ykuroda 0:13a5d365ba16 896 }
ykuroda 0:13a5d365ba16 897 }
ykuroda 0:13a5d365ba16 898
ykuroda 0:13a5d365ba16 899 /*** step 3. The work matrix is now diagonal, so ensure it's positive so its diagonal entries are the singular values ***/
ykuroda 0:13a5d365ba16 900
ykuroda 0:13a5d365ba16 901 for(Index i = 0; i < m_diagSize; ++i)
ykuroda 0:13a5d365ba16 902 {
ykuroda 0:13a5d365ba16 903 RealScalar a = abs(m_workMatrix.coeff(i,i));
ykuroda 0:13a5d365ba16 904 m_singularValues.coeffRef(i) = a;
ykuroda 0:13a5d365ba16 905 if(computeU() && (a!=RealScalar(0))) m_matrixU.col(i) *= m_workMatrix.coeff(i,i)/a;
ykuroda 0:13a5d365ba16 906 }
ykuroda 0:13a5d365ba16 907
ykuroda 0:13a5d365ba16 908 /*** step 4. Sort singular values in descending order and compute the number of nonzero singular values ***/
ykuroda 0:13a5d365ba16 909
ykuroda 0:13a5d365ba16 910 m_nonzeroSingularValues = m_diagSize;
ykuroda 0:13a5d365ba16 911 for(Index i = 0; i < m_diagSize; i++)
ykuroda 0:13a5d365ba16 912 {
ykuroda 0:13a5d365ba16 913 Index pos;
ykuroda 0:13a5d365ba16 914 RealScalar maxRemainingSingularValue = m_singularValues.tail(m_diagSize-i).maxCoeff(&pos);
ykuroda 0:13a5d365ba16 915 if(maxRemainingSingularValue == RealScalar(0))
ykuroda 0:13a5d365ba16 916 {
ykuroda 0:13a5d365ba16 917 m_nonzeroSingularValues = i;
ykuroda 0:13a5d365ba16 918 break;
ykuroda 0:13a5d365ba16 919 }
ykuroda 0:13a5d365ba16 920 if(pos)
ykuroda 0:13a5d365ba16 921 {
ykuroda 0:13a5d365ba16 922 pos += i;
ykuroda 0:13a5d365ba16 923 std::swap(m_singularValues.coeffRef(i), m_singularValues.coeffRef(pos));
ykuroda 0:13a5d365ba16 924 if(computeU()) m_matrixU.col(pos).swap(m_matrixU.col(i));
ykuroda 0:13a5d365ba16 925 if(computeV()) m_matrixV.col(pos).swap(m_matrixV.col(i));
ykuroda 0:13a5d365ba16 926 }
ykuroda 0:13a5d365ba16 927 }
ykuroda 0:13a5d365ba16 928
ykuroda 0:13a5d365ba16 929 m_singularValues *= scale;
ykuroda 0:13a5d365ba16 930
ykuroda 0:13a5d365ba16 931 m_isInitialized = true;
ykuroda 0:13a5d365ba16 932 return *this;
ykuroda 0:13a5d365ba16 933 }
ykuroda 0:13a5d365ba16 934
ykuroda 0:13a5d365ba16 935 namespace internal {
ykuroda 0:13a5d365ba16 936 template<typename _MatrixType, int QRPreconditioner, typename Rhs>
ykuroda 0:13a5d365ba16 937 struct solve_retval<JacobiSVD<_MatrixType, QRPreconditioner>, Rhs>
ykuroda 0:13a5d365ba16 938 : solve_retval_base<JacobiSVD<_MatrixType, QRPreconditioner>, Rhs>
ykuroda 0:13a5d365ba16 939 {
ykuroda 0:13a5d365ba16 940 typedef JacobiSVD<_MatrixType, QRPreconditioner> JacobiSVDType;
ykuroda 0:13a5d365ba16 941 EIGEN_MAKE_SOLVE_HELPERS(JacobiSVDType,Rhs)
ykuroda 0:13a5d365ba16 942
ykuroda 0:13a5d365ba16 943 template<typename Dest> void evalTo(Dest& dst) const
ykuroda 0:13a5d365ba16 944 {
ykuroda 0:13a5d365ba16 945 eigen_assert(rhs().rows() == dec().rows());
ykuroda 0:13a5d365ba16 946
ykuroda 0:13a5d365ba16 947 // A = U S V^*
ykuroda 0:13a5d365ba16 948 // So A^{-1} = V S^{-1} U^*
ykuroda 0:13a5d365ba16 949
ykuroda 0:13a5d365ba16 950 Matrix<Scalar, Dynamic, Rhs::ColsAtCompileTime, 0, _MatrixType::MaxRowsAtCompileTime, Rhs::MaxColsAtCompileTime> tmp;
ykuroda 0:13a5d365ba16 951 Index rank = dec().rank();
ykuroda 0:13a5d365ba16 952
ykuroda 0:13a5d365ba16 953 tmp.noalias() = dec().matrixU().leftCols(rank).adjoint() * rhs();
ykuroda 0:13a5d365ba16 954 tmp = dec().singularValues().head(rank).asDiagonal().inverse() * tmp;
ykuroda 0:13a5d365ba16 955 dst = dec().matrixV().leftCols(rank) * tmp;
ykuroda 0:13a5d365ba16 956 }
ykuroda 0:13a5d365ba16 957 };
ykuroda 0:13a5d365ba16 958 } // end namespace internal
ykuroda 0:13a5d365ba16 959
ykuroda 0:13a5d365ba16 960 /** \svd_module
ykuroda 0:13a5d365ba16 961 *
ykuroda 0:13a5d365ba16 962 * \return the singular value decomposition of \c *this computed by two-sided
ykuroda 0:13a5d365ba16 963 * Jacobi transformations.
ykuroda 0:13a5d365ba16 964 *
ykuroda 0:13a5d365ba16 965 * \sa class JacobiSVD
ykuroda 0:13a5d365ba16 966 */
ykuroda 0:13a5d365ba16 967 template<typename Derived>
ykuroda 0:13a5d365ba16 968 JacobiSVD<typename MatrixBase<Derived>::PlainObject>
ykuroda 0:13a5d365ba16 969 MatrixBase<Derived>::jacobiSvd(unsigned int computationOptions) const
ykuroda 0:13a5d365ba16 970 {
ykuroda 0:13a5d365ba16 971 return JacobiSVD<PlainObject>(*this, computationOptions);
ykuroda 0:13a5d365ba16 972 }
ykuroda 0:13a5d365ba16 973
ykuroda 0:13a5d365ba16 974 } // end namespace Eigen
ykuroda 0:13a5d365ba16 975
ykuroda 0:13a5d365ba16 976 #endif // EIGEN_JACOBISVD_H