/* C = cs_transpose (A), computes C=A', where A must be sparse. C = cs_transpose (A,kind) computes C=A.' if kind <= 0, C=A' if kind > 0 */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { CS_INT values ; if (nargout > 1 || nargin < 1 || nargin > 2) { mexErrMsgTxt ("Usage: C = cs_transpose(A,kind)") ; } values = (nargin > 1) ? mxGetScalar (pargin [1]) : 1 ; values = (values <= 0) ? -1 : 1 ; if (mxIsComplex (pargin [0])) { #ifndef NCOMPLEX cs_cl Amatrix, *A, *C ; A = cs_cl_mex_get_sparse (&Amatrix, 0, pargin [0]) ; /* get A */ C = cs_cl_transpose (A, values) ; /* C = A' */ pargout [0] = cs_cl_mex_put_sparse (&C) ; /* return C */ #else mexErrMsgTxt ("complex matrices not supported") ; #endif } else { cs_dl Amatrix, *A, *C ; A = cs_dl_mex_get_sparse (&Amatrix, 0, 1, pargin [0]) ; /* get A */ C = cs_dl_transpose (A, values) ; /* C = A' */ pargout [0] = cs_dl_mex_put_sparse (&C) ; /* return C */ } }
/* cs_sparse: convert triplet form into compress-column form sparse matrix */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { if (nargout > 1 || nargin != 3) { mexErrMsgTxt ("Usage: A = cs_sparse(i,j,x)") ; } if (mxIsComplex (pargin [2])) { #ifndef NCOMPLEX cs_cl *A, *C, *T, Tmatrix ; T = &Tmatrix ; /* get i,j,x and copy to triplet form */ T->nz = mxGetM (pargin [0]) ; T->p = cs_dl_mex_get_int (T->nz, pargin [0], &(T->n), 1) ; T->i = cs_dl_mex_get_int (T->nz, pargin [1], &(T->m), 1) ; cs_mex_check (1, T->nz, 1, 0, 0, 1, pargin [2]) ; T->x = cs_cl_mex_get_double (T->nz, pargin [2]) ; T->nzmax = T->nz ; C = cs_cl_compress (T) ; /* create sparse matrix C */ cs_cl_dupl (C) ; /* remove duplicates from C */ cs_cl_dropzeros (C) ; /* remove zeros from C */ A = cs_cl_transpose (C, -1) ; /* A=C.' */ cs_cl_spfree (C) ; pargout [0] = cs_cl_mex_put_sparse (&A) ; /* return A */ cs_free (T->p) ; cs_free (T->i) ; cs_free (T->x) ; /* free copy of complex values*/ #else mexErrMsgTxt ("complex matrices not supported") ; #endif } else { cs_dl *A, *C, *T, Tmatrix ; T = &Tmatrix ; /* get i,j,x and copy to triplet form */ T->nz = mxGetM (pargin [0]) ; T->p = cs_dl_mex_get_int (T->nz, pargin [0], &(T->n), 1) ; T->i = cs_dl_mex_get_int (T->nz, pargin [1], &(T->m), 1) ; cs_mex_check (1, T->nz, 1, 0, 0, 1, pargin [2]) ; T->x = mxGetPr (pargin [2]) ; T->nzmax = T->nz ; C = cs_dl_compress (T) ; /* create sparse matrix C */ cs_dl_dupl (C) ; /* remove duplicates from C */ cs_dl_dropzeros (C) ; /* remove zeros from C */ A = cs_dl_transpose (C, 1) ; /* A=C' */ cs_dl_spfree (C) ; pargout [0] = cs_dl_mex_put_sparse (&A) ; /* return A */ cs_free (T->p) ; cs_free (T->i) ; } }
void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { if (nargout > 1 || nargin < 2 || nargin > 4) { mexErrMsgTxt ("Usage: C = cs_add(A,B,alpha,beta)") ; } if (mxIsComplex (pargin [0]) || mxIsComplex (pargin [1]) || (nargin > 2 && mxIsComplex (pargin [2])) || (nargin > 3 && mxIsComplex (pargin [3]))) { #ifndef NCOMPLEX cs_complex_t alpha, beta ; cs_cl Amatrix, Bmatrix, *A, *B, *C, *D ; A = cs_cl_mex_get_sparse (&Amatrix, 0, pargin [0]) ; /* get A */ B = cs_cl_mex_get_sparse (&Bmatrix, 0, pargin [1]) ; /* get B */ alpha = (nargin < 3) ? 1 : get_complex (pargin [2]) ; /* get alpha */ beta = (nargin < 4) ? 1 : get_complex (pargin [3]) ; /* get beta */ C = cs_cl_add (A,B,alpha,beta) ; /* C = alpha*A + beta *B */ cs_cl_dropzeros (C) ; /* drop zeros */ D = cs_cl_transpose (C, 1) ; /* sort result via double transpose */ cs_cl_spfree (C) ; C = cs_cl_transpose (D, 1) ; cs_cl_spfree (D) ; pargout [0] = cs_cl_mex_put_sparse (&C) ; /* return C */ #else mexErrMsgTxt ("complex matrices not supported") ; #endif } else { double alpha, beta ; cs_dl Amatrix, Bmatrix, *A, *B, *C, *D ; A = cs_dl_mex_get_sparse (&Amatrix, 0, 1, pargin [0]) ; /* get A */ B = cs_dl_mex_get_sparse (&Bmatrix, 0, 1, pargin [1]) ; /* get B */ alpha = (nargin < 3) ? 1 : mxGetScalar (pargin [2]) ; /* get alpha */ beta = (nargin < 4) ? 1 : mxGetScalar (pargin [3]) ; /* get beta */ C = cs_dl_add (A,B,alpha,beta) ; /* C = alpha*A + beta *B */ cs_dl_dropzeros (C) ; /* drop zeros */ D = cs_dl_transpose (C, 1) ; /* sort result via double transpose */ cs_dl_spfree (C) ; C = cs_dl_transpose (D, 1) ; cs_dl_spfree (D) ; pargout [0] = cs_dl_mex_put_sparse (&C) ; /* return C */ } }
/* cs_updown: sparse Cholesky update/downdate (rank-1 or multiple rank) */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { CS_INT 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_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) ; } }
/* cs_lu: sparse LU factorization, with optional fill-reducing ordering */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { CS_INT n, order, *p ; double tol ; if (nargout > 4 || nargin > 3 || nargin < 1) { mexErrMsgTxt ("Usage: [L,U,p,q] = cs_lu (A,tol)") ; } if (nargin == 2) /* determine tol and ordering */ { tol = mxGetScalar (pargin [1]) ; order = (nargout == 4) ? 1 : 0 ; /* amd (A+A'), or natural */ } else { tol = 1 ; order = (nargout == 4) ? 2 : 0 ; /* amd(S'*S) w/dense rows or I */ } if (mxIsComplex (pargin [0])) { #ifndef NCOMPLEX cs_cls *S ; cs_cln *N ; cs_cl Amatrix, *A, *D ; A = cs_cl_mex_get_sparse (&Amatrix, 1, pargin [0]) ; /* get A */ n = A->n ; S = cs_cl_sqr (order, A, 0) ; /* symbolic ordering, no QR bound */ N = cs_cl_lu (A, S, tol) ; /* numeric factorization */ if (!N) mexErrMsgTxt ("cs_lu failed (singular, or out of memory)") ; cs_cl_free (A->x) ; /* complex copy no longer needed */ cs_cl_dropzeros (N->L) ; /* drop zeros from L and sort it */ D = cs_cl_transpose (N->L, 1) ; cs_cl_spfree (N->L) ; N->L = cs_cl_transpose (D, 1) ; cs_cl_spfree (D) ; cs_cl_dropzeros (N->U) ; /* drop zeros from U and sort it */ D = cs_cl_transpose (N->U, 1) ; cs_cl_spfree (N->U) ; N->U = cs_cl_transpose (D, 1) ; cs_cl_spfree (D) ; p = cs_cl_pinv (N->pinv, n) ; /* p=pinv' */ pargout [0] = cs_cl_mex_put_sparse (&(N->L)) ; /* return L */ pargout [1] = cs_cl_mex_put_sparse (&(N->U)) ; /* return U */ pargout [2] = cs_dl_mex_put_int (p, n, 1, 1) ; /* return p */ /* return Q */ if (nargout == 4) pargout [3] = cs_dl_mex_put_int (S->q, n, 1, 0) ; cs_cl_nfree (N) ; cs_cl_sfree (S) ; #else mexErrMsgTxt ("complex matrices not supported") ; #endif } else { cs_dls *S ; cs_dln *N ; cs_dl Amatrix, *A, *D ; A = cs_dl_mex_get_sparse (&Amatrix, 1, 1, pargin [0]) ; /* get A */ n = A->n ; S = cs_dl_sqr (order, A, 0) ; /* symbolic ordering, no QR bound */ N = cs_dl_lu (A, S, tol) ; /* numeric factorization */ if (!N) mexErrMsgTxt ("cs_lu failed (singular, or out of memory)") ; cs_dl_dropzeros (N->L) ; /* drop zeros from L and sort it */ D = cs_dl_transpose (N->L, 1) ; cs_dl_spfree (N->L) ; N->L = cs_dl_transpose (D, 1) ; cs_dl_spfree (D) ; cs_dl_dropzeros (N->U) ; /* drop zeros from U and sort it */ D = cs_dl_transpose (N->U, 1) ; cs_dl_spfree (N->U) ; N->U = cs_dl_transpose (D, 1) ; cs_dl_spfree (D) ; p = cs_dl_pinv (N->pinv, n) ; /* p=pinv' */ pargout [0] = cs_dl_mex_put_sparse (&(N->L)) ; /* return L */ pargout [1] = cs_dl_mex_put_sparse (&(N->U)) ; /* return U */ pargout [2] = cs_dl_mex_put_int (p, n, 1, 1) ; /* return p */ /* return Q */ if (nargout == 4) pargout [3] = cs_dl_mex_put_int (S->q, n, 1, 0) ; cs_dl_nfree (N) ; cs_dl_sfree (S) ; } }
/* cs_qr: sparse QR factorization */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { CS_INT m, n, order, *p ; if (nargout > 5 || nargin != 1) { mexErrMsgTxt ("Usage: [V,beta,p,R,q] = cs_qr(A)") ; } order = (nargout == 5) ? 3 : 0 ; /* determine ordering */ m = mxGetM (pargin [0]) ; n = mxGetN (pargin [0]) ; if (m < n) mexErrMsgTxt ("A must have # rows >= # columns") ; if (mxIsComplex (pargin [0])) { #ifndef NCOMPLEX cs_cls *S ; cs_cln *N ; cs_cl Amatrix, *A, *D ; A = cs_cl_mex_get_sparse (&Amatrix, 0, pargin [0]) ; /* get A */ S = cs_cl_sqr (order, A, 1) ; /* symbolic QR ordering & analysis*/ N = cs_cl_qr (A, S) ; /* numeric QR factorization */ cs_free (A->x) ; if (!N) mexErrMsgTxt ("qr failed") ; cs_cl_dropzeros (N->L) ; /* drop zeros from V and sort */ D = cs_cl_transpose (N->L, 1) ; cs_cl_spfree (N->L) ; N->L = cs_cl_transpose (D, 1) ; cs_cl_spfree (D) ; cs_cl_dropzeros (N->U) ; /* drop zeros from R and sort */ D = cs_cl_transpose (N->U, 1) ; cs_cl_spfree (N->U) ; N->U = cs_cl_transpose (D, 1) ; cs_cl_spfree (D) ; m = N->L->m ; /* m may be larger now */ p = cs_cl_pinv (S->pinv, m) ; /* p = pinv' */ pargout [0] = cs_cl_mex_put_sparse (&(N->L)) ; /* return V */ cs_dl_mex_put_double (n, N->B, &(pargout [1])) ; /* return beta */ pargout [2] = cs_dl_mex_put_int (p, m, 1, 1) ; /* return p */ pargout [3] = cs_cl_mex_put_sparse (&(N->U)) ; /* return R */ pargout [4] = cs_dl_mex_put_int (S->q, n, 1, 0) ; /* return q */ cs_cl_nfree (N) ; cs_cl_sfree (S) ; #else mexErrMsgTxt ("complex matrices not supported") ; #endif } else { cs_dls *S ; cs_dln *N ; cs_dl Amatrix, *A, *D ; A = cs_dl_mex_get_sparse (&Amatrix, 0, 1, pargin [0]) ; /* get A */ S = cs_dl_sqr (order, A, 1) ; /* symbolic QR ordering & analysis*/ N = cs_dl_qr (A, S) ; /* numeric QR factorization */ if (!N) mexErrMsgTxt ("qr failed") ; cs_dl_dropzeros (N->L) ; /* drop zeros from V and sort */ D = cs_dl_transpose (N->L, 1) ; cs_dl_spfree (N->L) ; N->L = cs_dl_transpose (D, 1) ; cs_dl_spfree (D) ; cs_dl_dropzeros (N->U) ; /* drop zeros from R and sort */ D = cs_dl_transpose (N->U, 1) ; cs_dl_spfree (N->U) ; N->U = cs_dl_transpose (D, 1) ; cs_dl_spfree (D) ; m = N->L->m ; /* m may be larger now */ p = cs_dl_pinv (S->pinv, m) ; /* p = pinv' */ pargout [0] = cs_dl_mex_put_sparse (&(N->L)) ; /* return V */ cs_dl_mex_put_double (n, N->B, &(pargout [1])) ; /* return beta */ pargout [2] = cs_dl_mex_put_int (p, m, 1, 1) ; /* return p */ pargout [3] = cs_dl_mex_put_sparse (&(N->U)) ; /* return R */ pargout [4] = cs_dl_mex_put_int (S->q, n, 1, 0) ; /* return q */ cs_dl_nfree (N) ; cs_dl_sfree (S) ; } }