Eigen  5.0.1
 
Loading...
Searching...
No Matches
BDCSVD_LAPACKE.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2022 Melven Roehrig-Zoellner <Melven.Roehrig-Zoellner@DLR.de>
5// Copyright (c) 2011, Intel Corporation. All rights reserved.
6//
7// This file is based on the JacobiSVD_LAPACKE.h originally from Intel -
8// see license notice below:
9// SPDX-License-Identifier: BSD-3-Clause
10/*
11 Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13
14 * Redistributions of source code must retain the above copyright notice, this
15 list of conditions and the following disclaimer.
16 * Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 * Neither the name of Intel Corporation nor the names of its contributors may
20 be used to endorse or promote products derived from this software without
21 specific prior written permission.
22
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
27 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34 ********************************************************************************
35 * Content : Eigen bindings to LAPACKe
36 * Singular Value Decomposition - SVD (divide and conquer variant)
37 ********************************************************************************
38*/
39#ifndef EIGEN_BDCSVD_LAPACKE_H
40#define EIGEN_BDCSVD_LAPACKE_H
41
42namespace Eigen {
43
44namespace internal {
45
46namespace lapacke_helpers {
47
49
50// defining a derived class to allow access to protected members
51template <typename MatrixType_, int Options>
52class BDCSVD_LAPACKE : public BDCSVD<MatrixType_, Options> {
54 typedef typename SVD::MatrixType MatrixType;
55 typedef typename SVD::Scalar Scalar;
56 typedef typename SVD::RealScalar RealScalar;
57
58 public:
59 // construct this by moving from a parent object
60 BDCSVD_LAPACKE(SVD&& svd) : SVD(std::move(svd)) {}
61
62 template <typename Derived>
63 void compute_impl_lapacke(const MatrixBase<Derived>& matrix, unsigned int computationOptions) {
64 SVD::allocate(matrix.rows(), matrix.cols(), computationOptions);
65
66 SVD::m_nonzeroSingularValues = SVD::m_diagSize;
67
68 // prepare arguments to ?gesdd
69 const lapack_int matrix_order = lapack_storage_of(matrix);
70 const char jobz = (SVD::m_computeFullU || SVD::m_computeFullV) ? 'A'
71 : (SVD::m_computeThinU || SVD::m_computeThinV) ? 'S'
72 : 'N';
73 const lapack_int u_cols = (jobz == 'A') ? to_lapack(SVD::rows()) : (jobz == 'S') ? to_lapack(SVD::diagSize()) : 1;
74 const lapack_int vt_rows = (jobz == 'A') ? to_lapack(SVD::cols()) : (jobz == 'S') ? to_lapack(SVD::diagSize()) : 1;
75 lapack_int ldu, ldvt;
76 Scalar *u, *vt, dummy;
77 MatrixType localU;
78 if (SVD::computeU() && !(SVD::m_computeThinU && SVD::m_computeFullV)) {
79 ldu = to_lapack(SVD::m_matrixU.outerStride());
80 u = SVD::m_matrixU.data();
81 } else if (SVD::computeV()) {
82 localU.resize(SVD::rows(), u_cols);
83 ldu = to_lapack(localU.outerStride());
84 u = localU.data();
85 } else {
86 ldu = 1;
87 u = &dummy;
88 }
89 MatrixType localV;
90 if (SVD::computeU() || SVD::computeV()) {
91 localV.resize(vt_rows, SVD::cols());
92 ldvt = to_lapack(localV.outerStride());
93 vt = localV.data();
94 } else {
95 ldvt = 1;
96 vt = &dummy;
97 }
98 MatrixType temp;
99 temp = matrix;
100
101 // actual call to ?gesdd
102 lapack_int info = gesdd(matrix_order, jobz, to_lapack(SVD::rows()), to_lapack(SVD::cols()), to_lapack(temp.data()),
103 to_lapack(temp.outerStride()), (RealScalar*)SVD::m_singularValues.data(), to_lapack(u), ldu,
104 to_lapack(vt), ldvt);
105
106 // Check the result of the LAPACK call
107 if (info < 0 || !SVD::m_singularValues.allFinite()) {
108 // this includes info == -4 => NaN entry in A
109 SVD::m_info = InvalidInput;
110 } else if (info > 0) {
111 SVD::m_info = NoConvergence;
112 } else {
113 SVD::m_info = Success;
114 if (SVD::m_computeThinU && SVD::m_computeFullV) {
115 SVD::m_matrixU = localU.leftCols(SVD::m_matrixU.cols());
116 }
117 if (SVD::computeV()) {
118 SVD::m_matrixV = localV.adjoint().leftCols(SVD::m_matrixV.cols());
119 }
120 }
121 SVD::m_isInitialized = true;
122 }
123};
124
125template <typename MatrixType_, int Options, typename Derived>
126BDCSVD<MatrixType_, Options>& BDCSVD_wrapper(BDCSVD<MatrixType_, Options>& svd, const MatrixBase<Derived>& matrix,
127 int computationOptions) {
128 // we need to move to the wrapper type and back
129 BDCSVD_LAPACKE<MatrixType_, Options> tmpSvd(std::move(svd));
130 tmpSvd.compute_impl_lapacke(matrix, computationOptions);
131 svd = std::move(tmpSvd);
132 return svd;
133}
134
135} // end namespace lapacke_helpers
136
137} // end namespace internal
138
139#define EIGEN_LAPACKE_SDD(EIGTYPE, EIGCOLROW, OPTIONS) \
140 template <> \
141 template <typename Derived> \
142 inline BDCSVD<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>, OPTIONS>& \
143 BDCSVD<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>, OPTIONS>::compute_impl( \
144 const MatrixBase<Derived>& matrix, unsigned int computationOptions) { \
145 return internal::lapacke_helpers::BDCSVD_wrapper(*this, matrix, computationOptions); \
146 }
147
148#define EIGEN_LAPACK_SDD_OPTIONS(OPTIONS) \
149 EIGEN_LAPACKE_SDD(double, ColMajor, OPTIONS) \
150 EIGEN_LAPACKE_SDD(float, ColMajor, OPTIONS) \
151 EIGEN_LAPACKE_SDD(dcomplex, ColMajor, OPTIONS) \
152 EIGEN_LAPACKE_SDD(scomplex, ColMajor, OPTIONS) \
153 \
154 EIGEN_LAPACKE_SDD(double, RowMajor, OPTIONS) \
155 EIGEN_LAPACKE_SDD(float, RowMajor, OPTIONS) \
156 EIGEN_LAPACKE_SDD(dcomplex, RowMajor, OPTIONS) \
157 EIGEN_LAPACKE_SDD(scomplex, RowMajor, OPTIONS)
158
159EIGEN_LAPACK_SDD_OPTIONS(0)
160EIGEN_LAPACK_SDD_OPTIONS(ComputeThinU)
161EIGEN_LAPACK_SDD_OPTIONS(ComputeThinV)
162EIGEN_LAPACK_SDD_OPTIONS(ComputeFullU)
163EIGEN_LAPACK_SDD_OPTIONS(ComputeFullV)
164EIGEN_LAPACK_SDD_OPTIONS(ComputeThinU | ComputeThinV)
165EIGEN_LAPACK_SDD_OPTIONS(ComputeFullU | ComputeFullV)
166EIGEN_LAPACK_SDD_OPTIONS(ComputeThinU | ComputeFullV)
167EIGEN_LAPACK_SDD_OPTIONS(ComputeFullU | ComputeThinV)
168
169#undef EIGEN_LAPACK_SDD_OPTIONS
170
171#undef EIGEN_LAPACKE_SDD
172
173} // end namespace Eigen
174
175#endif // EIGEN_BDCSVD_LAPACKE_H
BDCSVD()
Definition BDCSVD.h:121
@ InvalidInput
Definition Constants.h:464
@ Success
Definition Constants.h:457
@ NoConvergence
Definition Constants.h:461
@ ComputeFullV
Definition Constants.h:398
@ ComputeThinV
Definition Constants.h:400
@ ComputeFullU
Definition Constants.h:394
@ ComputeThinU
Definition Constants.h:396