/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab [ux,ispos] = psdfactor(x,K); ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { mxArray *myplhs[NPAROUT]; coneK cK; mwIndex k,nk,nksqr, sdplen,sdpdim,lenfull, ispos; const double *x; double *ux; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "psdfactor requires more input arguments"); mxAssert(nlhs <= NPAROUT, "psdfactor produces less output arguments"); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Compute statistics: sdpdim = rdim+hdim, sdplen = sum(K.s). ------------------------------------------------------------ */ lenfull = cK.lpN + cK.qDim + cK.rDim + cK.hDim; sdpdim = cK.rDim + cK.hDim; sdplen = cK.rLen + cK.hLen; /* ------------------------------------------------------------ Get input vector x, skip LP + Lorentz part ------------------------------------------------------------ */ x = mxGetPr(X_IN); if(mxGetM(X_IN) * mxGetN(X_IN) == lenfull) x += cK.lpN + cK.qDim; else mxAssert(mxGetM(X_IN) * mxGetN(X_IN) == sdpdim, "x size mismatch."); /* ------------------------------------------------------------ Allocate output UX(sdpdim), ispos(1). ------------------------------------------------------------ */ UX_OUT = mxCreateDoubleMatrix(sdpdim, (mwSize)1, mxREAL); ux = mxGetPr(UX_OUT); ISPOS_OUT = mxCreateDoubleMatrix((mwSize)1,(mwSize)1,mxREAL); /* ------------------------------------------------------------ PSD: Cholesky factorization. Initialize ispos = 1 and ux = x. ------------------------------------------------------------ */ ispos = 1; memcpy(ux, x, sdpdim * sizeof(double)); /* copy real + complex */ for(k = 0; k < cK.rsdpN; k++){ /* real symmetric */ nk = cK.sdpNL[k]; /* ------------------------------------------------------------ Attempt Cholesky on block k. Returns 1 if fail (i.e. not psd). ------------------------------------------------------------ */ if(cholnopiv(ux,nk)){ ispos = 0; break; } triu2sym(ux,nk); ux += SQR(nk); } /* ------------------------------------------------------------ Complex Hermitian PSD Cholesky factorization, no pivoting. ------------------------------------------------------------ */ if(ispos) for(; k < cK.sdpN; k++){ /* complex Hermitian */ nk = cK.sdpNL[k]; nksqr = SQR(nk); if(prpicholnopiv(ux,ux+nksqr,nk)){ ispos = 0; break; } triu2herm(ux,ux+nksqr,nk); ux += 2 * nksqr; } /* ------------------------------------------------------------ Return parameter ispos ------------------------------------------------------------ */ *mxGetPr(ISPOS_OUT) = ispos; /* ------------------------------------------------------------ Copy requested output parameters (at least 1), release others. ------------------------------------------------------------ */ k = MAX(nlhs, 1); memcpy(plhs,myplhs, k * sizeof(mxArray *)); for(; k < NPAROUT; k++) mxDestroyArray(myplhs[k]); }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab [qdetx,ux,ispos,perm] = factorK(x,K); ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { mxArray *myplhs[NPAROUT]; coneK cK; int i,k,nk,nksqr, sdplen,sdpdim,lenfull, fwsiz, ispos; const double *x; double *ux, *fwork, *permPr, *qdetx, *up, *uppi; int *iwork, *perm; double uxk; char use_pivot; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "factorK requires more input arguments"); mxAssert(nlhs <= NPAROUT, "factorK produces less output arguments"); use_pivot = (nlhs == NPAROUT); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Compute statistics: sdpdim = rdim+hdim, sdplen = sum(K.s). ------------------------------------------------------------ */ lenfull = cK.lpN + cK.qDim + cK.rDim + cK.hDim; sdpdim = cK.rDim + cK.hDim; sdplen = cK.rLen + cK.hLen; /* ------------------------------------------------------------ Get input vector x, skip LP part ------------------------------------------------------------ */ mxAssert(mxGetM(X_IN) * mxGetN(X_IN) == lenfull, "x size mismatch."); x = mxGetPr(X_IN) + cK.lpN; /* ------------------------------------------------------------ Allocate output qdetx(lorN), UX(sdpdim), perm(sdplen), ispos(1). ------------------------------------------------------------ */ QDETX_OUT = mxCreateDoubleMatrix(cK.lorN, 1, mxREAL); qdetx = mxGetPr(QDETX_OUT); UX_OUT = mxCreateDoubleMatrix(sdpdim, 1, mxREAL); ux = mxGetPr(UX_OUT); ISPOS_OUT = mxCreateDoubleMatrix(1,1,mxREAL); PERM_OUT = mxCreateDoubleMatrix(sdplen, 1, mxREAL); permPr = mxGetPr(PERM_OUT); /* ------------------------------------------------------------ Allocate working arrays iwork(sdplen), fwork(MAX(rmaxn^2,2*hmaxn^2) + MAX(rmaxn,hmaxn)) ------------------------------------------------------------ */ iwork = (int *) mxCalloc(sdplen, sizeof(int)); perm = iwork; fwsiz = MAX(cK.rMaxn,cK.hMaxn); fwork = (double *) mxCalloc(fwsiz + MAX(SQR(cK.rMaxn),2*SQR(cK.hMaxn)), sizeof(double)); up = fwork + fwsiz; uppi = up + SQR(cK.hMaxn); /* ------------------------------------------------------------ LORENTZ: qdetx = sqrt(qdet(x)) ------------------------------------------------------------ */ ispos = 1; for(k = 0; k < cK.lorN; k++){ nk = cK.lorNL[k]; if( (uxk = qdet(x,nk)) < 0.0){ ispos = 0; break; } else qdetx[k] = sqrt(uxk); x += nk; } /* ------------------------------------------------------------ PSD: Cholesky factorization. If use_pivot, then do pivoting. ------------------------------------------------------------ */ if(use_pivot){ if(ispos) for(k = 0; k < cK.rsdpN; k++){ /* real symmetric */ nk = cK.sdpNL[k]; if(cholpivot(up,perm, x,nk, fwork)){ ispos = 0; break; } uperm(ux, up, perm, nk); triu2sym(ux,nk); nksqr = SQR(nk); x += nksqr; ux += nksqr; perm += nk; } /* ------------------------------------------------------------ Complex Hermitian PSD pivoted Cholesky factorization ------------------------------------------------------------ */ if(ispos) for(; k < cK.sdpN; k++){ /* complex Hermitian */ nk = cK.sdpNL[k]; nksqr = SQR(nk); if(prpicholpivot(up,uppi,perm, x,x+nksqr,nk, fwork)){ ispos = 0; break; } uperm(ux, up, perm, nk); /* real part */ uperm(ux+nksqr, uppi, perm, nk); /* imaginary part */ triu2herm(ux,ux+nksqr,nk); nksqr += nksqr; /* 2*n^2 for real+imag */ x += nksqr; ux += nksqr; perm += nk; } /* ------------------------------------------------------------ Convert "perm" to Fortran-index in doubles. ------------------------------------------------------------ */ for(i = 0; i < sdplen; i++) permPr[i] = 1.0 + iwork[i]; } /* ------------------------------------------------------------ PSD, !use_pivot: Cholesky without pivoting. First let ux = x, then ux=chol(ux). ------------------------------------------------------------ */ else{ /* Cholesky real sym PSD without pivoting */ if(ispos){ memcpy(ux, x, sdpdim * sizeof(double)); /* copy real + complex */ for(k = 0; k < cK.rsdpN; k++){ /* real symmetric */ nk = cK.sdpNL[k]; if(cholnopiv(ux,nk)){ ispos = 0; break; } triu2sym(ux,nk); ux += SQR(nk); } } /* ------------------------------------------------------------ Complex Hermitian PSD Cholesky factorization, no pivoting. ------------------------------------------------------------ */ if(ispos) for(; k < cK.sdpN; k++){ /* complex Hermitian */ nk = cK.sdpNL[k]; nksqr = SQR(nk); if(prpicholnopiv(ux,ux+nksqr,nk)){ ispos = 0; break; } triu2herm(ux,ux+nksqr,nk); ux += 2 * nksqr; } } /* !use_pivot */ /* ------------------------------------------------------------ Return parameter ispos ------------------------------------------------------------ */ *mxGetPr(ISPOS_OUT) = ispos; /* ------------------------------------------------------------ Release working arrays ------------------------------------------------------------ */ mxFree(iwork); mxFree(fwork); /* ------------------------------------------------------------ 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]); }