Mercurial > octave
view liboctave/numeric/sparse-lu.cc @ 21202:f7121e111991
maint: indent #ifdef blocks in liboctave and src directories.
* Array-C.cc, Array-b.cc, Array-ch.cc, Array-d.cc, Array-f.cc, Array-fC.cc,
Array-i.cc, Array-idx-vec.cc, Array-s.cc, Array-str.cc, Array-util.cc,
Array-voidp.cc, Array.cc, CColVector.cc, CDiagMatrix.cc, CMatrix.cc,
CNDArray.cc, CRowVector.cc, CSparse.cc, CSparse.h, DiagArray2.cc, MArray-C.cc,
MArray-d.cc, MArray-f.cc, MArray-fC.cc, MArray-i.cc, MArray-s.cc, MArray.cc,
MDiagArray2.cc, MSparse-C.cc, MSparse-d.cc, MSparse.h, MatrixType.cc,
PermMatrix.cc, Range.cc, Sparse-C.cc, Sparse-b.cc, Sparse-d.cc, Sparse.cc,
boolMatrix.cc, boolNDArray.cc, boolSparse.cc, chMatrix.cc, chNDArray.cc,
dColVector.cc, dDiagMatrix.cc, dMatrix.cc, dNDArray.cc, dRowVector.cc,
dSparse.cc, dSparse.h, dim-vector.cc, fCColVector.cc, fCDiagMatrix.cc,
fCMatrix.cc, fCNDArray.cc, fCRowVector.cc, fColVector.cc, fDiagMatrix.cc,
fMatrix.cc, fNDArray.cc, fRowVector.cc, idx-vector.cc, int16NDArray.cc,
int32NDArray.cc, int64NDArray.cc, int8NDArray.cc, intNDArray.cc,
uint16NDArray.cc, uint32NDArray.cc, uint64NDArray.cc, uint8NDArray.cc,
blaswrap.c, cquit.c, f77-extern.cc, f77-fcn.c, f77-fcn.h, lo-error.c, quit.cc,
quit.h, CmplxAEPBAL.cc, CmplxCHOL.cc, CmplxGEPBAL.cc, CmplxHESS.cc, CmplxLU.cc,
CmplxQR.cc, CmplxQRP.cc, CmplxSCHUR.cc, CmplxSVD.cc, CollocWt.cc, DASPK.cc,
DASRT.cc, DASSL.cc, EIG.cc, LSODE.cc, ODES.cc, Quad.cc, base-lu.cc, base-qr.cc,
dbleAEPBAL.cc, dbleCHOL.cc, dbleGEPBAL.cc, dbleHESS.cc, dbleLU.cc, dbleQR.cc,
dbleQRP.cc, dbleSCHUR.cc, dbleSVD.cc, eigs-base.cc, fCmplxAEPBAL.cc,
fCmplxCHOL.cc, fCmplxGEPBAL.cc, fCmplxHESS.cc, fCmplxLU.cc, fCmplxQR.cc,
fCmplxQRP.cc, fCmplxSCHUR.cc, fCmplxSVD.cc, fEIG.cc, floatAEPBAL.cc,
floatCHOL.cc, floatGEPBAL.cc, floatHESS.cc, floatLU.cc, floatQR.cc,
floatQRP.cc, floatSCHUR.cc, floatSVD.cc, lo-mappers.cc, lo-specfun.cc,
oct-convn.cc, oct-fftw.cc, oct-fftw.h, oct-norm.cc, oct-rand.cc,
oct-spparms.cc, randgamma.c, randmtzig.c, randpoisson.c, sparse-chol.cc,
sparse-dmsolve.cc, sparse-lu.cc, sparse-qr.cc, mx-defs.h, dir-ops.cc,
file-ops.cc, file-stat.cc, lo-sysdep.cc, mach-info.cc, oct-env.cc,
oct-group.cc, oct-openmp.h, oct-passwd.cc, oct-syscalls.cc, oct-time.cc,
oct-uname.cc, pathlen.h, sysdir.h, syswait.h, cmd-edit.cc, cmd-hist.cc,
data-conv.cc, f2c-main.c, glob-match.cc, lo-array-errwarn.cc,
lo-array-gripes.cc, lo-cutils.c, lo-cutils.h, lo-ieee.cc, lo-math.h,
lo-regexp.cc, lo-utils.cc, oct-base64.cc, oct-glob.cc, oct-inttypes.cc,
oct-inttypes.h, oct-locbuf.cc, oct-mutex.cc, oct-refcount.h, oct-rl-edit.c,
oct-rl-hist.c, oct-shlib.cc, oct-sort.cc, pathsearch.cc, singleton-cleanup.cc,
sparse-sort.cc, sparse-util.cc, statdefs.h, str-vec.cc, unwind-prot.cc,
url-transfer.cc, display-available.h, main-cli.cc, main-gui.cc, main.in.cc,
mkoctfile.in.cc, octave-config.in.cc, shared-fcns.h:
indent #ifdef blocks in liboctave and src directories.
author | Rik <rik@octave.org> |
---|---|
date | Sat, 06 Feb 2016 06:40:13 -0800 |
parents | 7f35125714b4 |
children | 945695cafd2b |
line wrap: on
line source
/* Copyright (C) 2016 John W. Eaton Copyright (C) 2004-2015 David Bateman Copyright (C) 1998-2004 Andy Adler This file is part of Octave. Octave is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Octave is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Octave; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include "CSparse.h" #include "PermMatrix.h" #include "dSparse.h" #include "lo-error.h" #include "oct-locbuf.h" #include "oct-sparse.h" #include "oct-spparms.h" #include "sparse-lu.h" // Wrappers for SuiteSparse (formerly UMFPACK) functions that have // different names depending on the sparse matrix data type. // // All of these functions must be specialized to forward to the correct // SuiteSparse functions. template <typename T> void umfpack_defaults (double *Control); template <typename T> void umfpack_free_numeric (void **Numeric); template <typename T> void umfpack_free_symbolic (void **Symbolic); template <typename T> octave_idx_type umfpack_get_lunz (octave_idx_type *lnz, octave_idx_type *unz, void *Numeric); template <typename T> octave_idx_type umfpack_get_numeric (octave_idx_type *Lp, octave_idx_type *Lj, T *Lx, // Or Lz_packed octave_idx_type *Up, octave_idx_type *Ui, T *Ux, // Or Uz_packed octave_idx_type *p, octave_idx_type *q, double *Dz_packed, octave_idx_type *do_recip, double *Rs, void *Numeric); template <typename T> octave_idx_type umfpack_numeric (const octave_idx_type *Ap, const octave_idx_type *Ai, const T *Ax, // Or Az_packed void *Symbolic, void **Numeric, const double *Control, double *Info); template <typename T> octave_idx_type umfpack_qsymbolic (octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, const octave_idx_type *Ai, const T *Ax, // Or Az_packed const octave_idx_type *Qinit, void **Symbolic, const double *Control, double *Info); template <typename T> void umfpack_report_control (const double *Control); template <typename T> void umfpack_report_info (const double *Control, const double *Info); template <typename T> void umfpack_report_matrix (octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, const octave_idx_type *Ai, const T *Ax, // Or Az_packed octave_idx_type col_form, const double *Control); template <typename T> void umfpack_report_numeric (void *Numeric, const double *Control); template <typename T> void umfpack_report_perm (octave_idx_type np, const octave_idx_type *Perm, const double *Control); template <typename T> void umfpack_report_status (double *Control, octave_idx_type status); template <typename T> void umfpack_report_symbolic (void *Symbolic, const double *Control); // SparseMatrix Specialization. template <> inline void umfpack_defaults<double> (double *Control) { UMFPACK_DNAME (defaults) (Control); } template <> inline void umfpack_free_numeric<double> (void **Numeric) { UMFPACK_DNAME (free_numeric) (Numeric); } template <> inline void umfpack_free_symbolic<double> (void **Symbolic) { UMFPACK_DNAME (free_symbolic) (Symbolic); } template <> inline octave_idx_type umfpack_get_lunz<double> (octave_idx_type *lnz, octave_idx_type *unz, void *Numeric) { octave_idx_type ignore1, ignore2, ignore3; return UMFPACK_DNAME (get_lunz) (lnz, unz, &ignore1, &ignore2, &ignore3, Numeric); } template <> inline octave_idx_type umfpack_get_numeric<double> (octave_idx_type *Lp, octave_idx_type *Lj, double *Lx, octave_idx_type *Up, octave_idx_type *Ui, double *Ux, octave_idx_type *p, octave_idx_type *q, double *Dx, octave_idx_type *do_recip, double *Rs, void *Numeric) { return UMFPACK_DNAME (get_numeric) (Lp, Lj, Lx, Up, Ui, Ux, p, q, Dx, do_recip, Rs, Numeric); } template <> inline octave_idx_type umfpack_numeric<double> (const octave_idx_type *Ap, const octave_idx_type *Ai, const double *Ax, void *Symbolic, void **Numeric, const double *Control, double *Info) { return UMFPACK_DNAME (numeric) (Ap, Ai, Ax, Symbolic, Numeric, Control, Info); } template <> inline octave_idx_type umfpack_qsymbolic<double> (octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, const octave_idx_type *Ai, const double *Ax, const octave_idx_type *Qinit, void **Symbolic, const double *Control, double *Info) { return UMFPACK_DNAME (qsymbolic) (n_row, n_col, Ap, Ai, Ax, Qinit, Symbolic, Control, Info); } template <> inline void umfpack_report_control<double> (const double *Control) { UMFPACK_DNAME (report_control) (Control); } template <> inline void umfpack_report_info<double> (const double *Control, const double *Info) { UMFPACK_DNAME (report_info) (Control, Info); } template <> inline void umfpack_report_matrix<double> (octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, const octave_idx_type *Ai, const double *Ax, octave_idx_type col_form, const double *Control) { UMFPACK_DNAME (report_matrix) (n_row, n_col, Ap, Ai, Ax, col_form, Control); } template <> inline void umfpack_report_numeric<double> (void *Numeric, const double *Control) { UMFPACK_DNAME (report_numeric) (Numeric, Control); } template <> inline void umfpack_report_perm<double> (octave_idx_type np, const octave_idx_type *Perm, const double *Control) { UMFPACK_DNAME (report_perm) (np, Perm, Control); } template <> inline void umfpack_report_status<double> (double *Control, octave_idx_type status) { UMFPACK_DNAME (report_status) (Control, status); } template <> inline void umfpack_report_symbolic<double> (void *Symbolic, const double *Control) { UMFPACK_DNAME (report_symbolic) (Symbolic, Control); } // SparseComplexMatrix specialization. template <> inline void umfpack_defaults<Complex> (double *Control) { UMFPACK_ZNAME (defaults) (Control); } template <> inline void umfpack_free_numeric<Complex> (void **Numeric) { UMFPACK_ZNAME (free_numeric) (Numeric); } template <> inline void umfpack_free_symbolic<Complex> (void **Symbolic) { UMFPACK_ZNAME (free_symbolic) (Symbolic); } template <> inline octave_idx_type umfpack_get_lunz<Complex> (octave_idx_type *lnz, octave_idx_type *unz, void *Numeric) { octave_idx_type ignore1, ignore2, ignore3; return UMFPACK_ZNAME (get_lunz) (lnz, unz, &ignore1, &ignore2, &ignore3, Numeric); } template <> inline octave_idx_type umfpack_get_numeric<Complex> (octave_idx_type *Lp, octave_idx_type *Lj, Complex *Lz, octave_idx_type *Up, octave_idx_type *Ui, Complex *Uz, octave_idx_type *p, octave_idx_type *q, double *Dz, octave_idx_type *do_recip, double *Rs, void *Numeric) { return UMFPACK_ZNAME (get_numeric) (Lp, Lj, reinterpret_cast<double *> (Lz), 0, Up, Ui, reinterpret_cast<double *> (Uz), 0, p, q, reinterpret_cast<double *> (Dz), 0, do_recip, Rs, Numeric); } template <> inline octave_idx_type umfpack_numeric<Complex> (const octave_idx_type *Ap, const octave_idx_type *Ai, const Complex *Az, void *Symbolic, void **Numeric, const double *Control, double *Info) { return UMFPACK_ZNAME (numeric) (Ap, Ai, reinterpret_cast<const double *> (Az), 0, Symbolic, Numeric, Control, Info); } template <> inline octave_idx_type umfpack_qsymbolic<Complex> (octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, const octave_idx_type *Ai, const Complex *Az, const octave_idx_type *Qinit, void **Symbolic, const double *Control, double *Info) { return UMFPACK_ZNAME (qsymbolic) (n_row, n_col, Ap, Ai, reinterpret_cast<const double *> (Az), 0, Qinit, Symbolic, Control, Info); } template <> inline void umfpack_report_control<Complex> (const double *Control) { UMFPACK_ZNAME (report_control) (Control); } template <> inline void umfpack_report_info<Complex> (const double *Control, const double *Info) { UMFPACK_ZNAME (report_info) (Control, Info); } template <> inline void umfpack_report_matrix<Complex> (octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, const octave_idx_type *Ai, const Complex *Az, octave_idx_type col_form, const double *Control) { UMFPACK_ZNAME (report_matrix) (n_row, n_col, Ap, Ai, reinterpret_cast<const double *> (Az), 0, col_form, Control); } template <> inline void umfpack_report_numeric<Complex> (void *Numeric, const double *Control) { UMFPACK_ZNAME (report_numeric) (Numeric, Control); } template <> inline void umfpack_report_perm<Complex> (octave_idx_type np, const octave_idx_type *Perm, const double *Control) { UMFPACK_ZNAME (report_perm) (np, Perm, Control); } template <> inline void umfpack_report_status<Complex> (double *Control, octave_idx_type status) { UMFPACK_ZNAME (report_status) (Control, status); } template <> inline void umfpack_report_symbolic <Complex> (void *Symbolic, const double *Control) { UMFPACK_ZNAME (report_symbolic) (Symbolic, Control); } template <typename lu_type> sparse_lu<lu_type>::sparse_lu (const lu_type& a, const Matrix& piv_thres, bool scale) : Lfact (), Ufact (), Rfact (), cond (0), P (), Q () { #ifdef HAVE_UMFPACK octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); // Setup the control parameters Matrix Control (UMFPACK_CONTROL, 1); double *control = Control.fortran_vec (); umfpack_defaults<lu_elt_type> (control); double tmp = octave_sparse_params::get_key ("spumoni"); if (! xisnan (tmp)) Control (UMFPACK_PRL) = tmp; if (piv_thres.numel () == 2) { tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0)); if (! xisnan (tmp)) Control (UMFPACK_PIVOT_TOLERANCE) = tmp; tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1)); if (! xisnan (tmp)) Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; } else { tmp = octave_sparse_params::get_key ("piv_tol"); if (! xisnan (tmp)) Control (UMFPACK_PIVOT_TOLERANCE) = tmp; tmp = octave_sparse_params::get_key ("sym_tol"); if (! xisnan (tmp)) Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; } // Set whether we are allowed to modify Q or not tmp = octave_sparse_params::get_key ("autoamd"); if (! xisnan (tmp)) Control (UMFPACK_FIXQ) = tmp; // Turn-off UMFPACK scaling for LU if (scale) Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM; else Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; umfpack_report_control<lu_elt_type> (control); const octave_idx_type *Ap = a.cidx (); const octave_idx_type *Ai = a.ridx (); const lu_elt_type *Ax = a.data (); umfpack_report_matrix<lu_elt_type> (nr, nc, Ap, Ai, Ax, static_cast<octave_idx_type> (1), control); void *Symbolic; Matrix Info (1, UMFPACK_INFO); double *info = Info.fortran_vec (); int status = umfpack_qsymbolic<lu_elt_type> (nr, nc, Ap, Ai, Ax, 0, &Symbolic, control, info); if (status < 0) { umfpack_report_status<lu_elt_type> (control, status); umfpack_report_info<lu_elt_type> (control, info); umfpack_free_symbolic<lu_elt_type> (&Symbolic); (*current_liboctave_error_handler) ("sparse_lu: symbolic factorization failed"); } else { umfpack_report_symbolic<lu_elt_type> (Symbolic, control); void *Numeric; status = umfpack_numeric<lu_elt_type> (Ap, Ai, Ax, Symbolic, &Numeric, control, info); umfpack_free_symbolic<lu_elt_type> (&Symbolic); cond = Info (UMFPACK_RCOND); if (status < 0) { umfpack_report_status<lu_elt_type> (control, status); umfpack_report_info<lu_elt_type> (control, info); umfpack_free_numeric<lu_elt_type> (&Numeric); (*current_liboctave_error_handler) ("sparse_lu: numeric factorization failed"); } else { umfpack_report_numeric<lu_elt_type> (Numeric, control); octave_idx_type lnz, unz; status = umfpack_get_lunz<lu_elt_type> (&lnz, &unz, Numeric); if (status < 0) { umfpack_report_status<lu_elt_type> (control, status); umfpack_report_info<lu_elt_type> (control, info); umfpack_free_numeric<lu_elt_type> (&Numeric); (*current_liboctave_error_handler) ("sparse_lu: extracting LU factors failed"); } else { octave_idx_type n_inner = (nr < nc ? nr : nc); if (lnz < 1) Lfact = lu_type (n_inner, nr, static_cast<octave_idx_type> (1)); else Lfact = lu_type (n_inner, nr, lnz); octave_idx_type *Ltp = Lfact.cidx (); octave_idx_type *Ltj = Lfact.ridx (); lu_elt_type *Ltx = Lfact.data (); if (unz < 1) Ufact = lu_type (n_inner, nc, static_cast<octave_idx_type> (1)); else Ufact = lu_type (n_inner, nc, unz); octave_idx_type *Up = Ufact.cidx (); octave_idx_type *Uj = Ufact.ridx (); lu_elt_type *Ux = Ufact.data (); Rfact = SparseMatrix (nr, nr, nr); for (octave_idx_type i = 0; i < nr; i++) { Rfact.xridx (i) = i; Rfact.xcidx (i) = i; } Rfact.xcidx (nr) = nr; double *Rx = Rfact.data (); P.resize (dim_vector (nr, 1)); octave_idx_type *p = P.fortran_vec (); Q.resize (dim_vector (nc, 1)); octave_idx_type *q = Q.fortran_vec (); octave_idx_type do_recip; status = umfpack_get_numeric<lu_elt_type> (Ltp, Ltj, Ltx, Up, Uj, Ux, p, q, 0, &do_recip, Rx, Numeric); umfpack_free_numeric<lu_elt_type> (&Numeric); if (status < 0) { umfpack_report_status<lu_elt_type> (control, status); (*current_liboctave_error_handler) ("sparse_lu: extracting LU factors failed"); } else { Lfact = Lfact.transpose (); if (do_recip) for (octave_idx_type i = 0; i < nr; i++) Rx[i] = 1.0 / Rx[i]; umfpack_report_matrix<lu_elt_type> (nr, n_inner, Lfact.cidx (), Lfact.ridx (), Lfact.data (), static_cast<octave_idx_type> (1), control); umfpack_report_matrix<lu_elt_type> (n_inner, nc, Ufact.cidx (), Ufact.ridx (), Ufact.data (), static_cast<octave_idx_type> (1), control); umfpack_report_perm<lu_elt_type> (nr, p, control); umfpack_report_perm<lu_elt_type> (nc, q, control); } umfpack_report_info<lu_elt_type> (control, info); } } } #else (*current_liboctave_error_handler) ("support for UMFPACK was unavailable or disabled when liboctave was built"); #endif } template <typename lu_type> sparse_lu<lu_type>::sparse_lu (const lu_type& a, const ColumnVector& Qinit, const Matrix& piv_thres, bool scale, bool FixedQ, double droptol, bool milu, bool udiag) : Lfact (), Ufact (), Rfact (), cond (0), P (), Q () { #ifdef HAVE_UMFPACK if (milu) (*current_liboctave_error_handler) ("Modified incomplete LU not implemented"); octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); // Setup the control parameters Matrix Control (UMFPACK_CONTROL, 1); double *control = Control.fortran_vec (); umfpack_defaults<lu_elt_type> (control); double tmp = octave_sparse_params::get_key ("spumoni"); if (! xisnan (tmp)) Control (UMFPACK_PRL) = tmp; if (piv_thres.numel () == 2) { tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0)); if (! xisnan (tmp)) Control (UMFPACK_PIVOT_TOLERANCE) = tmp; tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1)); if (! xisnan (tmp)) Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; } else { tmp = octave_sparse_params::get_key ("piv_tol"); if (! xisnan (tmp)) Control (UMFPACK_PIVOT_TOLERANCE) = tmp; tmp = octave_sparse_params::get_key ("sym_tol"); if (! xisnan (tmp)) Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; } if (droptol >= 0.) Control (UMFPACK_DROPTOL) = droptol; // Set whether we are allowed to modify Q or not if (FixedQ) Control (UMFPACK_FIXQ) = 1.0; else { tmp = octave_sparse_params::get_key ("autoamd"); if (! xisnan (tmp)) Control (UMFPACK_FIXQ) = tmp; } // Turn-off UMFPACK scaling for LU if (scale) Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM; else Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; umfpack_report_control<lu_elt_type> (control); const octave_idx_type *Ap = a.cidx (); const octave_idx_type *Ai = a.ridx (); const lu_elt_type *Ax = a.data (); umfpack_report_matrix<lu_elt_type> (nr, nc, Ap, Ai, Ax, static_cast<octave_idx_type> (1), control); void *Symbolic; Matrix Info (1, UMFPACK_INFO); double *info = Info.fortran_vec (); int status; // Null loop so that qinit is imediately deallocated when not needed do { OCTAVE_LOCAL_BUFFER (octave_idx_type, qinit, nc); for (octave_idx_type i = 0; i < nc; i++) qinit[i] = static_cast<octave_idx_type> (Qinit (i)); status = umfpack_qsymbolic<lu_elt_type> (nr, nc, Ap, Ai, Ax, qinit, &Symbolic, control, info); } while (0); if (status < 0) { umfpack_report_status<lu_elt_type> (control, status); umfpack_report_info<lu_elt_type> (control, info); umfpack_free_symbolic<lu_elt_type> (&Symbolic); (*current_liboctave_error_handler) ("sparse_lu: symbolic factorization failed"); } else { umfpack_report_symbolic<lu_elt_type> (Symbolic, control); void *Numeric; status = umfpack_numeric<lu_elt_type> (Ap, Ai, Ax, Symbolic, &Numeric, control, info); umfpack_free_symbolic<lu_elt_type> (&Symbolic); cond = Info (UMFPACK_RCOND); if (status < 0) { umfpack_report_status<lu_elt_type> (control, status); umfpack_report_info<lu_elt_type> (control, info); umfpack_free_numeric<lu_elt_type> (&Numeric); (*current_liboctave_error_handler) ("sparse_lu: numeric factorization failed"); } else { umfpack_report_numeric<lu_elt_type> (Numeric, control); octave_idx_type lnz, unz; status = umfpack_get_lunz<lu_elt_type> (&lnz, &unz, Numeric); if (status < 0) { umfpack_report_status<lu_elt_type> (control, status); umfpack_report_info<lu_elt_type> (control, info); umfpack_free_numeric<lu_elt_type> (&Numeric); (*current_liboctave_error_handler) ("sparse_lu: extracting LU factors failed"); } else { octave_idx_type n_inner = (nr < nc ? nr : nc); if (lnz < 1) Lfact = lu_type (n_inner, nr, static_cast<octave_idx_type> (1)); else Lfact = lu_type (n_inner, nr, lnz); octave_idx_type *Ltp = Lfact.cidx (); octave_idx_type *Ltj = Lfact.ridx (); lu_elt_type *Ltx = Lfact.data (); if (unz < 1) Ufact = lu_type (n_inner, nc, static_cast<octave_idx_type> (1)); else Ufact = lu_type (n_inner, nc, unz); octave_idx_type *Up = Ufact.cidx (); octave_idx_type *Uj = Ufact.ridx (); lu_elt_type *Ux = Ufact.data (); Rfact = SparseMatrix (nr, nr, nr); for (octave_idx_type i = 0; i < nr; i++) { Rfact.xridx (i) = i; Rfact.xcidx (i) = i; } Rfact.xcidx (nr) = nr; double *Rx = Rfact.data (); P.resize (dim_vector (nr, 1)); octave_idx_type *p = P.fortran_vec (); Q.resize (dim_vector (nc, 1)); octave_idx_type *q = Q.fortran_vec (); octave_idx_type do_recip; status = umfpack_get_numeric<lu_elt_type> (Ltp, Ltj, Ltx, Up, Uj, Ux, p, q, 0, &do_recip, Rx, Numeric); umfpack_free_numeric<lu_elt_type> (&Numeric); if (status < 0) { umfpack_report_status<lu_elt_type> (control, status); (*current_liboctave_error_handler) ("sparse_lu: extracting LU factors failed"); } else { Lfact = Lfact.transpose (); if (do_recip) for (octave_idx_type i = 0; i < nr; i++) Rx[i] = 1.0 / Rx[i]; umfpack_report_matrix<lu_elt_type> (nr, n_inner, Lfact.cidx (), Lfact.ridx (), Lfact.data (), static_cast<octave_idx_type> (1), control); umfpack_report_matrix<lu_elt_type> (n_inner, nc, Ufact.cidx (), Ufact.ridx (), Ufact.data (), static_cast<octave_idx_type> (1), control); umfpack_report_perm<lu_elt_type> (nr, p, control); umfpack_report_perm<lu_elt_type> (nc, q, control); } umfpack_report_info<lu_elt_type> (control, info); } } } if (udiag) (*current_liboctave_error_handler) ("Option udiag of incomplete LU not implemented"); #else (*current_liboctave_error_handler) ("support for UMFPACK was unavailable or disabled when liboctave was built"); #endif } template <typename lu_type> lu_type sparse_lu<lu_type>::Y (void) const { octave_idx_type nr = Lfact.rows (); octave_idx_type nz = Lfact.cols (); octave_idx_type nc = Ufact.cols (); lu_type Yout (nr, nc, Lfact.nnz () + Ufact.nnz () - (nr<nz?nr:nz)); octave_idx_type ii = 0; Yout.xcidx (0) = 0; for (octave_idx_type j = 0; j < nc; j++) { for (octave_idx_type i = Ufact.cidx (j); i < Ufact.cidx (j + 1); i++) { Yout.xridx (ii) = Ufact.ridx (i); Yout.xdata (ii++) = Ufact.data (i); } if (j < nz) { // Note the +1 skips the 1.0 on the diagonal for (octave_idx_type i = Lfact.cidx (j) + 1; i < Lfact.cidx (j +1); i++) { Yout.xridx (ii) = Lfact.ridx (i); Yout.xdata (ii++) = Lfact.data (i); } } Yout.xcidx (j + 1) = ii; } return Yout; } template <typename lu_type> SparseMatrix sparse_lu<lu_type>::Pr (void) const { octave_idx_type nr = Lfact.rows (); SparseMatrix Pout (nr, nr, nr); for (octave_idx_type i = 0; i < nr; i++) { Pout.cidx (i) = i; Pout.ridx (P (i)) = i; Pout.data (i) = 1; } Pout.cidx (nr) = nr; return Pout; } template <typename lu_type> ColumnVector sparse_lu<lu_type>::Pr_vec (void) const { octave_idx_type nr = Lfact.rows (); ColumnVector Pout (nr); for (octave_idx_type i = 0; i < nr; i++) Pout.xelem (i) = static_cast<double> (P(i) + 1); return Pout; } template <typename lu_type> PermMatrix sparse_lu<lu_type>::Pr_mat (void) const { return PermMatrix (P, false); } template <typename lu_type> SparseMatrix sparse_lu<lu_type>::Pc (void) const { octave_idx_type nc = Ufact.cols (); SparseMatrix Pout (nc, nc, nc); for (octave_idx_type i = 0; i < nc; i++) { Pout.cidx (i) = i; Pout.ridx (i) = Q (i); Pout.data (i) = 1; } Pout.cidx (nc) = nc; return Pout; } template <typename lu_type> ColumnVector sparse_lu<lu_type>::Pc_vec (void) const { octave_idx_type nc = Ufact.cols (); ColumnVector Pout (nc); for (octave_idx_type i = 0; i < nc; i++) Pout.xelem (i) = static_cast<double> (Q(i) + 1); return Pout; } template <typename lu_type> PermMatrix sparse_lu<lu_type>::Pc_mat (void) const { return PermMatrix (Q, true); } // Instantiations we need. template class sparse_lu<SparseMatrix>; template class sparse_lu<SparseComplexMatrix>;