Пример #1
0
/* ************************************************************
   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]);
}
Пример #2
0
/* ************************************************************
   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]);
}