#include "mex.h" #include "math.h" #define GetMatInd(a,xi,yi) (yi*a.nx+xi) #define GetMatEl(a,xi,yi) (a.dat[GetMatInd(a,xi,yi)]) double max_element; typedef struct mat { double *dat; int nx,ny,nall; } Matrix; int bDbg=1; double dot(double *a, double *b, int n) { double s=0; double *ap,*bp; double *aend=&a[n]; for (ap=&a[0],bp=&b[0]; apmx) mx=(*p); for (p=A; pmax) max = curr; } return max; } void write_mat(Matrix p) { int ri,ci,ind=0; if (!bDbg) return; for (ri=0; rimax_el) max_el=tmp; logZ+= exp(tmp); p1+= phi.nx; } p2+= phi.nx; } logZ = log(logZ); /* return logZ; */ return max_el; } /* This is actually minus the distance */ /* Generate the logemb model. a and b are vectors of length m1.ny and m2.ny respectively */ double get_worst_max(Matrix phi, Matrix psi, double *a, double *b, int b_cond) { double max_el; double phi_max,psi_max,a_max,b_max; phi_max = mat_max_abs(phi.dat, phi.nall); psi_max = mat_max_abs(psi.dat, psi.nall); /* Calculate upper bound on distance between phi and psi */ if (phi_max>psi_max) max_el = 4*phi_max*phi_max*phi.nx; else max_el = 4*psi_max*psi_max*phi.nx; a_max = mat_max_abs(a, phi.ny); b_max = mat_max_abs(b, psi.ny); if (a_max>b_max) max_el+=a_max; else max_el+=b_max; return max_el; } /* This is actually minus the distance */ /* Generate the logemb model. a and b are vectors of length m1.ny and m2.ny respectively */ void mat_logemb_model(Matrix phi, Matrix psi, double *a, double *b, Matrix phi_expect, Matrix psi_expect, double *px, double *py ,double *p0_i, double *p0_j, double *p0_val, int n_p0, double *loglik, int b_cond) { int i1,i2,k,di; double *p1,*p2,*res_ptr; double *p_phiexp,*p_psiexp; double tmp,df; double Z=0; int D = phi_expect.nx; double *ap,*bp,*p_phie,*p_psie; int NX = phi.ny; int NY = psi.ny; int p0ind = 0; double *aend; double logZ; (*loglik) = 0; p2 = psi.dat; p_phiexp = phi_expect.dat; p_psiexp = psi_expect.dat; /* Reset everything */ /* Initialize max element only if needed */ if (max_element==0) /* max_element = get_worst_max(phi, psi, a, b, b_cond); */ max_element = get_maxel(phi, psi, a, b, b_cond); if (!b_cond) { memset(phi_expect.dat,0,phi_expect.nall*sizeof(double)); memset(psi_expect.dat,0,psi_expect.nall*sizeof(double)); } memset(px,0,NX*sizeof(double)); memset(py,0,NY*sizeof(double)); for (i2=0; i2< psi.ny; i2++) { p1 = phi.dat; p_psiexp = psi_expect.dat; for (i1=0; i1< phi.ny; i1++) { double d=0; /* Inlining of l2_dist */ tmp=0; { aend=&p1[phi.nx]; for (ap=&p1[0],bp=&p2[0]; apnx = nx; m->ny = ny; m->nall = nx*ny; m->dat = malloc(sizeof(double)*nx*ny); if (m->dat==NULL) printf("Error in allocation\n"); } void mat_sum_rows(Matrix m, double *sum) { int xi,yi; for (xi=0; xidat = mxGetPr(plhs); mat->nx = mxGetM(plhs); mat->ny = mxGetN(plhs); mat->nall = mat->nx*mat->ny; } void mat_set(Matrix A, Matrix B) { memcpy(A.dat,B.dat,A.nall*sizeof(double)); } void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double M; double log_thr; int Xs,D,Ys,i,j,ep=0; int maxentep; int pxy_size; double mx; Matrix phi,psi,phi_tr,psi_tr,phi_exp_d,psi_exp_d,psi_exp_m,phi_exp_m,grad_phi,grad_psi; double *px0,*py0,*px,*py,*pa,*pb,*grad_a,*grad_b; double Z,loglik; int xi,yi,di; int b_cond; /* Says if the model is conditioned on x, or joint */ double *p0_i,*p0_j,*p0_val; int Np0; MatFromMLab(prhs[0],&phi); /* Size NX,D */ MatFromMLab(prhs[1],&psi); /* Size NX,D */ MatFromMLab(prhs[2],&phi_tr); /* Size D,NX */ MatFromMLab(prhs[3],&psi_tr); /* Size D,NY */ px0 = mxGetPr(prhs[4]); py0 = mxGetPr(prhs[5]); MatFromMLab(prhs[6],&phi_exp_d); MatFromMLab(prhs[7],&psi_exp_d); pa = mxGetPr(prhs[8]); pb = mxGetPr(prhs[9]); b_cond = *mxGetPr(prhs[10]); p0_i = mxGetPr(prhs[11]); p0_j = mxGetPr(prhs[12]); p0_val = mxGetPr(prhs[13]); Xs = mxGetM(prhs[0]); D = mxGetN(prhs[0]); Ys = mxGetM(prhs[1]); Np0 = mxGetNumberOfElements(prhs[13]); pxy_size = Xs*Ys; plhs[0] = mxCreateDoubleMatrix(D,Xs,mxREAL); plhs[1] = mxCreateDoubleMatrix(D,Ys,mxREAL); plhs[2] = mxCreateDoubleMatrix(1,Xs,mxREAL); plhs[3] = mxCreateDoubleMatrix(1,Ys,mxREAL); plhs[4] = mxCreateDoubleMatrix(1,1,mxREAL); grad_phi.dat = mxGetPr(plhs[0]); grad_psi.dat = mxGetPr(plhs[1]); grad_phi.nx = D; grad_phi.ny = Xs; grad_phi.nall = Xs*D; grad_psi.nx = D; grad_psi.ny = Ys; grad_psi.nall = Ys*D; grad_a = mxGetPr(plhs[2]); grad_b = mxGetPr(plhs[3]); AllocMat(D,Ys,&phi_exp_m); AllocMat(D,Xs,&psi_exp_m); px = malloc(Xs*sizeof(double)); py = malloc(Ys*sizeof(double)); if (px==NULL || py==NULL) printf("Error in allocation\n"); max_element = 0; if (!b_cond) mat_logemb_model(phi_tr, psi_tr, pa, pb, phi_exp_m, psi_exp_m, px, py, p0_i, p0_j, p0_val, Np0, mxGetPr(plhs[4]),b_cond) ; else { /* Run logemb model one time to get the x partition function in px */ mat_logemb_model(phi_tr, psi_tr, pa, pb, phi_exp_m, psi_exp_m, px, py, p0_i, p0_j, p0_val, Np0, mxGetPr(plhs[4]),b_cond) ; /* Create new x factor */ for (xi=0; xi