Page MenuHomec4science

mexskron.c
No OneTemporary

File Metadata

Created
Sun, Jul 13, 20:53

mexskron.c

/***********************************************************************
* mexskron.c : * Find the matrix presentation of
* symmetric kronecker product skron(A,B), where
* A,B are symmetric.
*
* K = mexskron(blk,A,B,sym);
*
* sym = 1 if A=B
* = 0 otherwise
*
* (ij)-column = 0.5*svec(AUB + BUA)*xij, where
* xij = 1/2 if i=j
* = 1/sqrt(2) otherwise
* U = ei*ej' + ej*ei'.
*
* SDPT3: version 3.0
* Copyright (c) 1997 by
* K.C. Toh, M.J. Todd, R.H. Tutuncu
* Last Modified: 2 Feb 01
***********************************************************************/
#include <mex.h>
#include <math.h>
#if !defined(MAX)
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#endif
#if !defined(r2)
#define r2 1.41421356237309504880 /* sqrt(2) */
#endif
#if !defined(ir2)
#define ir2 0.70710678118654752440 /* 1/sqrt(2) */
#endif
/**********************************************************
* A, B may not be equal
***********************************************************/
void skron(int n, int maxblksize, double *P, double *Q,
double *x1, double *y1, double *x2, double *y2,
int r, int c, double *vvtmp)
{ int idx, i, j, k, rn, cn;
double tmp, tmp1, tmp2, tmp3, tmp4;
double hf=0.5;
rn = r*maxblksize; cn = c*maxblksize;
for (k=0; k<n; k++) {
x1[k] = P[k+rn]; y1[k] = Q[k+cn];
x2[k] = P[k+cn]; y2[k] = Q[k+rn];
}
if (r < c) {
idx = 0;
for (j=0; j<n; j++) {
tmp1 = hf*y1[j]; tmp2 = hf*y2[j];
tmp3 = hf*x1[j]; tmp4 = hf*x2[j];
for (i=0; i<j; i++) {
vvtmp[idx] = tmp1*x1[i]+tmp2*x2[i]+tmp3*y1[i]+tmp4*y2[i];
idx++; }
tmp = tmp1*x1[j]+tmp2*x2[j]+tmp3*y1[j]+tmp4*y2[j];
vvtmp[idx] = tmp*ir2;
idx++;
}
} else {
/*** r = c ***/
idx = 0;
for (j=0; j<n; j++) {
tmp1 = ir2*y1[j]; tmp2 = ir2*x1[j];
for (i=0; i<j; i++) {
vvtmp[idx] = tmp1*x1[i]+tmp2*y1[i];
idx++; }
vvtmp[idx] = y1[j]*x1[j];
idx++;
}
}
return;
}
/**********************************************************
* A=B
***********************************************************/
void skron2(int n, int maxblksize, double *P, double *Q,
double *x1, double *y1, double *x2, double *y2,
int r, int c, double *vvtmp)
{ int idx, i, j, k, rn, cn;
double tmp1, tmp2, tmp;
rn = r*maxblksize; cn = c*maxblksize;
for (k=0; k<n; k++) {
x1[k] = P[k+rn]; y1[k] = Q[k+cn];
x2[k] = P[k+cn]; y2[k] = Q[k+rn];
}
if (r < c) {
idx = 0;
for (j=0; j<n; j++) {
tmp1 = y1[j]; tmp2 = y2[j];
for (i=0; i<j; i++) {
vvtmp[idx] = tmp1*x1[i] + tmp2*x2[i];
idx++; }
tmp = tmp1*x1[j] + tmp2*x2[j];
vvtmp[idx] = tmp*ir2;
idx++;
}
} else {
/*** r = c ***/
idx = 0;
for (j=0; j<n; j++) {
tmp1 = r2*y1[j];
for (i=0; i<j; i++) {
vvtmp[idx] = tmp1*x1[i];
idx++; }
vvtmp[idx] = y1[j]*x1[j];
idx++;
}
}
return;
}
/**********************************************************
*
***********************************************************/
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] )
{ mxArray *blk_cell_pr;
mxArray *tmparr[3];
double *A, *B, *blksizetmp, *P, *Q, *V;
double *ii, *jj, *vv, *vvtmp, *x1, *y1, *x2, *y2;
mwIndex *irA, *jcA, *irB, *jcB, *irV, *jcV;
int *blksize, *blksize2, *cumblksize, *blksize4;
int isspA, isspB, sym;
mwIndex subs[2];
mwSize nsubs=2;
int m, n, n2, nsub, k, index, numblk, len, maxblksize;
int i, j, l, jn, idxstart, idxend, kstart, kend, idx, blklen;
int blklen2, rowidx, colidx;
/* CHECK FOR PROPER NUMBER OF ARGUMENTS */
if (nrhs < 3){
mexErrMsgTxt("mexskron: requires at least 3 input arguments."); }
if (nlhs != 1){
mexErrMsgTxt("mexskron: requires 1 output argument."); }
/* CHECK THE DIMENSIONS */
if (mxGetM(prhs[0]) > 1) {
mexErrMsgTxt("mexskron: blk can only have 1 row."); }
if (mxGetN(prhs[0]) != 2) {
mexErrMsgTxt("mexskron: blk must have 2 columns."); }
subs[0] = 0; subs[1] = 1;
index = mxCalcSingleSubscript(prhs[0],nsubs,subs);
blk_cell_pr = mxGetCell(prhs[0],index);
numblk = mxGetN(blk_cell_pr);
blksizetmp = mxGetPr(blk_cell_pr);
blksize = (int*)mxCalloc(numblk,sizeof(int));
for (k=0; k<numblk; k++) { blksize[k] = (int) blksizetmp[k]; }
cumblksize = (int*)mxCalloc(numblk+1,sizeof(int));
blksize2 = (int*)mxCalloc(numblk+1,sizeof(int));
blksize4 = (int*)mxCalloc(numblk+1,sizeof(int));
cumblksize[0] = 0; blksize2[0] = 0; blksize4[0] = 0;
maxblksize=0;
for (k=0; k<numblk; ++k) {
nsub = blksize[k];
n2 = nsub*(nsub+1)/2;
cumblksize[k+1] = cumblksize[k] + nsub;
blksize2[k+1] = blksize2[k] + n2;
blksize4[k+1] = blksize4[k] + n2*n2;
maxblksize = MAX(maxblksize,nsub);
}
/***** assign pointers *****/
m = mxGetM(prhs[1]);
n = mxGetN(prhs[1]);
if (m != n) {
mexErrMsgTxt("mexskron: matrix A must be square."); }
A = mxGetPr(prhs[1]);
isspA = mxIsSparse(prhs[1]);
if (isspA) { irA = mxGetIr(prhs[1]);
jcA = mxGetJc(prhs[1]); }
m = mxGetM(prhs[2]);
n = mxGetN(prhs[2]);
if (m != n) {
mexErrMsgTxt("mexskron: matrix B must be square."); }
B = mxGetPr(prhs[2]);
isspB = mxIsSparse(prhs[2]);
if (isspB) { irB = mxGetIr(prhs[2]);
jcB = mxGetJc(prhs[2]); }
if ((isspA+isspB)==1) {
mexErrMsgTxt("mexskron: A and B must be both sparse or both dense");
}
sym = 0;
if (nrhs == 4) {
if (mxGetPr(prhs[3]) != NULL) {
sym = (int)*mxGetPr(prhs[3]); }
}
/***** create temporary array *****/
tmparr[0] = mxCreateDoubleMatrix(maxblksize,maxblksize,mxREAL);
P = mxGetPr(tmparr[0]);
tmparr[1] = mxCreateDoubleMatrix(maxblksize,maxblksize,mxREAL);
Q = mxGetPr(tmparr[1]);
tmparr[2] = mxCreateDoubleMatrix(maxblksize*(maxblksize+1)/2,1,mxREAL);
vvtmp = mxGetPr(tmparr[2]);
x1 = (double*)mxCalloc(maxblksize,sizeof(double));
y1 = (double*)mxCalloc(maxblksize,sizeof(double));
x2 = (double*)mxCalloc(maxblksize,sizeof(double));
y2 = (double*)mxCalloc(maxblksize,sizeof(double));
/***** create return argument *****/
len = blksize4[numblk];
plhs[0] = mxCreateSparse(blksize2[numblk],blksize2[numblk],len,mxREAL);
V = mxGetPr(plhs[0]);
irV = mxGetIr(plhs[0]);
jcV = mxGetJc(plhs[0]);
/***** Do the computations in a subroutine *****/
for (l=0; l<numblk; l++) {
blklen = blksize[l];
/*----- copy lth block to P,Q -----*/
for (j=0; j<blklen; j++) {
jn = j*maxblksize;
for (k=0; k<blklen; k++) {
idx = k+jn;
P[idx] = 0; Q[idx] = 0; }
}
idxstart = cumblksize[l];
idxend = cumblksize[l+1];
if (isspA & isspB) {
for (j=idxstart; j<idxend; j++) {
kstart = jcA[j]; kend = jcA[j+1];
jn = (j-idxstart)*maxblksize;
for (k=kstart; k<kend; k++) {
idx = irA[k]-idxstart;
P[idx+jn] = A[k]; }
kstart = jcB[j]; kend = jcB[j+1];
for (k=kstart; k<kend; k++) {
idx = irB[k]-idxstart;
Q[idx+jn] = B[k]; }
}
} else {
for (j=idxstart; j<idxend; j++) {
colidx = j*cumblksize[numblk];
jn = (j-idxstart)*maxblksize;
for (k=idxstart; k<idxend; k++) {
idx = (k-idxstart) + jn;
P[idx] = A[k+colidx];
Q[idx] = B[k+colidx];
}
}
}
/*----- skron(P,Q) -----*/
blklen2 = blklen*(blklen+1)/2;
idx = blksize4[l];
for (j=0; j<blklen; j++) {
for (i=0; i<=j; i++) {
if (sym==0) {
skron(blklen,maxblksize,P,Q,x1,y1,x2,y2,i,j,vvtmp);
} else {
skron2(blklen,maxblksize,P,Q,x1,y1,x2,y2,i,j,vvtmp);
}
colidx = blksize2[l] + i + j*(j+1)/2;
rowidx = blksize2[l];
for (k=0; k<blklen2; k++) {
V[idx] = vvtmp[k];
irV[idx] = rowidx+k;
idx++;
}
jcV[colidx+1] = idx;
}
}
}
/***** free memory *************************/
mxFree(blksize); mxFree(blksize2);
mxFree(cumblksize); mxFree(blksize4);
mxFree(x1); mxFree(y1); mxFree(x2); mxFree(y2);
mxDestroyArray(*tmparr);
return;
}
/**********************************************************/

Event Timeline