Eigen  5.0.1
 
Loading...
Searching...
No Matches
AccelerateSupport.h
1// SPDX-FileCopyrightText: The Eigen Authors
2// SPDX-License-Identifier: MPL-2.0
3
4#ifndef EIGEN_ACCELERATESUPPORT_H
5#define EIGEN_ACCELERATESUPPORT_H
6
7#include <Accelerate/Accelerate.h>
8
9#include <Eigen/Sparse>
10
11namespace Eigen {
12
13template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool EnforceSquare_>
14class AccelerateImpl;
15
27template <typename MatrixType, int UpLo = Lower>
28using AccelerateLLT = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationCholesky, true>;
29
41template <typename MatrixType, int UpLo = Lower>
42using AccelerateLDLT = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationLDLT, true>;
43
55template <typename MatrixType, int UpLo = Lower>
56using AccelerateLDLTUnpivoted = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationLDLTUnpivoted, true>;
57
70template <typename MatrixType, int UpLo = Lower>
71using AccelerateLDLTSBK = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationLDLTSBK, true>;
72
84template <typename MatrixType, int UpLo = Lower>
85using AccelerateLDLTTPP = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationLDLTTPP, true>;
86
97template <typename MatrixType>
98using AccelerateQR = AccelerateImpl<MatrixType, 0, SparseFactorizationQR, false>;
99
110template <typename MatrixType>
111using AccelerateCholeskyAtA = AccelerateImpl<MatrixType, 0, SparseFactorizationCholeskyAtA, false>;
112
113namespace internal {
114template <typename T>
115struct AccelFactorizationDeleter {
116 void operator()(T* sym) const {
117 if (sym) {
118 SparseCleanup(*sym);
119 delete sym;
120 sym = nullptr;
121 }
122 }
123};
124
125template <typename DenseVecT, typename DenseMatT, typename SparseMatT, typename NumFactT>
126struct SparseTypesTraitBase {
127 typedef DenseVecT AccelDenseVector;
128 typedef DenseMatT AccelDenseMatrix;
129 typedef SparseMatT AccelSparseMatrix;
130
131 typedef SparseOpaqueSymbolicFactorization SymbolicFactorization;
132 typedef NumFactT NumericFactorization;
133
134 typedef AccelFactorizationDeleter<SymbolicFactorization> SymbolicFactorizationDeleter;
135 typedef AccelFactorizationDeleter<NumericFactorization> NumericFactorizationDeleter;
136};
137
138template <typename Scalar>
139struct SparseTypesTrait {};
140
141template <>
142struct SparseTypesTrait<double> : SparseTypesTraitBase<DenseVector_Double, DenseMatrix_Double, SparseMatrix_Double,
143 SparseOpaqueFactorization_Double> {};
144
145template <>
146struct SparseTypesTrait<float>
147 : SparseTypesTraitBase<DenseVector_Float, DenseMatrix_Float, SparseMatrix_Float, SparseOpaqueFactorization_Float> {
148};
149
150} // end namespace internal
151
152template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool EnforceSquare_>
153class AccelerateImpl : public SparseSolverBase<AccelerateImpl<MatrixType_, UpLo_, Solver_, EnforceSquare_> > {
154 protected:
155 using Base = SparseSolverBase<AccelerateImpl>;
156 using Base::derived;
157 using Base::m_isInitialized;
158
159 public:
160 using Base::_solve_impl;
161
162 typedef MatrixType_ MatrixType;
163 typedef typename MatrixType::Scalar Scalar;
164 typedef typename MatrixType::StorageIndex StorageIndex;
165 enum { ColsAtCompileTime = Dynamic, MaxColsAtCompileTime = Dynamic };
166 enum { UpLo = UpLo_ };
167
168 using AccelDenseVector = typename internal::SparseTypesTrait<Scalar>::AccelDenseVector;
169 using AccelDenseMatrix = typename internal::SparseTypesTrait<Scalar>::AccelDenseMatrix;
170 using AccelSparseMatrix = typename internal::SparseTypesTrait<Scalar>::AccelSparseMatrix;
171 using SymbolicFactorization = typename internal::SparseTypesTrait<Scalar>::SymbolicFactorization;
172 using NumericFactorization = typename internal::SparseTypesTrait<Scalar>::NumericFactorization;
173 using SymbolicFactorizationDeleter = typename internal::SparseTypesTrait<Scalar>::SymbolicFactorizationDeleter;
174 using NumericFactorizationDeleter = typename internal::SparseTypesTrait<Scalar>::NumericFactorizationDeleter;
175
176 AccelerateImpl() {
177 m_isInitialized = false;
178
179 EIGEN_IF_CONSTEXPR ((UpLo_ & Symmetric) == Symmetric) {
180 m_sparseKind = SparseSymmetric;
181 m_triType = (UpLo_ & Lower) ? SparseLowerTriangle : SparseUpperTriangle;
182 } else EIGEN_IF_CONSTEXPR ((UpLo_ & UnitLower) == UnitLower) {
183 m_sparseKind = SparseUnitTriangular;
184 m_triType = SparseLowerTriangle;
185 } else EIGEN_IF_CONSTEXPR ((UpLo_ & UnitUpper) == UnitUpper) {
186 m_sparseKind = SparseUnitTriangular;
187 m_triType = SparseUpperTriangle;
188 } else EIGEN_IF_CONSTEXPR ((UpLo_ & StrictlyLower) == StrictlyLower) {
189 m_sparseKind = SparseTriangular;
190 m_triType = SparseLowerTriangle;
191 } else EIGEN_IF_CONSTEXPR ((UpLo_ & StrictlyUpper) == StrictlyUpper) {
192 m_sparseKind = SparseTriangular;
193 m_triType = SparseUpperTriangle;
194 } else EIGEN_IF_CONSTEXPR ((UpLo_ & Lower) == Lower) {
195 m_sparseKind = SparseTriangular;
196 m_triType = SparseLowerTriangle;
197 } else EIGEN_IF_CONSTEXPR ((UpLo_ & Upper) == Upper) {
198 m_sparseKind = SparseTriangular;
199 m_triType = SparseUpperTriangle;
200 } else {
201 m_sparseKind = SparseOrdinary;
202 m_triType = (UpLo_ & Lower) ? SparseLowerTriangle : SparseUpperTriangle;
203 }
204
205 m_order = SparseOrderDefault;
206 }
207
208 explicit AccelerateImpl(const MatrixType& matrix) : AccelerateImpl() { compute(matrix); }
209
210 inline Index cols() const { return m_nCols; }
211 inline Index rows() const { return m_nRows; }
212
213 ComputationInfo info() const {
214 eigen_assert(m_isInitialized && "Decomposition is not initialized.");
215 return m_info;
216 }
217
218 void analyzePattern(const MatrixType& matrix);
219
220 void factorize(const MatrixType& matrix);
221
222 void compute(const MatrixType& matrix);
223
224 template <typename Rhs, typename Dest>
225 void _solve_impl(const MatrixBase<Rhs>& b, MatrixBase<Dest>& dest) const;
226
228 void setOrder(SparseOrder_t order) { m_order = order; }
229
230 private:
231 template <typename T>
232 void buildAccelSparseMatrix(const SparseMatrix<T>& a, AccelSparseMatrix& A, std::vector<long>& columnStarts) {
233 const Index nColumnsStarts = a.cols() + 1;
234
235 columnStarts.resize(nColumnsStarts);
236
237 for (Index i = 0; i < nColumnsStarts; i++) columnStarts[i] = a.outerIndexPtr()[i];
238
239 SparseAttributes_t attributes{};
240 attributes.transpose = false;
241 attributes.triangle = m_triType;
242 attributes.kind = m_sparseKind;
243
244 SparseMatrixStructure structure{};
245 structure.attributes = attributes;
246 structure.rowCount = static_cast<int>(a.rows());
247 structure.columnCount = static_cast<int>(a.cols());
248 structure.blockSize = 1;
249 structure.columnStarts = columnStarts.data();
250 structure.rowIndices = const_cast<int*>(a.innerIndexPtr());
251
252 A.structure = structure;
253 A.data = const_cast<T*>(a.valuePtr());
254 }
255
256 void doAnalysis(AccelSparseMatrix& A) {
257 m_numericFactorization.reset();
258
259 SparseSymbolicFactorOptions opts{};
260 opts.control = SparseDefaultControl;
261 opts.orderMethod = m_order;
262 opts.order = nullptr;
263 opts.ignoreRowsAndColumns = nullptr;
264 opts.malloc = malloc;
265 opts.free = free;
266 opts.reportError = nullptr;
267
268 m_symbolicFactorization.reset(new SymbolicFactorization(SparseFactor(Solver_, A.structure, opts)));
269
270 SparseStatus_t status = m_symbolicFactorization->status;
271
272 updateInfoStatus(status);
273
274 if (status != SparseStatusOK) m_symbolicFactorization.reset();
275 }
276
277 void doFactorization(AccelSparseMatrix& A) {
278 SparseStatus_t status = SparseStatusReleased;
279
280 if (m_symbolicFactorization) {
281 m_numericFactorization.reset(new NumericFactorization(SparseFactor(*m_symbolicFactorization, A)));
282
283 status = m_numericFactorization->status;
284
285 if (status != SparseStatusOK) m_numericFactorization.reset();
286 }
287
288 updateInfoStatus(status);
289 }
290
291 protected:
292 void updateInfoStatus(SparseStatus_t status) const {
293 switch (status) {
294 case SparseStatusOK:
295 m_info = Success;
296 break;
297 case SparseFactorizationFailed:
298 case SparseMatrixIsSingular:
299 m_info = NumericalIssue;
300 break;
301 case SparseInternalError:
302 case SparseParameterError:
303 case SparseStatusReleased:
304 default:
305 m_info = InvalidInput;
306 break;
307 }
308 }
309
310 mutable ComputationInfo m_info;
311 Index m_nRows, m_nCols;
312 std::unique_ptr<SymbolicFactorization, SymbolicFactorizationDeleter> m_symbolicFactorization;
313 std::unique_ptr<NumericFactorization, NumericFactorizationDeleter> m_numericFactorization;
314 SparseKind_t m_sparseKind;
315 SparseTriangle_t m_triType;
316 SparseOrder_t m_order;
317};
318
320template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool EnforceSquare_>
321void AccelerateImpl<MatrixType_, UpLo_, Solver_, EnforceSquare_>::compute(const MatrixType& a) {
322 EIGEN_IF_CONSTEXPR (EnforceSquare_) eigen_assert(a.rows() == a.cols());
323
324 m_nRows = a.rows();
325 m_nCols = a.cols();
326
327 AccelSparseMatrix A{};
328 std::vector<long> columnStarts;
329
330 buildAccelSparseMatrix(a, A, columnStarts);
331
332 doAnalysis(A);
333
334 if (m_symbolicFactorization) doFactorization(A);
335
336 m_isInitialized = true;
337}
338
345template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool EnforceSquare_>
346void AccelerateImpl<MatrixType_, UpLo_, Solver_, EnforceSquare_>::analyzePattern(const MatrixType& a) {
347 EIGEN_IF_CONSTEXPR (EnforceSquare_) eigen_assert(a.rows() == a.cols());
348
349 m_nRows = a.rows();
350 m_nCols = a.cols();
351
352 AccelSparseMatrix A{};
353 std::vector<long> columnStarts;
354
355 buildAccelSparseMatrix(a, A, columnStarts);
356
357 doAnalysis(A);
358
359 m_isInitialized = true;
360}
361
369template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool EnforceSquare_>
370void AccelerateImpl<MatrixType_, UpLo_, Solver_, EnforceSquare_>::factorize(const MatrixType& a) {
371 eigen_assert(m_symbolicFactorization && "You must first call analyzePattern()");
372 eigen_assert(m_nRows == a.rows() && m_nCols == a.cols());
373
374 EIGEN_IF_CONSTEXPR (EnforceSquare_) eigen_assert(a.rows() == a.cols());
375
376 AccelSparseMatrix A{};
377 std::vector<long> columnStarts;
378
379 buildAccelSparseMatrix(a, A, columnStarts);
380
381 doFactorization(A);
382}
383
384template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool EnforceSquare_>
385template <typename Rhs, typename Dest>
386void AccelerateImpl<MatrixType_, UpLo_, Solver_, EnforceSquare_>::_solve_impl(const MatrixBase<Rhs>& b,
387 MatrixBase<Dest>& x) const {
388 if (!m_numericFactorization) {
389 m_info = InvalidInput;
390 return;
391 }
392
393 eigen_assert(m_nRows == b.rows());
394 eigen_assert(((b.cols() == 1) || b.outerStride() == b.rows()));
395
396 SparseStatus_t status = SparseStatusOK;
397
398 Scalar* b_ptr = const_cast<Scalar*>(b.derived().data());
399 Scalar* x_ptr = const_cast<Scalar*>(x.derived().data());
400
401 AccelDenseMatrix xmat{};
402 xmat.attributes = SparseAttributes_t();
403 xmat.columnCount = static_cast<int>(x.cols());
404 xmat.rowCount = static_cast<int>(x.rows());
405 xmat.columnStride = xmat.rowCount;
406 xmat.data = x_ptr;
407
408 AccelDenseMatrix bmat{};
409 bmat.attributes = SparseAttributes_t();
410 bmat.columnCount = static_cast<int>(b.cols());
411 bmat.rowCount = static_cast<int>(b.rows());
412 bmat.columnStride = bmat.rowCount;
413 bmat.data = b_ptr;
414
415 SparseSolve(*m_numericFactorization, bmat, xmat);
416
417 updateInfoStatus(status);
418}
419
420} // end namespace Eigen
421
422#endif // EIGEN_ACCELERATESUPPORT_H
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
AccelerateImpl< MatrixType, UpLo|Symmetric, SparseFactorizationCholesky, true > AccelerateLLT
A direct Cholesky (LLT) factorization and solver based on Accelerate.
Definition AccelerateSupport.h:28
AccelerateImpl< MatrixType, UpLo|Symmetric, SparseFactorizationLDLTUnpivoted, true > AccelerateLDLTUnpivoted
A direct Cholesky-like LDL^T factorization and solver based on Accelerate with only 1x1 pivots and no...
Definition AccelerateSupport.h:56
AccelerateImpl< MatrixType, UpLo|Symmetric, SparseFactorizationLDLT, true > AccelerateLDLT
The default Cholesky (LDLT) factorization and solver based on Accelerate.
Definition AccelerateSupport.h:42
AccelerateImpl< MatrixType, UpLo|Symmetric, SparseFactorizationLDLTTPP, true > AccelerateLDLTTPP
A direct Cholesky (LDLT) factorization and solver based on Accelerate with full threshold partial piv...
Definition AccelerateSupport.h:85
AccelerateImpl< MatrixType, 0, SparseFactorizationCholeskyAtA, false > AccelerateCholeskyAtA
A QR factorization and solver based on Accelerate without storing Q (equivalent to A^TA = R^T R)
Definition AccelerateSupport.h:111
AccelerateImpl< MatrixType, UpLo|Symmetric, SparseFactorizationLDLTSBK, true > AccelerateLDLTSBK
A direct Cholesky (LDLT) factorization and solver based on Accelerate with Supernode Bunch-Kaufman an...
Definition AccelerateSupport.h:71
AccelerateImpl< MatrixType, 0, SparseFactorizationQR, false > AccelerateQR
A QR factorization and solver based on Accelerate.
Definition AccelerateSupport.h:98
ComputationInfo
Definition Constants.h:455
@ StrictlyLower
Definition Constants.h:224
@ StrictlyUpper
Definition Constants.h:226
@ UnitLower
Definition Constants.h:220
@ Symmetric
Definition Constants.h:230
@ UnitUpper
Definition Constants.h:222
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
@ NumericalIssue
Definition Constants.h:459
@ InvalidInput
Definition Constants.h:464
@ Success
Definition Constants.h:457