void prcomp(int n, int m,double **x,double **UtX,double *D) { int i,j; double *mu,*nu,*ltsigma,**xx,**V,**Vt; MAKE_VECTOR(mu,m); MAKE_VECTOR(ltsigma,m*(m+1)/2); meandispersion(x,n,m,mu,ltsigma); FREE_VECTOR(ltsigma); MAKE_MATRIX(xx,n,m); for(i=0;i<n;i++) { for(j=0;j<m;j++) xx[i][j]=(x[i][j]-mu[j])/sqrt(n-1.); } MAKE_MATRIX(V,m,m); i=svdd(xx,n,m,D,UtX,V); MAKE_MATRIX(Vt,m,m); matrpose(V,m,m,Vt); MAKE_VECTOR(nu,m); i=matxvec(Vt,m,m,mu,m,nu); FREE_MATRIX(Vt); FREE_VECTOR(mu); FREE_MATRIX(V); FREE_MATRIX(xx); for(i=0;i<n;i++) { for(j=0;j<m;j++) { UtX[i][j]*=D[j]; UtX[i][j]+=nu[j]; } } FREE_VECTOR(nu); return; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { /*declaration of variables*/ /*iteration variables*/ mwIndex i,j,k,numofnz; /*Auxillary variables*/ double tmplij, tmpljj; mwIndex tmprowind; /*Step 2:*/ mwSize m, n;/*m:number of rows, n:number of columns*/ mwSize nzmax;/*nnz of input*/ mwIndex rnzmax=100000000;/*rnzmax should be comparable with nzmax*/ mwIndex *ajc, *air; double *apr;/*CSC format of prhs[0]*/ double mu, eta1, eta2;/* mu is the shift, and eta1 is threshold*/ double *threshold; /*Step 3: */ mwIndex *zcolstart, *zcolend, *zrow; double *zval; mwIndex gap = 5000; /*Step 4:*/ double pjj,pij,lambda,zji; double *tmpAzj; /*Output:*/ mwIndex *ljc, *lir; double *lpr; /*---------------------------------------------*/ /* Step 1: Check input---------*/ if(nrhs != 4 && nrhs !=5) { mexErrMsgTxt("Four or Five Input Arguments are required"); } if(nlhs != 1) mexErrMsgTxt("One Output Argument Required\n"); /*Check whether prhs[] is sparse*/ if(mxIsSparse(prhs[0]) != 1) mexErrMsgTxt("Input Matrix Must Be Sparse\n"); /* ------------------------------*/ /* Step 2: Get Input Values------------*/ /*Read m and n from prhs[0]*/ m = mxGetM(prhs[0]); n = mxGetN(prhs[0]); nzmax = mxGetNzmax(prhs[0]); /*CSC format of A=prhs[0]*/ ajc = mxGetJc(prhs[0]); air = mxGetIr(prhs[0]); apr = mxGetPr(prhs[0]); /* Get shift*/ mu = mxGetScalar(prhs[1]); /*Get threshold*/ eta1 = mxGetScalar(prhs[2]); threshold = (double *)mxCalloc(n,sizeof(double)); for(j=0;j<n;j++) { for(i=ajc[j];i<ajc[j+1];i++)threshold[j] += absval(apr[i]); threshold[j] = eta1 * threshold[j]; } /*Get threshold parameter for Z*/ eta2 = mxGetScalar(prhs[3]); /* Get allocation parameter*/ if(nrhs == 5) { gap = (mwIndex)mxGetScalar(prhs[4]); if(gap > n)gap = n; } if(gap * m > rnzmax)rnzmax = (mwIndex)(gap*m); /*---------------------------------------*/ /*Step 3: Initialization of Z and L---------- */ zcolstart = (mwIndex *)mxCalloc(n, sizeof(mwIndex)); zcolend = (mwIndex *)mxCalloc(n, sizeof(mwIndex)); zrow = (mwIndex *)mxCalloc(rnzmax,sizeof(mwIndex)); zval = (double *)mxCalloc(rnzmax,sizeof(double)); if(zrow == NULL || zval == NULL){ printf("Out of memory, please use a smaller gap value\n"); return; } eyeinit(n, zcolstart, zcolend, zrow, zval, gap);/* Let Z be eye(n,n)*/ /*---------------------------------------*/ /* Step : Output */ plhs[0] = mxCreateSparse(n,n,rnzmax,mxREAL); ljc = mxGetJc(plhs[0]); lir = mxGetIr(plhs[0]); lpr = mxGetPr(plhs[0]); /*Step 4: Compute L*/ numofnz = 0; for(j=0;j<n;j++) { pjj = 0; tmpAzj = (double *)mxCalloc(m,sizeof(double)); matxvec(n,ajc,air,apr,zcolstart,zcolend,zrow,zval,j,tmpAzj); for(k=0;k<m;k++) if(tmpAzj[k] != 0)pjj += tmpAzj[k] * tmpAzj[k]; if(mu != 0){ for(i = zcolstart[j]; i <= zcolend[j]; i++) pjj -= mu * mu * zval[i] * zval[i]; } ljc[j] = numofnz; lir[numofnz] = j; lpr[numofnz] = sqrt(absval(pjj)); tmpljj = lpr[numofnz]; numofnz = numofnz + 1; if(tmpljj < 2.2e-16 ){ lpr[numofnz-1] = (threshold[j]>0)?threshold[j]:2.2e-16; continue; } for(i=j+1;i<n;i++) { pij = 0; for(k=ajc[i];k<ajc[i+1];k++) { tmprowind = air[k]; pij += apr[k] * tmpAzj[tmprowind]; } zji = 0; for(k=zcolend[i];k>=zcolstart[i];k--) { if(zrow[k]==j)zji = zval[k]; } pij -= mu * mu * zji; lambda = pij / pjj; tmplij = pij / tmpljj * signfun(pjj); if(absval(tmplij) > threshold[i]) { lir[numofnz] = i; lpr[numofnz] = tmplij; numofnz = numofnz + 1; addspvecs(zcolstart,zcolend,zrow,zval,i,j,-lambda,eta2); } } mxFree(tmpAzj); } ljc[n] = numofnz; }