void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { void *G ; cholmod_dense *X = NULL ; cholmod_sparse *A = NULL, *Z = NULL ; cholmod_common Common, *cm ; Long *Ap = NULL, *Ai ; double *Ax, *Az = NULL ; char filename [MAXLEN] ; Long nz, k, is_complex = FALSE, nrow = 0, ncol = 0, allzero ; int mtype ; /* ---------------------------------------------------------------------- */ /* start CHOLMOD and set parameters */ /* ---------------------------------------------------------------------- */ cm = &Common ; cholmod_l_start (cm) ; sputil_config (SPUMONI, cm) ; /* ---------------------------------------------------------------------- */ /* get inputs */ /* ---------------------------------------------------------------------- */ if (nargin < 1 || nargin > 2 || nargout > 2) { mexErrMsgTxt ("usage: [A Z] = mread (filename, prefer_binary)") ; } if (!mxIsChar (pargin [0])) { mexErrMsgTxt ("mread requires a filename") ; } mxGetString (pargin [0], filename, MAXLEN) ; sputil_file = fopen (filename, "r") ; if (sputil_file == NULL) { mexErrMsgTxt ("cannot open file") ; } if (nargin > 1) { cm->prefer_binary = (mxGetScalar (pargin [1]) != 0) ; } /* ---------------------------------------------------------------------- */ /* read the matrix, as either a dense or sparse matrix */ /* ---------------------------------------------------------------------- */ G = cholmod_l_read_matrix (sputil_file, 1, &mtype, cm) ; fclose (sputil_file) ; sputil_file = NULL ; if (G == NULL) { mexErrMsgTxt ("could not read file") ; } /* get the specific matrix (A or X), and change to ZOMPLEX if needed */ if (mtype == CHOLMOD_SPARSE) { A = (cholmod_sparse *) G ; nrow = A->nrow ; ncol = A->ncol ; is_complex = (A->xtype == CHOLMOD_COMPLEX) ; Ap = A->p ; Ai = A->i ; if (is_complex) { /* if complex, ensure A is ZOMPLEX */ cholmod_l_sparse_xtype (CHOLMOD_ZOMPLEX, A, cm) ; } Ax = A->x ; Az = A->z ; } else if (mtype == CHOLMOD_DENSE) { X = (cholmod_dense *) G ; nrow = X->nrow ; ncol = X->ncol ; is_complex = (X->xtype == CHOLMOD_COMPLEX) ; if (is_complex) { /* if complex, ensure X is ZOMPLEX */ cholmod_l_dense_xtype (CHOLMOD_ZOMPLEX, X, cm) ; } Ax = X->x ; Az = X->z ; } else { mexErrMsgTxt ("invalid file") ; } /* ---------------------------------------------------------------------- */ /* if requested, extract the zero entries and place them in Z */ /* ---------------------------------------------------------------------- */ if (nargout > 1) { if (mtype == CHOLMOD_SPARSE) { /* A is a sparse real/zomplex double matrix */ Z = sputil_extract_zeros (A, cm) ; } else { /* input is full; just return an empty Z matrix */ Z = cholmod_l_spzeros (nrow, ncol, 0, CHOLMOD_REAL, cm) ; } } /* ---------------------------------------------------------------------- */ /* prune the zero entries from A and set nzmax(A) to nnz(A) */ /* ---------------------------------------------------------------------- */ if (mtype == CHOLMOD_SPARSE) { sputil_drop_zeros (A) ; cholmod_l_reallocate_sparse (cholmod_l_nnz (A, cm), A, cm) ; } /* ---------------------------------------------------------------------- */ /* change a complex matrix to real if its imaginary part is all zero */ /* ---------------------------------------------------------------------- */ if (is_complex) { if (mtype == CHOLMOD_SPARSE) { nz = Ap [ncol] ; } else { nz = nrow * ncol ; } allzero = TRUE ; for (k = 0 ; k < nz ; k++) { if (Az [k] != 0) { allzero = FALSE ; break ; } } if (allzero) { /* discard the all-zero imaginary part */ if (mtype == CHOLMOD_SPARSE) { cholmod_l_sparse_xtype (CHOLMOD_REAL, A, cm) ; } else { cholmod_l_dense_xtype (CHOLMOD_REAL, X, cm) ; } } } /* ---------------------------------------------------------------------- */ /* return results to MATLAB */ /* ---------------------------------------------------------------------- */ if (mtype == CHOLMOD_SPARSE) { pargout [0] = sputil_put_sparse (&A, cm) ; } else { pargout [0] = sputil_put_dense (&X, cm) ; } if (nargout > 1) { pargout [1] = sputil_put_sparse (&Z, cm) ; } /* ---------------------------------------------------------------------- */ /* free workspace */ /* ---------------------------------------------------------------------- */ cholmod_l_finish (cm) ; cholmod_l_print_common (" ", cm) ; }
void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { double dummy = 0, one [2] = {1,0}, zero [2] = {0,0} ; cholmod_sparse *S, Smatrix ; cholmod_dense *F, Fmatrix, *C ; cholmod_common Common, *cm ; Long srow, scol, frow, fcol, crow, transpose ; /* ---------------------------------------------------------------------- */ /* start CHOLMOD and set parameters */ /* ---------------------------------------------------------------------- */ cm = &Common ; cholmod_l_start (cm) ; sputil_config (SPUMONI, cm) ; /* ---------------------------------------------------------------------- */ /* check inputs */ /* ---------------------------------------------------------------------- */ if (nargout > 1 || nargin < 2 || nargin > 3) { mexErrMsgTxt ("Usage: C = sdmult (S,F,transpose)") ; } srow = mxGetM (pargin [0]) ; scol = mxGetN (pargin [0]) ; frow = mxGetM (pargin [1]) ; fcol = mxGetN (pargin [1]) ; transpose = !((nargin == 2) || (mxGetScalar (pargin [2]) == 0)) ; if (frow != (transpose ? srow : scol)) { mexErrMsgTxt ("invalid inner dimensions") ; } if (!mxIsSparse (pargin [0]) || mxIsSparse (pargin [1])) { mexErrMsgTxt ("sdmult (S,F): S must be sparse, F must be full") ; } /* ---------------------------------------------------------------------- */ /* get S and F */ /* ---------------------------------------------------------------------- */ S = sputil_get_sparse (pargin [0], &Smatrix, &dummy, 0) ; F = sputil_get_dense (pargin [1], &Fmatrix, &dummy) ; /* ---------------------------------------------------------------------- */ /* C = S*F or S'*F */ /* ---------------------------------------------------------------------- */ crow = transpose ? scol : srow ; C = cholmod_l_allocate_dense (crow, fcol, crow, F->xtype, cm) ; cholmod_l_sdmult (S, transpose, one, zero, F, C, cm) ; pargout [0] = sputil_put_dense (&C, cm) ; /* ---------------------------------------------------------------------- */ /* free workspace and the CHOLMOD L, except for what is copied to MATLAB */ /* ---------------------------------------------------------------------- */ cholmod_l_finish (cm) ; cholmod_l_print_common (" ", cm) ; /* if (cm->malloc_count != (mxIsComplex (pargout [0]) + 1)) mexErrMsgTxt ("!"); */ }
void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { double dummy = 0, *Px, *Xsetx ; Long *Lp, *Lnz, *Xp, *Xi, xnz, *Perm, *Lprev, *Lnext, *Xsetp ; cholmod_sparse *Bset, Bmatrix, *Xset ; cholmod_dense *Bdense, *X, *Y, *E ; cholmod_factor *L ; cholmod_common Common, *cm ; Long k, j, n, head, tail, xsetlen ; int sys, kind ; /* ---------------------------------------------------------------------- */ /* start CHOLMOD and set parameters */ /* ---------------------------------------------------------------------- */ cm = &Common ; cholmod_l_start (cm) ; sputil_config (SPUMONI, cm) ; /* ---------------------------------------------------------------------- */ /* check inputs */ /* ---------------------------------------------------------------------- */ if (nargin != 5 || nargout > 2) { mexErrMsgTxt ("usage: [x xset] = lsubsolve (L,kind,P,b,system)") ; } n = mxGetN (pargin [0]) ; if (!mxIsSparse (pargin [0]) || n != mxGetM (pargin [0])) { mexErrMsgTxt ("lsubsolve: L must be sparse and square") ; } if (mxGetNumberOfElements (pargin [1]) != 1) { mexErrMsgTxt ("lsubsolve: kind must be a scalar") ; } if (mxIsSparse (pargin [2]) || !(mxIsEmpty (pargin [2]) || mxGetNumberOfElements (pargin [2]) == n)) { mexErrMsgTxt ("lsubsolve: P must be size n, or empty") ; } if (mxGetM (pargin [3]) != n || mxGetN (pargin [3]) != 1) { mexErrMsgTxt ("lsubsolve: b wrong dimension") ; } if (!mxIsSparse (pargin [3])) { mexErrMsgTxt ("lxbpattern: b must be sparse") ; } if (mxGetNumberOfElements (pargin [4]) != 1) { mexErrMsgTxt ("lsubsolve: system must be a scalar") ; } /* ---------------------------------------------------------------------- */ /* get the inputs */ /* ---------------------------------------------------------------------- */ kind = (int) sputil_get_integer (pargin [1], FALSE, 0) ; sys = (int) sputil_get_integer (pargin [4], FALSE, 0) ; /* ---------------------------------------------------------------------- */ /* get the sparse b */ /* ---------------------------------------------------------------------- */ /* get sparse matrix B (unsymmetric) */ Bset = sputil_get_sparse (pargin [3], &Bmatrix, &dummy, 0) ; Bdense = cholmod_l_sparse_to_dense (Bset, cm) ; Bset->x = NULL ; Bset->z = NULL ; Bset->xtype = CHOLMOD_PATTERN ; /* ---------------------------------------------------------------------- */ /* construct a shallow copy of the input sparse matrix L */ /* ---------------------------------------------------------------------- */ /* the construction of the CHOLMOD takes O(n) time and memory */ /* allocate the CHOLMOD symbolic L */ L = cholmod_l_allocate_factor (n, cm) ; L->ordering = CHOLMOD_NATURAL ; /* get the MATLAB L */ L->p = mxGetJc (pargin [0]) ; L->i = mxGetIr (pargin [0]) ; L->x = mxGetPr (pargin [0]) ; L->z = mxGetPi (pargin [0]) ; /* allocate and initialize the rest of L */ L->nz = cholmod_l_malloc (n, sizeof (Long), cm) ; Lp = L->p ; Lnz = L->nz ; for (j = 0 ; j < n ; j++) { Lnz [j] = Lp [j+1] - Lp [j] ; } /* these pointers are not accessed in cholmod_solve2 */ L->prev = cholmod_l_malloc (n+2, sizeof (Long), cm) ; L->next = cholmod_l_malloc (n+2, sizeof (Long), cm) ; Lprev = L->prev ; Lnext = L->next ; head = n+1 ; tail = n ; Lnext [head] = 0 ; Lprev [head] = -1 ; Lnext [tail] = -1 ; Lprev [tail] = n-1 ; for (j = 0 ; j < n ; j++) { Lnext [j] = j+1 ; Lprev [j] = j-1 ; } Lprev [0] = head ; L->xtype = (mxIsComplex (pargin [0])) ? CHOLMOD_ZOMPLEX : CHOLMOD_REAL ; L->nzmax = Lp [n] ; /* get the permutation */ if (mxIsEmpty (pargin [2])) { L->Perm = NULL ; Perm = NULL ; } else { L->ordering = CHOLMOD_GIVEN ; L->Perm = cholmod_l_malloc (n, sizeof (Long), cm) ; Perm = L->Perm ; Px = mxGetPr (pargin [2]) ; for (k = 0 ; k < n ; k++) { Perm [k] = ((Long) Px [k]) - 1 ; } } /* set the kind, LL' or LDL' */ L->is_ll = (kind == 0) ; /* cholmod_l_print_factor (L, "L", cm) ; */ /* ---------------------------------------------------------------------- */ /* solve the system */ /* ---------------------------------------------------------------------- */ X = cholmod_l_zeros (n, 1, L->xtype, cm) ; Xset = NULL ; Y = NULL ; E = NULL ; cholmod_l_solve2 (sys, L, Bdense, Bset, &X, &Xset, &Y, &E, cm) ; cholmod_l_free_dense (&Y, cm) ; cholmod_l_free_dense (&E, cm) ; /* ---------------------------------------------------------------------- */ /* return result */ /* ---------------------------------------------------------------------- */ pargout [0] = sputil_put_dense (&X, cm) ; /* fill numerical values of Xset with one's */ Xsetp = Xset->p ; xsetlen = Xsetp [1] ; Xset->x = cholmod_l_malloc (xsetlen, sizeof (double), cm) ; Xsetx = Xset->x ; for (k = 0 ; k < xsetlen ; k++) { Xsetx [k] = 1 ; } Xset->xtype = CHOLMOD_REAL ; pargout [1] = sputil_put_sparse (&Xset, cm) ; /* ---------------------------------------------------------------------- */ /* free workspace and the CHOLMOD L, except for what is copied to MATLAB */ /* ---------------------------------------------------------------------- */ L->p = NULL ; L->i = NULL ; L->x = NULL ; L->z = NULL ; cholmod_l_free_factor (&L, cm) ; cholmod_l_finish (cm) ; cholmod_l_print_common (" ", cm) ; }
void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { double dummy = 0, rcond, *p ; cholmod_sparse Amatrix, Bspmatrix, *A, *Bs, *Xs ; cholmod_dense Bmatrix, *X, *B ; cholmod_factor *L ; cholmod_common Common, *cm ; Int n, B_is_sparse, ordering, k, *Perm ; /* ---------------------------------------------------------------------- */ /* start CHOLMOD and set parameters */ /* ---------------------------------------------------------------------- */ cm = &Common ; cholmod_l_start (cm) ; sputil_config (SPUMONI, cm) ; /* There is no supernodal LDL'. If cm->final_ll = FALSE (the default), then * this mexFunction will use a simplicial LDL' when flops/lnz < 40, and a * supernodal LL' otherwise. This may give suprising results to the MATLAB * user, so always perform an LL' factorization by setting cm->final_ll * to TRUE. */ cm->final_ll = TRUE ; cm->quick_return_if_not_posdef = TRUE ; /* ---------------------------------------------------------------------- */ /* get inputs */ /* ---------------------------------------------------------------------- */ if (nargout > 2 || nargin < 2 || nargin > 3) { mexErrMsgTxt ("usage: [x,rcond] = cholmod2 (A,b,ordering)") ; } n = mxGetM (pargin [0]) ; if (!mxIsSparse (pargin [0]) || (n != mxGetN (pargin [0]))) { mexErrMsgTxt ("A must be square and sparse") ; } if (n != mxGetM (pargin [1])) { mexErrMsgTxt ("# of rows of A and B must match") ; } /* get sparse matrix A. Use triu(A) only. */ A = sputil_get_sparse (pargin [0], &Amatrix, &dummy, 1) ; /* get sparse or dense matrix B */ B = NULL ; Bs = NULL ; B_is_sparse = mxIsSparse (pargin [1]) ; if (B_is_sparse) { /* get sparse matrix B (unsymmetric) */ Bs = sputil_get_sparse (pargin [1], &Bspmatrix, &dummy, 0) ; } else { /* get dense matrix B */ B = sputil_get_dense (pargin [1], &Bmatrix, &dummy) ; } /* get the ordering option */ if (nargin < 3) { /* use default ordering */ ordering = -1 ; } else { /* use a non-default option */ ordering = mxGetScalar (pargin [2]) ; } p = NULL ; Perm = NULL ; if (ordering == 0) { /* natural ordering */ cm->nmethods = 1 ; cm->method [0].ordering = CHOLMOD_NATURAL ; cm->postorder = FALSE ; } else if (ordering == -1) { /* default strategy ... nothing to change */ } else if (ordering == -2) { /* default strategy, but with NESDIS in place of METIS */ cm->default_nesdis = TRUE ; } else if (ordering == -3) { /* use AMD only */ cm->nmethods = 1 ; cm->method [0].ordering = CHOLMOD_AMD ; cm->postorder = TRUE ; } else if (ordering == -4) { /* use METIS only */ cm->nmethods = 1 ; cm->method [0].ordering = CHOLMOD_METIS ; cm->postorder = TRUE ; } else if (ordering == -5) { /* use NESDIS only */ cm->nmethods = 1 ; cm->method [0].ordering = CHOLMOD_NESDIS ; cm->postorder = TRUE ; } else if (ordering == -6) { /* natural ordering, but with etree postordering */ cm->nmethods = 1 ; cm->method [0].ordering = CHOLMOD_NATURAL ; cm->postorder = TRUE ; } else if (ordering == -7) { /* always try both AMD and METIS, and pick the best */ cm->nmethods = 2 ; cm->method [0].ordering = CHOLMOD_AMD ; cm->method [1].ordering = CHOLMOD_METIS ; cm->postorder = TRUE ; } else if (ordering >= 1) { /* assume the 3rd argument is a user-provided permutation of 1:n */ if (mxGetNumberOfElements (pargin [2]) != n) { mexErrMsgTxt ("invalid input permutation") ; } /* copy from double to integer, and convert to 0-based */ p = mxGetPr (pargin [2]) ; Perm = cholmod_l_malloc (n, sizeof (Int), cm) ; for (k = 0 ; k < n ; k++) { Perm [k] = p [k] - 1 ; } /* check the permutation */ if (!cholmod_l_check_perm (Perm, n, n, cm)) { mexErrMsgTxt ("invalid input permutation") ; } /* use only the given permutation */ cm->nmethods = 1 ; cm->method [0].ordering = CHOLMOD_GIVEN ; cm->postorder = FALSE ; } else { mexErrMsgTxt ("invalid ordering option") ; } /* ---------------------------------------------------------------------- */ /* analyze and factorize */ /* ---------------------------------------------------------------------- */ L = cholmod_l_analyze_p (A, Perm, NULL, 0, cm) ; cholmod_l_free (n, sizeof (Int), Perm, cm) ; cholmod_l_factorize (A, L, cm) ; rcond = cholmod_l_rcond (L, cm) ; if (rcond == 0) { mexWarnMsgTxt ("Matrix is indefinite or singular to working precision"); } else if (rcond < DBL_EPSILON) { mexWarnMsgTxt ("Matrix is close to singular or badly scaled.") ; mexPrintf (" Results may be inaccurate. RCOND = %g.\n", rcond) ; } /* ---------------------------------------------------------------------- */ /* solve and return solution to MATLAB */ /* ---------------------------------------------------------------------- */ if (B_is_sparse) { /* solve AX=B with sparse X and B; return sparse X to MATLAB */ Xs = cholmod_l_spsolve (CHOLMOD_A, L, Bs, cm) ; pargout [0] = sputil_put_sparse (&Xs, cm) ; } else { /* solve AX=B with dense X and B; return dense X to MATLAB */ X = cholmod_l_solve (CHOLMOD_A, L, B, cm) ; pargout [0] = sputil_put_dense (&X, cm) ; } /* return statistics, if requested */ if (nargout > 1) { pargout [1] = mxCreateDoubleMatrix (1, 5, mxREAL) ; p = mxGetPr (pargout [1]) ; p [0] = rcond ; p [1] = L->ordering ; p [2] = cm->lnz ; p [3] = cm->fl ; p [4] = cm->memory_usage / 1048576. ; } cholmod_l_free_factor (&L, cm) ; cholmod_l_finish (cm) ; cholmod_l_print_common (" ", cm) ; /* if (cm->malloc_count != (mxIsComplex (pargout [0]) + (mxIsSparse (pargout[0]) ? 3:1))) mexErrMsgTxt ("memory leak!") ; */ }