/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab y = mJdetd(detd,K) ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { mwIndex i,nexti,k; double detdk; double *y; const double *detd; coneK cK; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ if(nrhs < NPARIN) mexErrMsgTxt("mJdetd requires more input arguments."); if (nlhs > NPAROUT) mexErrMsgTxt("mJdetd generates 1 output argument."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Get input detd ------------------------------------------------------------ */ if(mxGetM(DETD_IN) * mxGetN(DETD_IN) != cK.lorN) mexErrMsgTxt("detd size mismatch"); detd = mxGetPr(DETD_IN); /* ------------------------------------------------------------ Allocate output y(qDim) ------------------------------------------------------------ */ Y_OUT = mxCreateDoubleMatrix(cK.qDim, 1, mxREAL); y = mxGetPr(Y_OUT); /* ------------------------------------------------------------ LORENTZ: yk = [-detd(k); detd(k)* ones(nk-1,1)] ------------------------------------------------------------ */ i = 0; nexti = 0; for(k = 0; k < cK.lorN; k++){ nexti += cK.lorNL[k]; detdk = detd[k]; y[i] = -detdk; for(++i; i < nexti; i++) y[i] = detdk; } }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { int i,k, nk; double *y; const double *d,*rdetd,*x; coneK cK; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "qscaleK requires more input arguments."); mxAssert(nlhs <= NPAROUT, "qscaleK generates 1 output argument."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Get scale data: (d,rdetd) and input x. ------------------------------------------------------------ */ mxAssert(mxGetM(D_IN) * mxGetN(D_IN) >= cK.lpN + cK.qDim, "d size mismatch"); d = mxGetPr(D_IN) + cK.lpN; /* skip LP part */ mxAssert(mxGetM(RDETD_IN) * mxGetN(RDETD_IN) == cK.lorN, "rdetx size mismatch"); rdetd = mxGetPr(RDETD_IN); mxAssert(mxGetM(X_IN) * mxGetN(X_IN) == cK.qDim, "x size mismatch"); x = mxGetPr(X_IN); /* ------------------------------------------------------------ Allocate output Y ------------------------------------------------------------ */ Y_OUT = mxCreateDoubleMatrix(cK.qDim, 1, mxREAL); y = mxGetPr(Y_OUT); /* ------------------------------------------------------------ The actual job is done here: y=D(d)x, Lorentz part. ------------------------------------------------------------ */ for(k = 0; k < cK.lorN; k++){ /* LORENTZ */ nk = cK.lorNL[k]; qlmul(y, d,x,rdetd[k],nk); y += nk; x += nk; d += nk; } }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab y = vecsym(x,K) Computes "symmetrization of x: Yk = (Xk+Xk')/2 ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { mxArray *output_array[1], *Xk; coneK cK; int k, nk, nksqr, lqDim,lenfull; const double *x; double *y; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= 2, "vecsym requires 2 input arguments."); mxAssert(nlhs <= 1, "vecsym generates 1 output argument."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Compute some statistics based on cone K structure ------------------------------------------------------------ */ lqDim = cK.lpN + cK.qDim; lenfull = lqDim + cK.rDim + cK.hDim; /* ------------------------------------------------------------ Get input vector x ------------------------------------------------------------ */ mxAssert(!mxIsSparse(X_IN), "x must be full."); mxAssert(mxGetM(X_IN) * mxGetN(X_IN) == lenfull, "Parameter `x' size mismatch."); x = mxGetPr(X_IN); /* ------------------------------------------------------------ Allocate output vector y, and make it vecsym(x) ------------------------------------------------------------ */ Y_OUT = mxCreateDoubleMatrix(lenfull, 1, mxREAL); y = mxGetPr(Y_OUT); memcpy(y,x,lqDim * sizeof(double)); x += lqDim; y += lqDim; vecsymPSD(y, x,cK.rsdpN,cK.sdpN,cK.sdpNL); }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { int i,k, nk; double *y; const double *x,*qdetx; coneK cK; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "qinvsqrt requires more input arguments."); mxAssert(nlhs <= NPAROUT, "qinvsqrt generates less output arguments."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Get inputs x, qdetx ------------------------------------------------------------ */ mxAssert(mxGetM(X_IN) * mxGetN(X_IN) >= cK.lpN + cK.qDim, "x size mismatch"); x = mxGetPr(X_IN) + cK.lpN; /* skip LP part */ mxAssert(mxGetM(QDETX_IN) * mxGetN(QDETX_IN) == cK.lorN, "qdetx size mismatch"); qdetx = mxGetPr(QDETX_IN); /* ------------------------------------------------------------ Allocate output y ------------------------------------------------------------ */ Y_OUT = mxCreateDoubleMatrix(cK.qDim, 1, mxREAL); y = mxGetPr(Y_OUT); /* ------------------------------------------------------------ The actual job is done here: y = w^{-1/2}, Lorentz part. ------------------------------------------------------------ */ for(k = 0; k < cK.lorN; k++){ /* LORENTZ */ nk = cK.lorNL[k]; powminhalf(y, x,qdetx[k],nk); y += nk; x += nk; } }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { const mxArray *UD_FIELD; mwIndex lenfull, lenud, sdplen, fwsiz, i,k; double *fwork, *y,*permPr; const double *x,*ud; mwIndex *perm, *iwork; coneK cK; bool use_pivot, transp; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ if(nrhs < NPARIN){ transp = 0; mxAssert(nrhs >= NPARINMIN, "psdscale requires more input arguments."); } else transp = (bool)mxGetScalar(TRANSP_IN); mxAssert(nlhs <= NPAROUT, "psdscale generates less output arguments."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Get statistics of cone K structure ------------------------------------------------------------ */ lenud = cK.rDim + cK.hDim; lenfull = cK.lpN + cK.qDim + lenud; sdplen = cK.rLen + cK.hLen; /* ------------------------------------------------------------ Get scale data: ud.{u,perm}. ------------------------------------------------------------ */ if(!mxIsStruct(UD_IN)){ mxAssert(mxGetM(UD_IN) * mxGetN(UD_IN) == lenud, "ud size mismatch."); /* ud is vector */ ud = mxGetPr(UD_IN); use_pivot = 0; } else{ /* ud is structure */ UD_FIELD = mxGetField(UD_IN,(mwIndex)0,"u"); mxAssert( UD_FIELD!= NULL, "Field ud.u missing."); /* ud.u */ mxAssert(mxGetM(UD_FIELD) * mxGetN(UD_FIELD) == lenud, "ud.u size mismatch."); ud = mxGetPr(UD_FIELD); UD_FIELD = mxGetField(UD_IN,(mwIndex)0,"perm"); /* ud.perm */ if((use_pivot = (UD_FIELD != NULL))){ if(mxGetM(UD_FIELD) * mxGetN(UD_FIELD) == sdplen) permPr = mxGetPr(UD_FIELD); else { mxAssert(mxGetM(UD_FIELD) * mxGetN(UD_FIELD) == 0, "ud.perm size mismatch"); use_pivot = 0; } } } /* ------------------------------------------------------------ Get input x ------------------------------------------------------------ */ mxAssert(!mxIsSparse(X_IN), "Sparse x not supported by this version of psdscale."); x = mxGetPr(X_IN); /* ------------------------------------------------------------ Validate x-input, and let x point to PSD part. ------------------------------------------------------------ */ if(mxGetM(X_IN) * mxGetN(X_IN) == lenfull) x += cK.lpN + cK.qDim; else mxAssert(mxGetM(X_IN) * mxGetN(X_IN) == lenud, "size x mismatch."); /* ------------------------------------------------------------ Allocate output Y(lenud) ------------------------------------------------------------ */ Y_OUT = mxCreateDoubleMatrix(lenud, (mwSize)1, mxREAL); y = mxGetPr(Y_OUT); /* ------------------------------------------------------------ Allocate fwork 2 * [ max(cK.rMaxn^2, 2*cK.hMaxn^2) ] iwork = mwIndex(sdplen) ------------------------------------------------------------ */ fwsiz = MAX(SQR(cK.rMaxn),2*SQR(cK.hMaxn)); fwork = (double *) mxCalloc( MAX(1,2 * fwsiz), sizeof(double)); iwork = (mwIndex *) mxCalloc( MAX(1, sdplen), sizeof(mwIndex) ); /* ------------------------------------------------------------ Convert Fortran to C-style in perm: ------------------------------------------------------------ */ if(use_pivot){ perm = iwork; for(k = 0; k < sdplen; k++){ i = permPr[k]; perm[k] = --i; } } else perm = (mwIndex *) NULL; /* ------------------------------------------------------------ The actual job is done here:. ------------------------------------------------------------ */ psdscaleK(y, ud, perm, x, cK, transp, fwork); /* ------------------------------------------------------------ Release working arrays. ------------------------------------------------------------ */ mxFree(fwork); mxFree(iwork); }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab x = whichcpx(K) ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { int i,j,iwsiz, nxcomplex, cpxf; int *iwork, *lorNL, *rconeNL, *xcomplex; double *myPr; const double *xcomplexPr; mxArray *MY_FIELD; const char *CPXFieldnames[] = {"f", "q", "r", "x"}; coneK cK; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= 1, "whichcpx requires 1 input argument."); mxAssert(nlhs <= 1, "whichcpx generates 1 output argument."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); if( (MY_FIELD = mxGetField(K_IN,0,"xcomplex")) == NULL){ /* K.xcomplex */ nxcomplex = 0; } else{ nxcomplex = mxGetM(MY_FIELD) * mxGetN(MY_FIELD); xcomplexPr = mxGetPr(MY_FIELD); } if(nxcomplex > 0){ /* ------------------------------------------------------------ ALLOCATE working arrays: iwork(2*nxcomplex+lorN+rconeN)) ------------------------------------------------------------ */ iwsiz = 2* nxcomplex + cK.lorN + cK.rconeN; iwork = (int *) mxCalloc(MAX(iwsiz,1), sizeof(int)); xcomplex = iwork + nxcomplex; lorNL = xcomplex + nxcomplex; rconeNL = lorNL + cK.lorN; /* ------------------------------------------------------------ Convert double to int ------------------------------------------------------------ */ for(i = 0; i < nxcomplex; i++){ j = xcomplexPr[i]; /* double to int */ xcomplex[i] = --j; /* Fortran to C */ } for(i = 0; i < cK.lorN; i++) lorNL[i] = cK.lorNL[i]; /* double to int */ for(i = 0; i < cK.rconeN; i++) rconeNL[i] = cK.rconeNL[i]; /* double to int */ /* ------------------------------------------------------------ The real work: ------------------------------------------------------------ */ cpxf = whichcpx(iwork, xcomplex, lorNL,rconeNL, nxcomplex, cK.frN + cK.lpN, cK.lorN, cK.rconeN); nxcomplex -= cpxf; } /* ------------------------------------------------------------ If xcomplex = []: ------------------------------------------------------------ */ else{ cpxf = 0; iwsiz = 0; } /* ------------------------------------------------------------ Create output structure CPX ------------------------------------------------------------ */ CPX_OUT = mxCreateStructMatrix(1, 1, NCPX_FIELDS, CPXFieldnames); MY_FIELD = mxCreateDoubleMatrix(cpxf,1,mxREAL); /* cpx.f */ myPr = mxGetPr(MY_FIELD); for(i = 0; i < cpxf; i++) myPr[i] = 1.0 + iwork[i]; /* int to double */ mxSetField(CPX_OUT, 0,"f", MY_FIELD); MY_FIELD = mxCreateDoubleMatrix(cK.lorN,1,mxREAL); /* cpx.q */ if(iwsiz > 0){ myPr = mxGetPr(MY_FIELD); for(i = 0; i < cK.lorN; i++) myPr[i] = lorNL[i]; /* int to double */ } mxSetField(CPX_OUT, 0,"q", MY_FIELD); MY_FIELD = mxCreateDoubleMatrix(cK.rconeN,1,mxREAL); /* cpx.r */ if(iwsiz > 0){ myPr = mxGetPr(MY_FIELD); for(i = 0; i < cK.rconeN; i++) myPr[i] = rconeNL[i]; /* int to double */ } mxSetField(CPX_OUT, 0,"r", MY_FIELD); MY_FIELD = mxCreateDoubleMatrix(nxcomplex,1,mxREAL); /* cpx.x */ myPr = mxGetPr(MY_FIELD); for(i = 0; i < nxcomplex; i++) myPr[i] = 1.0 + xcomplex[i]; /* int to double */ mxSetField(CPX_OUT, 0,"x", MY_FIELD); /* ------------------------------------------------------------ Release working arrays ------------------------------------------------------------ */ if(iwsiz > 0) mxFree(iwork); }
/* ************************************************************ 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]); }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { int inz, i, k, nk, nksqr, lenud, sdplen, gnnz; int *gjc, *iwork; const double *gjcPr; const double *g, *gk; double *y; coneK cK; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "givensrot requires more input arguments."); mxAssert(nlhs <= NPAROUT, "givensrot generates less output arguments."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Get statistics of cone K structure ------------------------------------------------------------ */ lenud = cK.rDim + cK.hDim; sdplen = cK.rLen + cK.hLen; /* ------------------------------------------------------------ Get inputs gjc,g,x ------------------------------------------------------------ */ mxAssert(mxGetM(GJC_IN) * mxGetN(GJC_IN) == sdplen, "gjc size mismatch"); gjcPr = mxGetPr(GJC_IN); g = (double *) mxGetPr(G_IN); gnnz = mxGetM(G_IN) * mxGetN(G_IN); mxAssert(mxGetM(X_IN) == lenud && mxGetN(X_IN) == 1, "x size mismatch"); /* ------------------------------------------------------------ Allocate output y(lenud), and let y = x. ------------------------------------------------------------ */ Y_OUT = mxCreateDoubleMatrix(lenud, 1, mxREAL); y = mxGetPr(Y_OUT); memcpy(y, mxGetPr(X_IN), lenud * sizeof(double)); /* ------------------------------------------------------------ Allocate working array iwork(sum(K.s)) ------------------------------------------------------------ */ iwork = (int *) mxCalloc(MAX(1,sdplen), sizeof(int)); /* ------------------------------------------------------------ Convert gjcPr from float to int, and store in gjc:=iwork. ------------------------------------------------------------ */ gjc = iwork; for(i = 0; i < sdplen; i++) gjc[i] = gjcPr[i]; /* don't subtract 1: already C-style */ /* ------------------------------------------------------------ The actual job is done here: U_NEW = Q(g) * U_OLD ------------------------------------------------------------ */ inz = 0; for(k = 0; k < cK.rsdpN; k++){ /* real symmetric */ nk = cK.sdpNL[k]; nksqr = SQR(nk); mxAssert(inz + 2 * gjc[nk-1] <= gnnz, "g size mismatch"); gk = g+inz; matgivens(y, (twodouble *) gk, gjc, nk); y += nksqr; inz += 2 * gjc[nk-1]; /* each rotation consists of 2 doubles */ gjc += nk; } for(; k < cK.sdpN; k++){ /* complex Hermitian */ nk = cK.sdpNL[k]; nksqr = SQR(nk); mxAssert(inz + 3 * gjc[nk-1] <= gnnz, "g size mismatch"); gk = g+inz; prpimatgivens(y,y+nksqr, (tridouble *) gk, gjc, nk); nksqr += nksqr; y += nksqr; inz += 3 * gjc[nk-1]; /* each rotation consists of 3 doubles */ gjc += nk; } /* ------------------------------------------------------------ Release working arrays ------------------------------------------------------------ */ mxFree(iwork); }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab [lab,q] = eigK(x,K) Computes spectral coefficients of x w.r.t. K REMARK If this function is used internally by SeDuMi, then complex numbers are stored in a single real vector. To make it invokable from the Matlab command-line by the user, we also allow Matlab complex vector x. ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { mxArray *output_array[3], *Xk, *hXk; coneK cK; int k, nk, nksqr, lendiag,i,ii,nkp1, lenfull; double *lab,*q,*qpi,*labk,*xwork,*xpiwork; const double *x,*xpi; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "eigK requires more input arguments"); mxAssert(nlhs <= NPAROUT, "eigK produces less output arguments"); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Compute statistics based on cone K structure ------------------------------------------------------------ */ lendiag = cK.lpN + 2 * (cK.lorN + cK.rconeN) + cK.rLen + cK.hLen; lenfull = cK.lpN + cK.qDim + cK.rDim + cK.hDim; if(cK.rconeN > 0) for(i = 0; i < cK.rconeN; i++) lenfull += cK.rconeNL[i]; /* ------------------------------------------------------------ Get input vector x ------------------------------------------------------------ */ mxAssert(mxGetM(X_IN) * mxGetN(X_IN) == lenfull, "Size mismatch x"); mxAssert(!mxIsSparse(X_IN), "x must be full (not sparse)."); x = mxGetPr(X_IN); if(mxIsComplex(X_IN)) xpi = mxGetPi(X_IN) + cK.lpN; /* ------------------------------------------------------------ Allocate output LAB(diag), eigvec Q(full for psd) ------------------------------------------------------------ */ LAB_OUT = mxCreateDoubleMatrix(lendiag, 1, mxREAL); lab = mxGetPr(LAB_OUT); if(nlhs > 1){ if(mxIsComplex(X_IN)){ Q_OUT = mxCreateDoubleMatrix(cK.rDim, 1, mxCOMPLEX); qpi = mxGetPi(Q_OUT); } else Q_OUT = mxCreateDoubleMatrix(cK.rDim + cK.hDim, 1, mxREAL); q = mxGetPr(Q_OUT); } /* ------------------------------------------------------------ Allocate working arrays: ------------------------------------------------------------ */ Xk = mxCreateDoubleMatrix(0,0,mxREAL); hXk = mxCreateDoubleMatrix(0,0,mxCOMPLEX); if(mxIsComplex(X_IN)){ xwork = (double *) mxCalloc(MAX(1,2 * SQR(cK.rMaxn)), sizeof(double)); xpiwork = xwork + SQR(cK.rMaxn); } else xwork =(double *) mxCalloc(MAX(1,SQR(cK.rMaxn)+2*SQR(cK.hMaxn)), sizeof(double)); /* ------------------------------------------------------------ The actual job is done here:. ------------------------------------------------------------ */ if(cK.lpN){ /* ------------------------------------------------------------ LP: lab = x ------------------------------------------------------------ */ memcpy(lab, x, cK.lpN * sizeof(double)); lab += cK.lpN; x += cK.lpN; } /* ------------------------------------------------------------ CONSIDER FIRST MATLAB-REAL-TYPE: ------------------------------------------------------------ */ if(!mxIsComplex(X_IN)){ /* Not Matlab-type complex */ /* ------------------------------------------------------------ LORENTZ: (I) lab = qeig(x) ------------------------------------------------------------ */ for(k = 0; k < cK.lorN; k++){ nk = cK.lorNL[k]; qeig(lab,x,nk); lab += 2; x += nk; } /* ------------------------------------------------------------ RCONE: LAB = eig(X) (Lorentz-Rcone's are not used internally) ------------------------------------------------------------ */ for(k = 0; k < cK.rconeN; k++){ nk = cK.rconeNL[k]; rconeeig(lab,x[0],x[1],realssqr(x+2,nk-2)); lab += 2; x += nk; } /* ------------------------------------------------------------ PSD: (I) LAB = eig(X) ------------------------------------------------------------ */ if(nlhs < 2){ for(k=0; k < cK.rsdpN; k++){ /* real symmetric */ nk = cK.sdpNL[k]; symproj(xwork,x,nk); /* make it symmetric */ mxSetM(Xk, nk); mxSetN(Xk, nk); mxSetPr(Xk, xwork); mexCallMATLAB(1, output_array, 1, &Xk, "eig"); memcpy(lab, mxGetPr(output_array[0]), nk * sizeof(double)); /* ------------------------------------------------------------ With mexCallMATLAB, we invoked the mexFunction "eig", which allocates a matrix struct *output_array[0], AND a block for the float data of that matrix. ==> mxDestroyArray() does not only free the float data, it also releases the matrix struct (and this is what we want). ------------------------------------------------------------ */ mxDestroyArray(output_array[0]); lab += nk; x += SQR(nk); } /* ------------------------------------------------------------ WARNING: Matlab's eig doesn't recognize Hermitian, hence VERY slow ------------------------------------------------------------ */ for(; k < cK.sdpN; k++){ /* complex Hermitian */ nk = cK.sdpNL[k]; nksqr = SQR(nk); symproj(xwork,x,nk); /* make it Hermitian */ skewproj(xwork + nksqr,x+nksqr,nk); mxSetM(hXk, nk); mxSetN(hXk, nk); mxSetPr(hXk, xwork); mxSetPi(hXk, xwork + nksqr); mexCallMATLAB(1, output_array, 1, &hXk, "eig"); memcpy(lab, mxGetPr(output_array[0]), nk * sizeof(double)); mxDestroyArray(output_array[0]); lab += nk; x += 2 * nksqr; } } else{ /* ------------------------------------------------------------ SDP: (II) (Q,LAB) = eig(X) ------------------------------------------------------------ */ for(k=0; k < cK.rsdpN; k++){ /* real symmetric */ nk = cK.sdpNL[k]; symproj(xwork,x,nk); /* make it symmetric */ mxSetM(Xk, nk); mxSetN(Xk, nk); mxSetPr(Xk, xwork); mexCallMATLAB(2, output_array, 1, &Xk, "eig"); nksqr = SQR(nk); /* copy Q-matrix */ memcpy(q, mxGetPr(output_array[0]), nksqr * sizeof(double)); nkp1 = nk + 1; /* copy diag(Lab) */ labk = mxGetPr(output_array[1]); for(i = 0, ii = 0; i < nk; i++, ii += nkp1) lab[i] = labk[ii]; mxDestroyArray(output_array[0]); mxDestroyArray(output_array[1]); lab += nk; x += nksqr; q += nksqr; } for(; k < cK.sdpN; k++){ /* complex Hermitian */ nk = cK.sdpNL[k]; nksqr = SQR(nk); symproj(xwork,x,nk); /* make it Hermitian */ skewproj(xwork + nksqr,x+nksqr,nk); mxSetM(hXk, nk); mxSetN(hXk, nk); mxSetPr(hXk, xwork); mxSetPi(hXk, xwork+nksqr); mexCallMATLAB(2, output_array, 1, &hXk, "eig"); memcpy(q, mxGetPr(output_array[0]), nksqr * sizeof(double)); q += nksqr; if(mxIsComplex(output_array[0])) /* if any imaginary part */ memcpy(q, mxGetPi(output_array[0]), nksqr * sizeof(double)); nkp1 = nk + 1; /* copy diag(Lab) */ labk = mxGetPr(output_array[1]); for(i = 0, ii = 0; i < nk; i++, ii += nkp1) lab[i] = labk[ii]; mxDestroyArray(output_array[0]); mxDestroyArray(output_array[1]); lab += nk; x += 2 * nksqr; q += nksqr; } } /* [lab,q] = eigK */ } /* !iscomplex */ else{ /* is MATLAB type complex */ /* ------------------------------------------------------------ LORENTZ: (I) lab = qeig(x) ------------------------------------------------------------ */ for(k = 0; k < cK.lorN; k++){ nk = cK.lorNL[k]; cxqeig(lab,x,xpi,nk); lab += 2; x += nk; xpi += nk; } /* ------------------------------------------------------------ RCONE: LAB = eig(X) (Lorentz-Rcone's are not used internally) ------------------------------------------------------------ */ for(k = 0; k < cK.rconeN; k++){ nk = cK.rconeNL[k]; rconeeig(lab,x[0],x[1], realssqr(x+2,nk-2) + realssqr(xpi+2,nk-2)); lab += 2; x += nk; xpi += nk; } /* ------------------------------------------------------------ PSD: (I) LAB = eig(X) ------------------------------------------------------------ */ for(k = 0; k < cK.sdpN; k++){ nk = cK.sdpNL[k]; nksqr = SQR(nk); symproj(xwork,x,nk); /* make it Hermitian */ skewproj(xpiwork,xpi,nk); mxSetM(hXk, nk); mxSetN(hXk, nk); mxSetPr(hXk, xwork); mxSetPi(hXk, xpiwork); if(nlhs < 2){ mexCallMATLAB(1, output_array, 1, &hXk, "eig"); memcpy(lab, mxGetPr(output_array[0]), nk * sizeof(double)); } else{ mexCallMATLAB(2, output_array, 1, &hXk, "eig"); memcpy(q, mxGetPr(output_array[0]), nksqr * sizeof(double)); if(mxIsComplex(output_array[0])) /* if any imaginary part */ memcpy(qpi, mxGetPi(output_array[0]), nksqr * sizeof(double)); nkp1 = nk + 1; /* copy diag(Lab) */ labk = mxGetPr(output_array[1]); for(i = 0, ii = 0; i < nk; i++, ii += nkp1) lab[i] = labk[ii]; mxDestroyArray(output_array[1]); q += nksqr; qpi += nksqr; } mxDestroyArray(output_array[0]); lab += nk; x += nksqr; xpi += nksqr; } } /* iscomplex */ /* ------------------------------------------------------------ Release PSD-working arrays. ------------------------------------------------------------ */ mxSetM(Xk,0); mxSetN(Xk,0); mxSetPr(Xk, (double *) NULL); mxDestroyArray(Xk); mxSetM(hXk,0); mxSetN(hXk,0); mxSetPr(hXk, (double *) NULL); mxSetPi(hXk, (double *) NULL); mxDestroyArray(hXk); mxFree(xwork); }
/* ************************************************************ 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]); }
void mexFunction( const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[] ) { mxArray *output_array[3], *Xk; coneK cK; mwSize nk, nkp1, nksqr, lendiag, lenud, lenfull, nmax; mwIndex k, i, ii; double *lab, *q, *labk; const double *x; /* Argument check */ mxAssert(nrhs >= NPARIN, "psdeig requires more input arguments"); mxAssert(nlhs <= NPAROUT, "psdeig produces less output arguments"); /* Disassemble cone structure and determine output sizes */ conepars(K_IN, &cK); lendiag = cK.rLen + cK.hLen; lenud = cK.rDim + cK.hDim; lenfull = cK.lpN + cK.qDim + lenud; /* Get input vector x and skip to the PSD terms */ mxAssert( !mxIsSparse(X_IN), "x must be full (not sparse)." ); x = mxGetPr(X_IN); if ( mxGetM(X_IN) * mxGetN(X_IN) != lenud ) { mxAssert( mxGetM(X_IN) * mxGetN(X_IN) == lenfull, "Size mismatch x" ); x += cK.lpN + cK.qDim; } /* Allocate the output arrays */ LAB_OUT = mxCreateDoubleMatrix( lendiag, (mwSize)1, mxREAL ); lab = mxGetPr( LAB_OUT ); if ( nlhs > 1 ) { Q_OUT = mxCreateDoubleMatrix( lenud, (mwSize)1, mxREAL ); q = mxGetPr( Q_OUT ); } /* * Real symmetric matrices */ if ( cK.rsdpN != 0 ) { nmax = 1; for ( k = 0 ; k != cK.rsdpN ; ++k ) { nk = (mwSize)cK.sdpNL[k]; if ( nmax < nk ) nmax = nk; } Xk = mxCreateDoubleMatrix( nmax, nmax, mxREAL ); for ( k = 0 ; k != cK.rsdpN ; ++k ) { nk = (mwSize)cK.sdpNL[k]; nksqr = SQR(nk); mxSetM( Xk, nk ); mxSetN( Xk, nk ); /* Symmetric projection onto the work array */ symproj( mxGetPr(Xk), x, nk ); if ( nlhs <= 1 ) { /* One argument only: lab */ mexCallMATLAB( 1, output_array, 1, &Xk, "eig" ); memcpy( lab, mxGetPr(output_array[0]), nk * sizeof(double) ); mxDestroyArray( output_array[0] ); } else { /* First argument: Q */ mexCallMATLAB( 2, output_array, 1, &Xk, "eig" ); memcpy( q, mxGetPr(output_array[0]), nksqr * sizeof(double) ); q += nksqr; /* Second argument: extract diag(Lab) */ nkp1 = nk + 1; labk = mxGetPr( output_array[1] ); for(i = 0, ii = 0; i < nk; i++, ii += nkp1) lab[i] = labk[ii]; mxDestroyArray( output_array[0] ); mxDestroyArray( output_array[1] ); } lab += nk; x += nksqr; } mxDestroyArray( Xk ); } /* Complex Hermitian matrices * Note that if a complex argument is offered, even the "real" matrices * must be passed through here, just to be safe. */ if ( cK.sdpN != cK.rsdpN ) { nmax = 1; for ( k = cK.rsdpN ; k != cK.sdpN ; ++k ) { nk = (mwSize)cK.sdpNL[k]; if ( nmax < nk ) nmax = nk; } Xk = mxCreateDoubleMatrix( nmax, nmax, mxCOMPLEX ); for ( k = cK.rsdpN ; k != cK.sdpN ; ++k ) { nk = (mwSize)cK.sdpNL[k]; nksqr = SQR(nk); mxSetM(Xk, nk); mxSetN(Xk, nk); /* Skew-symmetric projection onto the work matrix */ symproj( mxGetPr(Xk), x, nk ); skewproj( mxGetPi(Xk), x + nksqr, nk ); if ( nlhs <= 1 ) { /* One argument only: lab */ mexCallMATLAB( 1, output_array, 1, &Xk, "eig" ); memcpy(lab, mxGetPr(output_array[0]), nk * sizeof(double)); mxDestroyArray(output_array[0]); } else { #ifdef USE_SVD mexCallMATLAB(3, output_array, 1, &Xk, "svd"); #else mexCallMATLAB(2, output_array, 1, &Xk, "eig"); #endif /* First argument: Q */ memcpy( q, mxGetPr(output_array[0]), nksqr * sizeof(double) ); q += nksqr; if( mxIsComplex(output_array[0]) ) /* if any imaginary part */ memcpy( q, mxGetPi(output_array[0]), nksqr * sizeof(double) ); q += nksqr; /* Second argument: extract diag(Lab) */ nkp1 = nk + 1; labk = mxGetPr(output_array[1]); for(i = 0, ii = 0; i < nk; i++, ii += nkp1) lab[i] = labk[ii]; mxDestroyArray(output_array[0]); mxDestroyArray(output_array[1]); #ifdef USE_SVD mxDestroyArray(output_array[2]); #endif } lab += nk; x += 2 * nksqr; } mxDestroyArray( Xk ); } }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { coneK cK; const mxArray *MY_FIELD; mwIndex m, i, j; const double *permPr; double *fwork; mwIndex *iwork, *perm, *invperm; jcir ada, ddota; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "getADA requires more input arguments."); mxAssert(nlhs <= NPAROUT, "getADA produces less output arguments."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); m = mxGetM(ADA_IN); /* ------------------------------------------------------------ Allocate output matrix ADA with sparsity structure of ADA_IN, and initialize as a copy of ADA_IN. ------------------------------------------------------------ */ mxAssert(mxGetN(ADA_IN) == m, "Size mismatch ADA."); mxAssert(mxIsSparse(ADA_IN), "ADA should be sparse."); ADA_OUT = mxDuplicateArray(ADA_IN); /* ADA = ADA_IN */ if(cK.lorN <= 0) /* READY if no LORENTZ blocks !*/ return; ada.jc = mxGetJc(ADA_OUT); ada.ir = mxGetIr(ADA_OUT); ada.pr = mxGetPr(ADA_OUT); /* ------------------------------------------------------------ DISASSEMBLE DAt structure: DAt.q ------------------------------------------------------------ */ mxAssert(mxIsStruct(DAT_IN), "DAt should be a structure."); MY_FIELD = mxGetField(DAT_IN,(mwIndex)0,"q"); /* DAt.q */ mxAssert( MY_FIELD != NULL, "Missing field DAt.q."); mxAssert(mxGetM(MY_FIELD) == cK.lorN && mxGetN(MY_FIELD) == m, "Size mismatch DAt.q"); mxAssert(mxIsSparse(MY_FIELD), "DAt.q should be sparse."); ddota.jc = mxGetJc(MY_FIELD); ddota.ir = mxGetIr(MY_FIELD); ddota.pr = mxGetPr(MY_FIELD); /* ------------------------------------------------------------ DISASSEMBLE Aord structure: Aord.qperm ------------------------------------------------------------ */ mxAssert(mxIsStruct(AORD_IN), "Aord should be a structure."); MY_FIELD = mxGetField(AORD_IN,(mwIndex)0,"qperm"); /* Aord.qperm */ mxAssert( MY_FIELD != NULL, "Missing field Aord.qperm."); mxAssert(mxGetM(MY_FIELD) * mxGetN(MY_FIELD) == m, "Size mismatch Aord.qperm."); permPr = mxGetPr(MY_FIELD); /* ------------------------------------------------------------ Only work to do if ~isempty(ddota): ------------------------------------------------------------ */ if(ddota.jc[m] > 0){ /* ------------------------------------------------------------ ALLOCATE working arrays: iwork(2*m) = [perm(m), invperm(m)]. fwork[lorN] ------------------------------------------------------------ */ iwork = (mwIndex *) mxCalloc(MAX(2 * m,1), sizeof(mwIndex)); perm = iwork; invperm = perm + m; fwork = (double *) mxCalloc(MAX(cK.lorN,1), sizeof(double)); /* ------------------------------------------------------------ perm to integer C-style ------------------------------------------------------------ */ for(i = 0; i < m; i++){ j = (mwIndex) permPr[i]; mxAssert(j>0,""); perm[i] = --j; } /* ------------------------------------------------------------ Let invperm(perm) = 0:m-1. ------------------------------------------------------------ */ for(i = 0; i < m; i++) invperm[perm[i]] = i; /* ------------------------------------------------------------ ACTUAL COMPUTATION: ADA += DAt.q'*DAt.q. ------------------------------------------------------------ */ getada2(ada, ddota, perm, invperm, m, cK.lorN, fwork); /* ------------------------------------------------------------ RELEASE WORKING ARRAYS. ------------------------------------------------------------ */ mxFree(fwork); mxFree(iwork); } /* !isempty(ddota) */ }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab x = eyeK(K) ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { int i,j,k, nk, lenfull; double *x; coneK cK; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs == 1, "eyeK requires 1 input argument."); mxAssert(nlhs == 1, "eyeK generates 1 output argument."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Get statistics of cone K structure ------------------------------------------------------------ */ lenfull = cK.lpN + cK.qDim + cK.rDim + cK.hDim; for(k = 0; k < cK.rconeN; k++) lenfull += cK.rconeNL[k]; /* ------------------------------------------------------------ Allocate output x ------------------------------------------------------------ */ X_OUT = mxCreateDoubleMatrix(lenfull, 1, mxREAL); x = mxGetPr(X_OUT); /* ------------------------------------------------------------ The actual job is done here:. ------------------------------------------------------------ */ /* ------------------------------------------------------------ LP: x = ones(K.l,1) ------------------------------------------------------------ */ for(k = 0; k < cK.lpN; k++) x[k] = 1.0; x += cK.lpN; /* ------------------------------------------------------------ LORENTZ: x(1) = sqrt(2) ------------------------------------------------------------ */ for(k = 0; k < cK.lorN; k++){ nk = cK.lorNL[k]; x[0] = M_SQRT2; x += nk; } /* ------------------------------------------------------------ RCONE: x(1) = x(2) = 1 ------------------------------------------------------------ */ for(k = 0; k < cK.rconeN; k++){ nk = cK.rconeNL[k]; x[0] = 1.0; x[1] = 1.0; x += nk; } /* ------------------------------------------------------------ PSD: x = eye(nk) ------------------------------------------------------------ */ for(k = 0; k < cK.sdpN; k++){ nk = cK.sdpNL[k]; for(i = 0, j = 0; i < nk; i++, j += nk+1) x[j] = 1.0; x += (1 + (k >= cK.rsdpN)) * SQR(nk); } }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab [beta,U,d,perm] = qrpfacK(x,K) ************************************************************ */ void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { mxArray *myplhs[NPAROUT]; coneK cK; mwIndex i,k,nk,nksqr, sdpdim, qsize; double *q, *r, *betak; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "qrK requires more input arguments"); mxAssert(nlhs <= NPAROUT, "qrK produces less output arguments"); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Compute statistics: sdpdim = rdim+hdim, qsize = sdpdim + hLen. ------------------------------------------------------------ */ sdpdim = cK.rDim + cK.hDim; qsize = sdpdim + cK.hLen; /* ------------------------------------------------------------ Check input vector x. ------------------------------------------------------------ */ mxAssert(mxGetM(X_IN) * mxGetN(X_IN) == sdpdim, "size mismatch x"); /* ------------------------------------------------------------ Allocate output Q(qsize), R(sdpdim) and let r = x. ------------------------------------------------------------ */ Q_OUT = mxCreateDoubleMatrix(qsize, (mwSize)1, mxREAL); q = mxGetPr(Q_OUT); R_OUT = mxCreateDoubleMatrix(sdpdim, (mwSize)1, mxREAL); r = mxGetPr(R_OUT); memcpy(r, mxGetPr(X_IN), sdpdim * sizeof(double)); /* ------------------------------------------------------------ The actual job is done here: ------------------------------------------------------------ */ for(k = 0; k < cK.rsdpN; k++){ /* real symmetric */ nk = (mwIndex) cK.sdpNL[k]; nksqr = SQR(nk); qrfac(q+nksqr-nk,q,r, nk); r += nksqr; q += nksqr; } for(; k < cK.sdpN; k++){ /* complex Hermitian */ nk = (mwIndex) cK.sdpNL[k]; nksqr = SQR(nk); betak = q + 2*nksqr; prpiqrfac(betak,q,q+nksqr, r,r+nksqr, nk); nksqr += nksqr; r += nksqr; q += nksqr + nk; /* nk for betak */ } /* ------------------------------------------------------------ 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]); }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab y = vectril(x,K) For the PSD submatrices, we let Yk = tril(Xk+Xk'). Complex numbers are stored as vec([real(Xk) imag(Xk)]). NB: x and y are sparse. ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { int i, j, k, jnz, m,lenfull, firstPSD, maxn, iwsize; jcir x,y; int *iwork, *psdNL, *blkstart, *xblk; char *cwork; double *fwork; coneK cK; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "vectril requires more input arguments"); mxAssert(nlhs <= NPAROUT, "vectril produces less output arguments"); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Compute statistics based on cone K structure ------------------------------------------------------------ */ firstPSD = cK.frN + cK.lpN + cK.qDim; for(i = 0; i < cK.rconeN; i++) /* add dim of rotated cone */ firstPSD += cK.rconeNL[i]; lenfull = firstPSD + cK.rDim + cK.hDim; /* ------------------------------------------------------------ Get inputs x, blkstart ------------------------------------------------------------ */ mxAssert(mxGetM(X_IN) == lenfull, "X size mismatch."); m = mxGetN(X_IN); /* number of columns to handle */ mxAssert( mxIsSparse(X_IN), "X should be sparse."); x.pr = mxGetPr(X_IN); x.jc = mxGetJc(X_IN); x.ir = mxGetIr(X_IN); /* ------------------------------------------------------------ Allocate output Y = sparse([],[],[],length(x),m,nnz(x)) ------------------------------------------------------------ */ Y_OUT = mxCreateSparse(lenfull, m, x.jc[m], mxREAL); y.pr = mxGetPr(Y_OUT); y.jc = mxGetJc(Y_OUT); y.ir = mxGetIr(Y_OUT); y.jc[0] = 0; /* ------------------------------------------------------------ If x = [], then we are ready with y=[]. Otherwise, proceed: ------------------------------------------------------------ */ if(x.jc[m] > 0){ /* ------------------------------------------------------------ Allocate iwork[iwsize], iwsize := maxn*(2*maxn+1)+log_2(1+maxn*(maxn-1)/2), where maxn := max(K.s); cwork[maxn*(maxn-1)/2], fwork(maxn^2), int psdNL(length(K.s)). int blkstart(sdpN+1), xblk(sdpDim) ------------------------------------------------------------ */ maxn = MAX(cK.rMaxn,cK.hMaxn); iwsize = log(1 + maxn*(maxn-1)/2) / log(2); iwsize += maxn * (2*maxn+1); iwork = (int *) mxCalloc(MAX(1,iwsize), sizeof(int)); cwork = (char *) mxCalloc(MAX(1,maxn*(maxn-1)/2), sizeof(char)); fwork = (double *) mxCalloc(MAX(1,SQR(maxn)), sizeof(double)); psdNL = (int *) mxCalloc(MAX(1,cK.sdpN), sizeof(int)); blkstart = (int *) mxCalloc(1 + cK.sdpN, sizeof(int)); xblk = (int *) mxCalloc(MAX(1,cK.rDim + cK.hDim), sizeof(int)); /* ------------------------------------------------------------ double -> int for K.s ------------------------------------------------------------ */ for(i = 0; i < cK.sdpN; i++) psdNL[i] = cK.sdpNL[i]; /* ------------------------------------------------------------ Let k = xblk(j-blkstart[0]) iff blkstart[k] <= j < blkstart[k+1], k=0:psdN-1. ------------------------------------------------------------ */ j = firstPSD; for(i = 0; i < cK.rsdpN; i++){ /* real sym */ blkstart[i] = j; j += SQR(psdNL[i]); } for(; i < cK.sdpN; i++){ /* complex herm. */ blkstart[i] = j; j += 2*SQR(psdNL[i]); } blkstart[cK.sdpN] = j; mxAssert(j - firstPSD == cK.rDim + cK.hDim, "Size mismatch blkstart, K."); j = 0; for(k = 0; k < cK.sdpN; k++){ i = blkstart[k+1] - blkstart[0]; while(j < i) xblk[j++] = k; } /* ------------------------------------------------------------ Let y(:,i)= vectril(x(:,i)), for i=1:m. ------------------------------------------------------------ */ jnz = 0; /* points into y */ for(i = 0; i < m; i++){ y.jc[i] = jnz; jnz += vectril(y.ir+jnz,y.pr+jnz, x.ir+x.jc[i],x.pr+x.jc[i], x.jc[i+1]-x.jc[i], psdNL, blkstart, xblk, cK.rsdpN,cK.sdpN, iwsize, cwork, iwork, fwork); } y.jc[m] = jnz; /* nnz written into y */ mxAssert(jnz <= x.jc[m],""); /* ------------------------------------------------------------ REALLOC: Shrink Y to its current size ------------------------------------------------------------ */ jnz = MAX(jnz,1); if( (y.pr = (double *) mxRealloc(y.pr, jnz*sizeof(double))) == NULL) mexErrMsgTxt("Memory reallocation error"); mxSetPr(Y_OUT,y.pr); if( (y.ir = (int *) mxRealloc(y.ir, jnz*sizeof(int))) == NULL) mexErrMsgTxt("Memory reallocation error"); mxSetIr(Y_OUT,y.ir); mxSetNzmax(Y_OUT,jnz); /* ------------------------------------------------------------ Release working arrays ------------------------------------------------------------ */ mxFree(xblk); mxFree(blkstart); mxFree(psdNL); mxFree(fwork); mxFree(iwork); mxFree(cwork); } }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { mwIndex lenfull, lenud, fwsiz, i, ifirst; double *fwork, *y; const double *x,*ud; mwIndex *psdNL; coneK cK; bool transp; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ if(nrhs < NPARIN){ transp = 0; mxAssert(nrhs >= NPARINMIN, "psdinvscale requires more input arguments."); } else transp = (bool) mxGetScalar(TRANSP_IN); mxAssert(nlhs <= NPAROUT, "psdinvscale generates 1 output argument."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Get statistics of cone K structure ------------------------------------------------------------ */ ifirst = cK.lpN + cK.qDim; lenud = cK.rDim + cK.hDim; lenfull = ifirst + lenud; /* ------------------------------------------------------------ Get inputs ud, x. ------------------------------------------------------------ */ mxAssert(mxGetM(UD_IN) * mxGetN(UD_IN) == lenud, "ud size mismatch."); ud = mxGetPr(UD_IN); mxAssert(!mxIsSparse(X_IN), "Sparse x not supported by this version of psdinvscale."); mxAssert(mxGetM(X_IN) * mxGetN(X_IN) == lenfull, "size x mismatch."); x = mxGetPr(X_IN) + ifirst; /* Jump to PSD part */ /* ------------------------------------------------------------ Allocate output Y ------------------------------------------------------------ */ Y_OUT = mxCreateDoubleMatrix(lenud, (mwSize)1, mxREAL); y = mxGetPr(Y_OUT); /* ------------------------------------------------------------ Allocate fwork [ max(cK.rMaxn^2, 2*cK.hMaxn^2) ] psdNL = mwIndex(cK.sdpN) ------------------------------------------------------------ */ fwsiz = MAX(SQR(cK.rMaxn),2*SQR(cK.hMaxn)); fwork = (double *) mxCalloc( MAX(1,fwsiz), sizeof(double)); psdNL = (mwIndex *) mxCalloc( MAX(1, cK.sdpN), sizeof(mwIndex) ); /* ------------------------------------------------------------ Convert double to mwIndex ------------------------------------------------------------ */ for(i = 0; i < cK.sdpN; i++) psdNL[i] = cK.sdpNL[i]; /* double to mwIndex */ /* ------------------------------------------------------------ The real job: ------------------------------------------------------------ */ psdinvscale(y, ud,x,psdNL,cK.rsdpN,cK.sdpN,transp, fwork); /* ------------------------------------------------------------ Release working arrays. ------------------------------------------------------------ */ mxFree(fwork); mxFree(psdNL); }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { mxArray *myplhs[NPAROUT]; int i,j,k, nk, nksqr, lenud, sdplen, gnnz, inz, maxKs,maxKssqr, rgnnz, hgnnz; const double *uOld, *permOld; double *u, *d, *gjcPr, *permPr, *fwork, *fworkpi; int *perm, *gjc; double *g, *gk; double maxusqr; coneK cK; char use_pivot; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARINMIN, "urotorder requires more input arguments."); mxAssert(nlhs <= NPAROUT, "urotorder generates less output arguments."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Get statistics of cone K structure ------------------------------------------------------------ */ lenud = cK.rDim + cK.hDim; sdplen = cK.rLen + cK.hLen; /* ------------------------------------------------------------ Get scalar input MAXU and input vectors U_IN, PERM_IN ------------------------------------------------------------ */ maxusqr = mxGetScalar(MAXU_IN); maxusqr *= maxusqr; mxAssert(mxGetM(U_IN) * mxGetN(U_IN) == lenud, "u size mismatch"); uOld = mxGetPr(U_IN); use_pivot = 0; if(nrhs >= NPARIN) /* Optional permIN */ if(mxGetM(PERM_IN) * mxGetN(PERM_IN) > 0) { mxAssert(mxGetM(PERM_IN) * mxGetN(PERM_IN) == sdplen, "perm size mismatch"); use_pivot = 1; permOld = mxGetPr(PERM_IN); } /* ------------------------------------------------------------ Allocate output U_OUT, and initialize u_out = u_in. ------------------------------------------------------------ */ U_OUT = mxCreateDoubleMatrix(lenud, 1, mxREAL); u = mxGetPr(U_OUT); memcpy(u, mxGetPr(U_IN), lenud * sizeof(double)); /* ------------------------------------------------------------ Allocate outputs PERM(sum(K.s)), GJC(sum(K.s)) ------------------------------------------------------------ */ PERM_OUT = mxCreateDoubleMatrix(sdplen, 1, mxREAL); permPr = mxGetPr(PERM_OUT); GJC_OUT = mxCreateDoubleMatrix(sdplen, 1, mxREAL); gjcPr = mxGetPr(GJC_OUT); /* ------------------------------------------------------------ Allocate g initially as length (lenud - cK.rLen) / 2. The final length can be shorter (viz. gjc[sum(K.s)]) ------------------------------------------------------------ */ rgnnz = (cK.rDim - cK.rLen) / 2; /* n(n-1)/2 real sym */ hgnnz = (cK.hDim - 2*cK.hLen) / 4; /* n(n-1)/2 complex herm */ gnnz = rgnnz * 2 + hgnnz * 3; g = (double *) mxCalloc(MAX(1, gnnz),sizeof(double)); /* ------------------------------------------------------------ Allocate working arrays: Let maxKssqr = max(rMaxn^2, 2*hMaxn^2), then integer perm(max(K.s)), gjc(max(K.s)) double d(max(K.s)), fwork(maxKs) ------------------------------------------------------------ */ maxKs = MAX(cK.rMaxn,cK.hMaxn); /* max(K.s) */ maxKssqr = MAX(SQR(cK.rMaxn),2 * SQR(cK.hMaxn)); /* max(K.s.^2) */ perm = (int *) mxCalloc(MAX(1,maxKs), sizeof(int)); gjc = (int *) mxCalloc(MAX(1,maxKs), sizeof(int)); d = (double *) mxCalloc(MAX(1,maxKs), sizeof(double)); fwork = (double *) mxCalloc(MAX(1,maxKssqr), sizeof(double)); fworkpi = fwork + SQR(cK.hMaxn); /* ------------------------------------------------------------ The actual job is done here: U_NEW = Q(g) * U_OLD ------------------------------------------------------------ */ inz = 0; for(k = 0; k < cK.rsdpN; k++) { /* real symmetric */ nk = cK.sdpNL[k]; nksqr = SQR(nk); memcpy(fwork, uOld, nksqr *sizeof(double)); /* k-th U-matrix */ gk = g+inz; rotorder(perm, fwork, gjc, (twodouble *) gk, d, maxusqr, nk); /* ------------------------------------------------------------ Physically reorder the columns from fwork into u. Then Let tril(U) = triu(U)' ------------------------------------------------------------ */ uperm(u, fwork, perm, nk); triu2sym(u,nk); /* ------------------------------------------------------------ Let perm_out = perm_in(perm) ------------------------------------------------------------ */ if(use_pivot) { for(i = 0; i < nk; i++) permPr[i] = permOld[perm[i]]; permOld += nk; } else for(i = 0; i < nk; i++) permPr[i] = 1.0 + perm[i]; for(i = 0; i < nk; i++) gjcPr[i] = gjc[i]; /* don't add 1 */ inz += 2 * gjc[nk-1]; /* next PSD block. Rotation g is 2 doubles */ gjcPr += nk; permPr += nk; uOld += nksqr; u += nksqr; } /* ------------------------------------------------------------ Complex Hermitian ------------------------------------------------------------ */ for(; k < cK.sdpN; k++) { /* complex Hermitian */ nk = cK.sdpNL[k]; nksqr = SQR(nk); memcpy(fwork, uOld, nksqr *sizeof(double)); /* k-th complex U-matrix */ memcpy(fworkpi, uOld+nksqr, nksqr *sizeof(double)); gk = g+inz; prpirotorder(perm, fwork,fworkpi, gjc, (tridouble *) gk, d, maxusqr, nk); /* ------------------------------------------------------------ Physically reorder the columns from fwork into u. Then Let tril(U) = triu(U)' ------------------------------------------------------------ */ uperm(u, fwork, perm, nk); /* real part */ uperm(u+nksqr, fworkpi, perm, nk); /* imaginary part */ triu2herm(u,u+nksqr, nk); /* ------------------------------------------------------------ Let perm_out = perm_in(perm) ------------------------------------------------------------ */ if(use_pivot) { for(i = 0; i < nk; i++) permPr[i] = permOld[perm[i]]; permOld += nk; } else for(i = 0; i < nk; i++) permPr[i] = 1.0 + perm[i]; for(i = 0; i < nk; i++) gjcPr[i] = gjc[i]; /* don't add 1 */ inz += 3 * gjc[nk-1]; /* next PSD block. Rotation g is 3 doubles */ gjcPr += nk; permPr += nk; nksqr += nksqr; uOld += nksqr; u += nksqr; } /* ------------------------------------------------------------ In total, we used inz doubles in Givens rotations. Reallocate (shrink) g accordingly. ------------------------------------------------------------ */ mxAssert(inz <= gnnz,""); if(inz > 0) { if((g = (double *) mxRealloc(g, inz * sizeof(double))) == NULL) mexErrMsgTxt("Memory allocation error."); } else { mxFree(g); g = (double *) NULL; } /* ------------------------------------------------------------ Assign g to a length inz output vector ------------------------------------------------------------ */ G_OUT = mxCreateDoubleMatrix(1, 1, mxREAL); mxFree(mxGetPr(G_OUT)); mxSetPr(G_OUT, (double *) g); mxSetM(G_OUT, inz); /* ------------------------------------------------------------ Release working arrays ------------------------------------------------------------ */ mxFree(fwork); mxFree(d); mxFree(gjc); 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]); }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { mxArray *output_array[3], *Xk, *hXk; coneK cK; int k, nk, nkp1, nksqr, lendiag,lenud, lenfull, i,ii; double *lab,*q,*labk,*xwork; const double *x; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "psdeig requires more input arguments"); mxAssert(nlhs <= NPAROUT, "psdeig produces less output arguments"); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Compute statistics based on cone K structure ------------------------------------------------------------ */ lendiag = cK.rLen + cK.hLen; lenud = cK.rDim + cK.hDim; lenfull = cK.lpN + cK.qDim + lenud; /* ------------------------------------------------------------ Get input vector x ------------------------------------------------------------ */ mxAssert(!mxIsSparse(X_IN), "x must be full (not sparse)."); x = mxGetPr(X_IN); if(mxGetM(X_IN) * mxGetN(X_IN) != lenud){ mxAssert(mxGetM(X_IN) * mxGetN(X_IN) == lenfull, "Size mismatch x"); x += cK.lpN + cK.qDim; /* point to PSD part */ } /* ------------------------------------------------------------ Allocate output LAB(diag), eigvec Q(full for psd) ------------------------------------------------------------ */ LAB_OUT = mxCreateDoubleMatrix(lendiag, 1, mxREAL); lab = mxGetPr(LAB_OUT); if(nlhs > 1){ Q_OUT = mxCreateDoubleMatrix(lenud, 1, mxREAL); q = mxGetPr(Q_OUT); } /* ------------------------------------------------------------ Allocate working arrays: ------------------------------------------------------------ */ Xk = mxCreateDoubleMatrix(0,0,mxREAL); hXk = mxCreateDoubleMatrix(0,0,mxCOMPLEX); xwork =(double *) mxCalloc(MAX(1,SQR(cK.rMaxn)+2*SQR(cK.hMaxn)), sizeof(double)); /* ------------------------------------------------------------ PSD: (I) LAB = eig(X) ------------------------------------------------------------ */ if(nlhs < 2){ for(k=0; k < cK.rsdpN; k++){ /* real symmetric */ nk = cK.sdpNL[k]; symproj(xwork,x,nk); /* make it symmetric */ mxSetM(Xk, nk); mxSetN(Xk, nk); mxSetPr(Xk, xwork); mexCallMATLAB(1, output_array, 1, &Xk, "eig"); memcpy(lab, mxGetPr(output_array[0]), nk * sizeof(double)); /* ------------------------------------------------------------ With mexCallMATLAB, we invoked the mexFunction "eig", which allocates a matrix struct *output_array[0], AND a block for the float data of that matrix. ==> mxDestroyArray() does not only free the float data, it also releases the matrix struct (and this is what we want). ------------------------------------------------------------ */ mxDestroyArray(output_array[0]); lab += nk; x += SQR(nk); } /* ------------------------------------------------------------ WARNING: Matlab's eig doesn't recognize Hermitian, hence VERY slow ------------------------------------------------------------ */ for(; k < cK.sdpN; k++){ /* complex Hermitian */ nk = cK.sdpNL[k]; nksqr = SQR(nk); symproj(xwork,x,nk); /* make it Hermitian */ skewproj(xwork + nksqr,x+nksqr,nk); mxSetM(hXk, nk); mxSetN(hXk, nk); mxSetPr(hXk, xwork); mxSetPi(hXk, xwork + nksqr); mexCallMATLAB(1, output_array, 1, &hXk, "eig"); memcpy(lab, mxGetPr(output_array[0]), nk * sizeof(double)); mxDestroyArray(output_array[0]); lab += nk; x += 2 * nksqr; } } /* nlhs < 2 */ else{ /* ------------------------------------------------------------ SDP: (II) (Q,LAB) = eig(X) ------------------------------------------------------------ */ for(k=0; k < cK.rsdpN; k++){ /* real symmetric */ nk = cK.sdpNL[k]; symproj(xwork,x,nk); /* make it symmetric */ mxSetM(Xk, nk); mxSetN(Xk, nk); mxSetPr(Xk, xwork); mexCallMATLAB(2, output_array, 1, &Xk, "eig"); nksqr = SQR(nk); /* copy Q-matrix */ memcpy(q, mxGetPr(output_array[0]), nksqr * sizeof(double)); nkp1 = nk + 1; /* copy diag(Lab) */ labk = mxGetPr(output_array[1]); for(i = 0, ii = 0; i < nk; i++, ii += nkp1) lab[i] = labk[ii]; mxDestroyArray(output_array[0]); mxDestroyArray(output_array[1]); lab += nk; x += nksqr; q += nksqr; } for(; k < cK.sdpN; k++){ /* complex Hermitian */ nk = cK.sdpNL[k]; nksqr = SQR(nk); symproj(xwork,x,nk); /* make it Hermitian */ skewproj(xwork + nksqr,x+nksqr,nk); mxSetM(hXk, nk); mxSetN(hXk, nk); mxSetPr(hXk, xwork); mxSetPi(hXk, xwork+nksqr); #ifdef USE_SVD mexCallMATLAB(3, output_array, 1, &hXk, "svd"); #else mexCallMATLAB(2, output_array, 1, &hXk, "eig"); #endif memcpy(q, mxGetPr(output_array[0]), nksqr * sizeof(double)); q += nksqr; if(mxIsComplex(output_array[0])) /* if any imaginary part */ memcpy(q, mxGetPi(output_array[0]), nksqr * sizeof(double)); nkp1 = nk + 1; /* copy diag(Lab) */ labk = mxGetPr(output_array[1]); for(i = 0, ii = 0; i < nk; i++, ii += nkp1) lab[i] = labk[ii]; mxDestroyArray(output_array[0]); mxDestroyArray(output_array[1]); #ifdef USE_SVD mxDestroyArray(output_array[2]); #endif lab += nk; x += 2 * nksqr; q += nksqr; } } /* [lab,q] = eigK */ /* ------------------------------------------------------------ Release PSD-working arrays. ------------------------------------------------------------ */ mxSetM(Xk,0); mxSetN(Xk,0); mxSetPr(Xk, (double *) NULL); mxDestroyArray(Xk); mxSetM(hXk,0); mxSetN(hXk,0); mxSetPr(hXk, (double *) NULL); mxSetPi(hXk, (double *) NULL); mxDestroyArray(hXk); mxFree(xwork); }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { mwIndex i, lenfull, lendiag, lenud, qsize; double *z, *fwork; const double *x,*y, *frms; mwIndex *sdpNL; coneK cK; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "psdinvjmul requires more input arguments."); mxAssert(nlhs <= NPAROUT, "psdinvjmul generates 1 output argument."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Get statistics of cone K structure ------------------------------------------------------------ */ lenud = cK.rDim + cK.hDim; qsize = lenud + cK.hLen; lenfull = cK.lpN + cK.qDim + lenud; lendiag = cK.lpN + 2 * cK.lorN + cK.rLen + cK.hLen; /* ------------------------------------------------------------ Get inputs x, frm, y. ------------------------------------------------------------ */ mxAssert(!mxIsSparse(X_IN) && !mxIsSparse(Y_IN), "Sparse inputs not supported by this version of psdinvjmul."); x = mxGetPr(X_IN); /* get x and y */ y = mxGetPr(Y_IN); if(mxGetM(Y_IN) * mxGetN(Y_IN) != lenud){ mxAssert(mxGetM(Y_IN) * mxGetN(Y_IN) == lenfull, "size y mismatch."); y += cK.lpN + cK.qDim; /* point to PSD */ } if(mxGetM(X_IN) * mxGetN(X_IN) != cK.rLen + cK.hLen){ mxAssert(mxGetM(X_IN) * mxGetN(X_IN) == lendiag, "size xlab mismatch."); x += cK.lpN + 2 * cK.lorN; /* point to PSD */ } mxAssert(mxGetM(FRM_IN) * mxGetN(FRM_IN) == qsize, "size xfrm mismatch."); frms = mxGetPr(FRM_IN); /* ------------------------------------------------------------ Allocate output Z ------------------------------------------------------------ */ Z_OUT = mxCreateDoubleMatrix(lenud, (mwIndex)1, mxREAL); z = mxGetPr(Z_OUT); /* ------------------------------------------------------------ Allocate working array fwork(max(rmaxn,2*hmaxn)) integer working array sdpNL(sdpN). ------------------------------------------------------------ */ fwork = (double *) mxCalloc(MAX(1,MAX(cK.rMaxn,2*cK.hMaxn)),sizeof(double)); sdpNL = (mwIndex *) mxCalloc(MAX(1,cK.sdpN), sizeof(mwIndex)); /* ------------------------------------------------------------ double to integer ------------------------------------------------------------ */ for(i = 0; i < cK.sdpN; i++) sdpNL[i] = (mwIndex) cK.sdpNL[i]; psdinvjmul(z,frms,x,y,sdpNL,cK.rsdpN,cK.sdpN, fwork); /* ------------------------------------------------------------ Release working array ------------------------------------------------------------ */ mxFree(sdpNL); mxFree(fwork); }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { mwIndex i,lendiag, lenfull, lenud,qsize; double *x, *fwork; const double *lab,*frms; mwIndex *sdpNL; coneK cK; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "psdframeit requires more input arguments."); mxAssert(nlhs <= NPAROUT, "psdframeit generates less output arguments."); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); /* ------------------------------------------------------------ Get statistics of cone K structure ------------------------------------------------------------ */ lenud = cK.rDim + cK.hDim; qsize = lenud + cK.hLen; lenfull = cK.lpN + cK.qDim + lenud; lendiag = cK.lpN + 2 * cK.lorN + cK.rLen + cK.hLen; /* ------------------------------------------------------------ Get inputs lab,frms ------------------------------------------------------------ */ lab = mxGetPr(LAB_IN); if(mxGetM(LAB_IN) * mxGetN(LAB_IN) != cK.rLen + cK.hLen){ mxAssert(mxGetM(LAB_IN) * mxGetN(LAB_IN) == lendiag, "lab size mismatch"); lab += cK.lpN + 2 * cK.lorN; } mxAssert(mxGetM(FRMS_IN) * mxGetN(FRMS_IN) == qsize, "frms size mismatch"); frms = mxGetPr(FRMS_IN); /* ------------------------------------------------------------ Allocate output x ------------------------------------------------------------ */ X_OUT = mxCreateDoubleMatrix(lenud, (mwSize)1, mxREAL); x = mxGetPr(X_OUT); /* ------------------------------------------------------------ Allocate working array fwork(max(rmaxn,2*hmaxn)) integer working array sdpNL(sdpN). ------------------------------------------------------------ */ fwork = (double *) mxCalloc(MAX(1,MAX(cK.rMaxn,2*cK.hMaxn)),sizeof(double)); sdpNL = (mwIndex *) mxCalloc(MAX(1,cK.sdpN), sizeof(mwIndex)); /* ------------------------------------------------------------ double to integer ------------------------------------------------------------ */ for(i = 0; i < cK.sdpN; i++) sdpNL[i] = cK.sdpNL[i]; /* ------------------------------------------------------------ PSD: X = Qb' * diag(lab) * Qb, Qb = Q_1*Q_2*..*Q_{n-1} where Q_k = I-ck*ck'/betak is an elementary Householder reflection. Format: frms = [c1, .., c_{n-1}, beta]. VERY INEFFICIENT !!!! ------------------------------------------------------------ */ psdframeit(x, frms,lab,sdpNL,cK.rsdpN,cK.sdpN,fwork); /* ------------------------------------------------------------ Release working array ------------------------------------------------------------ */ mxFree(sdpNL); mxFree(fwork); }
/* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */ void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { mwIndex i,j,jnz,MAXN, m,dimflqr,lenfull,reallength, nf,nx,ns, iwsize; mwIndex *iwork, *sdpNL, *cpxf, *cpxx, *cpxs, *cpxsi; bool *cwork; const double *cpxfPr, *cpxxPr, *cpxsPr, *xpi; mxArray *MY_FIELD; coneK cK; jcir x,y; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "makereal requires more input arguments"); mxAssert(nlhs <= NPAROUT, "makereal produces less output arguments"); /* ------------------------------------------------------------ Disassemble cone K structure ------------------------------------------------------------ */ conepars(K_IN, &cK); dimflqr = cK.frN + cK.lpN + cK.qDim; for(i = 0; i < cK.rconeN; i++) /* add dim of rotated cone */ dimflqr += cK.rconeNL[i]; lenfull = dimflqr + cK.rDim + cK.hDim; /* ------------------------------------------------------------ Disassemble cpx structure ------------------------------------------------------------ */ mxAssert(mxIsStruct(CPX_IN), "Parameter `cpx' should be a structure."); if( (MY_FIELD = mxGetField(CPX_IN,(mwIndex)0,"f")) == NULL) /* cpx.f */ nf = 0; else{ nf = mxGetM(MY_FIELD) * mxGetN(MY_FIELD); cpxfPr = mxGetPr(MY_FIELD); } if( (MY_FIELD = mxGetField(CPX_IN,(mwIndex)0,"s")) == NULL) /* cpx.s */ ns = 0; else{ ns = mxGetM(MY_FIELD) * mxGetN(MY_FIELD); cpxsPr = mxGetPr(MY_FIELD); } if( (MY_FIELD = mxGetField(CPX_IN,(mwIndex)0,"x")) == NULL) /* cpx.x */ nx = 0; else{ nx = mxGetM(MY_FIELD) * mxGetN(MY_FIELD); cpxxPr = mxGetPr(MY_FIELD); } /* ------------------------------------------------------------ Get input matrix x ------------------------------------------------------------ */ mxAssert(mxGetM(X_IN) == lenfull, "Size x mismatch."); m = mxGetN(X_IN); /* number of columns to handle */ mxAssert( mxIsSparse(X_IN), "X should be sparse."); x.pr = mxGetPr(X_IN); if(mxIsComplex(X_IN)) xpi = mxGetPi(X_IN); else xpi = (double *) NULL; x.jc = mxGetJc(X_IN); x.ir = mxGetIr(X_IN); /* ------------------------------------------------------------ Allocate iwork[iwsiz], cwork[MAXN], {K.s, cpx.{f[nf],x[nx],s[ns],si[2*ns]}} ------------------------------------------------------------ */ MAXN = MAX(MAX(nf,nx),2*ns); iwsize = floor(log(1.0 + MAXN) / log(2.0)); /* for binary tree search */ iwsize += 2 * ns + 2 + MAXN; iwork = (mwIndex *) mxCalloc(iwsize, sizeof(mwIndex)); cwork = (bool *) mxCalloc(MAX(1,MAXN), sizeof(bool)); sdpNL = (mwIndex *) mxCalloc(MAX(1, cK.sdpN + nf + nx + 3*ns), sizeof(mwIndex)); cpxf = sdpNL + cK.sdpN; cpxx = cpxf + nf; cpxs = cpxx + nx; cpxsi = cpxs + ns; /* length 2*ns */ /* ------------------------------------------------------------ Convert double to mwIndex ------------------------------------------------------------ */ for(i = 0; i < cK.sdpN; i++){ /* K.s */ j = cK.sdpNL[i]; sdpNL[i] = j; /* These are lengths, not subscripts!*/ } for(i = 0; i < nf; i++){ /* cpx.f */ j = cpxfPr[i]; cpxf[i] = --j; } for(i = 0; i < nx; i++){ /* cpx.x */ j = cpxxPr[i]; cpxx[i] = --j; } for(i = 0; i < ns; i++){ /* cpx.s */ j = cpxsPr[i]; cpxs[i] = --j; } /* ------------------------------------------------------------ Create cpxsi(1:2*ns). This lists the 1st subscript and the 1-beyond-last subscript of each Hermitian PSD matrix in x. ------------------------------------------------------------ */ jnz = dimflqr; j = 0; for(i = 0; i < ns; i++){ for(; j < cpxs[i]; j++) jnz += SQR(sdpNL[j]); cpxsi[2 * i] = jnz; /* start of Hermitian block */ jnz += SQR(sdpNL[j]); j++; cpxsi[2 * i + 1] = jnz; /* end of Hermitian block */ } /* ------------------------------------------------------------ Allocate output Y = sparse([],[],[],reallength(x),m,2 * nnz(x)) ------------------------------------------------------------ */ reallength = lenfull + nf + nx; for(i = 0; i < ns; i++){ reallength += cpxsi[2*i+1] - cpxsi[2*i]; } jnz = x.jc[m]; if(xpi != (double *) NULL) jnz *= 2; /* reserve room for imaginary parts */ Y_OUT = mxCreateSparse(reallength, m, jnz, mxREAL); y.pr = mxGetPr(Y_OUT); y.jc = mxGetJc(Y_OUT); y.ir = mxGetIr(Y_OUT); /* ------------------------------------------------------------ The real job, MAKEREAL: ------------------------------------------------------------ */ y.jc[0] = 0; jnz = 0; for(i = 0; i < m; i++){ y.jc[i] = jnz; j = x.jc[i+1] - x.jc[i]; jnz += makereal(y.ir+jnz, y.pr+jnz, x.ir+x.jc[i],x.pr+x.jc[i],xpi,j, cpxf,nf, cpxx,nx, cpxsi,ns, lenfull, dimflqr, cwork, iwork, iwsize); if(xpi != (double *) NULL) xpi += j; /* To next imaginary column */ } y.jc[i] = jnz; mxAssert(jnz <= mxGetNzmax(Y_OUT),""); /* ------------------------------------------------------------ REALLOC: Shrink Y to its current size ------------------------------------------------------------ */ jnz = MAX(jnz,1); if( (y.pr = (double *) mxRealloc(y.pr, jnz*sizeof(double))) == NULL) mexErrMsgTxt("Memory reallocation error"); mxSetPr(Y_OUT,y.pr); if( (y.ir = (mwIndex *) mxRealloc(y.ir, jnz*sizeof(mwIndex))) == NULL) mexErrMsgTxt("Memory reallocation error"); mxSetIr(Y_OUT,y.ir); mxSetNzmax(Y_OUT,jnz); /* ------------------------------------------------------------ Release working arrays ------------------------------------------------------------ */ mxFree(sdpNL); mxFree(cwork); mxFree(iwork); }