Mercurial > hg > octave-kai
changeset 7515:f3c00dc0912b
Eliminate the rest of the dispatched sparse functions
line wrap: on
line diff
--- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,9 @@ +2008-02-22 David Bateman <dbateman@free.fr> + + * interpreter/sparse.txi: Remove refernces to spdiag, spcumprod, + spcumsum, spprod, spsum, spsumsq, spchol, spchol2inv, spcholinv, + spinv and splu. + 2008-02-20 David Bateman <dbateman@free.fr> * interpreter/sparse.txi: Remove references to spmin, spmax,
--- a/doc/interpreter/sparse.txi +++ b/doc/interpreter/sparse.txi @@ -174,7 +174,7 @@ @table @asis @item Returned from a function There are many functions that directly return sparse matrices. These include -@dfn{speye}, @dfn{sprand}, @dfn{spdiag}, etc. +@dfn{speye}, @dfn{sprand}, @dfn{diag}, etc. @item Constructed from matrices or vectors The function @dfn{sparse} allows a sparse matrix to be constructed from three vectors representing the row, column and data. Alternatively, the @@ -202,22 +202,17 @@ elements of @var{d}. Other functions of interest that directly create sparse matrices, are -@dfn{spdiag} or its generalization @dfn{spdiags}, that can take the +@dfn{diag} or its generalization @dfn{spdiags}, that can take the definition of the diagonals of the matrix and create the sparse matrix that corresponds to this. For example @example -s = spdiag (sparse(randn(1,n)), -1); +s = diag (sparse(randn(1,n)), -1); @end example creates a sparse (@var{n}+1)-by-(@var{n}+1) sparse matrix with a single diagonal defined. -@DOCSTRING(spcumprod) - -@DOCSTRING(spcumsum) - -@DOCSTRING(spdiag) @DOCSTRING(spdiags) @@ -231,18 +226,12 @@ @DOCSTRING(spones) -@DOCSTRING(spprod) - @DOCSTRING(sprand) @DOCSTRING(sprandn) @DOCSTRING(sprandsym) -@DOCSTRING(spsum) - -@DOCSTRING(spsumsq) - The recommended way for the user to create a sparse matrix, is to create two vectors containing the row and column index of the data and a third vector of the same size containing the data to be stored. For example @@ -484,10 +473,7 @@ @dfn{dmperm}, @dfn{symamd}, @dfn{randperm}, @dfn{symrcm} @item Linear algebra: - @dfn{matrix_type}, @dfn{spchol}, @dfn{cpcholinv}, - @dfn{spchol2inv}, @dfn{spinv}, - @dfn{splchol}, @dfn{splu}, @dfn{normest}, @dfn{condest}, - @dfn{sprank} + @dfn{matrix_type}, @dfn{normest}, @dfn{condest}, @dfn{sprank} @c @dfn{spaugment} @c @dfn{eigs}, @dfn{svds} but these are in octave-forge for now @@ -497,9 +483,7 @@ @c @dfn{lsqr}, @dfn{minres}, @dfn{qmr}, @dfn{symmlq} @item Miscellaneous: - @dfn{spparms}, @dfn{symbfact}, @dfn{spstats}, - @dfn{spprod}, @dfn{spcumsum}, @dfn{spsum}, - @dfn{spsumsq}, @dfn{spdiag} + @dfn{spparms}, @dfn{symbfact}, @dfn{spstats} @end table In addition all of the standard Octave mapper functions (ie. basic @@ -833,18 +817,6 @@ @DOCSTRING(condest) -@DOCSTRING(spchol) - -@DOCSTRING(spcholinv) - -@DOCSTRING(spchol2inv) - -@DOCSTRING(spinv) - -@DOCSTRING(splchol) - -@DOCSTRING(splu) - @DOCSTRING(spparms) @DOCSTRING(sprank)
--- a/liboctave/CSparse.cc +++ b/liboctave/CSparse.cc @@ -1042,7 +1042,7 @@ Qinit(i) = i; MatrixType tmp_typ (MatrixType::Upper); - SparseComplexLU fact (*this, Qinit, -1.0, false); + SparseComplexLU fact (*this, Qinit, Matrix (), false, false); rcond = fact.rcond(); double rcond2; SparseComplexMatrix InvL = fact.L().transpose().
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,39 @@ +2008-02-22 David Bateman <dbateman@free.fr> + + * boolSparse.cc (SparseBoolMatrix SparseBoolMatrix::diag + (octave_idx_type) const): New method. + * boolSparse.h (SparseBoolMatrix SparseBoolMatrix::diag + (octave_idx_type) const): Declare it. + + * base-lu.h (lu_type Y (void) const): New method to return + factorization of xGETRF directly. + * sparse-base-lu.cc (template <class lu_type, class lu_elt_type, + class p_type, class p_elt_type> lu_type sparse_base_lu <lu_type, + lu_elt_type, p_type, p_elt_type> :: Y (void) const): New method + to simulate the retirn of xGETRF. + * sparse-base-lu.h (template <class lu_type, class lu_elt_type, + class p_type, class p_elt_type> lu_type sparse_base_lu <lu_type, + lu_elt_type, p_type, p_elt_type> :: Y (void) const): Declare it + (SparseMatrix R (void) const): Method to return scaling factors. + * SparsedbleLU.cc: Allow two element pivot thresholding and + scaling. + * SparseCmplxLU.cc: ditto. + * SparsedbleLU.h: Modify constructors to allow passing of two + element pivoting thresholds and flag for scaling + * SparseCmplxLU.h: ditto. + + * base-lu.cc (ColumnVector P_vec (void) const): New method to + return permutations as a vector. + * base-lu.h (ColumnVector P_vec (void) const): Declare it. + * sparse-base-lu.cc (ColumnVector Pr_vec (void) const): New method + return row permutations as a vector. + (ColumnVector Pc_vec (void) const): New method return column + permutations as a vector. + * sparse-base-lu.h (ColumnVector Pr_vec (void) const): Declare it. + (ColumnVector Pc_vec (void) const): Declare it. + + * oct-spparms.cc: Add sym_tol field. + 2008-02-20 David Bateman <dbateman@free.fr> * SparseComplexQR.cc (ComplexMatrix
--- a/liboctave/SparseCmplxLU.cc +++ b/liboctave/SparseCmplxLU.cc @@ -42,7 +42,7 @@ #include "oct-sparse.h" SparseComplexLU::SparseComplexLU (const SparseComplexMatrix& a, - double piv_thres) + const Matrix& piv_thres, bool scale) { #ifdef HAVE_UMFPACK octave_idx_type nr = a.rows (); @@ -56,20 +56,24 @@ double tmp = octave_sparse_params::get_key ("spumoni"); if (!xisnan (tmp)) Control (UMFPACK_PRL) = tmp; - if (piv_thres >= 0.) + if (piv_thres.nelem() != 2) { - piv_thres = (piv_thres > 1. ? 1. : piv_thres); - Control (UMFPACK_SYM_PIVOT_TOLERANCE) = piv_thres; - Control (UMFPACK_PIVOT_TOLERANCE) = piv_thres; + 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; - Control (UMFPACK_PIVOT_TOLERANCE) = tmp; - } } // Set whether we are allowed to modify Q or not @@ -78,7 +82,10 @@ Control (UMFPACK_FIXQ) = tmp; // Turn-off UMFPACK scaling for LU - Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + if (scale) + Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM; + else + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; UMFPACK_ZNAME (report_control) (control); @@ -173,6 +180,15 @@ octave_idx_type *Uj = Ufact.ridx (); Complex *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 (nr); octave_idx_type *p = P.fortran_vec (); @@ -185,11 +201,11 @@ NULL, Up, Uj, reinterpret_cast <double *> (Ux), NULL, p, q, NULL, NULL, - &do_recip, NULL, Numeric); + &do_recip, Rx, Numeric); UMFPACK_ZNAME (free_numeric) (&Numeric) ; - if (status < 0 || do_recip) + if (status < 0) { (*current_liboctave_error_handler) ("SparseComplexLU::SparseComplexLU extracting LU factors failed"); @@ -200,6 +216,10 @@ { Lfact = Lfact.transpose (); + if (do_recip) + for (octave_idx_type i = 0; i < nr; i++) + Rx[i] = 1.0 / Rx[i]; + UMFPACK_ZNAME (report_matrix) (nr, n_inner, Lfact.cidx (), Lfact.ridx (), reinterpret_cast<double *> (Lfact.data()), @@ -224,8 +244,9 @@ SparseComplexLU::SparseComplexLU (const SparseComplexMatrix& a, const ColumnVector& Qinit, - double piv_thres, bool FixedQ, - double droptol, bool milu, bool udiag) + const Matrix& piv_thres, bool scale, + bool FixedQ, double droptol, + bool milu, bool udiag) { #ifdef HAVE_UMFPACK if (milu) @@ -244,20 +265,24 @@ double tmp = octave_sparse_params::get_key ("spumoni"); if (!xisnan (tmp)) Control (UMFPACK_PRL) = tmp; - if (piv_thres >= 0.) + if (piv_thres.nelem() != 2) { - piv_thres = (piv_thres > 1. ? 1. : piv_thres); - Control (UMFPACK_SYM_PIVOT_TOLERANCE) = piv_thres; - Control (UMFPACK_PIVOT_TOLERANCE) = piv_thres; + 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_SYM_PIVOT_TOLERANCE) = tmp; - Control (UMFPACK_PIVOT_TOLERANCE) = 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.) @@ -274,7 +299,10 @@ } // Turn-off UMFPACK scaling for LU - Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + if (scale) + Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM; + else + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; UMFPACK_ZNAME (report_control) (control); @@ -379,6 +407,15 @@ octave_idx_type *Uj = Ufact.ridx (); Complex *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 (nr); octave_idx_type *p = P.fortran_vec (); @@ -392,22 +429,25 @@ NULL, Up, Uj, reinterpret_cast<double *> (Ux), NULL, p, q, NULL, NULL, - &do_recip, NULL, Numeric) ; + &do_recip, Rx, Numeric) ; UMFPACK_ZNAME (free_numeric) (&Numeric) ; - if (status < 0 || do_recip) + if (status < 0) { (*current_liboctave_error_handler) ("SparseComplexLU::SparseComplexLU extracting LU factors failed"); - UMFPACK_ZNAME (report_status) (control, - status); + UMFPACK_ZNAME (report_status) (control, status); } else { Lfact = Lfact.transpose (); + if (do_recip) + for (octave_idx_type i = 0; i < nr; i++) + Rx[i] = 1.0 / Rx[i]; + UMFPACK_ZNAME (report_matrix) (nr, n_inner, Lfact.cidx (), Lfact.ridx (),
--- a/liboctave/SparseCmplxLU.h +++ b/liboctave/SparseCmplxLU.h @@ -38,10 +38,13 @@ SparseComplexLU (void) : sparse_base_lu <SparseComplexMatrix, Complex, SparseMatrix, double> () { } - SparseComplexLU (const SparseComplexMatrix& a, double piv_thres = -1); + SparseComplexLU (const SparseComplexMatrix& a, + const Matrix& piv_thres = Matrix (), + bool scale = false); SparseComplexLU (const SparseComplexMatrix& a, const ColumnVector& Qinit, - double piv_thres = -1, bool FixedQ = false, + const Matrix& piv_thres = Matrix (), + bool scale = false, bool FixedQ = false, double droptol = -1., bool milu = false, bool udiag = false);
--- a/liboctave/SparsedbleLU.cc +++ b/liboctave/SparsedbleLU.cc @@ -41,7 +41,7 @@ #include "oct-sparse.h" -SparseLU::SparseLU (const SparseMatrix& a, double piv_thres) +SparseLU::SparseLU (const SparseMatrix& a, const Matrix& piv_thres, bool scale) { #ifdef HAVE_UMFPACK octave_idx_type nr = a.rows (); @@ -56,20 +56,24 @@ if (!xisnan (tmp)) Control (UMFPACK_PRL) = tmp; - if (piv_thres >= 0.) + if (piv_thres.nelem() != 2) { - piv_thres = (piv_thres > 1. ? 1. : piv_thres); - Control (UMFPACK_SYM_PIVOT_TOLERANCE) = piv_thres; - Control (UMFPACK_PIVOT_TOLERANCE) = piv_thres; + 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; - Control (UMFPACK_PIVOT_TOLERANCE) = tmp; - } } // Set whether we are allowed to modify Q or not @@ -77,8 +81,10 @@ if (!xisnan (tmp)) Control (UMFPACK_FIXQ) = tmp; - // Turn-off UMFPACK scaling for LU - Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + if (scale) + Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM; + else + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; UMFPACK_DNAME (report_control) (control); @@ -167,6 +173,15 @@ octave_idx_type *Uj = Ufact.ridx (); double *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 (nr); octave_idx_type *p = P.fortran_vec (); @@ -176,12 +191,12 @@ octave_idx_type do_recip; status = UMFPACK_DNAME (get_numeric) (Ltp, Ltj, Ltx, Up, Uj, Ux, p, q, NULL, - &do_recip, NULL, + &do_recip, Rx, Numeric) ; UMFPACK_DNAME (free_numeric) (&Numeric) ; - if (status < 0 || do_recip) + if (status < 0) { (*current_liboctave_error_handler) ("SparseLU::SparseLU extracting LU factors failed"); @@ -192,6 +207,10 @@ { Lfact = Lfact.transpose (); + if (do_recip) + for (octave_idx_type i = 0; i < nr; i++) + Rx[i] = 1.0 / Rx[i]; + UMFPACK_DNAME (report_matrix) (nr, n_inner, Lfact.cidx (), Lfact.ridx (), Lfact.data (), 1, control); @@ -212,8 +231,8 @@ } SparseLU::SparseLU (const SparseMatrix& a, const ColumnVector& Qinit, - double piv_thres, bool FixedQ, double droptol, - bool milu, bool udiag) + const Matrix& piv_thres, bool scale, bool FixedQ, + double droptol, bool milu, bool udiag) { #ifdef HAVE_UMFPACK if (milu) @@ -232,20 +251,25 @@ double tmp = octave_sparse_params::get_key ("spumoni"); if (!xisnan (tmp)) Control (UMFPACK_PRL) = tmp; - if (piv_thres >= 0.) + + if (piv_thres.nelem() != 2) { - piv_thres = (piv_thres > 1. ? 1. : piv_thres); - Control (UMFPACK_SYM_PIVOT_TOLERANCE) = piv_thres; - Control (UMFPACK_PIVOT_TOLERANCE) = piv_thres; + 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_SYM_PIVOT_TOLERANCE) = tmp; - Control (UMFPACK_PIVOT_TOLERANCE) = 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.) @@ -262,8 +286,10 @@ Control (UMFPACK_FIXQ) = tmp; } - // Turn-off UMFPACK scaling for LU - Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + if (scale) + Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM; + else + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; UMFPACK_DNAME (report_control) (control); @@ -363,6 +389,15 @@ octave_idx_type *Uj = Ufact.ridx (); double *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 (nr); octave_idx_type *p = P.fortran_vec (); @@ -373,11 +408,11 @@ status = UMFPACK_DNAME (get_numeric) (Ltp, Ltj, Ltx, Up, Uj, Ux, p, q, NULL, &do_recip, - NULL, Numeric) ; + Rx, Numeric) ; UMFPACK_DNAME (free_numeric) (&Numeric) ; - if (status < 0 || do_recip) + if (status < 0) { (*current_liboctave_error_handler) ("SparseLU::SparseLU extracting LU factors failed"); @@ -387,6 +422,11 @@ else { Lfact = Lfact.transpose (); + + if (do_recip) + for (octave_idx_type i = 0; i < nr; i++) + Rx[i] = 1.0 / Rx[i]; + UMFPACK_DNAME (report_matrix) (nr, n_inner, Lfact.cidx (), Lfact.ridx (),
--- a/liboctave/SparsedbleLU.h +++ b/liboctave/SparsedbleLU.h @@ -36,11 +36,13 @@ SparseLU (void) : sparse_base_lu <SparseMatrix, double, SparseMatrix, double> () { } - SparseLU (const SparseMatrix& a, double piv_thres = -1.0); + SparseLU (const SparseMatrix& a, const Matrix& piv_thres = Matrix(), + bool scale = false); SparseLU (const SparseMatrix& a, const ColumnVector& Qinit, - double piv_thres = -1.0, bool FixedQ = false, - double droptol = -1., bool milu = false, bool udiag = false); + const Matrix& piv_thres = Matrix(), bool scale = false, + bool FixedQ = false, double droptol = -1., + bool milu = false, bool udiag = false); SparseLU (const SparseLU& a) : sparse_base_lu <SparseMatrix, double, SparseMatrix, double> (a) { }
--- a/liboctave/base-lu.cc +++ b/liboctave/base-lu.cc @@ -98,6 +98,37 @@ return p; } +template <class lu_type, class lu_elt_type, class p_type, class p_elt_type> +ColumnVector +base_lu <lu_type, lu_elt_type, p_type, p_elt_type> :: P_vec (void) const +{ + octave_idx_type a_nr = a_fact.rows (); + + Array<octave_idx_type> pvt (a_nr); + + for (octave_idx_type i = 0; i < a_nr; i++) + pvt.xelem (i) = i; + + for (octave_idx_type i = 0; i < ipvt.length(); i++) + { + octave_idx_type k = ipvt.xelem (i); + + if (k != i) + { + octave_idx_type tmp = pvt.xelem (k); + pvt.xelem (k) = pvt.xelem (i); + pvt.xelem (i) = tmp; + } + } + + ColumnVector p (a_nr); + + for (octave_idx_type i = 0; i < a_nr; i++) + p.xelem (i) = static_cast<double> (pvt.xelem (i) + 1); + + return p; +} + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/liboctave/base-lu.h +++ b/liboctave/base-lu.h @@ -24,6 +24,7 @@ #define octave_base_lu_h 1 #include "MArray.h" +#include "dColVector.h" template <class lu_type, class lu_elt_type, class p_type, class p_elt_type> class @@ -51,8 +52,12 @@ lu_type U (void) const; + lu_type Y (void) const { return a_fact; } + p_type P (void) const; + ColumnVector P_vec (void) const; + protected: lu_type a_fact;
--- a/liboctave/boolSparse.cc +++ b/liboctave/boolSparse.cc @@ -140,6 +140,93 @@ SPARSE_ANY_OP (dim); } +SparseBoolMatrix +SparseBoolMatrix::diag (octave_idx_type k) const +{ + octave_idx_type nnr = rows (); + octave_idx_type nnc = cols (); + + if (k > 0) + nnc -= k; + else if (k < 0) + nnr += k; + + SparseBoolMatrix d; + + if (nnr > 0 && nnc > 0) + { + octave_idx_type ndiag = (nnr < nnc) ? nnr : nnc; + + // Count the number of non-zero elements + octave_idx_type nel = 0; + if (k > 0) + { + for (octave_idx_type i = 0; i < ndiag; i++) + if (elem (i, i+k) != 0.) + nel++; + } + else if ( k < 0) + { + for (octave_idx_type i = 0; i < ndiag; i++) + if (elem (i-k, i) != 0.) + nel++; + } + else + { + for (octave_idx_type i = 0; i < ndiag; i++) + if (elem (i, i) != 0.) + nel++; + } + + d = SparseBoolMatrix (ndiag, 1, nel); + d.xcidx (0) = 0; + d.xcidx (1) = nel; + + octave_idx_type ii = 0; + if (k > 0) + { + for (octave_idx_type i = 0; i < ndiag; i++) + { + bool tmp = elem (i, i+k); + if (tmp != 0.) + { + d.xdata (ii) = tmp; + d.xridx (ii++) = i; + } + } + } + else if ( k < 0) + { + for (octave_idx_type i = 0; i < ndiag; i++) + { + bool tmp = elem (i-k, i); + if (tmp != 0.) + { + d.xdata (ii) = tmp; + d.xridx (ii++) = i; + } + } + } + else + { + for (octave_idx_type i = 0; i < ndiag; i++) + { + bool tmp = elem (i, i); + if (tmp != 0.) + { + d.xdata (ii) = tmp; + d.xridx (ii++) = i; + } + } + } + } + else + (*current_liboctave_error_handler) + ("diag: requested diagonal out of range"); + + return d; +} + boolMatrix SparseBoolMatrix::matrix_value (void) const {
--- a/liboctave/boolSparse.h +++ b/liboctave/boolSparse.h @@ -88,6 +88,8 @@ SparseBoolMatrix concat (const SparseBoolMatrix& rb, const Array<octave_idx_type>& ra_idx); + SparseBoolMatrix diag (octave_idx_type k = 0) const; + boolMatrix matrix_value (void) const; SparseBoolMatrix squeeze (void) const;
--- a/liboctave/dSparse.cc +++ b/liboctave/dSparse.cc @@ -1116,7 +1116,7 @@ Qinit(i) = i; MatrixType tmp_typ (MatrixType::Upper); - SparseLU fact (*this, Qinit, -1.0, false); + SparseLU fact (*this, Qinit, Matrix(), false, false); rcond = fact.rcond(); double rcond2; SparseMatrix InvL = fact.L().transpose().tinverse(tmp_typ,
--- a/liboctave/oct-spparms.cc +++ b/liboctave/oct-spparms.cc @@ -111,35 +111,37 @@ void octave_sparse_params::do_defaults (void) { - params(0) = 0; // spumoni - params(1) = 1; // ths_rel - params(2) = 1; // ths_abs - params(3) = 0; // exact_d - params(4) = 3; // supernd - params(5) = 3; // rreduce - params(6) = 0.5; // wh_frac - params(7) = 1; // autommd - params(8) = 1; // autoamd - params(9) = 0.1; // piv_tol - params(10) = 0.5; // bandden - params(11) = 1; // umfpack + params(0) = 0; // spumoni + params(1) = 1; // ths_rel + params(2) = 1; // ths_abs + params(3) = 0; // exact_d + params(4) = 3; // supernd + params(5) = 3; // rreduce + params(6) = 0.5; // wh_frac + params(7) = 1; // autommd + params(8) = 1; // autoamd + params(9) = 0.1; // piv_tol + params(10) = 0.5; // bandden + params(11) = 1; // umfpack + params(12) = 0.001; // sym_tol } void octave_sparse_params::do_tight (void) { - params(0) = 0; // spumoni - params(1) = 1; // ths_rel - params(2) = 0; // ths_abs - params(3) = 1; // exact_d - params(4) = 1; // supernd - params(5) = 1; // rreduce - params(6) = 0.5; // wh_frac - params(7) = 1; // autommd - params(8) = 1; // autoamd - params(9) = 0.1; // piv_tol - params(10) = 0.5; // bandden - params(11) = 1; // umfpack + params(0) = 0; // spumoni + params(1) = 1; // ths_rel + params(2) = 0; // ths_abs + params(3) = 1; // exact_d + params(4) = 1; // supernd + params(5) = 1; // rreduce + params(6) = 0.5; // wh_frac + params(7) = 1; // autommd + params(8) = 1; // autoamd + params(9) = 0.1; // piv_tol + params(10) = 0.5; // bandden + params(11) = 1; // umfpack + params(12) = 0.001; // sym_tol } void @@ -157,6 +159,7 @@ keys(9) = "piv_tol"; keys(10) = "bandden"; keys(11) = "umfpack"; + keys(12) = "sym_tol"; } double
--- a/liboctave/oct-spparms.h +++ b/liboctave/oct-spparms.h @@ -33,7 +33,7 @@ #include "dColVector.h" #include "dNDArray.h" -#define OCTAVE_SPARSE_CONTROLS_SIZE 12 +#define OCTAVE_SPARSE_CONTROLS_SIZE 13 class OCTAVE_API
--- a/liboctave/sparse-base-lu.cc +++ b/liboctave/sparse-base-lu.cc @@ -28,9 +28,45 @@ #include "sparse-base-lu.h" template <class lu_type, class lu_elt_type, class p_type, class p_elt_type> +lu_type +sparse_base_lu <lu_type, lu_elt_type, p_type, p_elt_type> :: Y (void) const +{ + octave_idx_type nr = Lfact.rows (); + octave_idx_type nc = Ufact.rows (); + octave_idx_type rcmin = (nr > nc ? nr : nc); + + lu_type Yout (nr, nc, Lfact.nnz() + Ufact.nnz()); + 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 < rcmin) + { + // 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 <class lu_type, class lu_elt_type, class p_type, class p_elt_type> p_type sparse_base_lu <lu_type, lu_elt_type, p_type, p_elt_type> :: Pr (void) const { + octave_idx_type nr = Lfact.rows (); p_type Pout (nr, nr, nr); @@ -47,6 +83,21 @@ } template <class lu_type, class lu_elt_type, class p_type, class p_elt_type> +ColumnVector +sparse_base_lu <lu_type, lu_elt_type, p_type, p_elt_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 <class lu_type, class lu_elt_type, class p_type, class p_elt_type> p_type sparse_base_lu <lu_type, lu_elt_type, p_type, p_elt_type> :: Pc (void) const { @@ -65,6 +116,21 @@ return Pout; } +template <class lu_type, class lu_elt_type, class p_type, class p_elt_type> +ColumnVector +sparse_base_lu <lu_type, lu_elt_type, p_type, p_elt_type> :: Pc_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> (Q(i) + 1); + + return Pout; +} + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/liboctave/sparse-base-lu.h +++ b/liboctave/sparse-base-lu.h @@ -26,6 +26,7 @@ #define octave_sparse_base_lu_h 1 #include "MArray.h" +#include "dSparse.h" template <class lu_type, class lu_elt_type, class p_type, class p_elt_type> class @@ -57,10 +58,18 @@ lu_type U (void) const { return Ufact; } + SparseMatrix R (void) const { return Rfact; } + + lu_type Y (void) const; + p_type Pc (void) const; p_type Pr (void) const; + ColumnVector Pc_vec (void) const; + + ColumnVector Pr_vec (void) const; + const octave_idx_type * row_perm (void) const { return P.fortran_vec (); } const octave_idx_type * col_perm (void) const { return Q.fortran_vec (); } @@ -71,6 +80,7 @@ lu_type Lfact; lu_type Ufact; + SparseMatrix Rfact; double cond;
--- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,3 +1,8 @@ +2008-02-22 David Bateman <dbateman@free.fr> + + * sparse/pcg.m, sparse/spdiags, spstats.m: Remove references to + spdiag. + 2008-02-22 John W. Eaton <jwe@octave.org> * miscellaneous/fullfile.m: Improve handling of empty args and
--- a/scripts/sparse/pcg.m +++ b/scripts/sparse/pcg.m @@ -123,7 +123,7 @@ ## @example ## @group ## N = 10; -## A = spdiag ([1:N]); +## A = diag (sparse([1:N])); ## b = rand (N, 1); ## [L, U, P, Q] = luinc (A,1.e-3); ## @end group
--- a/scripts/sparse/spdiags.m +++ b/scripts/sparse/spdiags.m @@ -21,7 +21,7 @@ ## @deftypefnx {Function File} {@var{b} =} spdiags (@var{a}, @var{c}) ## @deftypefnx {Function File} {@var{b} =} spdiags (@var{v}, @var{c}, @var{a}) ## @deftypefnx {Function File} {@var{b} =} spdiags (@var{v}, @var{c}, @var{m}, @var{n}) -## A generalization of the function @code{spdiag}. Called with a single +## A generalization of the function @code{diag}. Called with a single ## input argument, the non-zero diagonals @var{c} of @var{A} are extracted. ## With two arguments the diagonals to extract are given by the vector ## @var{c}. @@ -56,8 +56,8 @@ if (nargin == 1 || nargin == 2) ## extract nonzero diagonals of v into A,c + [nr, nc] = size (v); [i, j, v] = find (v); - [nr, nc] = size (v); if (nargin == 1) ## c contains the active diagonals
--- a/scripts/sparse/spstats.m +++ b/scripts/sparse/spstats.m @@ -45,14 +45,14 @@ endif [n, m] = size (S); - count = spsum (sparse (i, j, 1, n, m)); + count = sum (sparse (i, j, 1, n, m)); if (nargout > 1) - mean = spsum (S) ./ count; + mean = sum (S) ./ count; endif if (nargout > 2) ## FIXME Variance with count = 0 or 1? diff = S - sparse (i, j, mean(j), n, m); - var = spsum (diff .* diff) ./ (count - 1); + var = sum (diff .* diff) ./ (count - 1); endif endfunction
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,31 @@ +2008-02-21 David Bateman <dbateman@free.fr> + + * DLD-FUNCTIONS/chol.c (Fchol, Fcholinv, Fchol2iinv): Treat + sparse matrices. Add the "lower" and "vector" flags. + * DLD-FUNCTIONS/inv.c (Finv): Treat sparse matrices. + * DLD-FUNCTION/sparse.cc (static bool is_sparse (const + octave_value&)): Remove and use arg.is_sparse_type () instead. + (Fspcumprod, Fspcumsum, Fspprod, spsum, spsumsq, spdiag): Remove. + * DLD-FUNCTIONS/splu.cc: Remove. + * DLD-FUNCTIONS/lu.cc: Treat sparse matrices, Add "vector" flag. + * DLD-FUNCTIONS/spchol.cc: Move to symbfact.cc + * DLD-FUNCTIONS/symbfact.cc: Remove cholesky functions Fspchol, + Fspcholinv, Fspchol2inv. + * DLD-FUNCTIONS/luinc.cc: Modify for new sparse LU + constructors. Ass the 'vector' flag. + * DLD-FUNCTIONS/spparms.cc: Add the sum_tol flag. + + * Makifile.in (DLD_XSRC): Remove spchol.cc, splu.cc and add + symbfact.cc + * data.cc (NATIVE_REDUCTION): Treat sparse matrices + (DATA_REDUCTION): Ditto. + (template <class T> static octave_value make_spdiag (const T&, + octave_idx_type)): New template function for sparse diag + function. Instantiate it. + (static octave_value make_diag (const octave_value&, + octave_idx_type): Use make_spdiag for sparse matrice. + (Fatan2): Compatibility fixes for mixed full/sparse matrices. + 2008-02-21 John W. Eaton <jwe@octave.org> * DLD-FUNCTIONS/fsolve.cc (fsolve_user_jacobian):
--- a/src/DLD-FUNCTIONS/chol.cc +++ b/src/DLD-FUNCTIONS/chol.cc @@ -27,7 +27,13 @@ #include "CmplxCHOL.h" #include "dbleCHOL.h" +#include "SparseCmplxCHOL.h" +#include "SparsedbleCHOL.h" +#include "oct-spparms.h" +#include "sparse-util.h" +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" #include "defun-dld.h" #include "error.h" #include "gripes.h" @@ -36,7 +42,11 @@ DEFUN_DLD (chol, args, nargout, "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {} chol (@var{a})\n\ +@deftypefn {Loadable Function} {@var{r}} = chol (@var{a})\n\ +@deftypefnx {Loadable Function} {[@var{r}, @var{p}]} = chol (@var{a})\n\ +@deftypefnx {Loadable Function} {[@var{r}, @var{p}, @var{q}]} = chol (@var{s})\n\ +@deftypefnx {Loadable Function} {[@var{r}, @var{p}, @var{q}]} = chol (@var{s}, 'vector')\n\ +@deftypefnx {Loadable Function} {[@var{l}, @dots{}]} = chol (@dots{}, 'lower')\n\ @cindex Cholesky factorization\n\ Compute the Cholesky factor, @var{r}, of the symmetric positive definite\n\ matrix @var{a}, where\n\ @@ -48,72 +58,216 @@ @ifinfo\n\ \n\ @example\n\ -r' * r = a.\n\ +@var{r}' * @var{r} = @var{a}.\n\ +@end example\n\ +@end ifinfo\n\ +\n\ +Called with one output argument @code{chol} fails if @var{a} or @var{s} is\n\ +not positive definite. With two or more output arguments @var{p} flags\n\ +whether the matrix was positive definite and @code{chol} does not fail. A\n\ +zero value indicated that the matrix was positive definite and the @var{r}\n\ +gives the factorization, annd @var{p} will have a positive value otherwise.\n\ +\n\ +If called with 3 outputs then a sparsity preserving row/column permutation\n\ +is applied to @var{a} prior to the factorization. That is @var{r}\n\ +is the factorization of @code{@var{a}(@var{q},@var{q})} such that\n\ +@iftex\n\ +@tex\n\ +$ R^T R = Q^T A Q$.\n\ +@end tex\n\ +@end iftex\n\ +@ifinfo\n\ +\n\ +@example\n\ +@var{r}' * @var{r} = @var{q}' * @var{a} * @var{q}.\n\ @end example\n\ @end ifinfo\n\ +\n\ +The sparsity preserving permutation is generally returned as a matrix.\n\ +However, given the flag 'vector', @var{q} will be returned as a vector\n\ +such that\n\ +@iftex\n\ +@tex\n\ +$ R^T R = A (Q, Q)$.\n\ +@end tex\n\ +@end iftex\n\ +@ifinfo\n\ +\n\ +@example\n\ +@var{r}' * @var{r} = a (@var{q}, @var{q}).\n\ +@end example\n\ +@end ifinfo\n\ +\n\ +Called with either a sparse or full matrix and uing the 'lower' flag,\n\ +@code{chol} returns the lower triangular factorization such that\n\ +@iftex\n\ +@tex\n\ +$ L L^T = A $.\n\ +@end tex\n\ +@end iftex\n\ +@ifinfo\n\ +\n\ +@example\n\ +@var{l} * @var{l}' = @var{a}.\n\ +@end example\n\ +@end ifinfo\n\ +\n\ +In general the lower trinagular factorization is significantly faster for\n\ +sparse matrices.\n\ @seealso{cholinv, chol2inv}\n\ @end deftypefn") { octave_value_list retval; + int nargin = args.length (); + bool LLt = false; + bool vecout = false; - int nargin = args.length (); - - if (nargin != 1 || nargout > 2) + if (nargin < 1 || nargin > 3 || nargout > 3 + || (! args(0).is_sparse_type () && nargout > 2)) { print_usage (); return retval; } - octave_value arg = args(0); - - octave_idx_type nr = arg.rows (); - octave_idx_type nc = arg.columns (); + int n = 1; + while (n < nargin && ! error_state) + { + std::string tmp = args(n++).string_value (); + + if (! error_state ) + { + if (tmp.compare ("vector") == 0) + vecout = true; + else if (tmp.compare ("lower") == 0) + LLt = true; + else if (tmp.compare ("upper") == 0) + LLt = false; + else + error ("chol: unexpected second or third input"); + } + else + error ("chol: expecting trailing string arguments"); + } - int arg_is_empty = empty_arg ("chol", nr, nc); + if (! error_state) + { + octave_value arg = args(0); + + octave_idx_type nr = arg.rows (); + octave_idx_type nc = arg.columns (); + bool natural = (nargout != 3); + + int arg_is_empty = empty_arg ("chol", nr, nc); - if (arg_is_empty < 0) - return retval; - if (arg_is_empty > 0) - return octave_value (Matrix ()); + if (arg_is_empty < 0) + return retval; + if (arg_is_empty > 0) + return octave_value (Matrix ()); + + if (arg.is_sparse_type ()) + { + if (arg.is_real_type ()) + { + SparseMatrix m = arg.sparse_matrix_value (); - if (arg.is_real_type ()) - { - Matrix m = arg.matrix_value (); + if (! error_state) + { + octave_idx_type info; + SparseCHOL fact (m, info, natural); + if (nargout == 3) + if (vecout) + retval(2) = fact.perm (); + else + retval(2) = fact.Q(); - if (! error_state) - { - octave_idx_type info; - CHOL fact (m, info); - if (nargout == 2 || info == 0) + if (nargout > 1 || info == 0) + { + retval(1) = fact.P(); + if (LLt) + retval(0) = fact.L(); + else + retval(0) = fact.R(); + } + else + error ("chol: matrix not positive definite"); + } + } + else if (arg.is_complex_type ()) { - retval(1) = static_cast<double> (info); - retval(0) = fact.chol_matrix (); + SparseComplexMatrix m = arg.sparse_complex_matrix_value (); + + if (! error_state) + { + octave_idx_type info; + SparseComplexCHOL fact (m, info, natural); + + if (nargout == 3) + if (vecout) + retval(2) = fact.perm (); + else + retval(2) = fact.Q(); + + if (nargout > 1 || info == 0) + { + retval(1) = fact.P(); + if (LLt) + retval(0) = fact.L(); + else + retval(0) = fact.R(); + } + else + error ("chol: matrix not positive definite"); + } } else - error ("chol: matrix not positive definite"); + gripe_wrong_type_arg ("chol", arg); } - } - else if (arg.is_complex_type ()) - { - ComplexMatrix m = arg.complex_matrix_value (); + else + { + if (arg.is_real_type ()) + { + Matrix m = arg.matrix_value (); - if (! error_state) - { - octave_idx_type info; - ComplexCHOL fact (m, info); - if (nargout == 2 || info == 0) + if (! error_state) + { + octave_idx_type info; + CHOL fact (m, info); + if (nargout == 2 || info == 0) + { + retval(1) = static_cast<double> (info); + if (LLt) + retval(0) = fact.chol_matrix ().transpose (); + else + retval(0) = fact.chol_matrix (); + } + else + error ("chol: matrix not positive definite"); + } + } + else if (arg.is_complex_type ()) { - retval(1) = static_cast<double> (info); - retval(0) = fact.chol_matrix (); + ComplexMatrix m = arg.complex_matrix_value (); + + if (! error_state) + { + octave_idx_type info; + ComplexCHOL fact (m, info); + if (nargout == 2 || info == 0) + { + retval(1) = static_cast<double> (info); + if (LLt) + retval(0) = fact.chol_matrix ().hermitian (); + else + retval(0) = fact.chol_matrix (); + } + else + error ("chol: matrix not positive definite"); + } } else - error ("chol: matrix not positive definite"); + gripe_wrong_type_arg ("chol", arg); } } - else - { - gripe_wrong_type_arg ("chol", arg); - } return retval; } @@ -141,36 +295,72 @@ retval = Matrix (); else { - if (arg.is_real_type ()) + if (arg.is_sparse_type ()) { - Matrix m = arg.matrix_value (); - - if (! error_state) + if (arg.is_real_type ()) { - octave_idx_type info; - CHOL chol (m, info); - if (info == 0) - retval = chol.inverse (); - else - error ("cholinv: matrix not positive definite"); + SparseMatrix m = arg.sparse_matrix_value (); + + if (! error_state) + { + octave_idx_type info; + SparseCHOL chol (m, info); + if (info == 0) + retval = chol.inverse (); + else + error ("cholinv: matrix not positive definite"); + } } - } - else if (arg.is_complex_type ()) - { - ComplexMatrix m = arg.complex_matrix_value (); - - if (! error_state) + else if (arg.is_complex_type ()) { - octave_idx_type info; - ComplexCHOL chol (m, info); - if (info == 0) - retval = chol.inverse (); - else - error ("cholinv: matrix not positive definite"); + SparseComplexMatrix m = arg.sparse_complex_matrix_value (); + + if (! error_state) + { + octave_idx_type info; + SparseComplexCHOL chol (m, info); + if (info == 0) + retval = chol.inverse (); + else + error ("cholinv: matrix not positive definite"); + } } + else + gripe_wrong_type_arg ("cholinv", arg); } else - gripe_wrong_type_arg ("chol", arg); + { + if (arg.is_real_type ()) + { + Matrix m = arg.matrix_value (); + + if (! error_state) + { + octave_idx_type info; + CHOL chol (m, info); + if (info == 0) + retval = chol.inverse (); + else + error ("cholinv: matrix not positive definite"); + } + } + else if (arg.is_complex_type ()) + { + ComplexMatrix m = arg.complex_matrix_value (); + + if (! error_state) + { + octave_idx_type info; + ComplexCHOL chol (m, info); + if (info == 0) + retval = chol.inverse (); + else + error ("cholinv: matrix not positive definite"); + } + } + else + gripe_wrong_type_arg ("chol", arg); + } } } else @@ -205,22 +395,44 @@ retval = Matrix (); else { - if (arg.is_real_type ()) + if (arg.is_sparse_type ()) { - Matrix r = arg.matrix_value (); + if (arg.is_real_type ()) + { + SparseMatrix r = arg.sparse_matrix_value (); - if (! error_state) - retval = chol2inv (r); - } - else if (arg.is_complex_type ()) - { - ComplexMatrix r = arg.complex_matrix_value (); + if (! error_state) + retval = chol2inv (r); + } + else if (arg.is_complex_type ()) + { + SparseComplexMatrix r = arg.sparse_complex_matrix_value (); - if (! error_state) - retval = chol2inv (r); + if (! error_state) + retval = chol2inv (r); + } + else + gripe_wrong_type_arg ("chol2inv", arg); } else - gripe_wrong_type_arg ("chol2inv", arg); + { + if (arg.is_real_type ()) + { + Matrix r = arg.matrix_value (); + + if (! error_state) + retval = chol2inv (r); + } + else if (arg.is_complex_type ()) + { + ComplexMatrix r = arg.complex_matrix_value (); + + if (! error_state) + retval = chol2inv (r); + } + else + gripe_wrong_type_arg ("chol2inv", arg); + } } } else
--- a/src/DLD-FUNCTIONS/inv.cc +++ b/src/DLD-FUNCTIONS/inv.cc @@ -38,6 +38,12 @@ Compute the inverse of the square matrix @var{a}. Return an estimate\n\ of the reciprocal condition number if requested, otherwise warn of an\n\ ill-conditioned matrix if the reciprocal condition number is small.\n\ +\n\ +If called with a sparse matrix, then in general @var{x} will be a full\n\ +matrix, and so if possible forming the inverse of a sparse matrix should\n\ +be avoided. It is significantly more accurate and faster to do\n\ +@code{@var{y} = @var{a} \\ @var{b}}, rather than\n\ +@code{@var{y} = inv (@var{a}) * @var{b}}.\n\ @end deftypefn") { octave_value_list retval; @@ -68,63 +74,73 @@ return retval; } + octave_value result; + octave_idx_type info; + double rcond = 0.0; if (arg.is_real_type ()) { - Matrix m = arg.matrix_value (); - - if (! error_state) + if (arg.is_sparse_type ()) { - MatrixType mattyp = args(0).matrix_type (); - - octave_idx_type info; - double rcond = 0.0; - - Matrix result = m.inverse (mattyp, info, rcond, 1); - - args(0).matrix_type (mattyp); - - if (nargout > 1) - retval(1) = rcond; - - retval(0) = result; - - volatile double xrcond = rcond; - xrcond += 1.0; - if (nargout < 2 && (info == -1 || xrcond == 1.0)) - warning ("inverse: matrix singular to machine precision,\ - rcond = %g", rcond); + SparseMatrix m = arg.sparse_matrix_value (); + if (! error_state) + { + MatrixType mattyp = args(0).matrix_type (); + result = m.inverse (mattyp, info, rcond, 1); + args(0).matrix_type (mattyp); + } + } + else + { + Matrix m = arg.matrix_value (); + if (! error_state) + { + MatrixType mattyp = args(0).matrix_type (); + result = m.inverse (mattyp, info, rcond, 1); + args(0).matrix_type (mattyp); + } } } else if (arg.is_complex_type ()) { - ComplexMatrix m = arg.complex_matrix_value (); - - if (! error_state) + if (arg.is_sparse_type ()) { - MatrixType mattyp = args(0).matrix_type (); - - octave_idx_type info; - double rcond = 0.0; - - ComplexMatrix result = m.inverse (mattyp, info, rcond, 1); + SparseComplexMatrix m = arg.sparse_complex_matrix_value (); + if (! error_state) + { + MatrixType mattyp = args(0).matrix_type (); + result = m.inverse (mattyp, info, rcond, 1); + args(0).matrix_type (mattyp); + } + } + else + { + ComplexMatrix m = arg.complex_matrix_value (); + if (! error_state) + { + MatrixType mattyp = args(0).matrix_type (); + result = m.inverse (mattyp, info, rcond, 1); + args(0).matrix_type (mattyp); + } + } - args(0).matrix_type (mattyp); - if (nargout > 1) - retval(1) = rcond; - - retval(0) = result; - - volatile double xrcond = rcond; - xrcond += 1.0; - if (nargout < 2 && (info == -1 || xrcond == 1.0)) - warning ("inverse: matrix singular to machine precision,\ - rcond = %g", rcond); - } } else + gripe_wrong_type_arg ("inv", arg); + + + if (! error_state) { - gripe_wrong_type_arg ("inv", arg); + if (nargout > 1) + retval(1) = rcond; + + retval(0) = result; + + volatile double xrcond = rcond; + xrcond += 1.0; + if (nargout < 2 && (info == -1 || xrcond == 1.0)) + warning ("inverse: matrix singular to machine precision, rcond = %g", + rcond); } return retval;
--- a/src/DLD-FUNCTIONS/lu.cc +++ b/src/DLD-FUNCTIONS/lu.cc @@ -27,21 +27,30 @@ #include "CmplxLU.h" #include "dbleLU.h" +#include "SparseCmplxLU.h" +#include "SparsedbleLU.h" #include "defun-dld.h" #include "error.h" #include "gripes.h" #include "oct-obj.h" #include "utils.h" +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" DEFUN_DLD (lu, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {[@var{l}, @var{u}, @var{p}] =} lu (@var{a})\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}] =} lu (@var{s})\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}, @var{r}] =} lu (@var{s})\n\ +@deftypefnx {Loadable Function} {[@dots{}] =} lu (@var{s}, @var{thres})\n\ +@deftypefnx {Loadable Function} {@var{y} =} lu (@dots{})\n\ +@deftypefnx {Loadable Function} {[@dots{}] =} lu (@dots{}, 'vector')\n\ @cindex LU decomposition\n\ -Compute the LU decomposition of @var{a}, using subroutines from\n\ -@sc{Lapack}. The result is returned in a permuted form, according to\n\ -the optional return value @var{p}. For example, given the matrix\n\ -@code{a = [1, 2; 3, 4]},\n\ +Compute the LU decomposition of @var{a}. If @var{a} is full subroutines from\n\ +@sc{Lapack} are used and if @var{a} is sparse then UMFPACK is used. The\n\ +result is returned in a permuted form, according to the optional return\n\ +value @var{p}. For example, given the matrix @code{a = [1, 2; 3, 4]},\n\ \n\ @example\n\ [l, u, p] = lu (a)\n\ @@ -68,18 +77,92 @@ @end example\n\ \n\ The matrix is not required to be square.\n\ +\n\ +Called with two or three output arguments and a spare input matrix,\n\ +then @dfn{lu} does not attempt to perform sparsity preserving column\n\ +permutations. Called with a fourth output argument, the sparsity\n\ +preserving column transformation @var{Q} is returned, such that\n\ +@code{@var{p} * @var{a} * @var{q} = @var{l} * @var{u}}.\n\ +\n\ +Called with a fifth output argument and a sparse input matrix, then\n\ +@dfn{lu} attempts to use a scaling factor @var{r} on the input matrix\n\ +such that @code{@var{p} * (@var{r} \\ @var{a}) * @var{q} = @var{l} * @var{u}}.\n\ +This typically leads to a sparser and more stable factorsation.\n\ +\n\ +An additional input argument @var{thres}, that defines the pivoting\n\ +threshold can be given. @var{thres} can be a scalar, in which case\n\ +it defines UMFPACK pivoting tolerance for both symmetric and unsymmetric\n\ +cases. If @var{thres} is a two element vector, then the first element\n\ +defines the pivoting tolerance for the unsymmetric UMFPACK pivoting\n\ +strategy and the second the symmetric strategy. By default, the values\n\ +defined by @code{spparms} are used and are by default @code{[0.1, 0.001]}.\n\ +\n\ +Given the string argument 'vector', @dfn{lu} returns the values of @var{p}\n\ +@var{q} as vector values, such that for full matrix, @code{@var{a}\n\ +(@var{p},:) = @var{l} * @var{u}}, and @code{@var{r}(@var{p},:) * @var{a}\n\ +(:, @var{q}) = @var{l} * @var{u}}.\n\ +\n\ +With two output arguments, returns the permuted forms of the upper and\n\ +lower triangular matrices, such that @code{@var{a} = @var{l} * @var{u}}.\n\ +With one output argument @var{y}, then the matrix returned by the @sc{Lapack}\n\ +routines is returned. If the input matrix is sparse then the matrix @var{l}\n\ +is embedded into @var{u} to give a return value similar to the full case.\n\ +For both full and sparse matrices, @dfn{lu} looses the permutation\n\ +information.\n\ @end deftypefn") { octave_value_list retval; + int nargin = args.length (); + bool issparse = (nargin > 0 && args(0).is_sparse_type ()); + bool scale = (nargout == 5); - int nargin = args.length (); - - if (nargin != 1 || nargout > 3) + if (nargin < 1 || (issparse && (nargin > 3 || nargout > 5)) + || (!issparse && (nargin > 2 || nargout > 3))) { print_usage (); return retval; } + bool vecout = false; + Matrix thres; + + int n = 1; + while (n < nargin && ! error_state) + { + if (args (n).is_string ()) + { + std::string tmp = args(n++).string_value (); + + if (! error_state ) + { + if (tmp.compare ("vector") == 0) + vecout = true; + else + error ("lu: unrecognized string argument"); + } + } + else + { + Matrix tmp = args(n++).matrix_value (); + + if (! error_state ) + { + if (!issparse) + error ("lu: can not define pivoting threshold for full matrices"); + else if (tmp.nelem () == 1) + { + thres.resize(1,2); + thres(0) = tmp(0); + thres(1) = tmp(0); + } + else if (tmp.nelem () == 2) + thres = tmp; + else + error ("lu: expecting 2 element vector for thres"); + } + } + } + octave_value arg = args(0); octave_idx_type nr = arg.rows (); @@ -87,18 +170,94 @@ int arg_is_empty = empty_arg ("lu", nr, nc); - if (arg_is_empty < 0) - return retval; - else if (arg_is_empty > 0) - return octave_value_list (3, Matrix ()); + if (issparse) + { + if (arg_is_empty < 0) + return retval; + else if (arg_is_empty > 0) + return octave_value_list (5, SparseMatrix ()); + + ColumnVector Qinit; + if (nargout < 4) + { + Qinit.resize (nc); + for (octave_idx_type i = 0; i < nc; i++) + Qinit (i) = i; + } + + if (arg.is_real_type ()) + { + SparseMatrix m = arg.sparse_matrix_value (); + + switch (nargout) + { + case 0: + case 1: + case 2: + { + SparseLU fact (m, Qinit, thres, false, true); + + if (nargout < 2) + retval (0) = fact.Y (); + else + { + SparseMatrix P = fact.Pr (); + SparseMatrix L = P.transpose () * fact.L (); + retval(1) = octave_value (fact.U (), + MatrixType (MatrixType::Upper)); + + retval(0) = octave_value (L, + MatrixType (MatrixType::Permuted_Lower, + nr, fact.row_perm ())); + } + } + break; - if (arg.is_real_type ()) - { - Matrix m = arg.matrix_value (); + case 3: + { + SparseLU fact (m, Qinit, thres, false, true); + + if (vecout) + retval (2) = fact.Pr_vec (); + else + retval(2) = fact.Pr (); + + retval(1) = octave_value (fact.U (), + MatrixType (MatrixType::Upper)); + retval(0) = octave_value (fact.L (), + MatrixType (MatrixType::Lower)); + } + break; + + case 4: + default: + { + SparseLU fact (m, thres, scale); - if (! error_state) + if (scale) + retval(4) = fact.R (); + + if (vecout) + { + retval(3) = fact.Pc_vec (); + retval(2) = fact.Pr_vec (); + } + else + { + retval(3) = fact.Pc (); + retval(2) = fact.Pr (); + } + retval(1) = octave_value (fact.U (), + MatrixType (MatrixType::Upper)); + retval(0) = octave_value (fact.L (), + MatrixType (MatrixType::Lower)); + } + break; + } + } + else if (arg.is_complex_type ()) { - LU fact (m); + SparseComplexMatrix m = arg.sparse_complex_matrix_value (); switch (nargout) { @@ -106,55 +265,154 @@ case 1: case 2: { - Matrix P = fact.P (); - Matrix L = P.transpose () * fact.L (); - retval(1) = fact.U (); - retval(0) = L; + SparseComplexLU fact (m, Qinit, thres, false, true); + + if (nargout < 2) + retval (0) = fact.Y (); + else + { + SparseMatrix P = fact.Pr (); + SparseComplexMatrix L = P.transpose () * fact.L (); + retval(1) = octave_value (fact.U (), + MatrixType (MatrixType::Upper)); + + retval(0) = octave_value (L, + MatrixType (MatrixType::Permuted_Lower, + nr, fact.row_perm ())); + } } break; case 3: + { + SparseComplexLU fact (m, Qinit, thres, false, true); + + if (vecout) + retval (2) = fact.Pr_vec (); + else + retval(2) = fact.Pr (); + + retval(1) = octave_value (fact.U (), + MatrixType (MatrixType::Upper)); + retval(0) = octave_value (fact.L (), + MatrixType (MatrixType::Lower)); + } + break; + + case 4: default: - retval(2) = fact.P (); - retval(1) = fact.U (); - retval(0) = fact.L (); + { + SparseComplexLU fact (m, thres, scale); + + if (scale) + retval(4) = fact.R (); + + if (vecout) + { + retval(3) = fact.Pc_vec (); + retval(2) = fact.Pr_vec (); + } + else + { + retval(3) = fact.Pc (); + retval(2) = fact.Pr (); + } + retval(1) = octave_value (fact.U (), + MatrixType (MatrixType::Upper)); + retval(0) = octave_value (fact.L (), + MatrixType (MatrixType::Lower)); + } break; } } - } - else if (arg.is_complex_type ()) - { - ComplexMatrix m = arg.complex_matrix_value (); - - if (! error_state) - { - ComplexLU fact (m); - - switch (nargout) - { - case 0: - case 1: - case 2: - { - Matrix P = fact.P (); - ComplexMatrix L = P.transpose () * fact.L (); - retval(1) = fact.U (); - retval(0) = L; - } - break; - - case 3: - default: - retval(2) = fact.P (); - retval(1) = fact.U (); - retval(0) = fact.L (); - break; - } - } + else + gripe_wrong_type_arg ("lu", arg); } else { - gripe_wrong_type_arg ("lu", arg); + if (arg_is_empty < 0) + return retval; + else if (arg_is_empty > 0) + return octave_value_list (3, Matrix ()); + + if (arg.is_real_type ()) + { + Matrix m = arg.matrix_value (); + + if (! error_state) + { + LU fact (m); + + switch (nargout) + { + case 0: + case 1: + retval(0) = fact.Y (); + break; + + case 2: + { + Matrix P = fact.P (); + Matrix L = P.transpose () * fact.L (); + retval(1) = fact.U (); + retval(0) = L; + } + break; + + case 3: + default: + { + if (vecout) + retval(2) = fact.P_vec (); + else + retval(2) = fact.P (); + retval(1) = fact.U (); + retval(0) = fact.L (); + } + break; + } + } + } + else if (arg.is_complex_type ()) + { + ComplexMatrix m = arg.complex_matrix_value (); + + if (! error_state) + { + ComplexLU fact (m); + + switch (nargout) + { + case 0: + case 1: + retval(0) = fact.Y (); + break; + + case 2: + { + Matrix P = fact.P (); + ComplexMatrix L = P.transpose () * fact.L (); + retval(1) = fact.U (); + retval(0) = L; + } + break; + + case 3: + default: + { + if (vecout) + retval(2) = fact.P_vec (); + else + retval(2) = fact.P (); + retval(1) = fact.U (); + retval(0) = fact.L (); + } + break; + } + } + } + else + gripe_wrong_type_arg ("lu", arg); } return retval;
--- a/src/DLD-FUNCTIONS/luinc.cc +++ b/src/DLD-FUNCTIONS/luinc.cc @@ -90,6 +90,9 @@ \n\ All other fields in @var{opts} are ignored. The outputs from @dfn{luinc}\n\ are the same as for @dfn{lu}.\n\ +\n\ +Given the string argument 'vector', @dfn{luinc} returns the values of @var{p}\n\ +@var{q} as vector values.\n\ @seealso{sparse, lu, cholinc}\n\ @end deftypefn") { @@ -98,15 +101,16 @@ if (nargin == 0) print_usage (); - else if (nargin != 2) + else if (nargin < 2 || nargin > 3) error ("luinc: incorrect number of arguments"); else { bool zero_level = false; bool milu = false; bool udiag = false; - bool thresh = -1; + Matrix thresh; double droptol = -1.; + bool vecout; if (args(1).is_string ()) { @@ -137,11 +141,34 @@ } if (map.contains ("thresh")) - thresh = map.contents ("thresh")(0).double_value (); + { + thresh = map.contents ("thresh")(0).matrix_value (); + + if (thresh.nelem () == 1) + { + thresh.resize(1,2); + thresh(1) = thresh(0); + } + else if (thresh.nelem () != 2) + error ("chol: expecting 2 element vector for thresh"); + } } else droptol = args(1).double_value (); + if (nargin == 3) + { + std::string tmp = args(2).string_value (); + + if (! error_state ) + { + if (tmp.compare ("vector") == 0) + vecout = true; + else + error ("luinc: unrecognized string argument"); + } + } + // FIXME Add code for zero-level factorization if (zero_level) error ("luinc: zero-level factorization not implemented"); @@ -166,7 +193,7 @@ case 1: case 2: { - SparseLU fact (sm, Qinit, thresh, true, droptol, + SparseLU fact (sm, Qinit, thresh, false, true, droptol, milu, udiag); if (! error_state) @@ -184,12 +211,15 @@ case 3: { - SparseLU fact (sm, Qinit, thresh, true, droptol, + SparseLU fact (sm, Qinit, thresh, false, true, droptol, milu, udiag); if (! error_state) { - retval(2) = fact.Pr (); + if (vecout) + retval(2) = fact.Pr_vec (); + else + retval(2) = fact.Pr (); retval(1) = octave_value (fact.U (), MatrixType (MatrixType::Upper)); retval(0) = octave_value (fact.L (), @@ -201,13 +231,21 @@ case 4: default: { - SparseLU fact (sm, Qinit, thresh, false, droptol, + SparseLU fact (sm, Qinit, thresh, false, false, droptol, milu, udiag); if (! error_state) { - retval(3) = fact.Pc (); - retval(2) = fact.Pr (); + if (vecout) + { + retval(3) = fact.Pc_vec (); + retval(2) = fact.Pr_vec (); + } + else + { + retval(3) = fact.Pc (); + retval(2) = fact.Pr (); + } retval(1) = octave_value (fact.U (), MatrixType (MatrixType::Upper)); retval(0) = octave_value (fact.L (), @@ -237,7 +275,7 @@ case 1: case 2: { - SparseComplexLU fact (sm, Qinit, thresh, true, + SparseComplexLU fact (sm, Qinit, thresh, false, true, droptol, milu, udiag); @@ -256,12 +294,15 @@ case 3: { - SparseComplexLU fact (sm, Qinit, thresh, true, + SparseComplexLU fact (sm, Qinit, thresh, false, true, droptol, milu, udiag); if (! error_state) { - retval(2) = fact.Pr (); + if (vecout) + retval(2) = fact.Pr_vec (); + else + retval(2) = fact.Pr (); retval(1) = octave_value (fact.U (), MatrixType (MatrixType::Upper)); retval(0) = octave_value (fact.L (), @@ -273,13 +314,21 @@ case 4: default: { - SparseComplexLU fact (sm, Qinit, thresh, false, + SparseComplexLU fact (sm, Qinit, thresh, false, false, droptol, milu, udiag); if (! error_state) { - retval(3) = fact.Pc (); - retval(2) = fact.Pr (); + if (vecout) + { + retval(3) = fact.Pc_vec (); + retval(2) = fact.Pr_vec (); + } + else + { + retval(3) = fact.Pc (); + retval(2) = fact.Pr (); + } retval(1) = octave_value (fact.U (), MatrixType (MatrixType::Upper)); retval(0) = octave_value (fact.L (),
--- a/src/DLD-FUNCTIONS/sparse.cc +++ b/src/DLD-FUNCTIONS/sparse.cc @@ -39,12 +39,6 @@ #include "ov-cx-sparse.h" #include "ov-bool-sparse.h" -static bool -is_sparse (const octave_value& arg) -{ - return (arg.is_sparse_type ()); -} - DEFUN_DLD (issparse, args, , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {} issparse (@var{expr})\n\ @@ -57,7 +51,7 @@ return octave_value (); } else - return octave_value (is_sparse (args(0))); + return octave_value (args(0).is_sparse_type ()); } DEFUN_DLD (sparse, args, , @@ -132,7 +126,7 @@ { octave_value arg = args (0); - if (is_sparse (arg)) + if (arg.is_sparse_type ()) { if (use_complex) { @@ -387,342 +381,6 @@ return retval; } -#define SPARSE_DIM_ARG_BODY(NAME, FUNC) \ - int nargin = args.length(); \ - octave_value retval; \ - if ((nargin != 1 ) && (nargin != 2)) \ - print_usage (); \ - else { \ - int dim = (nargin == 1 ? -1 : args(1).int_value(true) - 1); \ - if (error_state) return retval; \ - if (dim < -1 || dim > 1) { \ - error (#NAME ": invalid dimension argument = %d", dim + 1); \ - return retval; \ - } \ - if (args(0).type_id () == \ - octave_sparse_matrix::static_type_id () || args(0).type_id () == \ - octave_sparse_bool_matrix::static_type_id ()) { \ - retval = args(0).sparse_matrix_value () .FUNC (dim); \ - } else if (args(0).type_id () == \ - octave_sparse_complex_matrix::static_type_id ()) { \ - retval = args(0).sparse_complex_matrix_value () .FUNC (dim); \ - } else \ - print_usage (); \ - } \ - return retval - -// PKG_ADD: dispatch ("prod", "spprod", "sparse matrix"); -// PKG_ADD: dispatch ("prod", "spprod", "sparse complex matrix"); -// PKG_ADD: dispatch ("prod", "spprod", "sparse bool matrix"); -DEFUN_DLD (spprod, args, , - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {@var{y} =} spprod (@var{x},@var{dim})\n\ -Product of elements along dimension @var{dim}. If @var{dim} is omitted,\n\ -it defaults to 1 (column-wise products).\n\ -@seealso{spsum, spsumsq}\n\ -@end deftypefn") -{ - SPARSE_DIM_ARG_BODY (spprod, prod); -} - -// PKG_ADD: dispatch ("cumprod", "spcumprod", "sparse matrix"); -// PKG_ADD: dispatch ("cumprod", "spcumprod", "sparse complex matrix"); -// PKG_ADD: dispatch ("cumprod", "spcumprod", "sparse bool matrix"); -DEFUN_DLD (spcumprod, args, , - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {@var{y} =} spcumprod (@var{x},@var{dim})\n\ -Cumulative product of elements along dimension @var{dim}. If @var{dim}\n\ -is omitted, it defaults to 1 (column-wise cumulative products).\n\ -@seealso{spcumsum}\n\ -@end deftypefn") -{ - SPARSE_DIM_ARG_BODY (spcumprod, cumprod); -} - -// PKG_ADD: dispatch ("sum", "spsum", "sparse matrix"); -// PKG_ADD: dispatch ("sum", "spsum", "sparse complex matrix"); -// PKG_ADD: dispatch ("sum", "spsum", "sparse bool matrix"); -DEFUN_DLD (spsum, args, , - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {@var{y} =} spsum (@var{x},@var{dim})\n\ -Sum of elements along dimension @var{dim}. If @var{dim} is omitted, it\n\ -defaults to 1 (column-wise sum).\n\ -@seealso{spprod, spsumsq}\n\ -@end deftypefn") -{ - SPARSE_DIM_ARG_BODY (spsum, sum); -} - -// PKG_ADD: dispatch ("cumsum", "spcumsum", "sparse matrix"); -// PKG_ADD: dispatch ("cumsum", "spcumsum", "sparse complex matrix"); -// PKG_ADD: dispatch ("cumsum", "spcumsum", "sparse bool matrix"); -DEFUN_DLD (spcumsum, args, , - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {@var{y} =} spcumsum (@var{x},@var{dim})\n\ -Cumulative sum of elements along dimension @var{dim}. If @var{dim}\n\ -is omitted, it defaults to 1 (column-wise cumulative sums).\n\ -@seealso{spcumprod}\n\ -@end deftypefn") -{ - SPARSE_DIM_ARG_BODY (spcumsum, cumsum); -} - -// PKG_ADD: dispatch ("sumsq", "spsumsq", "sparse matrix"); -// PKG_ADD: dispatch ("sumsq", "spsumsq", "sparse complex matrix"); -// PKG_ADD: dispatch ("sumsq", "spsumsq", "sparse bool matrix"); -DEFUN_DLD (spsumsq, args, , - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {@var{y} =} spsumsq (@var{x},@var{dim})\n\ -Sum of squares of elements along dimension @var{dim}. If @var{dim}\n\ -is omitted, it defaults to 1 (column-wise sum of squares).\n\ -This function is equivalent to computing\n\ -@example\n\ -spsum (x .* spconj (x), dim)\n\ -@end example\n\ -but it uses less memory and avoids calling @code{spconj} if @var{x} is\n\ -real.\n\ -@seealso{spprod, spsum}\n\ -@end deftypefn") -{ - SPARSE_DIM_ARG_BODY (spsumsq, sumsq); -} - - -static octave_value -make_spdiag (const octave_value& a, const octave_value& b) -{ - octave_value retval; - - if (a.is_complex_type ()) - { - SparseComplexMatrix m = a.sparse_complex_matrix_value (); - octave_idx_type k = b.nint_value(true); - - if (error_state) - return retval; - - octave_idx_type nr = m.rows (); - octave_idx_type nc = m.columns (); - - if (nr == 0 || nc == 0) - retval = m; - else if (nr == 1 || nc == 1) - { - octave_idx_type roff = 0; - octave_idx_type coff = 0; - if (k > 0) - { - roff = 0; - coff = k; - } - else if (k < 0) - { - k = -k; - roff = k; - coff = 0; - } - - if (nr == 1) - { - octave_idx_type n = nc + k; - octave_idx_type nz = m.nzmax (); - SparseComplexMatrix r (n, n, nz); - for (octave_idx_type i = 0; i < coff+1; i++) - r.xcidx (i) = 0; - for (octave_idx_type j = 0; j < nc; j++) - { - for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) - { - r.xdata (i) = m.data (i); - r.xridx (i) = j + roff; - } - r.xcidx (j+coff+1) = m.cidx(j+1); - } - for (octave_idx_type i = nc+coff+1; i < n+1; i++) - r.xcidx (i) = nz; - retval = r; - } - else - { - octave_idx_type n = nr + k; - octave_idx_type nz = m.nzmax (); - octave_idx_type ii = 0; - octave_idx_type ir = m.ridx(0); - SparseComplexMatrix r (n, n, nz); - for (octave_idx_type i = 0; i < coff+1; i++) - r.xcidx (i) = 0; - for (octave_idx_type i = 0; i < nr; i++) - { - if (ir == i) - { - r.xdata (ii) = m.data (ii); - r.xridx (ii++) = ir + roff; - if (ii != nz) - ir = m.ridx (ii); - } - r.xcidx (i+coff+1) = ii; - } - for (octave_idx_type i = nr+coff+1; i < n+1; i++) - r.xcidx (i) = nz; - retval = r; - } - } - else - { - SparseComplexMatrix r = m.diag (k); - // Don't use numel, since it can overflow for very large matrices - if (r.rows () > 0 && r.cols () > 0) - retval = r; - } - } - else if (a.is_real_type ()) - { - SparseMatrix m = a.sparse_matrix_value (); - - octave_idx_type k = b.nint_value(true); - - if (error_state) - return retval; - - octave_idx_type nr = m.rows (); - octave_idx_type nc = m.columns (); - - if (nr == 0 || nc == 0) - retval = m; - else if (nr == 1 || nc == 1) - { - octave_idx_type roff = 0; - octave_idx_type coff = 0; - if (k > 0) - { - roff = 0; - coff = k; - } - else if (k < 0) - { - k = -k; - roff = k; - coff = 0; - } - - if (nr == 1) - { - octave_idx_type n = nc + k; - octave_idx_type nz = m.nzmax (); - SparseMatrix r (n, n, nz); - - for (octave_idx_type i = 0; i < coff+1; i++) - r.xcidx (i) = 0; - for (octave_idx_type j = 0; j < nc; j++) - { - for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) - { - r.xdata (i) = m.data (i); - r.xridx (i) = j + roff; - } - r.xcidx (j+coff+1) = m.cidx(j+1); - } - for (octave_idx_type i = nc+coff+1; i < n+1; i++) - r.xcidx (i) = nz; - retval = r; - } - else - { - octave_idx_type n = nr + k; - octave_idx_type nz = m.nzmax (); - octave_idx_type ii = 0; - octave_idx_type ir = m.ridx(0); - SparseMatrix r (n, n, nz); - for (octave_idx_type i = 0; i < coff+1; i++) - r.xcidx (i) = 0; - for (octave_idx_type i = 0; i < nr; i++) - { - if (ir == i) - { - r.xdata (ii) = m.data (ii); - r.xridx (ii++) = ir + roff; - if (ii != nz) - ir = m.ridx (ii); - } - r.xcidx (i+coff+1) = ii; - } - for (octave_idx_type i = nr+coff+1; i < n+1; i++) - r.xcidx (i) = nz; - retval = r; - } - } - else - { - SparseMatrix r = m.diag (k); - if (r.rows () > 0 && r.cols () > 0) - retval = r; - } - } - else - gripe_wrong_type_arg ("spdiag", a); - - return retval; -} - -static octave_value -make_spdiag (const octave_value& a) -{ - octave_value retval; - octave_idx_type nr = a.rows (); - octave_idx_type nc = a.columns (); - - if (nr == 0 || nc == 0) - retval = SparseMatrix (); - else - retval = make_spdiag (a, octave_value (0.)); - - return retval; -} - -// PKG_ADD: dispatch ("diag", "spdiag", "sparse matrix"); -// PKG_ADD: dispatch ("diag", "spdiag", "sparse complex matrix"); -// PKG_ADD: dispatch ("diag", "spdiag", "sparse bool matrix"); -DEFUN_DLD (spdiag, args, , - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {} spdiag (@var{v}, @var{k})\n\ -Return a diagonal matrix with the sparse vector @var{v} on diagonal\n\ -@var{k}. The second argument is optional. If it is positive, the vector is\n\ -placed on the @var{k}-th super-diagonal. If it is negative, it is placed\n\ -on the @var{-k}-th sub-diagonal. The default value of @var{k} is 0, and\n\ -the vector is placed on the main diagonal. For example,\n\ -\n\ -@example\n\ -@group\n\ -spdiag ([1, 2, 3], 1)\n\ -ans =\n\ -\n\ -Compressed Column Sparse (rows=4, cols=4, nnz=3)\n\ - (1 , 2) -> 1\n\ - (2 , 3) -> 2\n\ - (3 , 4) -> 3\n\ -@end group\n\ -@end example\n\ -\n\ -@noindent\n\ -Given a matrix argument, instead of a vector, @code{spdiag} extracts the\n\ -@var{k}-th diagonal of the sparse matrix.\n\ -@seealso{diag}\n\ -@end deftypefn") -{ - octave_value retval; - - int nargin = args.length (); - - if (nargin == 1 && args(0).is_defined ()) - retval = make_spdiag (args(0)); - else if (nargin == 2 && args(0).is_defined () && args(1).is_defined ()) - retval = make_spdiag (args(0), args(1)); - else - print_usage (); - - return retval; -} - /* ;;; Local Variables: *** ;;; mode: C++ ***
deleted file mode 100644 --- a/src/DLD-FUNCTIONS/splu.cc +++ /dev/null @@ -1,506 +0,0 @@ -/* - -Copyright (C) 2004, 2005, 2006, 2007 David Bateman -Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 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 "defun-dld.h" -#include "error.h" -#include "gripes.h" -#include "oct-obj.h" -#include "utils.h" - -#include "SparseCmplxLU.h" -#include "SparsedbleLU.h" -#include "ov-re-sparse.h" -#include "ov-cx-sparse.h" - -// PKG_ADD: dispatch ("lu", "splu", "sparse matrix"); -// PKG_ADD: dispatch ("lu", "splu", "sparse complex matrix"); -// PKG_ADD: dispatch ("lu", "splu", "sparse bool matrix"); -DEFUN_DLD (splu, args, nargout, - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {[@var{l}, @var{u}] =} splu (@var{a})\n\ -@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}] =} splu (@var{a})\n\ -@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}, @var{Q}] =} splu (@var{a})\n\ -@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}, @var{Q}] =} splu (@dots{}, @var{thres})\n\ -@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}] =} splu (@dots{}, @var{Q})\n\ -@cindex LU decomposition\n\ -Compute the LU decomposition of the sparse matrix @var{a}, using\n\ -subroutines from UMFPACK. The result is returned in a permuted\n\ -form, according to the optional return values @var{P} and @var{Q}.\n\ -\n\ -Called with two or three output arguments and a single input argument,\n\ -@dfn{splu} is a replacement for @dfn{lu}, and therefore the sparsity\n\ -preserving column permutations @var{Q} are not performed. Called with\n\ -a fourth output argument, the sparsity preserving column transformation\n\ -@var{Q} is returned, such that @code{@var{P} * @var{a} * @var{Q} =\n\ -@var{l} * @var{u}}.\n\ -\n\ -An additional input argument @var{thres}, that defines the pivoting\n\ -threshold can be given. Alternatively, the desired sparsity preserving\n\ -column permutations @var{Q} can be passed. Note that @var{Q} is assumed\n\ -to be fixed if there are fewer than four output arguments. Otherwise,\n\ -the updated column permutations are returned as the fourth argument.\n\ -\n\ -With two output arguments, returns the permuted forms of the upper and\n\ -lower triangular matrices, such that @code{@var{a} = @var{l} * @var{u}}.\n\ -With two or three output arguments, if a user-defined @var{Q} is given,\n\ -then @code{@var{u} * @var{Q}'} is returned. The matrix is not required to\n\ -be square.\n\ -@seealso{sparse, spinv, colamd, symamd}\n\ -@end deftypefn") -{ - octave_value_list retval; - - int nargin = args.length (); - - if (nargin < 1 || nargin > 3 || nargout > 4) - { - print_usage (); - return retval; - } - - octave_value arg = args(0); - - octave_idx_type nr = arg.rows (); - octave_idx_type nc = arg.columns (); - - int arg_is_empty = empty_arg ("splu", nr, nc); - - if (arg_is_empty < 0) - return retval; - else if (arg_is_empty > 0) - return octave_value_list (3, SparseMatrix ()); - - ColumnVector Qinit; - bool have_Qinit = false; - double thres = -1.; - - for (int k = 1; k < nargin; k++) - { - if (args(k).is_sparse_type ()) - { - SparseMatrix tmp = args (k).sparse_matrix_value (); - - if (error_state) - { - error ("splu: Not a valid permutation/threshold"); - return retval; - } - - dim_vector dv = tmp.dims (); - - if (dv(0) == 1 && dv(1) == 1) - thres = tmp (0); - else if (dv(0) == 1 || dv(1) == 1) - { - octave_idx_type nel = tmp.numel (); - Qinit.resize (nel); - for (octave_idx_type i = 0; i < nel; i++) - Qinit (i) = tmp (i) - 1; - have_Qinit = true; - } - else - { - octave_idx_type t_nc = tmp.cols (); - - if (tmp.nzmax () != t_nc) - error ("splu: Not a valid permutation matrix"); - else - { - for (octave_idx_type i = 0; i < t_nc + 1; i++) - if (tmp.cidx(i) != i) - { - error ("splu: Not a valid permutation matrix"); - break; - } - } - - if (!error_state) - { - for (octave_idx_type i = 0; i < t_nc; i++) - if (tmp.data (i) != 1.) - { - error ("splu: Not a valid permutation matrix"); - break; - } - else - Qinit (i) = tmp.ridx (i) - 1; - } - - if (! error_state) - have_Qinit = true; - } - } - else - { - NDArray tmp = args(k).array_value (); - - if (error_state) - return retval; - - dim_vector dv = tmp.dims (); - if (dv.length () > 2) - { - error ("splu: second argument must be a vector/matrix or a scalar"); - } - else if (dv(0) == 1 && dv(1) == 1) - thres = tmp (0); - else if (dv(0) == 1 || dv(1) == 1) - { - octave_idx_type nel = tmp.numel (); - Qinit.resize (nel); - for (octave_idx_type i = 0; i < nel; i++) - Qinit (i) = tmp (i) - 1; - have_Qinit = true; - } - else - { - SparseMatrix tmp2 (tmp); - - octave_idx_type t_nc = tmp2.cols (); - - if (tmp2.nzmax () != t_nc) - error ("splu: Not a valid permutation matrix"); - else - { - for (octave_idx_type i = 0; i < t_nc + 1; i++) - if (tmp2.cidx(i) != i) - { - error ("splu: Not a valid permutation matrix"); - break; - } - } - - if (!error_state) - { - for (octave_idx_type i = 0; i < t_nc; i++) - if (tmp2.data (i) != 1.) - { - error ("splu: Not a valid permutation matrix"); - break; - } - else - Qinit (i) = tmp2.ridx (i) - 1; - } - - if (! error_state) - have_Qinit = true; - } - } - } - - if (error_state) - return retval; - - if (arg.is_real_type ()) - { - SparseMatrix m = arg.sparse_matrix_value (); - - if (nargout < 4 && ! have_Qinit) - { - octave_idx_type m_nc = m.cols (); - Qinit.resize (m_nc); - for (octave_idx_type i = 0; i < m_nc; i++) - Qinit (i) = i; - } - - if (! error_state) - { - switch (nargout) - { - case 0: - case 1: - case 2: - { - SparseLU fact (m, Qinit, thres, true); - - SparseMatrix P = fact.Pr (); - SparseMatrix L = P.transpose () * fact.L (); - if (have_Qinit) - retval(1) = octave_value (fact.U () * fact.Pc ().transpose (), - MatrixType (MatrixType::Permuted_Upper, nc, fact.col_perm ())); - else - retval(1) = octave_value (fact.U (), - MatrixType (MatrixType::Upper)); - - retval(0) = octave_value (L, - MatrixType (MatrixType::Permuted_Lower, nr, fact.row_perm ())); - } - break; - - case 3: - { - SparseLU fact (m, Qinit, thres, true); - - retval(2) = fact.Pr (); - if (have_Qinit) - retval(1) = octave_value (fact.U () * fact.Pc ().transpose (), - MatrixType (MatrixType::Permuted_Upper, nc, fact.col_perm ())); - else - retval(1) = octave_value (fact.U (), - MatrixType (MatrixType::Upper)); - - retval(0) = octave_value (fact.L (), - MatrixType (MatrixType::Lower)); - } - break; - - case 4: - default: - { - if (have_Qinit) - { - SparseLU fact (m, Qinit, thres, false); - - retval(3) = fact.Pc (); - retval(2) = fact.Pr (); - retval(1) = octave_value (fact.U (), - MatrixType (MatrixType::Upper)); - retval(0) = octave_value (fact.L (), - MatrixType (MatrixType::Lower)); - } - else - { - SparseLU fact (m, thres); - - retval(3) = fact.Pc (); - retval(2) = fact.Pr (); - retval(1) = octave_value (fact.U (), - MatrixType (MatrixType::Upper)); - retval(0) = octave_value (fact.L (), - MatrixType (MatrixType::Lower)); - } - } - break; - } - } - } - else if (arg.is_complex_type ()) - { - SparseComplexMatrix m = arg.sparse_complex_matrix_value (); - - if (nargout < 4 && ! have_Qinit) - { - octave_idx_type m_nc = m.cols (); - Qinit.resize (m_nc); - for (octave_idx_type i = 0; i < m_nc; i++) - Qinit (i) = i; - } - - if (! error_state) - { - switch (nargout) - { - case 0: - case 1: - case 2: - { - SparseComplexLU fact (m, Qinit, thres, true); - - SparseMatrix P = fact.Pr (); - SparseComplexMatrix L = P.transpose () * fact.L (); - - if (have_Qinit) - retval(1) = octave_value (fact.U () * fact.Pc ().transpose (), - MatrixType (MatrixType::Permuted_Upper, nc, fact.col_perm ())); - else - retval(1) = octave_value (fact.U (), - MatrixType (MatrixType::Upper)); - - retval(0) = octave_value (L, - MatrixType (MatrixType::Permuted_Lower, nr, fact.row_perm ())); - } - break; - - case 3: - { - SparseComplexLU fact (m, Qinit, thres, true); - - retval(2) = fact.Pr (); - if (have_Qinit) - retval(1) = octave_value (fact.U () * fact.Pc ().transpose (), - MatrixType (MatrixType::Permuted_Upper, nc, fact.col_perm ())); - else - retval(1) = octave_value (fact.U (), - MatrixType (MatrixType::Upper)); - - retval(0) = octave_value (fact.L (), - MatrixType (MatrixType::Lower)); - } - break; - - case 4: - default: - { - if (have_Qinit) - { - SparseComplexLU fact (m, Qinit, thres, false); - - retval(3) = fact.Pc (); - retval(2) = fact.Pr (); - retval(1) = octave_value (fact.U (), - MatrixType (MatrixType::Upper)); - retval(0) = octave_value (fact.L (), - MatrixType (MatrixType::Lower)); - } - else - { - SparseComplexLU fact (m, thres); - - retval(3) = fact.Pc (); - retval(2) = fact.Pr (); - retval(1) = octave_value (fact.U (), - MatrixType (MatrixType::Upper)); - retval(0) = octave_value (fact.L (), - MatrixType (MatrixType::Lower)); - } - } - break; - } - } - } - else - { - gripe_wrong_type_arg ("splu", arg); - } - - return retval; -} - -// PKG_ADD: dispatch ("inv", "spinv", "sparse matrix"); -// PKG_ADD: dispatch ("inv", "spinv", "sparse complex matrix"); -// PKG_ADD: dispatch ("inv", "spinv", "sparse bool matrix"); -// PKG_ADD: dispatch ("inverse", "spinv", "sparse matrix"); -// PKG_ADD: dispatch ("inverse", "spinv", "sparse complex matrix"); -// PKG_ADD: dispatch ("inverse", "spinv", "sparse bool matrix"); -DEFUN_DLD (spinv, args, nargout, - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {[@var{x}, @var{rcond}] = } spinv (@var{a}, @var{Q})\n\ -Compute the inverse of the sparse square matrix @var{a}. Return an estimate\n\ -of the reciprocal condition number if requested, otherwise warn of an\n\ -ill-conditioned matrix if the reciprocal condition number is small.\n\ -This function takes advantage of the sparsity of the matrix to accelerate\n\ -the calculation of the inverse.\n\ -\n\ -In general @var{x} will be a full matrix, and so if possible forming the\n\ -inverse of a sparse matrix should be avoided. It is significantly more\n\ -accurate and faster to do @code{@var{y} = @var{a} \\ @var{b}}, rather\n\ -than @code{@var{y} = spinv (@var{a}) * @var{b}}.\n\ -@end deftypefn") -{ - octave_value_list retval; - - int nargin = args.length (); - - if (nargin != 1) - { - print_usage (); - return retval; - } - - octave_value arg = args(0); - - octave_idx_type nr = arg.rows (); - octave_idx_type nc = arg.columns (); - - int arg_is_empty = empty_arg ("spinverse", nr, nc); - - if (arg_is_empty < 0) - return retval; - else if (arg_is_empty > 0) - return octave_value (Matrix ()); - - if (nr != nc) - { - gripe_square_matrix_required ("spinverse"); - return retval; - } - - if (arg.is_real_type ()) - { - - SparseMatrix m = arg.sparse_matrix_value (); - - if (! error_state) - { - MatrixType mattyp = args(0).matrix_type (); - - octave_idx_type info; - double rcond = 0.0; - SparseMatrix result = m.inverse (mattyp, info, rcond, 1); - - args(0).matrix_type (mattyp); - - if (nargout > 1) - retval(1) = rcond; - - retval(0) = result; - - volatile double xrcond = rcond; - xrcond += 1.0; - if (nargout < 2 && (info == -1 || xrcond == 1.0)) - warning ("spinverse: matrix singular to machine precision,\ - rcond = %g", rcond); - } - } - else if (arg.is_complex_type ()) - { - SparseComplexMatrix m = arg.sparse_complex_matrix_value (); - - if (! error_state) - { - MatrixType mattyp = args(0).matrix_type (); - - octave_idx_type info; - double rcond = 0.0; - - SparseComplexMatrix result = m.inverse (mattyp, info, rcond, 1); - - args(0).matrix_type (mattyp); - - if (nargout > 1) - retval(1) = rcond; - - retval(0) = result; - - volatile double xrcond = rcond; - xrcond += 1.0; - if (nargout < 2 && (info == -1 || xrcond == 1.0)) - warning ("spinverse: matrix singular to machine precision,\ - rcond = %g", rcond); - } - } - else - gripe_wrong_type_arg ("spinverse", arg); - - return retval; -} - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/
--- a/src/DLD-FUNCTIONS/spparms.cc +++ b/src/DLD-FUNCTIONS/spparms.cc @@ -72,8 +72,11 @@ use the sparsity preserving amd functions (default 1)\n\ @item piv_tol\n\ The pivot tolerance of the UMFPACK solvers (default 0.1)\n\ +@item sym_tol\n\ +The pivot tolerance of the UMFPACK symmetric solvers (default 0.001)\n\ @item bandden\n\ -?? (default 0.5)\n\ +The density of non-zero elements in a banded matrix before it is treated\n\ +by the LAPACK banded solvers (default 0.5)\n\ @item umfpack\n\ Flag whether the UMFPACK or mmd solvers are used for the LU, '\\' and\n\ '/' operations (default 1)\n\
rename from src/DLD-FUNCTIONS/spchol.cc rename to src/DLD-FUNCTIONS/symbfact.cc --- a/src/DLD-FUNCTIONS/spchol.cc +++ b/src/DLD-FUNCTIONS/symbfact.cc @@ -25,313 +25,19 @@ #include <config.h> #endif +#include "SparseCmplxCHOL.h" +#include "SparsedbleCHOL.h" +#include "oct-spparms.h" +#include "sparse-util.h" + +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" #include "defun-dld.h" #include "error.h" #include "gripes.h" #include "oct-obj.h" #include "utils.h" -#include "SparseCmplxCHOL.h" -#include "SparsedbleCHOL.h" -#include "ov-re-sparse.h" -#include "ov-cx-sparse.h" -#include "oct-spparms.h" -#include "sparse-util.h" - -static octave_value_list -sparse_chol (const octave_value_list& args, const int nargout, - const std::string& name, const bool LLt) -{ - octave_value_list retval; - int nargin = args.length (); - - if (nargin != 1 || nargout > 3) - { - print_usage (); - return retval; - } - - octave_value arg = args(0); - - octave_idx_type nr = arg.rows (); - octave_idx_type nc = arg.columns (); - bool natural = (nargout != 3); - - int arg_is_empty = empty_arg (name.c_str(), nr, nc); - - if (arg_is_empty < 0) - return retval; - if (arg_is_empty > 0) - return octave_value (Matrix ()); - - if (arg.is_real_type ()) - { - SparseMatrix m = arg.sparse_matrix_value (); - - if (! error_state) - { - octave_idx_type info; - SparseCHOL fact (m, info, natural); - if (nargout == 3) - retval(2) = fact.Q(); - - if (nargout > 1 || info == 0) - { - retval(1) = fact.P(); - if (LLt) - retval(0) = fact.L(); - else - retval(0) = fact.R(); - } - else - error ("%s: matrix not positive definite", name.c_str()); - } - } - else if (arg.is_complex_type ()) - { - SparseComplexMatrix m = arg.sparse_complex_matrix_value (); - - if (! error_state) - { - octave_idx_type info; - SparseComplexCHOL fact (m, info, natural); - - if (nargout == 3) - retval(2) = fact.Q(); - - if (nargout > 1 || info == 0) - { - retval(1) = fact.P(); - if (LLt) - retval(0) = fact.L(); - else - retval(0) = fact.R(); - } - else - error ("%s: matrix not positive definite", name.c_str()); - } - } - else - gripe_wrong_type_arg (name.c_str(), arg); - - return retval; -} - -// PKG_ADD: dispatch ("chol", "spchol", "sparse matrix"); -// PKG_ADD: dispatch ("chol", "spchol", "sparse complex matrix"); -// PKG_ADD: dispatch ("chol", "spchol", "sparse bool matrix"); -DEFUN_DLD (spchol, args, nargout, - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {@var{r} =} spchol (@var{a})\n\ -@deftypefnx {Loadable Function} {[@var{r}, @var{p}] =} spchol (@var{a})\n\ -@deftypefnx {Loadable Function} {[@var{r}, @var{p}, @var{q}] =} spchol (@var{a})\n\ -@cindex Cholesky factorization\n\ -Compute the Cholesky factor, @var{r}, of the symmetric positive definite\n\ -sparse matrix @var{a}, where\n\ -@iftex\n\ -@tex\n\ -$ R^T R = A $.\n\ -@end tex\n\ -@end iftex\n\ -@ifinfo\n\ -\n\ -@example\n\ -r' * r = a.\n\ -@end example\n\ -@end ifinfo\n\ -\n\ -If called with 2 or more outputs @var{p} is the 0 when @var{r} is positive\n\ -definite and @var{p} is a positive integer otherwise.\n\ -\n\ -If called with 3 outputs then a sparsity preserving row/column permutation\n\ -is applied to @var{a} prior to the factorization. That is @var{r}\n\ -is the factorization of @code{@var{a}(@var{q},@var{q})} such that\n\ -@iftex\n\ -@tex\n\ -$ R^T R = Q A Q^T$.\n\ -@end tex\n\ -@end iftex\n\ -@ifinfo\n\ -\n\ -@example\n\ -r' * r = q * a * q'.\n\ -@end example\n\ -@end ifinfo\n\ -\n\ -Note that @code{splchol} factorization is faster and uses less memory.\n\ -@seealso{spcholinv, spchol2inv, splchol}\n\ -@end deftypefn") -{ - return sparse_chol (args, nargout, "spchol", false); -} - -// PKG_ADD: dispatch ("lchol", "splchol", "sparse matrix"); -// PKG_ADD: dispatch ("lchol", "splchol", "sparse complex matrix"); -// PKG_ADD: dispatch ("lchol", "splchol", "sparse bool matrix"); -DEFUN_DLD (splchol, args, nargout, - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {@var{l} =} splchol (@var{a})\n\ -@deftypefnx {Loadable Function} {[@var{l}, @var{p}] =} splchol (@var{a})\n\ -@deftypefnx {Loadable Function} {[@var{l}, @var{p}, @var{q}] =} splchol (@var{a})\n\ -@cindex Cholesky factorization\n\ -Compute the Cholesky factor, @var{l}, of the symmetric positive definite\n\ -sparse matrix @var{a}, where\n\ -@iftex\n\ -@tex\n\ -$ L L^T = A $.\n\ -@end tex\n\ -@end iftex\n\ -@ifinfo\n\ -\n\ -@example\n\ -l * l' = a.\n\ -@end example\n\ -@end ifinfo\n\ -\n\ -If called with 2 or more outputs @var{p} is the 0 when @var{l} is positive\n\ -definite and @var{l} is a positive integer otherwise.\n\ -\n\ -If called with 3 outputs that a sparsity preserving row/column permutation\n\ -is applied to @var{a} prior to the factorization. That is @var{l}\n\ -is the factorization of @code{@var{a}(@var{q},@var{q})} such that\n\ -@iftex\n\ -@tex\n\ -$ L R^T = A (Q, Q)$.\n\ -@end tex\n\ -@end iftex\n\ -@ifinfo\n\ -\n\ -@example\n\ -r * r' = a (q, q).\n\ -@end example\n\ -@end ifinfo\n\ -\n\ -Note that @code{splchol} factorization is faster and uses less memory\n\ -than @code{spchol}. @code{splchol(@var{a})} is equivalent to\n\ -@code{spchol(@var{a})'}.\n\ -@seealso{spcholinv, spchol2inv, splchol}\n\ -@end deftypefn") -{ - return sparse_chol (args, nargout, "splchol", true); -} - -// PKG_ADD: dispatch ("cholinv", "spcholinv", "sparse matrix"); -// PKG_ADD: dispatch ("cholinv", "spcholinv", "sparse complex matrix"); -// PKG_ADD: dispatch ("cholinv", "spcholinv", "sparse bool matrix"); -DEFUN_DLD (spcholinv, args, , - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {} spcholinv (@var{a})\n\ -Use the Cholesky factorization to compute the inverse of the\n\ -sparse symmetric positive definite matrix @var{a}.\n\ -@seealso{spchol, spchol2inv}\n\ -@end deftypefn") -{ - octave_value retval; - - int nargin = args.length (); - - if (nargin == 1) - { - octave_value arg = args(0); - - octave_idx_type nr = arg.rows (); - octave_idx_type nc = arg.columns (); - - if (nr == 0 || nc == 0) - retval = Matrix (); - else - { - if (arg.is_real_type ()) - { - SparseMatrix m = arg.sparse_matrix_value (); - - if (! error_state) - { - octave_idx_type info; - SparseCHOL chol (m, info); - if (info == 0) - retval = chol.inverse (); - else - error ("spcholinv: matrix not positive definite"); - } - } - else if (arg.is_complex_type ()) - { - SparseComplexMatrix m = arg.sparse_complex_matrix_value (); - - if (! error_state) - { - octave_idx_type info; - SparseComplexCHOL chol (m, info); - if (info == 0) - retval = chol.inverse (); - else - error ("spcholinv: matrix not positive definite"); - } - } - else - gripe_wrong_type_arg ("spcholinv", arg); - } - } - else - print_usage (); - - return retval; -} - -// PKG_ADD: dispatch ("chol2inv", "spchol2inv", "sparse matrix"); -// PKG_ADD: dispatch ("chol2inv", "spchol2inv", "sparse complex matrix"); -// PKG_ADD: dispatch ("chol2inv", "spchol2inv", "sparse bool matrix"); -DEFUN_DLD (spchol2inv, args, , - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {} spchol2inv (@var{u})\n\ -Invert a sparse symmetric, positive definite square matrix from its\n\ -Cholesky decomposition, @var{u}. Note that @var{u} should be an\n\ -upper-triangular matrix with positive diagonal elements.\n\ -@code{chol2inv (@var{u})} provides @code{inv (@var{u}'*@var{u})} but\n\ -it is much faster than using @code{inv}.\n\ -@seealso{spchol, spcholinv}\n\ -@end deftypefn") -{ - octave_value retval; - - int nargin = args.length (); - - if (nargin == 1) - { - octave_value arg = args(0); - - octave_idx_type nr = arg.rows (); - octave_idx_type nc = arg.columns (); - - if (nr == 0 || nc == 0) - retval = Matrix (); - else - { - if (arg.is_real_type ()) - { - SparseMatrix r = arg.sparse_matrix_value (); - - if (! error_state) - retval = chol2inv (r); - } - else if (arg.is_complex_type ()) - { - SparseComplexMatrix r = arg.sparse_complex_matrix_value (); - - if (! error_state) - retval = chol2inv (r); - } - else - gripe_wrong_type_arg ("spchol2inv", arg); - } - } - else - print_usage (); - - return retval; -} - DEFUN_DLD (symbfact, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {[@var{count}, @var{h}, @var{parent}, @var{post}, @var{r}] =} symbfact (@var{s}, @var{typ}, @var{mode})\n\
--- a/src/Makefile.in +++ b/src/Makefile.in @@ -70,8 +70,8 @@ givens.cc hess.cc inv.cc kron.cc lsode.cc \ lu.cc luinc.cc matrix_type.cc md5sum.cc minmax.cc pinv.cc qr.cc \ quad.cc qz.cc rand.cc regexp.cc schur.cc sparse.cc \ - spchol.cc splu.cc spparms.cc \ - sqrtm.cc svd.cc syl.cc symrcm.cc time.cc tsearch.cc typecast.cc \ + spparms.cc sqrtm.cc svd.cc syl.cc symrcm.cc symbfact.cc \ + time.cc tsearch.cc typecast.cc \ urlwrite.cc __contourc__.cc __delaunayn__.cc __dsearchn__.cc \ __glpk__.cc __lin_interpn__.cc __pchip_deriv__.cc \ __qp__.cc __voronoi__.cc
--- a/src/data.cc +++ b/src/data.cc @@ -455,20 +455,11 @@ if (! error_state) { - if (arg_x.is_sparse_type ()) - { - SparseMatrix x = arg_x.sparse_matrix_value (); - - if (! error_state) - retval = map_d_s (atan2, y, x); - } - else - { - NDArray x = arg_x.array_value (); - - if (! error_state) - retval = map_d_m (atan2, y, x); - } + // Even if x is sparse return a full matrix here + NDArray x = arg_x.array_value (); + + if (! error_state) + retval = map_d_m (atan2, y, x); } } else if (x_is_scalar) @@ -480,7 +471,7 @@ if (! error_state) { double x = arg_x.double_value (); - + if (! error_state) retval = map_s_d (atan2, y, x); } @@ -500,7 +491,8 @@ } else if (y_dims == x_dims) { - if (arg_y.is_sparse_type () || arg_x.is_sparse_type ()) + // Even if y is sparse return a full matrix here + if (arg_x.is_sparse_type ()) { SparseMatrix y = arg_y.sparse_matrix_value (); @@ -712,21 +704,67 @@ { \ if (dim >= -1) \ { \ - if (isnative) \ - { \ - if NATIVE_REDUCTION_1 (FCN, uint8, dim) \ - else if NATIVE_REDUCTION_1 (FCN, uint16, dim) \ - else if NATIVE_REDUCTION_1 (FCN, uint32, dim) \ - else if NATIVE_REDUCTION_1 (FCN, uint64, dim) \ - else if NATIVE_REDUCTION_1 (FCN, int8, dim) \ - else if NATIVE_REDUCTION_1 (FCN, int16, dim) \ - else if NATIVE_REDUCTION_1 (FCN, int32, dim) \ - else if NATIVE_REDUCTION_1 (FCN, int64, dim) \ - else if NATIVE_REDUCTION_1 (FCN, bool, dim) \ - else if (arg.is_char_matrix ()) \ - { \ - error (#FCN, ": invalid char type"); \ + if (arg.is_sparse_type ()) \ + { \ + if (arg.is_real_type ()) \ + { \ + SparseMatrix tmp = arg.sparse_matrix_value (); \ + \ + if (! error_state) \ + retval = tmp.FCN (dim); \ + } \ + else \ + { \ + SparseComplexMatrix tmp = arg.sparse_complex_matrix_value (); \ + \ + if (! error_state) \ + retval = tmp.FCN (dim); \ + } \ + } \ + else \ + { \ + if (isnative) \ + { \ + if NATIVE_REDUCTION_1 (FCN, uint8, dim) \ + else if NATIVE_REDUCTION_1 (FCN, uint16, dim) \ + else if NATIVE_REDUCTION_1 (FCN, uint32, dim) \ + else if NATIVE_REDUCTION_1 (FCN, uint64, dim) \ + else if NATIVE_REDUCTION_1 (FCN, int8, dim) \ + else if NATIVE_REDUCTION_1 (FCN, int16, dim) \ + else if NATIVE_REDUCTION_1 (FCN, int32, dim) \ + else if NATIVE_REDUCTION_1 (FCN, int64, dim) \ + else if NATIVE_REDUCTION_1 (FCN, bool, dim) \ + else if (arg.is_char_matrix ()) \ + { \ + error (#FCN, ": invalid char type"); \ + } \ + else if (arg.is_complex_type ()) \ + { \ + ComplexNDArray tmp = arg.complex_array_value (); \ + \ + if (! error_state) \ + retval = tmp.FCN (dim); \ + } \ + else if (arg.is_real_type ()) \ + { \ + NDArray tmp = arg.array_value (); \ + \ + if (! error_state) \ + retval = tmp.FCN (dim); \ + } \ + else \ + { \ + gripe_wrong_type_arg (#FCN, arg); \ + return retval; \ + } \ } \ + else if (arg.is_real_type ()) \ + { \ + NDArray tmp = arg.array_value (); \ + \ + if (! error_state) \ + retval = tmp.FCN (dim); \ + } \ else if (arg.is_complex_type ()) \ { \ ComplexNDArray tmp = arg.complex_array_value (); \ @@ -734,37 +772,11 @@ if (! error_state) \ retval = tmp.FCN (dim); \ } \ - else if (arg.is_real_type ()) \ - { \ - NDArray tmp = arg.array_value (); \ - \ - if (! error_state) \ - retval = tmp.FCN (dim); \ - } \ - else \ + else \ { \ gripe_wrong_type_arg (#FCN, arg); \ return retval; \ } \ - } \ - else if (arg.is_real_type ()) \ - { \ - NDArray tmp = arg.array_value (); \ - \ - if (! error_state) \ - retval = tmp.FCN (dim); \ - } \ - else if (arg.is_complex_type ()) \ - { \ - ComplexNDArray tmp = arg.complex_array_value (); \ - \ - if (! error_state) \ - retval = tmp.FCN (dim); \ - } \ - else \ - { \ - gripe_wrong_type_arg (#FCN, arg); \ - return retval; \ } \ } \ else \ @@ -795,17 +807,37 @@ { \ if (arg.is_real_type ()) \ { \ - NDArray tmp = arg.array_value (); \ + if (arg.is_sparse_type ()) \ + { \ + SparseMatrix tmp = arg.sparse_matrix_value (); \ \ - if (! error_state) \ - retval = tmp.FCN (dim); \ + if (! error_state) \ + retval = tmp.FCN (dim); \ + } \ + else \ + { \ + NDArray tmp = arg.array_value (); \ + \ + if (! error_state) \ + retval = tmp.FCN (dim); \ + } \ } \ else if (arg.is_complex_type ()) \ { \ - ComplexNDArray tmp = arg.complex_array_value (); \ + if (arg.is_sparse_type ()) \ + { \ + SparseComplexMatrix tmp = arg.sparse_complex_matrix_value (); \ \ - if (! error_state) \ - retval = tmp.FCN (dim); \ + if (! error_state) \ + retval = tmp.FCN (dim); \ + } \ + else \ + { \ + ComplexNDArray tmp = arg.complex_array_value (); \ + \ + if (! error_state) \ + retval = tmp.FCN (dim); \ + } \ } \ else \ { \ @@ -946,6 +978,94 @@ make_diag (const uint64NDArray& v, octave_idx_type k); #endif +template <class T> +static octave_value +make_spdiag (const T& v, octave_idx_type k) +{ + octave_value retval; + dim_vector dv = v.dims (); + octave_idx_type nr = dv (0); + octave_idx_type nc = dv (1); + + if (nr == 0 || nc == 0) + retval = T (); + else if (nr != 1 && nc != 1) + retval = v.diag (k); + else + { + octave_idx_type roff = 0; + octave_idx_type coff = 0; + if (k > 0) + { + roff = 0; + coff = k; + } + else if (k < 0) + { + roff = -k; + coff = 0; + } + + if (nr == 1) + { + octave_idx_type n = nc + std::abs (k); + octave_idx_type nz = v.nzmax (); + T r (n, n, nz); + for (octave_idx_type i = 0; i < coff+1; i++) + r.xcidx (i) = 0; + for (octave_idx_type j = 0; j < nc; j++) + { + for (octave_idx_type i = v.cidx(j); i < v.cidx(j+1); i++) + { + r.xdata (i) = v.data (i); + r.xridx (i) = j + roff; + } + r.xcidx (j+coff+1) = v.cidx(j+1); + } + for (octave_idx_type i = nc+coff+1; i < n+1; i++) + r.xcidx (i) = nz; + retval = r; + } + else + { + octave_idx_type n = nr + std::abs (k); + octave_idx_type nz = v.nzmax (); + octave_idx_type ii = 0; + octave_idx_type ir = v.ridx(0); + T r (n, n, nz); + for (octave_idx_type i = 0; i < coff+1; i++) + r.xcidx (i) = 0; + for (octave_idx_type i = 0; i < nr; i++) + { + if (ir == i) + { + r.xdata (ii) = v.data (ii); + r.xridx (ii++) = ir + roff; + if (ii != nz) + ir = v.ridx (ii); + } + r.xcidx (i+coff+1) = ii; + } + for (octave_idx_type i = nr+coff+1; i < n+1; i++) + r.xcidx (i) = nz; + retval = r; + } + } + + return retval; +} + +#if !defined (CXX_NEW_FRIEND_TEMPLATE_DECL) +static octave_value +make_spdiag (const SparseMatrix& v, octave_idx_type k); + +static octave_value +make_spdiag (const SparseComplexMatrix& v, octave_idx_type k); + +static octave_value +make_spdiag (const SparseBoolMatrix& v, octave_idx_type k); +#endif + static octave_value make_diag (const octave_value& a, octave_idx_type k) { @@ -954,17 +1074,35 @@ if (result_type == "double") { - if (a.is_real_type ()) + if (a.is_sparse_type ()) { - Matrix m = a.matrix_value (); - if (!error_state) - retval = make_diag (m, k); + if (a.is_real_type ()) + { + SparseMatrix m = a.sparse_matrix_value (); + if (!error_state) + retval = make_spdiag (m, k); + } + else + { + SparseComplexMatrix m = a.sparse_complex_matrix_value (); + if (!error_state) + retval = make_spdiag (m, k); + } } else { - ComplexMatrix m = a.complex_matrix_value (); - if (!error_state) - retval = make_diag (m, k); + if (a.is_real_type ()) + { + Matrix m = a.matrix_value (); + if (!error_state) + retval = make_diag (m, k); + } + else + { + ComplexMatrix m = a.complex_matrix_value (); + if (!error_state) + retval = make_diag (m, k); + } } } #if 0 @@ -983,9 +1121,18 @@ } else if (result_type == "logical") { - boolMatrix m = a.bool_matrix_value (); - if (!error_state) - retval = make_diag (m, k); + if (a.is_sparse_type ()) + { + SparseBoolMatrix m = a.sparse_bool_matrix_value (); + if (!error_state) + retval = make_spdiag (m, k); + } + else + { + boolMatrix m = a.bool_matrix_value (); + if (!error_state) + retval = make_diag (m, k); + } } else if (result_type == "int8") retval = make_diag (a.int8_array_value (), k);
--- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,10 @@ +2008-02-22 David Bateman <dbateman@free.fr> + + * build_sparse_tests.sh: Replaced removed sparse functions like + spdiag with their generic names. Fix lu tests for modified + syntax. Test vector and scaling or LU and chol functions. + * test_linalg.m: Change error message of failing chol/lu test. + 2008-02-19 David Bateman <dbateman@free.fr> * build_sparse_tests.sh: Replaced removed spars functions like
--- a/test/build_sparse_tests.sh +++ b/test/build_sparse_tests.sh @@ -180,11 +180,11 @@ %% of a singular matrix, which is consistent with the full matrix %% behaviour. They are therefore disabled.. %!testif HAVE_UMFPACK -%! assert(spinv(sparse([1,1;1,1+i])),sparse([1-1i,1i;1i,-1i]),10*eps); -% !error spinv( sparse( [1,1;1,1] ) ); -% !error spinv( sparse( [0,0;0,1] ) ); -% !error spinv( sparse( [0,0;0,1+i] ) ); -% !error spinv( sparse( [0,0;0,0] ) ); +%! assert(inv(sparse([1,1;1,1+i])),sparse([1-1i,1i;1i,-1i]),10*eps); +% !error inv( sparse( [1,1;1,1] ) ); +% !error inv( sparse( [0,0;0,1] ) ); +% !error inv( sparse( [0,0;0,1+i] ) ); +% !error inv( sparse( [0,0;0,0] ) ); %% error handling in constructor %!error sparse(1,[2,3],[1,2,3]); @@ -388,18 +388,18 @@ gen_matrixdiag_tests() { cat >>$TESTS <<EOF %% Matrix diagonal tests (uses af,as,bf,bs) -%!assert(spdiag(as),sparse(diag(af))) -%!assert(spdiag(bs),sparse(diag(bf))) -%!assert(spdiag(as,1),sparse(diag(af,1))) -%!assert(spdiag(bs,1),sparse(diag(bf,1))) -%!assert(spdiag(as,-1),sparse(diag(af,-1))) -%!assert(spdiag(bs,-1),sparse(diag(bf,-1))) -%!assert(spdiag(as(:)),sparse(diag(af(:)))) -%!assert(spdiag(as(:),1),sparse(diag(af(:),1))) -%!assert(spdiag(as(:),-1),sparse(diag(af(:),-1))) -%!assert(spdiag(as(:)'),sparse(diag(af(:)'))) -%!assert(spdiag(as(:)',1),sparse(diag(af(:)',1))) -%!assert(spdiag(as(:)',-1),sparse(diag(af(:)',-1))) +%!assert(diag(as),sparse(diag(af))) +%!assert(diag(bs),sparse(diag(bf))) +%!assert(diag(as,1),sparse(diag(af,1))) +%!assert(diag(bs,1),sparse(diag(bf,1))) +%!assert(diag(as,-1),sparse(diag(af,-1))) +%!assert(diag(bs,-1),sparse(diag(bf,-1))) +%!assert(diag(as(:)),sparse(diag(af(:)))) +%!assert(diag(as(:),1),sparse(diag(af(:),1))) +%!assert(diag(as(:),-1),sparse(diag(af(:),-1))) +%!assert(diag(as(:)'),sparse(diag(af(:)'))) +%!assert(diag(as(:)',1),sparse(diag(af(:)',1))) +%!assert(diag(as(:)',-1),sparse(diag(af(:)',-1))) %!assert(spdiags(as,[0,1]),[diag(af,0),diag(af,1)]) %!test [tb,tc]=spdiags(as); %! assert(spdiags(tb,tc,sparse(zeros(size(as)))),as) @@ -531,21 +531,21 @@ %!assert(!issparse(af)) %!assert(!(issparse(af)&&iscomplex(af))) %!assert(!(issparse(af)&&isreal(af))) -%!assert(spsum(as),sparse(sum(af))) -%!assert(spsum(as,1),sparse(sum(af,1))) -%!assert(spsum(as,2),sparse(sum(af,2))) -%!assert(spcumsum(as),sparse(cumsum(af))) -%!assert(spcumsum(as,1),sparse(cumsum(af,1))) -%!assert(spcumsum(as,2),sparse(cumsum(af,2))) -%!assert(spsumsq(as),sparse(sumsq(af))) -%!assert(spsumsq(as,1),sparse(sumsq(af,1))) -%!assert(spsumsq(as,2),sparse(sumsq(af,2))) -%!assert(spprod(as),sparse(prod(af))) -%!assert(spprod(as,1),sparse(prod(af,1))) -%!assert(spprod(as,2),sparse(prod(af,2))) -%!assert(spcumprod(as),sparse(cumprod(af))) -%!assert(spcumprod(as,1),sparse(cumprod(af,1))) -%!assert(spcumprod(as,2),sparse(cumprod(af,2))) +%!assert(sum(as),sparse(sum(af))) +%!assert(sum(as,1),sparse(sum(af,1))) +%!assert(sum(as,2),sparse(sum(af,2))) +%!assert(cumsum(as),sparse(cumsum(af))) +%!assert(cumsum(as,1),sparse(cumsum(af,1))) +%!assert(cumsum(as,2),sparse(cumsum(af,2))) +%!assert(sumsq(as),sparse(sumsq(af))) +%!assert(sumsq(as,1),sparse(sumsq(af,1))) +%!assert(sumsq(as,2),sparse(sumsq(af,2))) +%!assert(prod(as),sparse(prod(af))) +%!assert(prod(as,1),sparse(prod(af,1))) +%!assert(prod(as,2),sparse(prod(af,2))) +%!assert(cumprod(as),sparse(cumprod(af))) +%!assert(cumprod(as,1),sparse(cumprod(af,1))) +%!assert(cumprod(as,2),sparse(cumprod(af,2))) %!assert(min(as),sparse(min(af))) %!assert(full(min(as(:))),min(af(:))) @@ -634,20 +634,20 @@ %! assert(det(bs+speye(size(bs))),det(bf+eye(size(bf))),100*eps*abs(det(bf+eye(size(bf))))) %!testif HAVE_UMFPACK -%! [l,u]=splu(sparse([1,1;1,1])); +%! [l,u]=lu(sparse([1,1;1,1])); %! assert(l*u,[1,1;1,1],10*eps); %!testif HAVE_UMFPACK -%! [l,u]=splu(sparse([1,1;1,1+i])); +%! [l,u]=lu(sparse([1,1;1,1+i])); %! assert(l,sparse([1,2,2],[1,1,2],1),10*eps); %! assert(u,sparse([1,1,2],[1,2,2],[1,1,1i]),10*eps); %!testif HAVE_UMFPACK ;# permuted LU -%! [L,U] = splu(bs); +%! [L,U] = lu(bs); %! assert(L*U,bs,1e-10); %!testif HAVE_UMFPACK ;# simple LU + row permutations -%! [L,U,P] = splu(bs); +%! [L,U,P] = lu(bs); %! assert(P'*L*U,bs,1e-10); %! # triangularity %! [i,j,v]=find(L); @@ -656,7 +656,7 @@ %! assert(j-i>=0); %!testif HAVE_UMFPACK ;# simple LU + row/col permutations -%! [L,U,P,Q] = splu(bs); +%! [L,U,P,Q] = lu(bs); %! assert(P'*L*U*Q',bs,1e-10); %! # triangularity %! [i,j,v]=find(L); @@ -664,18 +664,18 @@ %! [i,j,v]=find(U); %! assert(j-i>=0); -%!testif HAVE_UMFPACK ;# LU with fixed column permutation -%! [L,U,P] = splu(bs,colamd(bs)); -%! assert(P'*L*U,bs,1e-10); +%!testif HAVE_UMFPACK ;# LU with vector permutations +%! [L,U,P] = lu(bs,'vector'); +%! assert(L(P,:)*U,bs,1e-10); %! # triangularity %! [i,j,v]=find(L); %! assert(i-j>=0); -%! [i,j,v]=find(U(:,colamd(bs))); +%! [i,j,v]=find(U); %! assert(j-i>=0); -%!testif HAVE_UMFPACK ;# LU with initial column permutation -%! [L,U,P,Q] = splu(bs,colamd(bs)); -%! assert(P'*L*U*Q',bs,1e-10); +%!testif HAVE_UMFPACK ;# LU with scaling +%! [L,U,P,Q,R] = lu(bs); +%! assert(R*P'*L*U*Q',bs,1e-10); %! # triangularity %! [i,j,v]=find(L); %! assert(i-j>=0); @@ -683,7 +683,7 @@ %! assert(j-i>=0); %!testif HAVE_UMFPACK ;# inverse -%! assert(spinv(bs)*bs,sparse(eye(rows(bs))),1e-10); +%! assert(inv(bs)*bs,sparse(eye(rows(bs))),1e-10); %!assert(bf\as',bf\af',100*eps); %!assert(bs\af',bf\af',100*eps); @@ -696,25 +696,25 @@ gen_cholesky_tests() { cat >>$TESTS <<EOF %!testif HAVE_CHOLMOD -%! assert(spchol(bs)'*spchol(bs),bs,1e-10); +%! assert(chol(bs)'*chol(bs),bs,1e-10); %!testif HAVE_CHOLMOD -%! assert(splchol(bs)*splchol(bs)',bs,1e-10); +%! assert(chol(bs,'lower')*chol(bs,'lower')',bs,1e-10); %!testif HAVE_CHOLMOD -%! assert(splchol(bs),spchol(bs)',1e-10); +%! assert(chol(bs,'lower'),chol(bs)',1e-10); %!testif HAVE_CHOLMOD ;# Return Partial Cholesky factorization -%! [RS,PS] = spchol(bs); +%! [RS,PS] = chol(bs); %! assert(RS'*RS,bs,1e-10); %! assert(PS,0); -%! [LS,PS] = splchol(bs); +%! [LS,PS] = chol(bs,'lower'); %! assert(LS*LS',bs,1e-10); %! assert(PS,0); %!testif HAVE_CHOLMOD ;# Permuted Cholesky factorization -%! [RS,PS,QS] = spchol(bs); +%! [RS,PS,QS] = chol(bs); %! assert(RS'*RS,QS*bs*QS',1e-10); %! assert(PS,0); -%! [LS,PS,QS] = splchol(bs); +%! [LS,PS,QS] = chol(bs,'lower'); %! assert(LS*LS',QS*bs*QS',1e-10); %! assert(PS,0);
--- a/test/test_linalg.m +++ b/test/test_linalg.m @@ -106,7 +106,7 @@ %!error <Invalid call to chol.*> chol (); %% test/octave.test/linalg/chol-5.m -%!error <Invalid call to chol.*> chol (1, 2); +%!error <unexpected second or third input.*> chol (1, 2); %% test/octave.test/linalg/hess-1.m %!test @@ -124,7 +124,7 @@ %!error hess ([1, 2; 3, 4; 5, 6]); %% test/octave.test/linalg/lu-1.m -%!assert(all (all (lu ([1, 2; 3, 4]) - [1/3, 1; 1, 0] < eps))); +%!assert(all (all (lu ([1, 2; 3, 4]) - [3, 4; 1/3, 2/3] < eps))); %% test/octave.test/linalg/lu-2.m %!test @@ -139,11 +139,17 @@ %! && abs (u - [3, 4; 0, 2/3]) < sqrt (eps) %! && abs (p - [0, 1; 1, 0]) < sqrt (eps))); +%!test +%! [l, u, p] = lu ([1, 2; 3, 4],'vector'); +%! assert((abs (l - [1, 0; 1/3, 1]) < sqrt (eps) +%! && abs (u - [3, 4; 0, 2/3]) < sqrt (eps) +%! && abs (p - [2;1]) < sqrt (eps))); + %% test/octave.test/linalg/lu-4.m %!error <Invalid call to lu.*> lu (); %% test/octave.test/linalg/lu-5.m -%!error <Invalid call to lu.*> lu ([1, 2; 3, 4], 2); +%!error lu ([1, 2; 3, 4], 2); %% test/octave.test/linalg/lu-6.m %!test