/* ========================================================================== */
/* === klus mexFunction ===================================================== */
/* ========================================================================== */

/* Solve Ax=b using KLU, with ordering provided by CHOLMOD 
 *
 * [x, Info] = klus (A, b)	    order A+A' for each block
 * [x, Info] = klus (A, b, 0)	    order A'A for each block
 *
 * b may be n-by-m with m > 1.  It must be dense.
 */

/* ========================================================================== */

#include "klu.h"
#include "klu_cholmod.h"
#include "mex.h"

void mexFunction
(
    int	nargout,
    mxArray *pargout [ ],
    int	nargin,
    const mxArray *pargin [ ]
)
{
    double condest ;
    double *Ax, *Info, *B, *X ;
    int n, *Ap, *Ai, k, nrhs, result, symmetric ;
    klu_symbolic *Symbolic ;
    klu_numeric *Numeric ;
    klu_common Common ;

    /* ---------------------------------------------------------------------- */
    /* get inputs */
    /* ---------------------------------------------------------------------- */

    if (nargin < 2 || nargin > 3 || nargout > 2)
    {
	mexErrMsgTxt ("Usage: [x, Info] = klus (A, b, options)") ;
    }

    /* get sparse matrix A */
    n = mxGetN (pargin [0]) ;
    if (!mxIsSparse (pargin [0]) || n != mxGetM (pargin [0]) ||
	mxIsComplex (pargin [0]) || n == 0)
    {
    	mexErrMsgTxt ("klus: A must be sparse, square, real, and non-empty") ;
    }
    Ap = mxGetJc (pargin [0]) ;
    Ai = mxGetIr (pargin [0]) ;
    Ax = mxGetPr (pargin [0]) ;

    /* get dense vector B */
    B = mxGetPr (pargin [1]) ;
    nrhs = mxGetN (pargin [1]) ;
    if (mxIsSparse (pargin [1]) || n != mxGetM (pargin [1]) ||
	mxIsComplex (pargin [1]) || nrhs == 0)
    {
    	mexErrMsgTxt (
	    "klus: B must be dense, real, non-empty, and correct dimensions") ;
    }

    /* get options */
    symmetric = (nargin == 2) || (mxGetScalar (pargin [2])) ;

    /* get control parameters */
    klu_defaults (&Common) ;
    Common.ordering = 3 ;
    Common.user_order = klu_cholmod ;
    Common.user_data = &symmetric ;

    /* hack
    Common.btf = 0 ; printf ("btf off\n") ;
    */

    /* allocate Info output */
    pargout [1] = mxCreateDoubleMatrix (1, 3, mxREAL) ;
    Info = mxGetPr (pargout [1]) ;
    for (k = 0 ; k < 3 ; k++) Info [k] = -1 ;

    /* ---------------------------------------------------------------------- */
    /* analyze */
    /* ---------------------------------------------------------------------- */

    Symbolic = klu_analyze (n, Ap, Ai, &Common) ;
    if (Symbolic == (klu_symbolic *) NULL)
    {
	mexErrMsgTxt ("klu_analyze failed") ;
    }

    Info [0] = Symbolic->nblocks ;
    Info [1] = Symbolic->maxblock ;

    /* ---------------------------------------------------------------------- */
    /* factorize */
    /* ---------------------------------------------------------------------- */

    Numeric = klu_factor (Ap, Ai, Ax, Symbolic, &Common) ;
    if (Common.status == KLU_SINGULAR)
    {
	printf("# singular column : %d\n", Common.singular_col) ;
    }
    if (Common.status != KLU_OK)
    {
	mexErrMsgTxt ("klu_factor failed") ;
    }

    /* nz in L, U, and off-diagonal blocks */
    Info [2] = Numeric->lnz + Numeric->unz + n + Common.noffdiag ;

    klu_condest (Ap, Ax, Symbolic, Numeric, &condest, &Common) ;
    printf ("cond est %g\n", condest) ;

    /* ---------------------------------------------------------------------- */
    /* allocate outputs and set X=B */
    /* ---------------------------------------------------------------------- */

    pargout [0] = mxCreateDoubleMatrix (n, nrhs, mxREAL) ;
    X = mxGetPr (pargout [0]) ;
    for (k = 0 ; k < n*nrhs ; k++) X [k] = B [k] ;

    /* ---------------------------------------------------------------------- */
    /* solve (overwrites right-hand-side with solution) */
    /* ---------------------------------------------------------------------- */

    result = klu_solve (Symbolic, Numeric, n, nrhs, X, &Common) ;

    /* ---------------------------------------------------------------------- */
    /* free Symbolic and Numeric objects, and free workspace */
    /* ---------------------------------------------------------------------- */

    result = klu_free_symbolic (&Symbolic, &Common) ;
    result = klu_free_numeric (&Numeric, &Common) ;
}


syntax highlighted by Code2HTML, v. 0.9.1