예제 #1
0
파일: ldlsymbolmex.c 프로젝트: Al-th/matlab
void mexFunction
(
    int	nargout,
    mxArray *pargout[ ],
    int	nargin,
    const mxArray *pargin[ ]
)
{
    Long i, n, *Pattern, *Flag, *Lp, *Ap, *Ai, *Lnz, *Parent,
	*P, *Pinv, nn, k, j, permute ;
    double flops, *p ;

    /* ---------------------------------------------------------------------- */
    /* get inputs and allocate workspace */
    /* ---------------------------------------------------------------------- */

    if (nargin == 0 || nargin > 2)
    {
	mexErrMsgTxt ("Usage:\n"
	    "  [Lnz, Parent, flopcount] = ldl (A) ;\n"
	    "  [Lnz, Parent, flopcount] = ldl (A, P) ;\n") ;
    }
    n = mxGetM (pargin [0]) ;
    if (!mxIsSparse (pargin [0]) || n != mxGetN (pargin [0])
	    || mxIsComplex (pargin [0]))
    {
    	mexErrMsgTxt ("ldlsymbol: A must be sparse, square, and real") ;
    }

    nn = (n == 0) ? 1 : n ;

    /* get sparse matrix A */
    Ap = (Long *) mxGetJc (pargin [0]) ;
    Ai = (Long *) mxGetIr (pargin [0]) ;

    /* get fill-reducing ordering, if present */
    permute = ((nargin > 1) && !mxIsEmpty (pargin [1])) ;
    if (permute)
    {
	if (mxGetM (pargin [1]) * mxGetN (pargin [1]) != n ||
		mxIsSparse (pargin [1]))
	{
	    mexErrMsgTxt ("ldlsymbol: invalid input permutation\n") ;
	}
	P    = (Long *) mxMalloc (nn * sizeof (Long)) ;
	Pinv = (Long *) mxMalloc (nn * sizeof (Long)) ;
	p = mxGetPr (pargin [1]) ;
	for (k = 0 ; k < n ; k++)
	{
	    P [k] = p [k] - 1 ;	/* convert to 0-based */
	}
    }
    else
    {
	P    = (Long *) NULL ;
	Pinv = (Long *) NULL ;
    }

    /* allocate first part of L */
    Lp      = (Long *) mxMalloc ((n+1) * sizeof (Long)) ;
    Parent  = (Long *) mxMalloc (nn * sizeof (Long)) ;

    /* get workspace */
    Flag    = (Long *) mxMalloc (nn * sizeof (Long)) ;
    Pattern = (Long *) mxMalloc (nn * sizeof (Long)) ;
    Lnz     = (Long *) mxMalloc (nn * sizeof (Long)) ;

    /* make sure the input P is valid */
    if (permute && !ldl_l_valid_perm (n, P, Flag))
    {
	mexErrMsgTxt ("ldlsymbol: invalid input permutation\n") ;
    }

    /* note that we assume that the input matrix is valid */

    /* ---------------------------------------------------------------------- */
    /* symbolic factorization to get Lp, Parent, Lnz, and optionally Pinv */
    /* ---------------------------------------------------------------------- */

    ldl_l_symbolic (n, Ap, Ai, Lp, Parent, Lnz, Flag, P, Pinv) ;

    /* ---------------------------------------------------------------------- */
    /* create outputs */
    /* ---------------------------------------------------------------------- */

    /* create the output Lnz vector */
    pargout [0] = mxCreateDoubleMatrix (1, n, mxREAL) ;
    p = mxGetPr (pargout [0]) ;
    for (j = 0 ; j < n ; j++)
    {
	p [j] = Lnz [j] ;
    }

    /* return elimination tree (add 1 to change from 0-based to 1-based) */
    if (nargout > 1)
    {
	pargout [1] = mxCreateDoubleMatrix (1, n, mxREAL) ;
	p = mxGetPr (pargout [1]) ;
	for (i = 0 ; i < n ; i++)
	{
	    p [i] = Parent [i] + 1 ;
	}
    }

    if (nargout > 2)
    {
	/* find flop count for ldl_l_numeric */
	flops = 0 ;
	for (k = 0 ; k < n ; k++)
	{
	    flops += ((double) Lnz [k]) * (Lnz [k] + 2) ;
	}
	pargout [2] = mxCreateDoubleMatrix (1, 1, mxREAL) ;
	p = mxGetPr (pargout [2]) ;
	p [0] = flops ;
    }

    if (permute)
    {
	mxFree (P) ;
	mxFree (Pinv) ;
    }
    mxFree (Lp) ;
    mxFree (Parent) ;
    mxFree (Flag) ;
    mxFree (Pattern) ;
    mxFree (Lnz) ;
}
예제 #2
0
파일: ldlmex.c 프로젝트: Ascronia/fieldtrip
void mexFunction
(
    int	nargout,
    mxArray *pargout[ ],
    int	nargin,
    const mxArray *pargin[ ]
)
{
    UF_long i, n, *Pattern, *Flag, *Li, *Lp, *Ap, *Ai, *Lnz, *Parent, do_chol,
	nrhs = 0, lnz, do_solve, *P, *Pinv, nn, k, j, permute, *Dp = NULL, *Di,
	d, do_flops, psrc, pdst ;
    double *Y, *D, *Lx, *Ax, flops, *X = NULL, *B = NULL, *p ;

    /* ---------------------------------------------------------------------- */
    /* get inputs and allocate workspace */
    /* ---------------------------------------------------------------------- */

    do_chol  = (nargin > 0) && (nargin <= 2) && (nargout <= 4) ;
    do_solve = (nargin == 3) && (nargout <= 2) ;
    if (!(do_chol || do_solve))
    {
	mexErrMsgTxt ("Usage:\n"
	    "  [L, D, etree, flopcount] = ldl (A) ;\n"
	    "  [L, D, etree, flopcount] = ldl (A, P) ;\n"
	    "  [x, flopcount] = ldl (A, [ ], b) ;\n"
	    "  [x, flopcount] = ldl (A, P, b) ;\n"
	    "The etree and flopcount arguments are optional.") ;
    }
    n = mxGetM (pargin [0]) ;
    if (!mxIsSparse (pargin [0]) || n != mxGetN (pargin [0])
	    || mxIsComplex (pargin [0]))
    {
    	mexErrMsgTxt ("ldl: A must be sparse, square, and real") ;
    }
    if (do_solve)
    {
	if (mxIsSparse (pargin [2]) || n != mxGetM (pargin [2])
	    || !mxIsDouble (pargin [2]) || mxIsComplex (pargin [2]))
	{
	    mexErrMsgTxt (
		"ldl: b must be dense, real, and with proper dimension") ;
	}
    }
    nn = (n == 0) ? 1 : n ;

    /* get sparse matrix A */
    Ap = (UF_long *) mxGetJc (pargin [0]) ;
    Ai = (UF_long *) mxGetIr (pargin [0]) ;
    Ax = mxGetPr (pargin [0]) ;

    /* get fill-reducing ordering, if present */
    permute = ((nargin > 1) && !mxIsEmpty (pargin [1])) ;
    if (permute)
    {
	if (mxGetM (pargin [1]) * mxGetN (pargin [1]) != n ||
		mxIsSparse (pargin [1]))
	{
	    mexErrMsgTxt ("ldl: invalid input permutation\n") ;
	}
	P    = (UF_long *) mxMalloc (nn * sizeof (UF_long)) ;
	Pinv = (UF_long *) mxMalloc (nn * sizeof (UF_long)) ;
	p = mxGetPr (pargin [1]) ;
	for (k = 0 ; k < n ; k++)
	{
	    P [k] = p [k] - 1 ;	/* convert to 0-based */
	}
    }
    else
    {
	P    = (UF_long *) NULL ;
	Pinv = (UF_long *) NULL ;
    }

    /* allocate first part of L */
    Lp      = (UF_long *) mxMalloc ((n+1) * sizeof (UF_long)) ;
    Parent  = (UF_long *) mxMalloc (nn * sizeof (UF_long)) ;

    /* get workspace */
    Y       = (double *)  mxMalloc (nn * sizeof (double)) ;
    Flag    = (UF_long *) mxMalloc (nn * sizeof (UF_long)) ;
    Pattern = (UF_long *) mxMalloc (nn * sizeof (UF_long)) ;
    Lnz     = (UF_long *) mxMalloc (nn * sizeof (UF_long)) ;

    /* make sure the input P is valid */
    if (permute && !ldl_l_valid_perm (n, P, Flag))
    {
	mexErrMsgTxt ("ldl: invalid input permutation\n") ;
    }

    /* note that we assume that the input matrix is valid */

    /* ---------------------------------------------------------------------- */
    /* symbolic factorization to get Lp, Parent, Lnz, and optionally Pinv */
    /* ---------------------------------------------------------------------- */

    ldl_l_symbolic (n, Ap, Ai, Lp, Parent, Lnz, Flag, P, Pinv) ;
    lnz = Lp [n] ;

    /* ---------------------------------------------------------------------- */
    /* create outputs */
    /* ---------------------------------------------------------------------- */

    if (do_chol)
    {
	/* create the output matrix L, using the Lp array from ldl_l_symbolic */
	pargout [0] = mxCreateSparse (n, n, lnz+1, mxREAL) ;
	mxFree (mxGetJc (pargout [0])) ;
	mxSetJc (pargout [0], (void *) Lp) ;	/* Lp is not mxFree'd */
	Li = (UF_long *) mxGetIr (pargout [0]) ;
	Lx = mxGetPr (pargout [0]) ;

	/* create sparse diagonal matrix D */
	if (nargout > 1)
	{
	    pargout [1] = mxCreateSparse (n, n, nn, mxREAL) ;
	    Dp = (UF_long *) mxGetJc (pargout [1]) ;
	    Di = (UF_long *) mxGetIr (pargout [1]) ;
	    for (j = 0 ; j < n ; j++)
	    {
		Dp [j] = j ;
		Di [j] = j ;
	    }
	    Dp [n] = n ;
	    D = mxGetPr (pargout [1])  ;
	}
	else
	{
	    D  = (double *) mxMalloc (nn * sizeof (double)) ;
	}

	/* return elimination tree (add 1 to change from 0-based to 1-based) */
	if (nargout > 2)
	{
	    pargout [2] = mxCreateDoubleMatrix (1, n, mxREAL) ;
	    p = mxGetPr (pargout [2]) ;
	    for (i = 0 ; i < n ; i++)
	    {
		p [i] = Parent [i] + 1 ;
	    }
	}

	do_flops = (nargout == 4) ? (3) : (-1) ;
    }
    else
    {
	/* create L and D as temporary matrices */
	Li = (UF_long *)    mxMalloc ((lnz+1) * sizeof (UF_long)) ;
	Lx = (double *) mxMalloc ((lnz+1) * sizeof (double)) ;
	D  = (double *) mxMalloc (nn * sizeof (double)) ;

	/* create solution x */
	nrhs = mxGetN (pargin [2]) ;
	pargout [0] = mxCreateDoubleMatrix (n, nrhs, mxREAL) ;
	X = mxGetPr (pargout [0]) ;
	B = mxGetPr (pargin [2]) ;

	do_flops = (nargout == 2) ? (1) : (-1) ;
    }

    if (do_flops >= 0)
    {
	/* find flop count for ldl_l_numeric */
	flops = 0 ;
	for (k = 0 ; k < n ; k++)
	{
	    flops += ((double) Lnz [k]) * (Lnz [k] + 2) ;
	}
	if (do_solve)
	{
	    /* add flop count for solve */
	    for (k = 0 ; k < n ; k++)
	    {
		flops += 4 * ((double) Lnz [k]) + 1 ;
	    }
	}
	pargout [do_flops] = mxCreateDoubleMatrix (1, 1, mxREAL) ;
	p = mxGetPr (pargout [do_flops]) ;
	p [0] = flops ;
    }

    /* ---------------------------------------------------------------------- */
    /* numeric factorization to get Li, Lx, and D */
    /* ---------------------------------------------------------------------- */

    d = ldl_l_numeric (n, Ap, Ai, Ax, Lp, Parent, Lnz, Li, Lx, D, Y, Flag,
	Pattern, P, Pinv) ;

    /* ---------------------------------------------------------------------- */
    /* singular case : truncate the factorization */
    /* ---------------------------------------------------------------------- */

    if (d != n)
    {
	/* D [d] is zero:  report error, or clean up */
	if (do_chol && do_flops < 0)
	{
	    mexErrMsgTxt ("ldl: zero pivot encountered\n") ;
	}
	else
	{
	    /* L and D are incomplete, compact them */
	    if (do_chol)
	    {
		for (k = d ; k < n ; k++)
		{
		    Dp [k] = d ;
		}
		Dp [n] = d ;
	    }
	    for (k = d ; k < n ; k++)
	    {
		D [k] = 0 ;
	    }
	    pdst = 0 ;
	    for (k = 0 ; k < d ; k++)
	    {
		for (psrc = Lp [k] ; psrc < Lp [k] + Lnz [k] ; psrc++)
		{
		    Li [pdst] = Li [psrc] ;
		    Lx [pdst] = Lx [psrc] ;
		    pdst++ ;
		}
	    }
	    for (k = 0 ; k < d  ; k++)
	    {
		Lp [k+1] = Lp [k] + Lnz [k] ;
	    }
	    for (k = d ; k <= n ; k++)
	    {
		Lp [k] = pdst ;
	    }
	    if (do_flops >= 0)
	    {
		/* return -d instead of the flop count (convert to 1-based) */
		p = mxGetPr (pargout [do_flops]) ;
		p [0] = -(1+d) ;
	    }
	}
    }

    /* ---------------------------------------------------------------------- */
    /* solve Ax=b, if requested */
    /* ---------------------------------------------------------------------- */

    if (do_solve)
    {
	if (permute)
	{
	    for (j = 0 ; j < nrhs ; j++)
	    {
		ldl_l_perm (n, Y, B, P) ;		    /* y = Pb */
		ldl_l_lsolve (n, Y, Lp, Li, Lx) ;	    /* y = L\y */
		ldl_l_dsolve (n, Y, D) ;		    /* y = D\y */
		ldl_l_ltsolve (n, Y, Lp, Li, Lx) ;	    /* y = L'\y */
		ldl_l_permt (n, X, Y, P) ;		    /* x = P'y */
		X += n ;
		B += n ;
	    }
	}
	else
	{
	    for (j = 0 ; j < nrhs ; j++)
	    {
		for (k = 0 ; k < n ; k++)		    /* x = b */
		{
		    X [k] = B [k] ;
		}
		ldl_l_lsolve (n, X, Lp, Li, Lx) ;	    /* x = L\x */
		ldl_l_dsolve (n, X, D) ;		    /* x = D\x */
		ldl_l_ltsolve (n, X, Lp, Li, Lx) ;	    /* x = L'\x */
		X += n ;
		B += n ;
	    }
	}
	/* free the matrix L */
	mxFree (Lp) ;
	mxFree (Li) ;
	mxFree (Lx) ;
	mxFree (D) ;
    }

    /* ---------------------------------------------------------------------- */
    /* free workspace */
    /* ---------------------------------------------------------------------- */

    if (do_chol && nargout < 2)
    {
	mxFree (D) ;
    }
    if (permute)
    {
	mxFree (P) ;
	mxFree (Pinv) ;
    }
    mxFree (Parent) ;
    mxFree (Y) ;
    mxFree (Flag) ;
    mxFree (Pattern) ;
    mxFree (Lnz) ;
}