Mercurial > hg > octave-jordi
view libinterp/dldfcn/symbfact.cc @ 20938:b17fda023ca6
maint: Use new C++ archetype in more files.
Place input validation first in files.
Move declaration of retval down in function to be closer to point of usage.
Eliminate else clause after if () error.
Use "return ovl()" where it makes sense.
* find.cc, gammainc.cc, gcd.cc, getgrent.cc, getpwent.cc, givens.cc,
graphics.cc, help.cc, hess.cc, hex2num.cc, input.cc, kron.cc, load-path.cc,
load-save.cc, lookup.cc, mappers.cc, matrix_type.cc, mgorth.cc, nproc.cc,
ordschur.cc, pager.cc, pinv.cc, pr-output.cc, profiler.cc, psi.cc, quad.cc,
rcond.cc, regexp.cc, schur.cc, sighandlers.cc, sparse.cc, str2double.cc,
strfind.cc, strfns.cc, sub2ind.cc, svd.cc, sylvester.cc, symtab.cc,
syscalls.cc, sysdep.cc, time.cc, toplev.cc, tril.cc, tsearch.cc, typecast.cc,
urlwrite.cc, utils.cc, variables.cc, __delaunayn__.cc, __eigs__.cc,
__glpk__.cc, __magick_read__.cc, __osmesa_print__.cc, __voronoi__.cc, amd.cc,
audiodevinfo.cc, audioread.cc, chol.cc, colamd.cc, dmperm.cc, fftw.cc, qr.cc,
symbfact.cc, symrcm.cc, ov-bool-mat.cc, ov-cell.cc, ov-class.cc,
ov-classdef.cc, ov-fcn-handle.cc, ov-fcn-inline.cc, ov-flt-re-mat.cc,
ov-java.cc, ov-null-mat.cc, ov-oncleanup.cc, ov-re-mat.cc, ov-struct.cc,
ov-typeinfo.cc, ov-usr-fcn.cc, ov.cc, octave.cc:
Use new C++ archetype in more files.
author | Rik <rik@octave.org> |
---|---|
date | Fri, 18 Dec 2015 15:37:22 -0800 |
parents | 8da80da1ac37 |
children | 48b2ad5ee801 |
line wrap: on
line source
/* Copyright (C) 2005-2015 David Bateman Copyright (C) 1998-2005 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 "SparseCmplxCHOL.h" #include "SparsedbleCHOL.h" #include "oct-spparms.h" #include "sparse-util.h" #include "oct-locbuf.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" DEFUN_DLD (symbfact, args, nargout, "-*- texinfo -*-\n\ @deftypefn {} {[@var{count}, @var{h}, @var{parent}, @var{post}, @var{r}] =} symbfact (@var{S})\n\ @deftypefnx {} {[@dots{}] =} symbfact (@var{S}, @var{typ})\n\ @deftypefnx {} {[@dots{}] =} symbfact (@var{S}, @var{typ}, @var{mode})\n\ \n\ Perform a symbolic factorization analysis on the sparse matrix @var{S}.\n\ \n\ The input variables are\n\ \n\ @table @var\n\ @item S\n\ @var{S} is a complex or real sparse matrix.\n\ \n\ @item typ\n\ Is the type of the factorization and can be one of\n\ \n\ @table @samp\n\ @item sym\n\ Factorize @var{S}. This is the default.\n\ \n\ @item col\n\ Factorize @code{@var{S}' * @var{S}}.\n\ \n\ @item row\n\ Factorize @tcode{@var{S} * @var{S}'}.\n\ \n\ @item lo\n\ Factorize @tcode{@var{S}'}\n\ @end table\n\ \n\ @item mode\n\ The default is to return the Cholesky@tie{}factorization for @var{r}, and if\n\ @var{mode} is @qcode{'L'}, the conjugate transpose of the\n\ Cholesky@tie{}factorization is returned. The conjugate transpose version is\n\ faster and uses less memory, but returns the same values for @var{count},\n\ @var{h}, @var{parent} and @var{post} outputs.\n\ @end table\n\ \n\ The output variables are\n\ \n\ @table @var\n\ @item count\n\ The row counts of the Cholesky@tie{}factorization as determined by @var{typ}.\n\ \n\ @item h\n\ The height of the elimination tree.\n\ \n\ @item parent\n\ The elimination tree itself.\n\ \n\ @item post\n\ A sparse boolean matrix whose structure is that of the Cholesky\n\ factorization as determined by @var{typ}.\n\ @end table\n\ @end deftypefn") { #ifdef HAVE_CHOLMOD int nargin = args.length (); if (nargin < 1 || nargin > 3 || nargout > 5) print_usage (); octave_value_list retval; cholmod_common Common; cholmod_common *cm = &Common; CHOLMOD_NAME(start) (cm); double spu = octave_sparse_params::get_key ("spumoni"); if (spu == 0.) { cm->print = -1; SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0); } else { cm->print = static_cast<int> (spu) + 2; SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint); } cm->error_handler = &SparseCholError; SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex); SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot); double dummy; cholmod_sparse Astore; cholmod_sparse *A = &Astore; A->packed = true; A->sorted = true; A->nz = 0; #ifdef USE_64_BIT_IDX_T A->itype = CHOLMOD_LONG; #else A->itype = CHOLMOD_INT; #endif A->dtype = CHOLMOD_DOUBLE; A->stype = 1; A->x = &dummy; if (args(0).is_real_type ()) { const SparseMatrix a = args(0).sparse_matrix_value (); A->nrow = a.rows (); A->ncol = a.cols (); A->p = a.cidx (); A->i = a.ridx (); A->nzmax = a.nnz (); A->xtype = CHOLMOD_REAL; if (a.rows () > 0 && a.cols () > 0) A->x = a.data (); } else if (args(0).is_complex_type ()) { const SparseComplexMatrix a = args(0).sparse_complex_matrix_value (); A->nrow = a.rows (); A->ncol = a.cols (); A->p = a.cidx (); A->i = a.ridx (); A->nzmax = a.nnz (); A->xtype = CHOLMOD_COMPLEX; if (a.rows () > 0 && a.cols () > 0) A->x = a.data (); } else gripe_wrong_type_arg ("symbfact", args(0)); octave_idx_type coletree = false; octave_idx_type n = A->nrow; if (nargin > 1) { char ch; std::string str = args(1).string_value (); ch = tolower (str.c_str ()[0]); if (ch == 'r') A->stype = 0; else if (ch == 'c') { n = A->ncol; coletree = true; A->stype = 0; } else if (ch == 's') A->stype = 1; else if (ch == 's') A->stype = -1; else error ("symbfact: unrecognized TYP in symbolic factorization"); } if (A->stype && A->nrow != A->ncol) error ("symbfact: S must be a square matrix"); OCTAVE_LOCAL_BUFFER (octave_idx_type, Parent, n); OCTAVE_LOCAL_BUFFER (octave_idx_type, Post, n); OCTAVE_LOCAL_BUFFER (octave_idx_type, ColCount, n); OCTAVE_LOCAL_BUFFER (octave_idx_type, First, n); OCTAVE_LOCAL_BUFFER (octave_idx_type, Level, n); cholmod_sparse *F = CHOLMOD_NAME(transpose) (A, 0, cm); cholmod_sparse *Aup, *Alo; if (A->stype == 1 || coletree) { Aup = A ; Alo = F ; } else { Aup = F ; Alo = A ; } CHOLMOD_NAME(etree) (Aup, Parent, cm); if (cm->status < CHOLMOD_OK) error ("symbfact: matrix corrupted"); if (CHOLMOD_NAME(postorder) (Parent, n, 0, Post, cm) != n) error ("symbfact: postorder failed"); CHOLMOD_NAME(rowcolcounts) (Alo, 0, 0, Parent, Post, 0, ColCount, First, Level, cm); if (cm->status < CHOLMOD_OK) error ("symbfact: matrix corrupted"); if (nargout > 4) { cholmod_sparse *A1, *A2; if (A->stype == 1) { A1 = A; A2 = 0; } else if (A->stype == -1) { A1 = F; A2 = 0; } else if (coletree) { A1 = F; A2 = A; } else { A1 = A; A2 = F; } // count the total number of entries in L octave_idx_type lnz = 0 ; for (octave_idx_type j = 0 ; j < n ; j++) lnz += ColCount[j]; // allocate the output matrix L (pattern-only) SparseBoolMatrix L (n, n, lnz); // initialize column pointers lnz = 0; for (octave_idx_type j = 0 ; j < n ; j++) { L.xcidx(j) = lnz; lnz += ColCount[j]; } L.xcidx(n) = lnz; /* create a copy of the column pointers */ octave_idx_type *W = First; for (octave_idx_type j = 0 ; j < n ; j++) W[j] = L.xcidx (j); // get workspace for computing one row of L cholmod_sparse *R = CHOLMOD_NAME (allocate_sparse) (n, 1, n, false, true, 0, CHOLMOD_PATTERN, cm); octave_idx_type *Rp = static_cast<octave_idx_type *>(R->p); octave_idx_type *Ri = static_cast<octave_idx_type *>(R->i); // compute L one row at a time for (octave_idx_type k = 0 ; k < n ; k++) { // get the kth row of L and store in the columns of L CHOLMOD_NAME (row_subtree) (A1, A2, k, Parent, R, cm) ; for (octave_idx_type p = 0 ; p < Rp[1] ; p++) L.xridx (W[Ri[p]]++) = k ; // add the diagonal entry L.xridx (W[k]++) = k ; } // free workspace CHOLMOD_NAME (free_sparse) (&R, cm) ; // transpose L to get R, or leave as is if (nargin < 3) L = L.transpose (); // fill numerical values of L with one's for (octave_idx_type p = 0 ; p < lnz ; p++) L.xdata(p) = true; retval(4) = L; } ColumnVector tmp (n); if (nargout > 3) { for (octave_idx_type i = 0; i < n; i++) tmp(i) = Post[i] + 1; retval(3) = tmp; } if (nargout > 2) { for (octave_idx_type i = 0; i < n; i++) tmp(i) = Parent[i] + 1; retval(2) = tmp; } if (nargout > 1) { /* compute the elimination tree height */ octave_idx_type height = 0 ; for (int i = 0 ; i < n ; i++) height = (height > Level[i] ? height : Level[i]); height++ ; retval(1) = static_cast<double> (height); } for (octave_idx_type i = 0; i < n; i++) tmp(i) = ColCount[i]; retval(0) = tmp; return retval; #else error ("symbfact: not available in this version of Octave"); #endif }