core/matlab/examples/refbook/utdu_slv.c

00001 /* $Revision: 1.1 $ $Date: 2007/12/11 19:59:58 $ */
00002 /*=========================================================
00003  * utdu_slv.c
00004  * example for illustrating how to use LAPACK within a C
00005  * MEX-file on Windows or HP-UX.  This differs from the
00006  * other platforms in that the LAPACK symbols are not
00007  * exported with underscores e.g., dsysvx instead of dsysvx_
00008  *
00009  * UTDU_SLV Solves the symmetric indefinite system of linear 
00010  * equations A*X=B for X.
00011  * X = UTDU_SLV(A,B) computes a symmetric (Hermitian) indefinite 
00012  * factorization of A and returns the result X such that A*X is B. 
00013  * B must have as many rows as A.
00014  *
00015  * This is a MEX-file for MATLAB.
00016  * Copyright 1984-2006 The MathWorks, Inc.
00017  *=======================================================*/
00018 
00019 #if !defined(_WIN32)
00020 #define zhesvx zhesvx_
00021 #define dsysvx dsysvx_
00022 #endif
00023 
00024 #include "mex.h"
00025 #include "fort.h"
00026 
00027 extern void zhesvx(
00028     char   *fact,
00029     char   *uplo,
00030     int    *n,
00031     int    *nrhs,
00032     double *a,
00033     int    *lda,
00034     double *af,
00035     int    *ldaf,
00036     int    *ipiv,
00037     double *b,
00038     int    *ldb,
00039     double *x,
00040     int    *ldx,
00041     double *rcond,
00042     double *ferr,
00043     double *berr,
00044     double *work,
00045     int    *lwork,
00046     double *rwork,
00047     int    *info
00048 );
00049 
00050 extern void dsysvx(
00051     char   *fact,
00052     char   *uplo,
00053     int    *n,
00054     int    *nrhs,
00055     double *a,
00056     int    *lda,
00057     double *af,
00058     int    *ldaf,
00059     int    *ipiv,
00060     double *b,
00061     int    *ldb,
00062     double *x,
00063     int    *ldx,
00064     double *rcond,
00065     double *ferr,
00066     double *berr,
00067     double *work,
00068     int    *lwork,
00069     int    *iwork,
00070     int    *info
00071 );
00072 
00073 void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] )
00074 {
00075 
00076     /* mex interface to LAPACK functions dsysvx and zhesvx */
00077 
00078     char fact[2] = {'N','\0'}, uplo[2] = {'U','\0'};
00079     char msg[101];
00080     int cplx, info, n, nrhsb, lda, ldaf, ldb, ldx, lwork;
00081     int *ipiv, *iwork=NULL;
00082     double *A, *AF, *b, *x, rcond, *ferr, *berr, *work1, *work, *rwork=NULL;
00083     
00084     if ((nlhs > 1) || (nrhs != 2)) {
00085       mexErrMsgTxt("Expect 2 input arguments and return 1 output argument");
00086     }
00087 
00088     /*
00089      * FORTRAN/LAPACK uses 32-bit integers at present
00090      */
00091     mxAssert(mxGetM(prhs[0])<INT_MAX, "Matrix is too large for 32-bit LAPACK");
00092     mxAssert(mxGetN(prhs[0])<INT_MAX, "Matrix is too large for 32-bit LAPACK");
00093     mxAssert(mxGetM(prhs[1])<INT_MAX, "Matrix is too large for 32-bit LAPACK");
00094     mxAssert(mxGetN(prhs[1])<INT_MAX, "Matrix is too large for 32-bit LAPACK");
00095 
00096     n = (int)mxGetN(prhs[0]);
00097     nrhsb = (int)mxGetN(prhs[1]);
00098     lda = (int)mxGetM(prhs[0]);
00099     if (lda != n) {
00100       mexErrMsgTxt("Matrix must be square and symmetric");
00101     }
00102     cplx = (mxGetPi(prhs[0]) || mxGetPi(prhs[1]));
00103     if (cplx) {
00104       A = mat2fort(prhs[0],lda,n);
00105       AF = (double *)mxCalloc(2*lda*n,sizeof(double));
00106     } else {
00107       A = mxGetPr(prhs[0]);
00108       AF = (double *)mxCalloc(lda*n,sizeof(double));
00109     }
00110     ldaf = lda;
00111     ipiv = (int *)mxCalloc(n,sizeof(int));
00112     ldb = (int)mxGetM(prhs[1]);
00113     if (lda != ldb) {
00114       mexErrMsgTxt("A and b must have the same number of rows");
00115     }
00116     ldx = ldb;
00117     ferr = (double *)mxCalloc(nrhsb,sizeof(double));
00118     berr = (double *)mxCalloc(nrhsb,sizeof(double));
00119     lwork = -1;
00120     info = 0;
00121     if (cplx) {
00122       b = mat2fort(prhs[1],ldb,nrhsb);
00123       x = (double *)mxCalloc(2*ldb*nrhsb,sizeof(double));
00124       work1 = (double *)mxCalloc(2,sizeof(double));
00125       rwork = (double *)mxCalloc(n,sizeof(double));
00126       /* Query zhesvx on the value of lwork */
00127       zhesvx ( fact, uplo, &n, &nrhsb, A, &lda, AF, &ldaf, ipiv, b, &ldb,
00128         x, &ldx, &rcond, ferr, berr, work1, &lwork, rwork, &info );
00129         if (info < 0) {
00130           sprintf(msg, "Input %d to zhesvx had an illegal value",-info);
00131           mexErrMsgTxt(msg);
00132         }
00133       lwork = (int)(work1[0]);
00134       work = (double *)mxCalloc(2*lwork,sizeof(double));
00135         zhesvx ( fact, uplo, &n, &nrhsb, A, &lda, AF, &ldaf, ipiv, b, &ldb,
00136           x, &ldx, &rcond, ferr, berr, work, &lwork, rwork, &info );
00137         if (info < 0) {
00138           sprintf(msg, "Input %d to zhesvx had an illegal value",-info);
00139           mexErrMsgTxt(msg);
00140         }
00141     } else {
00142       b = mxGetPr(prhs[1]);
00143       x = (double *)mxCalloc(ldb*nrhsb,sizeof(double));
00144       work1 = (double *)mxCalloc(1,sizeof(double));
00145       iwork = (int *)mxCalloc(n,sizeof(int));
00146       /* Query dsysvx on the value of lwork */
00147       dsysvx ( fact, uplo, &n, &nrhsb, A, &lda, AF, &ldaf, ipiv, b, &ldb,
00148         x, &ldx, &rcond, ferr, berr, work1, &lwork, iwork, &info );
00149         if (info < 0) {
00150           sprintf(msg, "Input %d to dsysvx had an illegal value",-info);
00151           mexErrMsgTxt(msg);
00152         }
00153       lwork = (int)(work1[0]);
00154       work = (double *)mxCalloc(lwork,sizeof(double));
00155         dsysvx ( fact, uplo, &n, &nrhsb, A, &lda, AF, &ldaf, ipiv, b, &ldb,
00156           x, &ldx, &rcond, ferr, berr, work, &lwork, iwork, &info );
00157         if (info < 0) {
00158           sprintf(msg, "Input %d to dsysvx had an illegal value",-info);
00159           mexErrMsgTxt(msg);
00160         }
00161     }
00162 
00163     if (rcond == 0) {
00164       sprintf(msg,"Matrix is singular to working precision.");
00165       mexErrMsgTxt(msg);
00166     } else if (rcond < mxGetEps()) {
00167       sprintf(msg,"Matrix is close to singular or badly scaled.\n"
00168         "         Results may be inaccurate. RCOND = %g",rcond);
00169       mexWarnMsgTxt(msg);
00170     }
00171 
00172     if (cplx) {
00173       plhs[0] = fort2mat(x,ldx,ldx,nrhsb);
00174       mxFree(A);
00175       mxFree(b);
00176       mxFree(rwork);
00177     } else {
00178       plhs[0] = mxCreateDoubleMatrix(ldx,nrhsb,0);
00179       mxSetPr(plhs[0],x);
00180       mxFree(iwork);
00181     }
00182 
00183     mxFree(AF);
00184     mxFree(ipiv);
00185     mxFree(ferr);
00186     mxFree(berr);
00187     mxFree(work1);
00188     mxFree(work);
00189 }

GridLAB-DTM Version 1.0
An open-source project initiated by the US Department of Energy