// CXSparse/MATLAB/CSparse/cs_updown_mex: sparse Cholesky update/downdate // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs_mex.h" /* cs_updown: sparse Cholesky update/downdate (rank-1 or multiple rank) */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { int64_t ignore, j, k, n, lnz, *parent, sigma = 1, cp [2], ok ; char sigma_string [20] ; if (nargout > 1 || nargin < 3 || nargin > 4) { mexErrMsgTxt ("Usage: L = cs_updown(L,C,parent,sigma)") ; } if (nargin > 3 && mxIsChar (pargin [3])) { mxGetString (pargin [3], sigma_string, 8) ; sigma = (sigma_string [0] == '-') ? (-1) : 1 ; } n = mxGetN (pargin [0]) ; parent = cs_dl_mex_get_int (n, pargin [2], &ignore, 0) ; /* get parent*/ if (mxIsComplex (pargin [0]) || mxIsComplex (pargin [1])) { #ifndef NCOMPLEX cs_cl Lmatrix, *Lin, Cmatrix, *C, *L, Cvector, *Cvec ; /* get input L, and copy MATLAB complex to C complex type */ Lin = cs_cl_mex_get_sparse (&Lmatrix, 1, pargin [0]) ; /* make a copy of L (this can take more work than updating L itself) */ lnz = Lin->p [n] ; L = cs_cl_spalloc (n, n, lnz, 0, 0) ; for (j = 0 ; j <= n ; j++) L->p [j] = Lin->p [j] ; for (k = 0 ; k < lnz ; k++) L->i [k] = Lin->i [k] ; /* complex values already copied into Lin->x, use shallow copy for L */ L->x = Lin->x ; cs_mex_check (0, n, -1, 0, 1, 1, pargin [1]) ; /* get C */ C = cs_cl_mex_get_sparse (&Cmatrix, 0, pargin [1]) ; /* do the update one column at a time */ Cvec = &Cvector ; Cvec->m = n ; Cvec->n = 1 ; Cvec->p = cp ; Cvec->nz = -1 ; cp [0] = 0 ; for (k = 0 ; k < C->n ; k++) { /* extract C(:,k) */ cp [1] = C->p [k+1] - C->p [k] ; Cvec->nzmax = cp [1] ; Cvec->i = C->i + C->p [k] ; Cvec->x = C->x + C->p [k] ; /* update/downdate */ ok = cs_cl_updown (L, sigma, Cvec, parent) ; if (!ok) mexErrMsgTxt ("matrix is not positive definite") ; } /* return new L */ pargout [0] = cs_cl_mex_put_sparse (&L) ; cs_cl_free (C->x) ; /* free complex copy of C */ #else mexErrMsgTxt ("complex matrices not supported") ; #endif } else { cs_dl Lmatrix, *Lin, Cmatrix, *C, *L, Cvector, *Cvec ; /* get input L */ Lin = cs_dl_mex_get_sparse (&Lmatrix, 1, 1, pargin [0]) ; /* make a copy of L (this can take more work than updating L itself) */ lnz = Lin->p [n] ; L = cs_dl_spalloc (n, n, lnz, 1, 0) ; for (j = 0 ; j <= n ; j++) L->p [j] = Lin->p [j] ; for (k = 0 ; k < lnz ; k++) L->i [k] = Lin->i [k] ; for (k = 0 ; k < lnz ; k++) L->x [k] = Lin->x [k] ; cs_mex_check (0, n, -1, 0, 1, 1, pargin [1]) ; /* get C */ C = cs_dl_mex_get_sparse (&Cmatrix, 0, 1, pargin [1]) ; /* do the update one column at a time */ Cvec = &Cvector ; Cvec->m = n ; Cvec->n = 1 ; Cvec->p = cp ; Cvec->nz = -1 ; cp [0] = 0 ; for (k = 0 ; k < C->n ; k++) { /* extract C(:,k) */ cp [1] = C->p [k+1] - C->p [k] ; Cvec->nzmax = cp [1] ; Cvec->i = C->i + C->p [k] ; Cvec->x = C->x + C->p [k] ; /* update/downdate */ ok = cs_dl_updown (L, sigma, Cvec, parent) ; if (!ok) mexErrMsgTxt ("matrix is not positive definite") ; } /* return new L */ pargout [0] = cs_dl_mex_put_sparse (&L) ; } }