| #ifndef EIGEN_ACCELERATESUPPORT_H | 
 | #define EIGEN_ACCELERATESUPPORT_H | 
 |  | 
 | #include <Accelerate/Accelerate.h> | 
 |  | 
 | #include <Eigen/Sparse> | 
 |  | 
 | namespace Eigen { | 
 |  | 
 | template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool EnforceSquare_> | 
 | class AccelerateImpl; | 
 |  | 
 | /** \ingroup AccelerateSupport_Module | 
 |  * \class AccelerateLLT | 
 |  * \brief A direct Cholesky (LLT) factorization and solver based on Accelerate | 
 |  * | 
 |  * \warning Only single and double precision real scalar types are supported by Accelerate | 
 |  * | 
 |  * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> | 
 |  * \tparam UpLo_ additional information about the matrix structure. Default is Lower. | 
 |  * | 
 |  * \sa \ref TutorialSparseSolverConcept, class AccelerateLLT | 
 |  */ | 
 | template <typename MatrixType, int UpLo = Lower> | 
 | using AccelerateLLT = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationCholesky, true>; | 
 |  | 
 | /** \ingroup AccelerateSupport_Module | 
 |  * \class AccelerateLDLT | 
 |  * \brief The default Cholesky (LDLT) factorization and solver based on Accelerate | 
 |  * | 
 |  * \warning Only single and double precision real scalar types are supported by Accelerate | 
 |  * | 
 |  * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> | 
 |  * \tparam UpLo_ additional information about the matrix structure. Default is Lower. | 
 |  * | 
 |  * \sa \ref TutorialSparseSolverConcept, class AccelerateLDLT | 
 |  */ | 
 | template <typename MatrixType, int UpLo = Lower> | 
 | using AccelerateLDLT = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationLDLT, true>; | 
 |  | 
 | /** \ingroup AccelerateSupport_Module | 
 |  * \class AccelerateLDLTUnpivoted | 
 |  * \brief A direct Cholesky-like LDL^T factorization and solver based on Accelerate with only 1x1 pivots and no pivoting | 
 |  * | 
 |  * \warning Only single and double precision real scalar types are supported by Accelerate | 
 |  * | 
 |  * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> | 
 |  * \tparam UpLo_ additional information about the matrix structure. Default is Lower. | 
 |  * | 
 |  * \sa \ref TutorialSparseSolverConcept, class AccelerateLDLTUnpivoted | 
 |  */ | 
 | template <typename MatrixType, int UpLo = Lower> | 
 | using AccelerateLDLTUnpivoted = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationLDLTUnpivoted, true>; | 
 |  | 
 | /** \ingroup AccelerateSupport_Module | 
 |  * \class AccelerateLDLTSBK | 
 |  * \brief A direct Cholesky (LDLT) factorization and solver based on Accelerate with Supernode Bunch-Kaufman and static | 
 |  * pivoting | 
 |  * | 
 |  * \warning Only single and double precision real scalar types are supported by Accelerate | 
 |  * | 
 |  * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> | 
 |  * \tparam UpLo_ additional information about the matrix structure. Default is Lower. | 
 |  * | 
 |  * \sa \ref TutorialSparseSolverConcept, class AccelerateLDLTSBK | 
 |  */ | 
 | template <typename MatrixType, int UpLo = Lower> | 
 | using AccelerateLDLTSBK = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationLDLTSBK, true>; | 
 |  | 
 | /** \ingroup AccelerateSupport_Module | 
 |  * \class AccelerateLDLTTPP | 
 |  * \brief A direct Cholesky (LDLT) factorization and solver based on Accelerate with full threshold partial pivoting | 
 |  * | 
 |  * \warning Only single and double precision real scalar types are supported by Accelerate | 
 |  * | 
 |  * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> | 
 |  * \tparam UpLo_ additional information about the matrix structure. Default is Lower. | 
 |  * | 
 |  * \sa \ref TutorialSparseSolverConcept, class AccelerateLDLTTPP | 
 |  */ | 
 | template <typename MatrixType, int UpLo = Lower> | 
 | using AccelerateLDLTTPP = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationLDLTTPP, true>; | 
 |  | 
 | /** \ingroup AccelerateSupport_Module | 
 |  * \class AccelerateQR | 
 |  * \brief A QR factorization and solver based on Accelerate | 
 |  * | 
 |  * \warning Only single and double precision real scalar types are supported by Accelerate | 
 |  * | 
 |  * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> | 
 |  * | 
 |  * \sa \ref TutorialSparseSolverConcept, class AccelerateQR | 
 |  */ | 
 | template <typename MatrixType> | 
 | using AccelerateQR = AccelerateImpl<MatrixType, 0, SparseFactorizationQR, false>; | 
 |  | 
 | /** \ingroup AccelerateSupport_Module | 
 |  * \class AccelerateCholeskyAtA | 
 |  * \brief A QR factorization and solver based on Accelerate without storing Q (equivalent to A^TA = R^T R) | 
 |  * | 
 |  * \warning Only single and double precision real scalar types are supported by Accelerate | 
 |  * | 
 |  * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> | 
 |  * | 
 |  * \sa \ref TutorialSparseSolverConcept, class AccelerateCholeskyAtA | 
 |  */ | 
 | template <typename MatrixType> | 
 | using AccelerateCholeskyAtA = AccelerateImpl<MatrixType, 0, SparseFactorizationCholeskyAtA, false>; | 
 |  | 
 | namespace internal { | 
 | template <typename T> | 
 | struct AccelFactorizationDeleter { | 
 |   void operator()(T* sym) { | 
 |     if (sym) { | 
 |       SparseCleanup(*sym); | 
 |       delete sym; | 
 |       sym = nullptr; | 
 |     } | 
 |   } | 
 | }; | 
 |  | 
 | template <typename DenseVecT, typename DenseMatT, typename SparseMatT, typename NumFactT> | 
 | struct SparseTypesTraitBase { | 
 |   typedef DenseVecT AccelDenseVector; | 
 |   typedef DenseMatT AccelDenseMatrix; | 
 |   typedef SparseMatT AccelSparseMatrix; | 
 |  | 
 |   typedef SparseOpaqueSymbolicFactorization SymbolicFactorization; | 
 |   typedef NumFactT NumericFactorization; | 
 |  | 
 |   typedef AccelFactorizationDeleter<SymbolicFactorization> SymbolicFactorizationDeleter; | 
 |   typedef AccelFactorizationDeleter<NumericFactorization> NumericFactorizationDeleter; | 
 | }; | 
 |  | 
 | template <typename Scalar> | 
 | struct SparseTypesTrait {}; | 
 |  | 
 | template <> | 
 | struct SparseTypesTrait<double> : SparseTypesTraitBase<DenseVector_Double, DenseMatrix_Double, SparseMatrix_Double, | 
 |                                                        SparseOpaqueFactorization_Double> {}; | 
 |  | 
 | template <> | 
 | struct SparseTypesTrait<float> | 
 |     : SparseTypesTraitBase<DenseVector_Float, DenseMatrix_Float, SparseMatrix_Float, SparseOpaqueFactorization_Float> { | 
 | }; | 
 |  | 
 | }  // end namespace internal | 
 |  | 
 | template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool EnforceSquare_> | 
 | class AccelerateImpl : public SparseSolverBase<AccelerateImpl<MatrixType_, UpLo_, Solver_, EnforceSquare_> > { | 
 |  protected: | 
 |   using Base = SparseSolverBase<AccelerateImpl>; | 
 |   using Base::derived; | 
 |   using Base::m_isInitialized; | 
 |  | 
 |  public: | 
 |   using Base::_solve_impl; | 
 |  | 
 |   typedef MatrixType_ MatrixType; | 
 |   typedef typename MatrixType::Scalar Scalar; | 
 |   typedef typename MatrixType::StorageIndex StorageIndex; | 
 |   enum { ColsAtCompileTime = Dynamic, MaxColsAtCompileTime = Dynamic }; | 
 |   enum { UpLo = UpLo_ }; | 
 |  | 
 |   using AccelDenseVector = typename internal::SparseTypesTrait<Scalar>::AccelDenseVector; | 
 |   using AccelDenseMatrix = typename internal::SparseTypesTrait<Scalar>::AccelDenseMatrix; | 
 |   using AccelSparseMatrix = typename internal::SparseTypesTrait<Scalar>::AccelSparseMatrix; | 
 |   using SymbolicFactorization = typename internal::SparseTypesTrait<Scalar>::SymbolicFactorization; | 
 |   using NumericFactorization = typename internal::SparseTypesTrait<Scalar>::NumericFactorization; | 
 |   using SymbolicFactorizationDeleter = typename internal::SparseTypesTrait<Scalar>::SymbolicFactorizationDeleter; | 
 |   using NumericFactorizationDeleter = typename internal::SparseTypesTrait<Scalar>::NumericFactorizationDeleter; | 
 |  | 
 |   AccelerateImpl() { | 
 |     m_isInitialized = false; | 
 |  | 
 |     auto check_flag_set = [](int value, int flag) { return ((value & flag) == flag); }; | 
 |  | 
 |     if (check_flag_set(UpLo_, Symmetric)) { | 
 |       m_sparseKind = SparseSymmetric; | 
 |       m_triType = (UpLo_ & Lower) ? SparseLowerTriangle : SparseUpperTriangle; | 
 |     } else if (check_flag_set(UpLo_, UnitLower)) { | 
 |       m_sparseKind = SparseUnitTriangular; | 
 |       m_triType = SparseLowerTriangle; | 
 |     } else if (check_flag_set(UpLo_, UnitUpper)) { | 
 |       m_sparseKind = SparseUnitTriangular; | 
 |       m_triType = SparseUpperTriangle; | 
 |     } else if (check_flag_set(UpLo_, StrictlyLower)) { | 
 |       m_sparseKind = SparseTriangular; | 
 |       m_triType = SparseLowerTriangle; | 
 |     } else if (check_flag_set(UpLo_, StrictlyUpper)) { | 
 |       m_sparseKind = SparseTriangular; | 
 |       m_triType = SparseUpperTriangle; | 
 |     } else if (check_flag_set(UpLo_, Lower)) { | 
 |       m_sparseKind = SparseTriangular; | 
 |       m_triType = SparseLowerTriangle; | 
 |     } else if (check_flag_set(UpLo_, Upper)) { | 
 |       m_sparseKind = SparseTriangular; | 
 |       m_triType = SparseUpperTriangle; | 
 |     } else { | 
 |       m_sparseKind = SparseOrdinary; | 
 |       m_triType = (UpLo_ & Lower) ? SparseLowerTriangle : SparseUpperTriangle; | 
 |     } | 
 |  | 
 |     m_order = SparseOrderDefault; | 
 |   } | 
 |  | 
 |   explicit AccelerateImpl(const MatrixType& matrix) : AccelerateImpl() { compute(matrix); } | 
 |  | 
 |   ~AccelerateImpl() {} | 
 |  | 
 |   inline Index cols() const { return m_nCols; } | 
 |   inline Index rows() const { return m_nRows; } | 
 |  | 
 |   ComputationInfo info() const { | 
 |     eigen_assert(m_isInitialized && "Decomposition is not initialized."); | 
 |     return m_info; | 
 |   } | 
 |  | 
 |   void analyzePattern(const MatrixType& matrix); | 
 |  | 
 |   void factorize(const MatrixType& matrix); | 
 |  | 
 |   void compute(const MatrixType& matrix); | 
 |  | 
 |   template <typename Rhs, typename Dest> | 
 |   void _solve_impl(const MatrixBase<Rhs>& b, MatrixBase<Dest>& dest) const; | 
 |  | 
 |   /** Sets the ordering algorithm to use. */ | 
 |   void setOrder(SparseOrder_t order) { m_order = order; } | 
 |  | 
 |  private: | 
 |   template <typename T> | 
 |   void buildAccelSparseMatrix(const SparseMatrix<T>& a, AccelSparseMatrix& A, std::vector<long>& columnStarts) { | 
 |     const Index nColumnsStarts = a.cols() + 1; | 
 |  | 
 |     columnStarts.resize(nColumnsStarts); | 
 |  | 
 |     for (Index i = 0; i < nColumnsStarts; i++) columnStarts[i] = a.outerIndexPtr()[i]; | 
 |  | 
 |     SparseAttributes_t attributes{}; | 
 |     attributes.transpose = false; | 
 |     attributes.triangle = m_triType; | 
 |     attributes.kind = m_sparseKind; | 
 |  | 
 |     SparseMatrixStructure structure{}; | 
 |     structure.attributes = attributes; | 
 |     structure.rowCount = static_cast<int>(a.rows()); | 
 |     structure.columnCount = static_cast<int>(a.cols()); | 
 |     structure.blockSize = 1; | 
 |     structure.columnStarts = columnStarts.data(); | 
 |     structure.rowIndices = const_cast<int*>(a.innerIndexPtr()); | 
 |  | 
 |     A.structure = structure; | 
 |     A.data = const_cast<T*>(a.valuePtr()); | 
 |   } | 
 |  | 
 |   void doAnalysis(AccelSparseMatrix& A) { | 
 |     m_numericFactorization.reset(nullptr); | 
 |  | 
 |     SparseSymbolicFactorOptions opts{}; | 
 |     opts.control = SparseDefaultControl; | 
 |     opts.orderMethod = m_order; | 
 |     opts.order = nullptr; | 
 |     opts.ignoreRowsAndColumns = nullptr; | 
 |     opts.malloc = malloc; | 
 |     opts.free = free; | 
 |     opts.reportError = nullptr; | 
 |  | 
 |     m_symbolicFactorization.reset(new SymbolicFactorization(SparseFactor(Solver_, A.structure, opts))); | 
 |  | 
 |     SparseStatus_t status = m_symbolicFactorization->status; | 
 |  | 
 |     updateInfoStatus(status); | 
 |  | 
 |     if (status != SparseStatusOK) m_symbolicFactorization.reset(nullptr); | 
 |   } | 
 |  | 
 |   void doFactorization(AccelSparseMatrix& A) { | 
 |     SparseStatus_t status = SparseStatusReleased; | 
 |  | 
 |     if (m_symbolicFactorization) { | 
 |       m_numericFactorization.reset(new NumericFactorization(SparseFactor(*m_symbolicFactorization, A))); | 
 |  | 
 |       status = m_numericFactorization->status; | 
 |  | 
 |       if (status != SparseStatusOK) m_numericFactorization.reset(nullptr); | 
 |     } | 
 |  | 
 |     updateInfoStatus(status); | 
 |   } | 
 |  | 
 |  protected: | 
 |   void updateInfoStatus(SparseStatus_t status) const { | 
 |     switch (status) { | 
 |       case SparseStatusOK: | 
 |         m_info = Success; | 
 |         break; | 
 |       case SparseFactorizationFailed: | 
 |       case SparseMatrixIsSingular: | 
 |         m_info = NumericalIssue; | 
 |         break; | 
 |       case SparseInternalError: | 
 |       case SparseParameterError: | 
 |       case SparseStatusReleased: | 
 |       default: | 
 |         m_info = InvalidInput; | 
 |         break; | 
 |     } | 
 |   } | 
 |  | 
 |   mutable ComputationInfo m_info; | 
 |   Index m_nRows, m_nCols; | 
 |   std::unique_ptr<SymbolicFactorization, SymbolicFactorizationDeleter> m_symbolicFactorization; | 
 |   std::unique_ptr<NumericFactorization, NumericFactorizationDeleter> m_numericFactorization; | 
 |   SparseKind_t m_sparseKind; | 
 |   SparseTriangle_t m_triType; | 
 |   SparseOrder_t m_order; | 
 | }; | 
 |  | 
 | /** Computes the symbolic and numeric decomposition of matrix \a a */ | 
 | template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool EnforceSquare_> | 
 | void AccelerateImpl<MatrixType_, UpLo_, Solver_, EnforceSquare_>::compute(const MatrixType& a) { | 
 |   if (EnforceSquare_) eigen_assert(a.rows() == a.cols()); | 
 |  | 
 |   m_nRows = a.rows(); | 
 |   m_nCols = a.cols(); | 
 |  | 
 |   AccelSparseMatrix A{}; | 
 |   std::vector<long> columnStarts; | 
 |  | 
 |   buildAccelSparseMatrix(a, A, columnStarts); | 
 |  | 
 |   doAnalysis(A); | 
 |  | 
 |   if (m_symbolicFactorization) doFactorization(A); | 
 |  | 
 |   m_isInitialized = true; | 
 | } | 
 |  | 
 | /** Performs a symbolic decomposition on the sparsity pattern of matrix \a a. | 
 |  * | 
 |  * This function is particularly useful when solving for several problems having the same structure. | 
 |  * | 
 |  * \sa factorize() | 
 |  */ | 
 | template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool EnforceSquare_> | 
 | void AccelerateImpl<MatrixType_, UpLo_, Solver_, EnforceSquare_>::analyzePattern(const MatrixType& a) { | 
 |   if (EnforceSquare_) eigen_assert(a.rows() == a.cols()); | 
 |  | 
 |   m_nRows = a.rows(); | 
 |   m_nCols = a.cols(); | 
 |  | 
 |   AccelSparseMatrix A{}; | 
 |   std::vector<long> columnStarts; | 
 |  | 
 |   buildAccelSparseMatrix(a, A, columnStarts); | 
 |  | 
 |   doAnalysis(A); | 
 |  | 
 |   m_isInitialized = true; | 
 | } | 
 |  | 
 | /** Performs a numeric decomposition of matrix \a a. | 
 |  * | 
 |  * The given matrix must have the same sparsity pattern as the matrix on which the symbolic decomposition has been | 
 |  * performed. | 
 |  * | 
 |  * \sa analyzePattern() | 
 |  */ | 
 | template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool EnforceSquare_> | 
 | void AccelerateImpl<MatrixType_, UpLo_, Solver_, EnforceSquare_>::factorize(const MatrixType& a) { | 
 |   eigen_assert(m_symbolicFactorization && "You must first call analyzePattern()"); | 
 |   eigen_assert(m_nRows == a.rows() && m_nCols == a.cols()); | 
 |  | 
 |   if (EnforceSquare_) eigen_assert(a.rows() == a.cols()); | 
 |  | 
 |   AccelSparseMatrix A{}; | 
 |   std::vector<long> columnStarts; | 
 |  | 
 |   buildAccelSparseMatrix(a, A, columnStarts); | 
 |  | 
 |   doFactorization(A); | 
 | } | 
 |  | 
 | template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool EnforceSquare_> | 
 | template <typename Rhs, typename Dest> | 
 | void AccelerateImpl<MatrixType_, UpLo_, Solver_, EnforceSquare_>::_solve_impl(const MatrixBase<Rhs>& b, | 
 |                                                                               MatrixBase<Dest>& x) const { | 
 |   if (!m_numericFactorization) { | 
 |     m_info = InvalidInput; | 
 |     return; | 
 |   } | 
 |  | 
 |   eigen_assert(m_nRows == b.rows()); | 
 |   eigen_assert(((b.cols() == 1) || b.outerStride() == b.rows())); | 
 |  | 
 |   SparseStatus_t status = SparseStatusOK; | 
 |  | 
 |   Scalar* b_ptr = const_cast<Scalar*>(b.derived().data()); | 
 |   Scalar* x_ptr = const_cast<Scalar*>(x.derived().data()); | 
 |  | 
 |   AccelDenseMatrix xmat{}; | 
 |   xmat.attributes = SparseAttributes_t(); | 
 |   xmat.columnCount = static_cast<int>(x.cols()); | 
 |   xmat.rowCount = static_cast<int>(x.rows()); | 
 |   xmat.columnStride = xmat.rowCount; | 
 |   xmat.data = x_ptr; | 
 |  | 
 |   AccelDenseMatrix bmat{}; | 
 |   bmat.attributes = SparseAttributes_t(); | 
 |   bmat.columnCount = static_cast<int>(b.cols()); | 
 |   bmat.rowCount = static_cast<int>(b.rows()); | 
 |   bmat.columnStride = bmat.rowCount; | 
 |   bmat.data = b_ptr; | 
 |  | 
 |   SparseSolve(*m_numericFactorization, bmat, xmat); | 
 |  | 
 |   updateInfoStatus(status); | 
 | } | 
 |  | 
 | }  // end namespace Eigen | 
 |  | 
 | #endif  // EIGEN_ACCELERATESUPPORT_H |