ITK 6.0.0
Insight Toolkit
 
Loading...
Searching...
No Matches
itkMathSVD.h
Go to the documentation of this file.
1/*=========================================================================
2 *
3 * Copyright NumFOCUS
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18#ifndef itkMathSVD_h
19#define itkMathSVD_h
20
21#include "itkMacro.h"
23#include "vnl/vnl_matrix.h"
24#include "vnl/vnl_matrix_fixed.h"
25#include "vnl/vnl_vector.h"
26#include "vnl/vnl_vector_fixed.h"
27
28#include "itk_eigen.h"
29#include ITK_EIGEN(Dense)
30
31#include <limits>
32#include <type_traits>
33
34namespace itk
35{
36// Forward-declared to break the itkMatrix.h <-> itkMathSVD.h include cycle; the
37// itk::Matrix SVD overload needs the complete type only at instantiation, where
38// the caller has already included itkMatrix.h.
39template <typename T, unsigned int VRows, unsigned int VColumns>
40class Matrix;
41
42namespace Math
43{
44
45namespace detail
46{
47// rcond < 0 selects an automatic relative threshold of n * epsilon.
48template <typename TReal>
49TReal
50ResolveRcond(TReal rcond, unsigned int n)
51{
52 return rcond < TReal{ 0 } ? static_cast<TReal>(n) * std::numeric_limits<TReal>::epsilon() : rcond;
53}
54
55// Moore-Penrose pseudo-inverse V diag(1/w) U^T, with singular values at or below
56// rcond*max(w) treated as zero. U and V may be distinct types (rectangular fixed).
57template <typename TMatrixU, typename TVector, typename TMatrixV, typename TReal>
58auto
59PseudoInverse(const TMatrixU & U, const TVector & W, const TMatrixV & V, TReal rcond)
60{
61 const unsigned int k = W.size();
62 // W is sorted descending (Eigen guarantee), so W[0] is the max without an O(k) scan.
63 const TReal tol = ResolveRcond(rcond, k) * W[0];
64 TMatrixV scaledV = V;
65 for (unsigned int col = 0; col < k; ++col)
66 {
67 const TReal s = (W[col] > tol) ? TReal{ 1 } / W[col] : TReal{ 0 };
68 for (unsigned int i = 0; i < scaledV.rows(); ++i)
69 {
70 scaledV(i, col) *= s;
71 }
72 }
73 return scaledV * U.transpose();
74}
75
76// Least-squares / minimum-norm solution x = V diag(1/w) U^T b of A x = b.
77template <typename TMatrixU, typename TVector, typename TMatrixV, typename TVectorB, typename TReal>
78auto
79SolveLinear(const TMatrixU & U, const TVector & W, const TMatrixV & V, const TVectorB & b, TReal rcond)
80{
81 const unsigned int n = W.size();
82 const TReal tol = ResolveRcond(rcond, n) * W[0]; // W sorted descending; W[0] == max
83 auto utb = U.transpose() * b;
84 for (unsigned int k = 0; k < n; ++k)
85 {
86 utb[k] = (W[k] > tol) ? utb[k] / W[k] : TReal{ 0 };
87 }
88 return V * utb;
89}
90
91template <typename TVector, typename TReal>
92unsigned int
93NumericalRank(const TVector & W, TReal rcond)
94{
95 const unsigned int n = W.size();
96 const TReal tol = ResolveRcond(rcond, n) * W[0]; // W sorted descending; W[0] == max
97 unsigned int count = 0;
98 for (unsigned int k = 0; k < n; ++k)
99 {
100 if (W[k] > tol)
101 {
102 ++count;
103 }
104 }
105 return count;
106}
107
108// Reconstruct U diag(w) V^T, treating singular values at or below rcond*max(w) as
109// zero (a truncated, rank-reduced reconstruction of A).
110template <typename TMatrixU, typename TVector, typename TMatrixV, typename TReal>
111auto
112Recompose(const TMatrixU & U, const TVector & W, const TMatrixV & V, TReal rcond)
113{
114 const unsigned int k = W.size();
115 const TReal tol = ResolveRcond(rcond, k) * W[0]; // W sorted descending; W[0] == max
116 TMatrixU scaledU = U;
117 for (unsigned int col = 0; col < k; ++col)
118 {
119 const TReal s = (W[col] > tol) ? W[col] : TReal{ 0 };
120 for (unsigned int i = 0; i < scaledU.rows(); ++i)
121 {
122 scaledU(i, col) *= s;
123 }
124 }
125 return scaledU * V.transpose();
126}
127
128// Reconstruct U diag(w') V^T with caller-supplied singular values (no truncation);
129// serves the modify-W-then-recompose idiom (value clamping/inversion/zeroing).
130template <typename TMatrixU, typename TVector, typename TMatrixV>
131auto
132RecomposeWith(const TMatrixU & U, const TVector & modifiedW, const TMatrixV & V)
133{
134 TMatrixU scaledU = U;
135 for (unsigned int col = 0; col < modifiedW.size(); ++col)
136 {
137 for (unsigned int i = 0; i < scaledU.rows(); ++i)
138 {
139 scaledU(i, col) *= modifiedW[col];
140 }
141 }
142 return scaledU * V.transpose();
143}
144
145// Reciprocal condition number sigma_min/sigma_max; 0 when the matrix is singular.
146template <typename TVector>
147auto
148WellCondition(const TVector & W) -> std::decay_t<decltype(W[0])>
149{
150 const unsigned int k = W.size();
151 if (k == 0 || W[0] == 0)
152 {
153 return 0;
154 }
155 return W[k - 1] / W[0]; // W sorted descending
156}
157
158// Product of the singular values (|det A| for a square A).
159template <typename TVector>
160auto
161DeterminantMagnitude(const TVector & W) -> std::decay_t<decltype(W[0])>
162{
163 std::decay_t<decltype(W[0])> product{ 1 };
164 for (unsigned int k = 0; k < W.size(); ++k)
165 {
166 product *= W[k];
167 }
168 return product;
169}
170} // namespace detail
171
174template <typename TReal, unsigned int VDim>
176{
177 vnl_matrix_fixed<TReal, VDim, VDim> U{};
178 vnl_vector_fixed<TReal, VDim> W{};
179 vnl_matrix_fixed<TReal, VDim, VDim> V{};
180
182 vnl_matrix_fixed<TReal, VDim, VDim>
183 PseudoInverse(TReal rcond = TReal{ -1 }) const
184 {
185 return detail::PseudoInverse(U, W, V, rcond);
186 }
187
189 vnl_vector_fixed<TReal, VDim>
190 Solve(const vnl_vector_fixed<TReal, VDim> & b, TReal rcond = TReal{ -1 }) const
191 {
192 return detail::SolveLinear(U, W, V, b, rcond);
193 }
194
196 unsigned int
197 Rank(TReal rcond = TReal{ -1 }) const
198 {
199 return detail::NumericalRank(W, rcond);
200 }
201
203 vnl_matrix_fixed<TReal, VDim, VDim>
204 Recompose(TReal rcond = TReal{ -1 }) const
205 {
206 return detail::Recompose(U, W, V, rcond);
207 }
208
210 vnl_matrix_fixed<TReal, VDim, VDim>
211 RecomposeWith(const vnl_vector_fixed<TReal, VDim> & modifiedW) const
212 {
213 return detail::RecomposeWith(U, modifiedW, V);
214 }
215
218 vnl_vector_fixed<TReal, VDim>
220 {
221 return V.get_column(VDim - 1);
222 }
223
225 TReal
227 {
228 return detail::WellCondition(W);
229 }
230
232 TReal
234 {
236 }
237};
238
242template <typename TReal>
244{
245 vnl_matrix<TReal> U{};
246 vnl_vector<TReal> W{};
247 vnl_matrix<TReal> V{};
248
250 vnl_matrix<TReal>
251 PseudoInverse(TReal rcond = TReal{ -1 }) const
252 {
253 return detail::PseudoInverse(U, W, V, rcond);
254 }
255
257 vnl_vector<TReal>
258 Solve(const vnl_vector<TReal> & b, TReal rcond = TReal{ -1 }) const
259 {
260 return detail::SolveLinear(U, W, V, b, rcond);
261 }
262
264 unsigned int
265 Rank(TReal rcond = TReal{ -1 }) const
266 {
267 return detail::NumericalRank(W, rcond);
268 }
269
271 vnl_matrix<TReal>
272 Recompose(TReal rcond = TReal{ -1 }) const
273 {
274 return detail::Recompose(U, W, V, rcond);
275 }
276
278 vnl_matrix<TReal>
279 RecomposeWith(const vnl_vector<TReal> & modifiedW) const
280 {
281 return detail::RecomposeWith(U, modifiedW, V);
282 }
283
288 vnl_vector<TReal>
290 {
291 if (U.rows() < V.rows())
292 {
293 itkGenericExceptionMacro(
294 "NullVector() requires rows >= cols; the thin V of an underdetermined input does not span the nullspace.");
295 }
296 return V.get_column(V.cols() - 1);
297 }
298
300 TReal
302 {
303 return detail::WellCondition(W);
304 }
305
307 TReal
309 {
311 }
312};
313
317template <typename TReal, unsigned int VRows, unsigned int VCols>
319{
320 static constexpr unsigned int K = (VRows < VCols) ? VRows : VCols;
321
322 vnl_matrix_fixed<TReal, VRows, K> U{};
323 vnl_vector_fixed<TReal, K> W{};
324 vnl_matrix_fixed<TReal, VCols, K> V{};
325
327 vnl_matrix_fixed<TReal, VCols, VRows>
328 PseudoInverse(TReal rcond = TReal{ -1 }) const
329 {
330 return detail::PseudoInverse(U, W, V, rcond);
331 }
332
334 vnl_vector_fixed<TReal, VCols>
335 Solve(const vnl_vector_fixed<TReal, VRows> & b, TReal rcond = TReal{ -1 }) const
336 {
337 return detail::SolveLinear(U, W, V, b, rcond);
338 }
339
341 unsigned int
342 Rank(TReal rcond = TReal{ -1 }) const
343 {
344 return detail::NumericalRank(W, rcond);
345 }
346
348 vnl_matrix_fixed<TReal, VRows, VCols>
349 Recompose(TReal rcond = TReal{ -1 }) const
350 {
351 return detail::Recompose(U, W, V, rcond);
352 }
353
355 vnl_matrix_fixed<TReal, VRows, VCols>
356 RecomposeWith(const vnl_vector_fixed<TReal, K> & modifiedW) const
357 {
358 return detail::RecomposeWith(U, modifiedW, V);
359 }
360
364 vnl_vector_fixed<TReal, VCols>
366 {
367 static_assert(VRows >= VCols, "NullVector() requires VRows >= VCols (thin V cannot span the nullspace).");
368 return V.get_column(K - 1);
369 }
370
372 TReal
374 {
375 return detail::WellCondition(W);
376 }
377
379 TReal
381 {
383 }
384};
385
386namespace detail
387{
388// Above this compile-time size the fixed overload delegates to the runtime path
389// (keeps a large VDim off Eigen's stack-allocation limit).
390constexpr unsigned int kFixedSVDMaxDim = 16;
391
392// JacobiSVD+NoQRPreconditioner is fastest for small square inputs; BDCSVD is
393// faster and more accurate for larger n.
394constexpr unsigned int kJacobiMaxDim = 6;
395
396// Runtime-sized square SVD: JacobiSVD + NoQRPreconditioner for small n, BDCSVD for
397// larger n where Jacobi sweeps scale poorly. Throws on a failed decomposition.
398template <typename TReal>
399void
400DynamicSquareSVDEigen(const TReal * inData, unsigned int n, TReal * uData, TReal * wData, TReal * vData)
401{
402 using RowMajor = Eigen::Matrix<TReal, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
403 using ColMajor = Eigen::Matrix<TReal, Eigen::Dynamic, Eigen::Dynamic>;
404 constexpr int full = Eigen::ComputeFullU | Eigen::ComputeFullV;
405
406 const Eigen::Map<const RowMajor> inMap(inData, n, n);
407 Eigen::Map<RowMajor> uMap(uData, n, n);
408 Eigen::Map<RowMajor> vMap(vData, n, n);
409
410 const auto extract = [&](const auto & svd) {
411 if (svd.info() != Eigen::Success)
412 {
413 itkGenericExceptionMacro("itk::Math::SVD failed; input is likely non-finite (NaN/Inf).");
414 }
415 uMap = svd.matrixU();
416 vMap = svd.matrixV();
417 for (unsigned int i = 0; i < n; ++i)
418 {
419 wData[i] = svd.singularValues()[i];
420 }
421 };
422
423 if (n <= kJacobiMaxDim)
424 {
425 extract(Eigen::JacobiSVD < ColMajor, full | Eigen::NoQRPreconditioner > (inMap));
426 }
427 else
428 {
429 extract(Eigen::BDCSVD<ColMajor, full>(inMap));
430 }
431}
432
433// NoQRPreconditioner skips the column-pivot QR (wasted for a square input); large
434// VDim falls back to the runtime path. Throws on a failed/non-finite decomposition.
435template <unsigned int VDim, typename TReal>
436void
437SquareSVDEigen(const TReal * inData, TReal * uData, TReal * wData, TReal * vData)
438{
439 if constexpr (VDim > kFixedSVDMaxDim)
440 {
441 DynamicSquareSVDEigen<TReal>(inData, VDim, uData, wData, vData);
442 }
443 else
444 {
445 // Compile-time sizes ≤ kFixedSVDMaxDim always take JacobiSVD: it stack-allocates,
446 // fully unrolls, and beats BDCSVD's dynamic setup at these sizes (kJacobiMaxDim
447 // gates only the runtime path, where BDCSVD's allocation pays off for larger n).
448 using RowMajor = Eigen::Matrix<TReal, VDim, VDim, Eigen::RowMajor>;
449 using ColMajor = Eigen::Matrix<TReal, VDim, VDim>;
450 constexpr int options = Eigen::ComputeFullU | Eigen::ComputeFullV | Eigen::NoQRPreconditioner;
451
452 const Eigen::Map<const RowMajor> inMap(inData);
453 const Eigen::JacobiSVD<ColMajor, options> svd(inMap);
454 if (svd.info() != Eigen::Success)
455 {
456 itkGenericExceptionMacro("itk::Math::SVD failed; input is likely non-finite (NaN/Inf).");
457 }
458
459 Eigen::Map<RowMajor> uMap(uData);
460 Eigen::Map<RowMajor> vMap(vData);
461 uMap = svd.matrixU();
462 vMap = svd.matrixV();
463 for (unsigned int i = 0; i < VDim; ++i)
464 {
465 wData[i] = svd.singularValues()[i];
466 }
467 }
468}
469
470// Rectangular SVD via BDCSVD with thin U/V (Eigen's general engine for non-square
471// inputs). For an m x n input: U is m x k, V is n x k, W has length k = min(m, n).
472// Throws on a failed decomposition.
473template <typename TReal>
474void
475RectangularSVDEigen(const TReal * inData,
476 unsigned int rows,
477 unsigned int cols,
478 TReal * uData,
479 TReal * wData,
480 TReal * vData)
481{
482 using RowMajor = Eigen::Matrix<TReal, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
483 using ColMajor = Eigen::Matrix<TReal, Eigen::Dynamic, Eigen::Dynamic>;
484 constexpr int thin = Eigen::ComputeThinU | Eigen::ComputeThinV;
485 const unsigned int k = (rows < cols) ? rows : cols;
486
487 const Eigen::Map<const RowMajor> inMap(inData, rows, cols);
488 const Eigen::BDCSVD<ColMajor, thin> svd(inMap);
489 if (svd.info() != Eigen::Success)
490 {
491 itkGenericExceptionMacro("itk::Math::SVD failed; input is likely non-finite (NaN/Inf).");
492 }
493 Eigen::Map<RowMajor> uMap(uData, rows, k);
494 Eigen::Map<RowMajor> vMap(vData, cols, k);
495 uMap = svd.matrixU();
496 vMap = svd.matrixV();
497 for (unsigned int i = 0; i < k; ++i)
498 {
499 wData[i] = svd.singularValues()[i];
500 }
501}
502} // namespace detail
503
504// The Eigen JacobiSVD/BDCSVD instantiations behind the detail engines dominate
505// compile memory: without pre-instantiation, GCC needs ~2 GB per translation unit
506// that inverts an itk::Matrix. Declare the common specializations extern and define
507// them once in itkMathSVD.cxx so consumers link instead of re-instantiating them.
508#if defined(ITKCommon_EXPORTS)
509# define ITKCommon_EXPORT_EXPLICIT ITK_TEMPLATE_EXPORT
510#else
511# define ITKCommon_EXPORT_EXPLICIT ITKCommon_EXPORT
512#endif
513
514#define ITK_MATH_SVD_FIXED_DIMS(F) F(1) F(2) F(3) F(4) F(5) F(6)
515
516namespace detail
517{
518ITK_GCC_PRAGMA_DIAG_PUSH()
519ITK_GCC_PRAGMA_DIAG(ignored "-Wattributes")
520
521#define ITK_MATH_SVD_EXTERN_FIXED(D) \
522 extern template ITKCommon_EXPORT_EXPLICIT void SquareSVDEigen<D, float>(const float *, float *, float *, float *); \
523 extern template ITKCommon_EXPORT_EXPLICIT void SquareSVDEigen<D, double>( \
524 const double *, double *, double *, double *);
526#undef ITK_MATH_SVD_EXTERN_FIXED
527
528extern template ITKCommon_EXPORT_EXPLICIT void
529DynamicSquareSVDEigen<float>(const float *, unsigned int, float *, float *, float *);
530extern template ITKCommon_EXPORT_EXPLICIT void
531DynamicSquareSVDEigen<double>(const double *, unsigned int, double *, double *, double *);
532extern template ITKCommon_EXPORT_EXPLICIT void
533RectangularSVDEigen<float>(const float *, unsigned int, unsigned int, float *, float *, float *);
534extern template ITKCommon_EXPORT_EXPLICIT void
535RectangularSVDEigen<double>(const double *, unsigned int, unsigned int, double *, double *, double *);
536
537ITK_GCC_PRAGMA_DIAG_POP()
538} // namespace detail
539
540#undef ITKCommon_EXPORT_EXPLICIT
541
572template <typename TReal, unsigned int VDim>
574SVD(const vnl_matrix_fixed<TReal, VDim, VDim> & A, bool canonicalizeSigns = true)
575{
577 detail::SquareSVDEigen<VDim>(A.data_block(), result.U.data_block(), result.W.data_block(), result.V.data_block());
578 if (canonicalizeSigns)
579 {
581 }
582 return result;
583}
584
586template <typename TReal, unsigned int VDim>
587FixedSquareSVDResult<TReal, VDim>
588SVD(const Matrix<TReal, VDim, VDim> & A, bool canonicalizeSigns = true)
589{
590 return SVD<TReal, VDim>(A.GetVnlMatrix(), canonicalizeSigns);
591}
592
596template <typename TReal, unsigned int VRows, unsigned int VCols, typename = std::enable_if_t<VRows != VCols>>
597FixedRectangularSVDResult<TReal, VRows, VCols>
598SVD(const vnl_matrix_fixed<TReal, VRows, VCols> & A, bool canonicalizeSigns = true)
599{
602 A.data_block(), VRows, VCols, result.U.data_block(), result.W.data_block(), result.V.data_block());
603 if (canonicalizeSigns)
604 {
606 }
607 return result;
608}
609
611template <typename TReal, unsigned int VRows, unsigned int VCols, typename = std::enable_if_t<VRows != VCols>>
612FixedRectangularSVDResult<TReal, VRows, VCols>
613SVD(const Matrix<TReal, VRows, VCols> & A, bool canonicalizeSigns = true)
614{
615 return SVD<TReal, VRows, VCols>(A.GetVnlMatrix(), canonicalizeSigns);
616}
617
621template <typename TReal>
622SVDResult<TReal>
623SVD(const vnl_matrix<TReal> & A, bool canonicalizeSigns = true)
624{
625 const unsigned int rows = A.rows();
626 const unsigned int cols = A.cols();
627 if (rows == 0 || cols == 0)
628 {
629 itkGenericExceptionMacro("itk::Math::SVD requires a non-empty matrix.");
630 }
631 const unsigned int k = (rows < cols) ? rows : cols;
632 SVDResult<TReal> result;
633 result.U.set_size(rows, k);
634 result.V.set_size(cols, k);
635 result.W.set_size(k);
636 if (rows == cols)
637 {
639 A.data_block(), rows, result.U.data_block(), result.W.data_block(), result.V.data_block());
640 }
641 else
642 {
644 A.data_block(), rows, cols, result.U.data_block(), result.W.data_block(), result.V.data_block());
645 }
646 if (canonicalizeSigns)
647 {
649 }
650 return result;
651}
652
653} // namespace Math
654} // namespace itk
655
656#endif // itkMathSVD_h
A templated class holding a M x N size Matrix.
Definition itkMatrix.h:71
InternalMatrixType & GetVnlMatrix()
Definition itkMatrix.h:232
FixedSquareSVDResult< TReal, VDim > SVD(const vnl_matrix_fixed< TReal, VDim, VDim > &A, bool canonicalizeSigns=true)
Singular value decomposition A = U diag(W) V^T, backed by Eigen.
Definition itkMathSVD.h:574
#define ITKCommon_EXPORT_EXPLICIT
Definition itkMathSVD.h:511
#define ITK_MATH_SVD_EXTERN_FIXED(D)
Definition itkMathSVD.h:521
#define ITK_MATH_SVD_FIXED_DIMS(F)
Definition itkMathSVD.h:514
Cholesky-based linear algebra for symmetric matrices, backed by Eigen.
void DynamicSquareSVDEigen(const TReal *inData, unsigned int n, TReal *uData, TReal *wData, TReal *vData)
Definition itkMathSVD.h:400
void RectangularSVDEigen(const TReal *inData, unsigned int rows, unsigned int cols, TReal *uData, TReal *wData, TReal *vData)
Definition itkMathSVD.h:475
template void RectangularSVDEigen< double >(const double *, unsigned int, unsigned int, double *, double *, double *)
TReal ResolveRcond(TReal rcond, unsigned int n)
Definition itkMathSVD.h:50
auto PseudoInverse(const TMatrixU &U, const TVector &W, const TMatrixV &V, TReal rcond)
Definition itkMathSVD.h:59
auto RecomposeWith(const TMatrixU &U, const TVector &modifiedW, const TMatrixV &V)
Definition itkMathSVD.h:132
auto WellCondition(const TVector &W) -> std::decay_t< decltype(W[0])>
Definition itkMathSVD.h:148
auto DeterminantMagnitude(const TVector &W) -> std::decay_t< decltype(W[0])>
Definition itkMathSVD.h:161
template void DynamicSquareSVDEigen< double >(const double *, unsigned int, double *, double *, double *)
constexpr unsigned int kFixedSVDMaxDim
Definition itkMathSVD.h:390
constexpr unsigned int kJacobiMaxDim
Definition itkMathSVD.h:394
template void RectangularSVDEigen< float >(const float *, unsigned int, unsigned int, float *, float *, float *)
auto Recompose(const TMatrixU &U, const TVector &W, const TMatrixV &V, TReal rcond)
Definition itkMathSVD.h:112
void SquareSVDEigen(const TReal *inData, TReal *uData, TReal *wData, TReal *vData)
Definition itkMathSVD.h:437
unsigned int NumericalRank(const TVector &W, TReal rcond)
Definition itkMathSVD.h:93
template void DynamicSquareSVDEigen< float >(const float *, unsigned int, float *, float *, float *)
auto SolveLinear(const TMatrixU &U, const TVector &W, const TMatrixV &V, const TVectorB &b, TReal rcond)
Definition itkMathSVD.h:79
void CanonicalizeColumnSignsPaired(TMatrixU &u, TMatrixV &paired)
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
vnl_vector_fixed< TReal, K > W
Definition itkMathSVD.h:323
vnl_matrix_fixed< TReal, VCols, VRows > PseudoInverse(TReal rcond=TReal{ -1 }) const
Definition itkMathSVD.h:328
vnl_matrix_fixed< TReal, VRows, K > U
Definition itkMathSVD.h:322
vnl_matrix_fixed< TReal, VCols, K > V
Definition itkMathSVD.h:324
vnl_matrix_fixed< TReal, VRows, VCols > Recompose(TReal rcond=TReal{ -1 }) const
Definition itkMathSVD.h:349
vnl_matrix_fixed< TReal, VRows, VCols > RecomposeWith(const vnl_vector_fixed< TReal, K > &modifiedW) const
Definition itkMathSVD.h:356
unsigned int Rank(TReal rcond=TReal{ -1 }) const
Definition itkMathSVD.h:342
vnl_vector_fixed< TReal, VCols > NullVector() const
Definition itkMathSVD.h:365
static constexpr unsigned int K
Definition itkMathSVD.h:320
vnl_vector_fixed< TReal, VCols > Solve(const vnl_vector_fixed< TReal, VRows > &b, TReal rcond=TReal{ -1 }) const
Definition itkMathSVD.h:335
vnl_matrix_fixed< TReal, VDim, VDim > PseudoInverse(TReal rcond=TReal{ -1 }) const
Definition itkMathSVD.h:183
vnl_vector_fixed< TReal, VDim > Solve(const vnl_vector_fixed< TReal, VDim > &b, TReal rcond=TReal{ -1 }) const
Definition itkMathSVD.h:190
vnl_matrix_fixed< TReal, VDim, VDim > Recompose(TReal rcond=TReal{ -1 }) const
Definition itkMathSVD.h:204
vnl_vector_fixed< TReal, VDim > NullVector() const
Definition itkMathSVD.h:219
vnl_vector_fixed< TReal, VDim > W
Definition itkMathSVD.h:178
vnl_matrix_fixed< TReal, VDim, VDim > U
Definition itkMathSVD.h:177
vnl_matrix_fixed< TReal, VDim, VDim > V
Definition itkMathSVD.h:179
unsigned int Rank(TReal rcond=TReal{ -1 }) const
Definition itkMathSVD.h:197
vnl_matrix_fixed< TReal, VDim, VDim > RecomposeWith(const vnl_vector_fixed< TReal, VDim > &modifiedW) const
Definition itkMathSVD.h:211
vnl_matrix< TReal > Recompose(TReal rcond=TReal{ -1 }) const
Definition itkMathSVD.h:272
TReal WellCondition() const
Definition itkMathSVD.h:301
vnl_matrix< TReal > PseudoInverse(TReal rcond=TReal{ -1 }) const
Definition itkMathSVD.h:251
vnl_matrix< TReal > V
Definition itkMathSVD.h:247
unsigned int Rank(TReal rcond=TReal{ -1 }) const
Definition itkMathSVD.h:265
TReal DeterminantMagnitude() const
Definition itkMathSVD.h:308
vnl_vector< TReal > NullVector() const
Definition itkMathSVD.h:289
vnl_vector< TReal > W
Definition itkMathSVD.h:246
vnl_matrix< TReal > U
Definition itkMathSVD.h:245
vnl_matrix< TReal > RecomposeWith(const vnl_vector< TReal > &modifiedW) const
Definition itkMathSVD.h:279
vnl_vector< TReal > Solve(const vnl_vector< TReal > &b, TReal rcond=TReal{ -1 }) const
Definition itkMathSVD.h:258