void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { cs Lmatrix, Bmatrix, *L, *B ; double *x ; int k, i, j, top, *xi, *perm ; if (nargout > 1 || nargin != 2) { mexErrMsgTxt ("Usage: x = cs_reach(L,b)") ; } /* get inputs */ L = cs_mex_get_sparse (&Lmatrix, 1, 1, pargin [0]) ; B = cs_mex_get_sparse (&Bmatrix, 0, 1, pargin [1]) ; cs_mex_check (0, L->n, 1, 0, 1, 1, pargin [1]) ; perm = cs_malloc (L->n, sizeof (int)) ; for (k = 0 ; k < L->n ; k++) perm [k] = k ; xi = cs_calloc (3*L->n, sizeof (int)) ; top = cs_reach (L, B, 0, xi, perm) ; pargout [0] = mxCreateDoubleMatrix (L->n - top, 1, mxREAL) ; x = mxGetPr (pargout [0]) ; for (j = 0, i = top ; i < L->n ; i++, j++) x [j] = xi [i] ; cs_free (xi) ; cs_free (perm) ; }
/* cs_add: sparse matrix addition */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { double alpha, beta ; cs Amatrix, Bmatrix, *A, *B, *C, *D ; if (nargout > 1 || nargin < 2 || nargin > 4) { mexErrMsgTxt ("Usage: C = cs_add(A,B,alpha,beta)") ; } A = cs_mex_get_sparse (&Amatrix, 0, 1, pargin [0]) ; /* get A */ B = cs_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_add (A,B,alpha,beta) ; /* C = alpha*A + beta *B */ cs_dropzeros (C) ; /* drop zeros */ D = cs_transpose (C, 1) ; /* sort result via double transpose */ cs_spfree (C) ; C = cs_transpose (D, 1) ; cs_spfree (D) ; pargout [0] = cs_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 Lmatrix, *Lin, Cmatrix, *C, *L, Cvector, *Cvec ; int ignore, j, k, n, lnz, *parent, sigma = 1, cp [2] ; char sigma_string [20] ; if (nargout > 1 || nargin < 3 || nargin > 4) { mexErrMsgTxt ("Usage: L = cs_updown(L,C,parent,sigma)") ; } Lin = cs_mex_get_sparse (&Lmatrix, 1, 1, pargin [0]) ; /* get input L */ n = Lin->n ; if (nargin > 3 && mxIsChar (pargin [3])) { mxGetString (pargin [3], sigma_string, 8) ; sigma = (sigma_string [0] == '-') ? (-1) : 1 ; } /* make a copy of L (this can take more work than updating L itself) */ lnz = Lin->p [n] ; L = cs_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_mex_get_sparse (&Cmatrix, 0, 1, pargin [1]) ; parent = cs_mex_get_int (n, pargin [2], &ignore, 0) ; /* get parent */ /* 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] ; cs_updown (L, sigma, Cvec, parent) ; /* update/downdate */ } pargout [0] = cs_mex_put_sparse (&L) ; /* return new L */ }
void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { cs *A, Amatrix ; double *x ; int i, m, n, *imatch, *jmatch ; if (nargout > 1 || nargin != 1) { mexErrMsgTxt ("Usage: p = cr_maxtransr(A)") ; } /* get inputs */ A = cs_mex_get_sparse (&Amatrix, 0, 0, pargin [0]) ; m = A->m ; n = A->n ; jmatch = maxtrans (A) ; imatch = invmatch (jmatch, m, n) ; /* imatch = inverse of jmatch */ pargout [0] = mxCreateDoubleMatrix (1, n, mxREAL) ; x = mxGetPr (pargout [0]) ; for (i = 0 ; i < n ; i++) x [i] = imatch [i] + 1 ; cs_free (jmatch) ; cs_free (imatch) ; }
/* cs_permute: permute a sparse matrix */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { cs Amatrix, *A, *C, *D ; int ignore, *P, *Q, *Pinv ; if (nargout > 1 || nargin != 3) { mexErrMsgTxt ("Usage: C = cs_permute(A,p,q)") ; } A = cs_mex_get_sparse (&Amatrix, 0, 1, pargin [0]) ; /* get A */ P = cs_mex_get_int (A->m, pargin [1], &ignore, 1) ; /* get P */ Q = cs_mex_get_int (A->n, pargin [2], &ignore, 1) ; /* get Q */ Pinv = cs_pinv (P, A->m) ; /* P = Pinv' */ C = cs_permute (A, Pinv, Q, 1) ; /* C = A(p,q) */ D = cs_transpose (C, 1) ; /* sort C via double transpose */ cs_spfree (C) ; C = cs_transpose (D, 1) ; cs_spfree (D) ; pargout [0] = cs_mex_put_sparse (&C) ; /* return C */ cs_free (Pinv) ; cs_free (P) ; cs_free (Q) ; }
/* cs_symperm: symmetric permutation of a symmetric sparse matrix. */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { cs Amatrix, *A, *C, *D ; csi ignore, n, *P, *Pinv ; if (nargout > 1 || nargin != 2) { mexErrMsgTxt ("Usage: C = cs_symperm(A,p)") ; } A = cs_mex_get_sparse (&Amatrix, 1, 1, pargin [0]) ; n = A->n ; P = cs_mex_get_int (n, pargin [1], &ignore, 1) ; /* get P */ Pinv = cs_pinv (P, n) ; /* P=Pinv' */ C = cs_symperm (A, Pinv, 1) ; /* C = A(p,p) */ D = cs_transpose (C, 1) ; /* sort C */ cs_spfree (C) ; C = cs_transpose (D, 1) ; cs_spfree (D) ; pargout [0] = cs_mex_put_sparse (&C) ; /* return C */ cs_free (P) ; cs_free (Pinv) ; }
void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { cs Umatrix, Bmatrix, *U, *B, *X ; double *x, *b ; int top, nz, p, *xi ; if (nargout > 1 || nargin != 2) { mexErrMsgTxt ("Usage: x = cs_usolve(U,b)") ; } U = cs_mex_get_sparse (&Umatrix, 1, 1, pargin [0]) ; /* get U */ if (mxIsSparse (pargin [1])) { B = cs_mex_get_sparse (&Bmatrix, 0, 1, pargin [1]) ;/* get sparse b */ cs_mex_check (0, U->n, 1, 0, 1, 1, pargin [1]) ; xi = cs_malloc (2*U->n, sizeof (int)) ; /* get workspace */ x = cs_malloc (U->n, sizeof (double)) ; top = cs_spsolve (U, B, 0, xi, x, NULL, 0) ; /* x = U\b */ X = cs_spalloc (U->n, 1, U->n-top, 1, 0) ; /* create sparse x*/ X->p [0] = 0 ; nz = 0 ; for (p = top ; p < U->n ; p++) { X->i [nz] = xi [p] ; X->x [nz++] = x [xi [p]] ; } X->p [1] = nz ; pargout [0] = cs_mex_put_sparse (&X) ; cs_free (x) ; cs_free (xi) ; } else { b = cs_mex_get_double (U->n, pargin [1]) ; /* get full b */ x = cs_mex_put_double (U->n, b, &(pargout [0])) ; /* x = b */ cs_usolve (U, x) ; /* x = U\x */ } }
/* cs_lu: sparse LU factorization, with optional fill-reducing ordering */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { css *S ; csn *N ; cs Amatrix, *A, *D ; csi n, order, *p ; double tol ; if (nargout > 4 || nargin > 3 || nargin < 1) { mexErrMsgTxt ("Usage: [L,U,p,q] = cs_lu (A,tol)") ; } A = cs_mex_get_sparse (&Amatrix, 1, 1, pargin [0]) ; /* get A */ n = A->n ; 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 */ } S = cs_sqr (order, A, 0) ; /* symbolic ordering, no QR bound */ N = cs_lu (A, S, tol) ; /* numeric factorization */ if (!N) mexErrMsgTxt ("cs_lu failed (singular, or out of memory)") ; cs_dropzeros (N->L) ; /* drop zeros from L and sort it */ D = cs_transpose (N->L, 1) ; cs_spfree (N->L) ; N->L = cs_transpose (D, 1) ; cs_spfree (D) ; cs_dropzeros (N->U) ; /* drop zeros from U and sort it */ D = cs_transpose (N->U, 1) ; cs_spfree (N->U) ; N->U = cs_transpose (D, 1) ; cs_spfree (D) ; p = cs_pinv (N->pinv, n) ; /* p=pinv' */ pargout [0] = cs_mex_put_sparse (&(N->L)) ; /* return L */ pargout [1] = cs_mex_put_sparse (&(N->U)) ; /* return U */ pargout [2] = cs_mex_put_int (p, n, 1, 1) ; /* return p */ /* return Q */ if (nargout == 4) pargout [3] = cs_mex_put_int (S->q, n, 1, 0) ; cs_nfree (N) ; cs_sfree (S) ; }
/* cs_print: print the contents of a sparse matrix. */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { cs Amatrix, *A ; int brief ; if (nargout > 0 || nargin < 1 || nargin > 2) { mexErrMsgTxt ("Usage: cs_print(A,brief)") ; } A = cs_mex_get_sparse (&Amatrix, 0, 1, pargin [0]) ; /* get A */ brief = (nargin < 2) ? 0 : mxGetScalar (pargin [1]) ; /* get brief */ cs_print (A, brief) ; /* print A */ }
/* cs_qr: sparse QR factorization */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { css *S ; csn *N ; cs Amatrix, *A, *D ; csi m, n, order, *p ; if (nargout > 5 || nargin != 1) { mexErrMsgTxt ("Usage: [V,beta,p,R,q] = cs_qr(A)") ; } A = cs_mex_get_sparse (&Amatrix, 0, 1, pargin [0]) ; /* get A */ m = A->m ; n = A->n ; if (m < n) mexErrMsgTxt ("A must have # rows >= # columns") ; order = (nargout == 5) ? 3 : 0 ; /* determine ordering */ S = cs_sqr (order, A, 1) ; /* symbolic QR ordering & analysis*/ N = cs_qr (A, S) ; /* numeric QR factorization */ if (!N) mexErrMsgTxt ("qr failed") ; cs_dropzeros (N->L) ; /* drop zeros from V and sort */ D = cs_transpose (N->L, 1) ; cs_spfree (N->L) ; N->L = cs_transpose (D, 1) ; cs_spfree (D) ; cs_dropzeros (N->U) ; /* drop zeros from R and sort */ D = cs_transpose (N->U, 1) ; cs_spfree (N->U) ; N->U = cs_transpose (D, 1) ; cs_spfree (D) ; m = N->L->m ; /* m may be larger now */ p = cs_pinv (S->pinv, m) ; /* p = pinv' */ pargout [0] = cs_mex_put_sparse (&(N->L)) ; /* return V */ cs_mex_put_double (n, N->B, &(pargout [1])) ; /* return beta */ pargout [2] = cs_mex_put_int (p, m, 1, 1) ; /* return p */ pargout [3] = cs_mex_put_sparse (&(N->U)) ; /* return R */ pargout [4] = cs_mex_put_int (S->q, n, 1, 0) ; /* return q */ cs_nfree (N) ; cs_sfree (S) ; }
void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { cs Amatrix, *A ; int m, n, mn, m2, n2, k, s, j, ij, sj, si, p, *Ap, *Ai ; double aij, *S, *Ax ; if (nargout > 1 || nargin < 1 || nargin > 2) { mexErrMsgTxt ("Usage: S = cs_thumb(A,k)") ; } A = cs_mex_get_sparse (&Amatrix, 0, 1, pargin [0]) ; /* get A */ m = A->m ; n = A->n ; mn = CS_MAX (m,n) ; k = (nargin == 1) ? 256 : mxGetScalar (pargin [1]) ; /* get k */ /* s = size of each submatrix; A(1:s,1:s) maps to S(1,1) */ s = (mn < k) ? 1 : (int) ceil ((double) mn / (double) k) ; m2 = (int) ceil ((double) m / (double) s) ; n2 = (int) ceil ((double) n / (double) s) ; /* create S */ pargout [0] = mxCreateDoubleMatrix (m2, n2, mxREAL) ; S = mxGetPr (pargout [0]) ; Ap = A->p ; Ai = A->i ; Ax = A->x ; for (j = 0 ; j < n ; j++) { sj = j/s ; for (p = Ap [j] ; p < Ap [j+1] ; p++) { si = Ai [p] / s ; ij = INDEX (si,sj,m2) ; aij = fabs (Ax [p]) ; if (ISNAN (aij)) aij = BIG_VALUE ; aij = CS_MIN (BIG_VALUE, aij) ; S [ij] = CS_MAX (S [ij], aij) ; } } }
/* cs_ltsolve: solve an upper triangular system L'*x=b */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { cs Lmatrix, *L ; double *x, *b ; if (nargout > 1 || nargin != 2) { mexErrMsgTxt ("Usage: x = cs_ltsolve(L,b)") ; } L = cs_mex_get_sparse (&Lmatrix, 1, 1, pargin [0]) ; /* get L */ b = cs_mex_get_double (L->n, pargin [1]) ; /* get b */ x = cs_mex_put_double (L->n, b, &(pargout [0])) ; /* x = b */ cs_ltsolve (L, x) ; /* x = L'\x */ }
/* z = cs_gaxpy (A,x,y) computes z = A*x+y */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { cs Amatrix, *A ; double *x, *y, *z ; if (nargout > 1 || nargin != 3) { mexErrMsgTxt ("Usage: z = cs_gaxpy(A,x,y)") ; } A = cs_mex_get_sparse (&Amatrix, 0, 1, pargin [0]) ; /* get A */ x = cs_mex_get_double (A->n, pargin [1]) ; /* get x */ y = cs_mex_get_double (A->m, pargin [2]) ; /* get y */ z = cs_mex_put_double (A->m, y, &(pargout [0])) ; /* z = y */ cs_gaxpy (A, x, z) ; /* z = z + A*x */ }
/* cs_amd: approximate minimum degree ordering */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { cs Amatrix, *A ; int *P, order ; if (nargout > 1 || nargin < 1 || nargin > 2) { mexErrMsgTxt ("Usage: p = cs_amd(A,order)") ; } A = cs_mex_get_sparse (&Amatrix, 0, 0, pargin [0]) ; /* get A */ order = (nargin > 1) ? mxGetScalar (pargin [1]) : 1 ; /* get ordering */ order = CS_MAX (order, 1) ; order = CS_MIN (order, 3) ; P = cs_amd (order, A) ; /* min. degree ordering */ pargout [0] = cs_mex_put_int (P, A->n, 1, 1) ; /* return P */ }
/* cs_dmperm: maximum matching or Dulmage-Mendelsohn permutation. */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { double seed ; cs *A, Amatrix ; csd *D ; csi m, n, *jmatch, iseed ; if (nargin < 1 || nargin > 2 || nargout > 6) { mexErrMsgTxt ("Usage: [p,q,r,s,cc,rr] = cs_dmperm (A,seed)") ; } seed = (nargin > 1) ? mxGetScalar (pargin [1]) : 0 ; /* get seed */ iseed = (seed > 0 && seed < 1) ? (seed * RAND_MAX) : seed ; A = cs_mex_get_sparse (&Amatrix, 0, 0, pargin [0]) ; /* get A */ n = A->n ; m = A->m ; if (nargout <= 1) { jmatch = cs_maxtrans (A, iseed) ; /* max. matching */ pargout [0] = cs_mex_put_int (jmatch+m, n, 1, 0) ; /* return imatch */ cs_free (jmatch) ; } else { D = cs_dmperm (A, iseed) ; /* Dulmage-Mendelsohn decomposition */ pargout [0] = cs_mex_put_int (D->p, m, 1, 0) ; pargout [1] = cs_mex_put_int (D->q, n, 1, 0) ; pargout [2] = cs_mex_put_int (D->r, D->nb+1, 1, 0) ; pargout [3] = cs_mex_put_int (D->s, D->nb+1, 1, 0) ; pargout [4] = cs_mex_put_int (D->cc, 5, 1, 0) ; pargout [5] = cs_mex_put_int (D->rr, 5, 1, 0) ; cs_dfree (D) ; } }
/* cs_lusol: solve A*x=b using a sparse LU factorization */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { cs *A, Amatrix ; csi order ; double *x, *b, tol ; if (nargout > 1 || nargin < 2 || nargin > 4) { mexErrMsgTxt ("Usage: x = cs_lusol(A,b,order,tol)") ; } A = cs_mex_get_sparse (&Amatrix, 1, 1, pargin [0]) ; /* get A */ b = cs_mex_get_double (A->n, pargin [1]) ; /* get b */ x = cs_mex_put_double (A->n, b, &(pargout [0])) ; /* x = b */ order = (nargin < 3) ? 2 : mxGetScalar (pargin [2]) ; order = CS_MAX (order, 0) ; order = CS_MIN (order, 3) ; if (nargin == 2) { tol = 1 ; /* normal partial pivoting */ } else if (nargin == 3) { tol = (order == 1) ? 0.001 : 1 ; /* tol = 0.001 for amd(A+A') */ } else { tol = mxGetScalar (pargin [3]) ; } if (!cs_lusol (order, A, x, tol)) /* x = A\x */ { mexErrMsgTxt ("LU factorization failed (singular or out of memory)") ; } }
/* cs_droptol: remove small entries from A */ void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { cs Amatrix, *C, *A ; int j, k ; double tol ; if (nargout > 1 || nargin != 2) { mexErrMsgTxt ("Usage: C = cs_droptol(A,tol)") ; } A = cs_mex_get_sparse (&Amatrix, 0, 1, pargin [0]) ; /* get A */ tol = mxGetScalar (pargin [1]) ; /* get tol */ C = cs_spalloc (A->m, A->n, A->nzmax, 1, 0) ; /* C = A */ for (j = 0 ; j <= A->n ; j++) C->p [j] = A->p [j] ; for (k = 0 ; k < A->nzmax ; k++) C->i [k] = A->i [k] ; for (k = 0 ; k < A->nzmax ; k++) C->x [k] = A->x [k] ; cs_droptol (C, tol) ; /* drop from C */ pargout [0] = cs_mex_put_sparse (&C) ; /* return C */ }