/* ========================================================================== */ /* === CHOLMOD/MATLAB/ldlupdate mexFunction ================================= */ /* ========================================================================== */ /* ----------------------------------------------------------------------------- * CHOLMOD/MATLAB Module. Copyright (C) 2005-2006, Timothy A. Davis * The CHOLMOD/MATLAB Module is licensed under Version 2.0 of the GNU * General Public License. See gpl.txt for a text of the license. * CHOLMOD is also available under other licenses; contact authors for details. * http://www.cise.ufl.edu/research/sparse * MATLAB(tm) is a Trademark of The MathWorks, Inc. * -------------------------------------------------------------------------- */ /* Multiple-rank update or downdate of a sparse LDL' factorization. * * Usage: * * LD = ldlupdate (LD,C) update an LDL' factorization * LD = ldlupdate (LD,C,'+') update an LDL' factorization * LD = ldlupdate (LD,C,'-') downdate an LDL' factorization * * See ldlupdate.m for details. LD and C must be real and sparse. * * The bulk of the time is spent copying the input LD to the output LD. This * mexFunction could be much faster if it could safely modify its input LD. */ #include "cholmod_matlab.h" void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { double dummy = 0 ; double *Lx, *Lx2 ; int *Li, *Lp, *Li2, *Lp2, *Lnz2, *ColCount ; cholmod_sparse Cmatrix, *C, *Lsparse ; cholmod_factor *L ; cholmod_common Common, *cm ; int j, k, s, update, n, lnz ; char buf [LEN] ; /* ---------------------------------------------------------------------- */ /* start CHOLMOD and set parameters */ /* ---------------------------------------------------------------------- */ cm = &Common ; cholmod_start (cm) ; sputil_config (SPUMONI, cm) ; /* ---------------------------------------------------------------------- */ /* check inputs */ /* ---------------------------------------------------------------------- */ if (nargout > 1 || nargin < 2 || nargin > 3) { mexErrMsgTxt ("Usage: L = ldlupdate (L, C, '+')") ; } n = mxGetN (pargin [0]) ; k = mxGetN (pargin [1]) ; if (!mxIsSparse (pargin [0]) || !mxIsSparse (pargin [1]) || n != mxGetM (pargin [0]) || n != mxGetM (pargin [1]) || mxIsComplex (pargin [0]) || mxIsComplex (pargin [1])) { mexErrMsgTxt ("ldlupdate: C and/or L not sparse, complex, or wrong" " dimensions") ; } /* ---------------------------------------------------------------------- */ /* determine if we're doing an update or downdate */ /* ---------------------------------------------------------------------- */ update = TRUE ; if (nargin > 2 && mxIsChar (pargin [2])) { mxGetString (pargin [2], buf, LEN) ; if (buf [0] == '-') { update = FALSE ; } else if (buf [0] != '+') { mexErrMsgTxt ("ldlupdate: update string must be '+' or '-'") ; } } /* ---------------------------------------------------------------------- */ /* get C: sparse matrix of incoming/outgoing columns */ /* ---------------------------------------------------------------------- */ C = sputil_get_sparse (pargin [1], &Cmatrix, &dummy, 0) ; /* ---------------------------------------------------------------------- */ /* construct a copy of the input sparse matrix L */ /* ---------------------------------------------------------------------- */ /* get the MATLAB L */ Lp = mxGetJc (pargin [0]) ; Li = mxGetIr (pargin [0]) ; Lx = mxGetPr (pargin [0]) ; /* allocate the CHOLMOD symbolic L */ L = cholmod_allocate_factor (n, cm) ; L->ordering = CHOLMOD_NATURAL ; ColCount = L->ColCount ; for (j = 0 ; j < n ; j++) { ColCount [j] = Lp [j+1] - Lp [j] ; } /* allocate space for a CHOLMOD LDL' packed factor */ cholmod_change_factor (CHOLMOD_REAL, FALSE, FALSE, TRUE, TRUE, L, cm) ; /* copy MATLAB L into CHOLMOD L */ Lp2 = L->p ; Li2 = L->i ; Lx2 = L->x ; Lnz2 = L->nz ; lnz = L->nzmax ; for (j = 0 ; j <= n ; j++) { Lp2 [j] = Lp [j] ; } for (j = 0 ; j < n ; j++) { Lnz2 [j] = Lp [j+1] - Lp [j] ; } for (s = 0 ; s < lnz ; s++) { Li2 [s] = Li [s] ; } for (s = 0 ; s < lnz ; s++) { Lx2 [s] = Lx [s] ; } /* ---------------------------------------------------------------------- */ /* update/downdate the LDL' factorization */ /* ---------------------------------------------------------------------- */ if (!cholmod_updown (update, C, L, cm)) { mexErrMsgTxt ("ldlupdate failed\n") ; } /* ---------------------------------------------------------------------- */ /* copy the results back to MATLAB */ /* ---------------------------------------------------------------------- */ /* change L back to packed LDL' (it may have become unpacked if the * sparsity pattern changed). This change takes O(n) time if the pattern * of L wasn't updated. */ Lsparse = cholmod_factor_to_sparse (L, cm) ; /* return L as a sparse matrix */ pargout [0] = sputil_put_sparse (&Lsparse, cm) ; /* ---------------------------------------------------------------------- */ /* free workspace and the CHOLMOD L, except for what is copied to MATLAB */ /* ---------------------------------------------------------------------- */ cholmod_free_factor (&L, cm) ; cholmod_finish (cm) ; cholmod_print_common (" ", cm) ; /* if (cm->malloc_count != 3 + mxIsComplex (pargout[0])) mexErrMsgTxt ("!") ; */ }