📄 mexsparchol.c
字号:
*pnadd = nadd; return ix;}/* ============================================================ MAIN: MEXFUNCTION ============================================================ *//* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]){ const mxArray *L_FIELD; mxArray *myplhs[NPAROUT]; int m, i, j, inz, iwsiz, nsuper, tmpsiz, fwsiz, nskip, nadd, m1; double *fwork, *d, *skipPr, *orgd; const double *permPr,*xsuperPr,*Ppr,*absd; int *perm, *snode, *xsuper, *iwork, *xlindx, *skip, *skipJc; const int *LINir, *Pjc, *Pir; double canceltol, maxu, abstol; jcir L; char useAbsd, useDelay;/* ------------------------------------------------------------ Check for proper number of arguments blkchol(L,P, pars,absd) with nparinmin=2. ------------------------------------------------------------ */ if(nrhs < NPARINMIN) mexErrMsgTxt("blkchol requires more input arguments"); if(nlhs > NPAROUT) mexErrMsgTxt("blkchol produces less output arguments");/* ------------------------------------------------------------ Get input matrix P to be factored. ------------------------------------------------------------ */ if( (m = mxGetM(P_IN)) != mxGetN(P_IN)) mexErrMsgTxt("P must be square"); if(!mxIsSparse(P_IN)) mexErrMsgTxt("P must be sparse"); Pjc = mxGetJc(P_IN); Pir = mxGetIr(P_IN); Ppr = mxGetPr(P_IN);/* ------------------------------------------------------------ Disassemble block Cholesky structure L ------------------------------------------------------------ */ if(!mxIsStruct(L_IN)) mexErrMsgTxt("Parameter `L' should be a structure."); if( (L_FIELD = mxGetField(L_IN,0,"perm")) == NULL) /* L.perm */ mexErrMsgTxt("Missing field L.perm."); if(m != mxGetM(L_FIELD) * mxGetN(L_FIELD)) mexErrMsgTxt("perm size mismatch"); permPr = mxGetPr(L_FIELD); if( (L_FIELD = mxGetField(L_IN,0,"L")) == NULL) /* L.L */ mexErrMsgTxt("Missing field L.L."); if( m != mxGetM(L_FIELD) || m != mxGetN(L_FIELD) ) mexErrMsgTxt("Size L.L mismatch."); if(!mxIsSparse(L_FIELD)) mexErrMsgTxt("L.L should be sparse."); L.jc = mxGetJc(L_FIELD); LINir = mxGetIr(L_FIELD); if( (L_FIELD = mxGetField(L_IN,0,"xsuper")) == NULL) /* L.xsuper */ mexErrMsgTxt("Missing field L.xsuper."); nsuper = mxGetM(L_FIELD) * mxGetN(L_FIELD) - 1; if( nsuper > m ) mexErrMsgTxt("Size L.xsuper mismatch."); xsuperPr = mxGetPr(L_FIELD); if( (L_FIELD = mxGetField(L_IN,0,"tmpsiz")) == NULL) /* L.tmpsiz */ mexErrMsgTxt("Missing field L.tmpsiz."); tmpsiz = mxGetScalar(L_FIELD);/* ------------------------------------------------------------ Disassemble pars structure: canceltol, maxu ------------------------------------------------------------ */ canceltol = 1E-15; /* supply with defaults */ maxu = 5E5; abstol = 1E-20; useAbsd = 0; useDelay = 0; if(nrhs >= NPARINMIN + 1){ /* 3rd argument = pars */ if(!mxIsStruct(PARS_IN)) mexErrMsgTxt("Parameter `pars' should be a structure."); if( (L_FIELD = mxGetField(PARS_IN,0,"canceltol")) != NULL) canceltol = mxGetScalar(L_FIELD); /* pars.canceltol */ if( (L_FIELD = mxGetField(PARS_IN,0,"maxu")) != NULL) maxu = mxGetScalar(L_FIELD); /* pars.maxu */ if( (L_FIELD = mxGetField(PARS_IN,0,"abstol")) != NULL){ abstol = mxGetScalar(L_FIELD); /* pars.abstol */ abstol = MAX(abstol, 0.0); } if( (L_FIELD = mxGetField(PARS_IN,0,"delay")) != NULL) useDelay = mxGetScalar(L_FIELD); /* pars.delay *//* ------------------------------------------------------------ Get optional vector absd ------------------------------------------------------------ */ if(nrhs >= NPARIN){ useAbsd = 1; absd = mxGetPr(ABSD_IN); if(m != mxGetM(ABSD_IN) * mxGetN(ABSD_IN)) mexErrMsgTxt("absd size mismatch"); } }/* ------------------------------------------------------------ Create sparse output matrix L(m x m). ------------------------------------------------------------ */ L_OUT = mxCreateSparse(m,m, L.jc[m],mxREAL); L.ir = mxGetIr(L_OUT); L.pr = mxGetPr(L_OUT); memcpy(mxGetJc(L_OUT), L.jc, (m+1) * sizeof(int)); memcpy(L.ir, LINir, L.jc[m] * sizeof(int));/* ------------------------------------------------------------ Create ouput vector d(m). ------------------------------------------------------------ */ D_OUT = mxCreateDoubleMatrix(m,1,mxREAL); d = mxGetPr(D_OUT);/* ------------------------------------------------------------ Compute required sizes of working arrays: iwsiz = 2*(m + nsuper). fwsiz = tmpsiz. ------------------------------------------------------------ */ iwsiz = MAX(2*(m+nsuper), 1); fwsiz = MAX(tmpsiz, 1);/* ------------------------------------------------------------ Allocate working arrays: integer: perm(m), snode(m), xsuper(nsuper+1), iwork(iwsiz), xlindx(m+1), skip(m), double: orgd(m), fwork(fwsiz). ------------------------------------------------------------ */ m1 = MAX(m,1); /* avoid alloc to 0 */ perm = (int *) mxCalloc(m1,sizeof(int)); snode = (int *) mxCalloc(m1,sizeof(int)); xsuper = (int *) mxCalloc(nsuper+1,sizeof(int)); iwork = (int *) mxCalloc(iwsiz,sizeof(int)); xlindx = (int *) mxCalloc(m+1,sizeof(int)); skip = (int *) mxCalloc(m1, sizeof(int)); orgd = (double *) mxCalloc(m1,sizeof(double)); fwork = (double *) mxCalloc(fwsiz,sizeof(double)); /* ------------------------------------------------------------ Convert PERM, XSUPER to integer and C-Style ------------------------------------------------------------ */ for(i = 0; i < m; i++){ j = permPr[i]; perm[i] = --j; } for(i = 0; i <= nsuper; i++){ j = xsuperPr[i]; xsuper[i] = --j; }/* ------------------------------------------------------------ Let L = tril(P(PERM,PERM)), uses orgd(m) as temp working storage. ------------------------------------------------------------ */ permuteP(L.jc,L.ir,L.pr, Pjc,Pir,Ppr, perm, orgd, m);/* ------------------------------------------------------------ If no orgd has been supplied, take orgd = diag(L on input) Otherwise, let orgd = absd(perm). ------------------------------------------------------------ */ if(useAbsd) for(j = 0; j < m; j++) orgd[j] = absd[perm[j]]; else for(j = 0; j < m; j++) orgd[j] = L.pr[L.jc[j]];/* ------------------------------------------------------------ Create "snode" and "xlindx"; change L.ir to the compact subscript array (with xlindx), and do BLOCK SPARSE CHOLESKY. ------------------------------------------------------------ */ nskip = spchol(m, nsuper, xsuper, snode, xlindx, L.ir, orgd, L.jc, L.pr, d, perm, abstol, canceltol, maxu, skip, &nadd, iwsiz, iwork, fwsiz, fwork); if(nskip < 0) mexErrMsgTxt("Insufficient workspace in pblkchol");/* ------------------------------------------------------------ Copy original row-indices from LINir to L.ir. ------------------------------------------------------------ */ memcpy(L.ir, LINir, L.jc[m] * sizeof(int));/* ------------------------------------------------------------ Create output matrices skip = sparse([],[],[],m,1,nskip), diagadd = sparse([],[],[],m,1,nadd), ------------------------------------------------------------ */ SKIP_OUT = mxCreateSparse(m,1, MAX(1,nskip),mxREAL); memcpy(mxGetIr(SKIP_OUT), skip, nskip * sizeof(int)); skipJc = mxGetJc(SKIP_OUT); skipJc[0] = 0; skipJc[1] = nskip; skipPr = mxGetPr(SKIP_OUT);/* ------------------------------------------------------------ useDelay = 1 then L(:,i) is i-th column before ith pivot; useful for pivot-delaying strategy. (Fwslv(L, L(:,i)) still required.) ------------------------------------------------------------ */ if(useDelay == 1) for(j = 0; j < nskip; j++) skipPr[j] = 1.0; else for(j = 0; j < nskip; j++){ i = skip[j]; skipPr[j] = L.pr[L.jc[i]]; /* Set skipped l(:,i)=ei. */ L.pr[L.jc[i]] = 1.0; fzeros(L.pr+L.jc[i]+1,L.jc[i+1]-L.jc[i]-1); } DIAGADD_OUT = mxCreateSparse(m,1, MAX(1,nadd),mxREAL); memcpy(mxGetIr(DIAGADD_OUT), iwork, nadd * sizeof(int)); skipJc = mxGetJc(DIAGADD_OUT); skipJc[0] = 0; skipJc[1] = nadd; skipPr = mxGetPr(DIAGADD_OUT); for(j = 0; j < nadd; j++) skipPr[j] = orgd[iwork[j]];/* ------------------------------------------------------------ Release working arrays. ------------------------------------------------------------ */ mxFree(fwork); mxFree(orgd); mxFree(skip); mxFree(xlindx); mxFree(iwork); mxFree(xsuper); mxFree(snode); mxFree(perm);/* ------------------------------------------------------------ Copy requested output parameters (at least 1), release others. ------------------------------------------------------------ */ i = MAX(nlhs, 1); memcpy(plhs,myplhs, i * sizeof(mxArray *)); for(; i < NPAROUT; i++) mxDestroyArray(myplhs[i]);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -