/*
 * The mex function runs a MST problem.
 */
void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[])
{ 
    mwIndex i;
    
    mwIndex mrows, ncols;
    
    mwIndex n,nz;
    
    /* sparse matrix */
    mwIndex *ia, *ja;
    
    /* matching */
    mwIndex *m;
    double *m_double;
    
    /* output */
    int verify = 0;
    
    /* 
     * The current calling pattern is
     * test_matching_mex(A,matching)
     */
    
    const mxArray* arg_matrix;
    const mxArray* arg_matching;
    int required_arguments = 2;
    
    if (nrhs != required_arguments) {
        mexErrMsgIdAndTxt("matlab_bgl:invalidMexArgument",
            "the function requires %i arguments, not %i\n", 
            required_arguments, nrhs);
    }
    
    arg_matrix = prhs[0];
    arg_matching = prhs[1];
    
    /* The first input must be a sparse matrix. */
    mrows = mxGetM(arg_matrix);
    ncols = mxGetN(arg_matrix);
    if (mrows != ncols || !mxIsSparse(arg_matrix)) {
        mexErrMsgIdAndTxt("matlab_bgl:invalidMexArgument",
            "the matrix must be sparse and square");
    }

    n = mrows;
    
    /* The second input must be of size n */
    if (mxGetNumberOfElements(arg_matching) != n) {
        mexErrMsgIdAndTxt("matlab_bgl:invalidMexArgument",
            "the matching must be size %i not %i", n,
            mxGetNumberOfElements(arg_matching));
    }
    m_double = mxGetPr(arg_matching);
    m = mxCalloc(n, sizeof(mwIndex));
    for (i=0; i < n; i++) {
        m[i] = (mwIndex)m_double[i] ;
        if (m[i] == 0) { m[i] = n; }
        else { --m[i]; }
    }
    
    /* Get the sparse matrix */
    
    /* recall that we've transposed the matrix */
    ja = mxGetIr(arg_matrix);
    ia = mxGetJc(arg_matrix);
    
    nz = ia[n];
    
    plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);

    #ifdef _DEBUG
    mexPrintf("test_maximum_cardinality_matching...");
    #endif 

    test_maximum_cardinality_matching(n, ja, ia, m, &verify);
    
    *mxGetPr(plhs[0]) = (double)verify;
    
    #ifdef _DEBUG
    mexPrintf("return\n");
    #endif 
    
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
    /* Variables */
    int k,nSamples,maxIter,sparse=0,*iVals,average=0,loss;
    long i,j,nVars,one=1;
    
    mwIndex *jc,*ir;
    
    double *w, *Xt, *y, lambda, *stepSizes, innerProd, alpha,sig,c=1,cA=1,tau=0,*wAvg,*averageWeights,weightedAverage=0,scaling;
    
    /* Input */
    
    if (nrhs < 6)
        mexErrMsgTxt("Exactly 6 arguments are needed: {w,Xy,y,lambda,stepSizes,iVals}");
    
    w = mxGetPr(prhs[0]);
    Xt = mxGetPr(prhs[1]);
    y = mxGetPr(prhs[2]);
    lambda = mxGetScalar(prhs[3]);
    stepSizes = mxGetPr(prhs[4]);
    iVals = (int*)mxGetPr(prhs[5]);
    
    if (!mxIsClass(prhs[5],"int32"))
        mexErrMsgTxt("iVals must be int32");
    
    /* Compute Sizes */
    nVars = mxGetM(prhs[1]);
    nSamples = mxGetN(prhs[1]);
    maxIter = mxGetM(prhs[4]);
    
    if (nVars != mxGetM(prhs[0]))
        mexErrMsgTxt("w and Xt must have the same number of rows");
    if (nSamples != mxGetM(prhs[2]))
        mexErrMsgTxt("number of columns of Xt must be the same as the number of rows in y");
    if (maxIter != mxGetM(prhs[5]))
        mexErrMsgTxt("iVals and stepSizes must have the same number of rows");
    if (nrhs > 7 && maxIter != mxGetM(prhs[7]))
        mexErrMsgTxt("iVals and averageWeights must have the same number of rows");
    
    if (mxIsSparse(prhs[1])) {
        sparse = 1;
        jc = mxGetJc(prhs[1]);
        ir = mxGetIr(prhs[1]);
    }
    
    
    if (nlhs > 0) {
        average = 1;
        plhs[0] = mxCreateDoubleMatrix(nVars,1,mxREAL);
        wAvg = mxGetPr(plhs[0]);
    }
    
    for(k=0;k<maxIter;k++)
    {
        /* Select next training example */
        i = iVals[k]-1;
        
        /* Compute Inner Product of Parameters with Features */
        innerProd = 0;
        if(sparse) {
            for(j=jc[i];j<jc[i+1];j++)
                innerProd += w[ir[j]]*Xt[j];
            innerProd *= c;
        }
        else
            innerProd = ddot(&nVars,w,&one,&Xt[nVars*i],&one);
        sig = -y[i]/(1+exp(y[i]*innerProd));
        
        /* Compute step size */
        alpha = stepSizes[k];
        
        /* Update parameters */
        if (sparse) {
            if (alpha*lambda != 1) {
                c *= 1-alpha*lambda;
            }
            else {
                c = 1;
                scaling = 0.0;
                dscal(&nVars,&scaling,w,&one);
            }
            for(j=jc[i];j<jc[i+1];j++)
                w[ir[j]] -= alpha*Xt[j]*sig/c;
            
        }
        else {
            scaling = 1-alpha*lambda;
            dscal(&nVars,&scaling,w,&one);
            scaling = -alpha*sig;
            daxpy(&nVars,&scaling,&Xt[i*nVars],&one,w,&one);
        }
        
        /* Average */
        if(average) {
            if (sparse) {
                if (k > 0)
                    cA *= (double)k/(double)(k+1);
                for(j=jc[i];j<jc[i+1];j++)
                    wAvg[ir[j]] += tau*alpha*Xt[j]*sig/c;
                tau += (c/cA)/(double)(k+1);
            }
            else {
                scaling = 1.0;
                daxpy(&nVars,&scaling,w,&one,wAvg,&one);
            }
        }
        
    }

    if(sparse) {
        dscal(&nVars,&c,w,&one);
    }
        
    if(average) {
        if (sparse) {
            scaling = tau/c;
            daxpy(&nVars,&scaling,w,&one,wAvg,&one);
            dscal(&nVars,&cA,wAvg,&one);
        }
        else
        {
            scaling = 1.0/maxIter;
            dscal(&nVars,&scaling,wAvg,&one);
        }
    }
    
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
	int     i, j, NS, NZB, count, bdim, match, domain, bindex, sindex, nzCounts=0;
	int     *observed, *bsubv, *ssubv, *bir, *sir, *bjc, *sjc, *mask, *ssize, *bcumprod, *scumprod;
	double  *pDomain, *pSize, *bpr, *spr;
	mxArray *pTemp;

	pTemp = mxGetField(prhs[0], 0, "CPT");
	bpr = mxGetPr(pTemp);
	bir = mxGetIr(pTemp);
	bjc = mxGetJc(pTemp);
	NZB = bjc[1];
	pTemp = mxGetField(prhs[0], 0, "sizes");
	pSize = mxGetPr(pTemp);

	pDomain = mxGetPr(prhs[1]);
	bdim = mxGetNumberOfElements(prhs[1]);

	mask = malloc(bdim * sizeof(int));
	ssize = malloc(bdim * sizeof(int));
	observed = malloc(bdim * sizeof(int));

	for(i=0; i<bdim; i++){
		ssize[i] = (int)pSize[i];
	}

	count = 0;
	for(i=0; i<bdim; i++){
		domain = (int)pDomain[i] - 1;
		pTemp = mxGetCell(prhs[2], domain);
		if(pTemp){
			mask[count] = i;
			ssize[i] = 1;
			observed[count] = (int)mxGetScalar(pTemp) - 1;
			count++;
		}
	}

	if(count == 0){
		pTemp = mxGetField(prhs[0], 0, "CPT");
		plhs[0] = mxDuplicateArray(pTemp);
		free(mask);
		free(ssize);
		free(observed);
		return;
	}

	bsubv = malloc(bdim * sizeof(int));
	ssubv = malloc(count * sizeof(int));
	bcumprod = malloc(bdim * sizeof(int));
	scumprod = malloc(bdim * sizeof(int));

	NS = 1;
	for(i=0; i<bdim; i++){
		NS *= ssize[i];
	}

	plhs[0] = mxCreateSparse(NS, 1, NS, mxREAL);
	spr = mxGetPr(plhs[0]);
	sir = mxGetIr(plhs[0]);
	sjc = mxGetJc(plhs[0]);
	sjc[0] = 0;
	sjc[1] = NS;

	bcumprod[0] = 1;
	scumprod[0] = 1;
	for(i=0; i<bdim-1; i++){
		bcumprod[i+1] = bcumprod[i] * (int)pSize[i];
		scumprod[i+1] = scumprod[i] * ssize[i];
	}

	nzCounts = 0;
	for(i=0; i<NZB; i++){
		bindex = bir[i];
		ind_subv(bindex, bcumprod, bdim, bsubv);
		for(j=0; j<count; j++){
			ssubv[j] = bsubv[mask[j]];
		}
		match = 1;
		for(j=0; j<count; j++){
			if((ssubv[j]) != observed[j]){
				match = 0;
				break;
			}
		}
		if(match){
			spr[nzCounts] = bpr[i];
			sindex = subv_ind(bdim, scumprod, bsubv);
			sir[nzCounts] = sindex;
			nzCounts++;
		}
	}

	reset_nzmax(plhs[0], NS, nzCounts);
	free(mask);
	free(ssize);
	free(observed);
	free(bsubv);
	free(ssubv);
	free(bcumprod);
	free(scumprod);
}
Exemple #4
0
/* ************************************************************
   PROCEDURE mexFunction - Entry for Matlab
   ************************************************************ */
void mexFunction(int nlhs, mxArray *plhs[],
                int nrhs, const mxArray *prhs[])
{
  jcir At;
  mwIndex i,j, nblk,m, L, iwsize;
  mwIndex *iwork, *Ablkjc, *blkstart;
  const mwIndex *rowj;
  double *AblkjcPr;
  const double *blkstartPr;
  bool *cwork;
/* ------------------------------------------------------------
   Check for proper number of arguments
   ------------------------------------------------------------ */
  mxAssert(nrhs >= NPARIN, "partitA requires more input arguments.");
  mxAssert(nlhs <= NPAROUT, "partitA produces less output arguments.");
/* --------------------------------------------------
   GET inputs At, blkstart
   -------------------------------------------------- */
  mxAssert(mxIsSparse(AT_IN), "At must be a sparse matrix.");
  At.jc = mxGetJc(AT_IN);
  At.ir = mxGetIr(AT_IN);
  m = mxGetN(AT_IN);
  nblk = mxGetM(BLKSTART_IN) * mxGetN(BLKSTART_IN);
  blkstartPr = mxGetPr(BLKSTART_IN);
/* ------------------------------------------------------------
   Allocate working array Ablkjc((nblk+2) * m), iwork(log_2(1+nblk)),
   blkstart(nblk)
   ------------------------------------------------------------ */
  iwsize = (mwIndex) floor(log(1.0+nblk)/log(2.0));
  iwork = (mwIndex *) mxCalloc(MAX(iwsize,1), sizeof(mwIndex));
  Ablkjc = (mwIndex *) mxCalloc(MAX((nblk+2)*m,1), sizeof(mwIndex));
  blkstart = (mwIndex *) mxCalloc(MAX(nblk,1), sizeof(mwIndex));
  cwork = (bool *) mxCalloc(MAX(nblk,1), sizeof(bool));
/* ------------------------------------------------------------
   Translate blkstart from Fortran-double to C-mwIndex
   ------------------------------------------------------------ */
  for(i = 0; i < nblk; i++){                         /* to integers */
    j = (mwIndex) blkstartPr[i];
    mxAssert(j>0,"");
    blkstart[i] = --j;
  }
/* ------------------------------------------------------------
   The real job:
   ------------------------------------------------------------ */
  partitA(Ablkjc, At.jc,At.ir, blkstart, m,nblk, iwsize,cwork,iwork);
/* ------------------------------------------------------------
   Create output Ablkjc m x nblk.
   ------------------------------------------------------------ */
  ABLKJC_OUT = mxCreateDoubleMatrix(m, nblk, mxREAL);
  AblkjcPr = mxGetPr(ABLKJC_OUT);
  rowj = Ablkjc;
  L = nblk+2;
  for(j = 0; j < nblk; j++){
    ++rowj;
    for(i = 0; i < m; i++)
      AblkjcPr[i] = (double) rowj[i*L];      /* convert mwIndex to double */
    AblkjcPr += m;
  }
/* ------------------------------------------------------------
   Release working arrays
   ------------------------------------------------------------ */
  mxFree(cwork);
  mxFree(iwork);
  mxFree(Ablkjc);
  mxFree(blkstart);
}
Exemple #5
0
int flip(mxArray *X, const mxArray *DL, const mxArray *A, const mxArray *dDL, 
        const mxArray *s, mwSize offset, mwSize T, const mxArray *h, 
        const mxArray *wws, const mxArray *wVs)
{
    const mwSize *sz = mxGetDimensions(dDL);
    mwSize D = sz[0], M = sz[1], p = sz[3], Ndt = sz[4];
    mwSize N = mxGetM(DL);
    mwSize Tdt = ceil((double) N / (double) Ndt);
    mwSize lenh = mxGetM(h);
    mwSize pad = (lenh - 1) / 2;
    
    // find maximum
    double *DLpr = mxGetPr(DL);
    double max = 0, d;
    int iMax = -1, jMax = -1;
    for (mwSize j = 0; j != M; ++j) {
        for (mwSize i = offset + 1; i != offset + T + 1; ++i) {
            d = DLpr[N * j + i];
            if (d >= max) {
                max = d;
                iMax = i;
                jMax = j;
            }
        }
    }
    
    double Xij;
    double *Xpr = mxGetPr(X), *Xpi = mxGetPi(X);
    double *hpr = mxGetPr(h), *Apr = mxGetPr(A);
    mwIndex *Xir = mxGetIr(X), *Xjc = mxGetJc(X);
    double sgn;
    if (max > 0) {

        // find location in sparse array
        double a = 0, r = 0;
        int sub;
        mwSize l = Xjc[jMax];
        while (l != Xjc[jMax + 1] && Xir[l] <= iMax) {
            if (Xir[l] == iMax) {
                a = Xpr[l];
                r = Xpi[l];
                break;
            } else {
                ++l;
            }
        }
        
        if (a == 0) { // add spike - subsample
            
            // determine amplitude and subsample shift
            sgn = 1;
            max = 0;
            for (mwSize j = 0; j != p; ++j) {
                double m = 0;
                for (mwSize i = 0; i != lenh; ++i) {
                    m = m + DLpr[jMax * N + iMax - pad + i] * hpr[j * lenh + i];
                }
                if (m > max) {
                    sub = j;
                    max = m;
                }
            }
            for (mwSize i = 0; i != lenh; ++i) {
                a = a + Apr[N * jMax + iMax - pad + i] * hpr[sub * lenh + i];
            }
            r = (double) (sub - (int) p / 2) / (double) p; // CHECK

            // grow sparse array if necessary
            mwSize nzmax = mxGetNzmax(X);
            if (Xjc[M] == nzmax) { // grow X
                nzmax *= 2;
                mxSetNzmax(X, nzmax);
                Xir = (mwIndex*) mxRealloc(Xir, nzmax * sizeof(*Xir));
                mxSetIr(X, Xir);
                Xpr = (double*) mxRealloc(Xpr, nzmax * sizeof(*Xpr));
                mxSetPr(X, Xpr);
                Xpi = (double*) mxRealloc(Xpi, nzmax * sizeof(*Xpi));
                mxSetPi(X, Xpi);
            }
            
            // add values to sparse array
            //   real: amplitude
            //   imag: subsample (> 0 => shift right, < 0 => shift left)
            for (mwSize j = jMax; j != M; ++j) {
                ++Xjc[j + 1];
            }
            for (mwSize i = Xjc[M] - 1; i > l; --i) {
                Xir[i] = Xir[i - 1];
                Xpr[i] = Xpr[i - 1];
                Xpi[i] = Xpi[i - 1];
            }
            Xir[l] = iMax;
            Xpr[l] = a;
            Xpi[l] = r;
                    
        } else { // remove spike
            
            sgn = -1;
            for (mwSize j = jMax + 1; j != M + 1; ++j) {
                --Xjc[j];
            }
            for (; l != Xjc[M]; ++l) {
                Xir[l] = Xir[l + 1];
                Xpr[l] = Xpr[l + 1];
                Xpi[l] = Xpi[l + 1];
            }
        }

        // update change in posterior
        double DLij = DLpr[N * jMax + iMax]; 
        sub = (int) p / 2 - round(r * (double) p);
        mwSize t = iMax / Tdt;
        mwSize start = D * M * (jMax + M * (sub + p * t));
        mwSize ii;
        double dA;
        double *dDLpr = mxGetPr(dDL), *wwspr = mxGetPr(wws), 
               *wVspr = mxGetPr(wVs), *spr = mxGetPr(s);
        for (mwSize j = 0; j != M; ++j) {
            for (mwSize i = 0; i != D; ++i) {
                dA = dDLpr[start + D * j + i] * a * sgn / wwspr[Ndt * j + t];
                ii = N * j + iMax + spr[i];
                Apr[ii] = Apr[ii] - dA;
                DLpr[ii] = DLpr[ii] - dA * (wVspr[ii] + a * dDLpr[start + D * j + i]);
                DLpr[N * jMax + iMax] = -DLij;
            }
        }
    
    } else {
        iMax = -1;
    }
    return iMax;
}
Exemple #6
0
 void
mexFunction(int nlhs, Matrix **plhs, int nrhs, Matrix **prhs)
{
	FILE *nl;
	char *buf1, buf[512], *what;
	static fint n, nc, nz;
	fint nerror;
	real *J1, *W, *c, *f, *g, *v, *t, *x;
	static real *J;
	cgrad *cg, **cgp;
	static size_t Jsize;
	Jmp_buf err_jmp0;
	ASL_pfgh *asl = (ASL_pfgh*)cur_ASL;
	static fint nhnz;
	static real *Hsp;
	real *H, *He;
	int *Ir, *Jc;
	fint *hcs, *hr, i;

	if (nrhs == 1 && mxIsString(prhs[0])) {
		if (nlhs != 6)
			usage();
		if (mxGetString(prhs[0], buf1 = buf, sizeof(buf)))
			mexErrMsgTxt("Expected 'stub' as argument\n");
		at_end();
		mexAtExit(at_end);
		asl = (ASL_pfgh*)ASL_alloc(ASL_read_pfgh);
		return_nofile = 1;
		if (!(nl = jac0dim(buf1,strlen(buf)))) {
			sprintf(msgbuf, "Can't open %.*s\n",
				sizeof(msgbuf)-20, buf);
			mexErrMsgTxt(msgbuf);
			}
		if (n_obj <= 0)
			printf("Warning: objectve == 0\n");
		n = n_var;
		nc = n_con;
		nz = nzc;
		J = (real *)M1alloc(nz*sizeof(real));
		X0 = mxGetPr(plhs[0] = mxCreateFull(n, 1, REAL));
		LUv = mxGetPr(plhs[1] = mxCreateFull(n, 1, REAL));
		Uvx = mxGetPr(plhs[2] = mxCreateFull(n, 1, REAL));
		pi0 = mxGetPr(plhs[3] = mxCreateFull(nc, 1, REAL));
		LUrhs = mxGetPr(plhs[4] = mxCreateFull(nc, 1, REAL));
		Urhsx = mxGetPr(plhs[5] = mxCreateFull(nc, 1, REAL));
		pfgh_read(nl, ASL_findgroups);
		Jsize = nc*n*sizeof(real);

		/* Arrange to compute the whole sparese Hessian */
		/* of the Lagrangian function (both triangles). */

		nhnz = sphsetup(0, 0, nc > 0, 0);
		Hsp = (real *)M1alloc(nhnz*sizeof(real));
		return;
		}

	if (!filename)
		mexErrMsgTxt("spamfunc(\"stub\") has not been called\n");
	nerror = -1;
	err_jmp1 = &err_jmp0;
	if (nlhs == 2) {
		if (nrhs != 2)
			usage();
		x = sizechk(prhs[0],"x",n);
		t = sizechk(prhs[1],"0 or 1", 1);
		if (t[0] == 0.) {
			f = mxGetPr(plhs[0] = mxCreateFull(1, 1, REAL));
			c = mxGetPr(plhs[1] = mxCreateFull(nc, 1, REAL));
			if (setjmp(err_jmp0.jb)) {
				sprintf(msgbuf, "Trouble evaluating %s\n",
					what);
				mexErrMsgTxt(msgbuf);
				}
			what = "f";
			*f = objval(0, x, &nerror);
			what = "c";
			conval(x, c, &nerror);
			return;
			}
		g = mxGetPr(plhs[0] = mxCreateFull(n, 1, REAL));
		J1 = mxGetPr(plhs[1] = mxCreateSparse(nc, n, nz, REAL));
		what = "g";
		objgrd(0, x, g, &nerror);
		if (nc) {
			what = "J";
			jacval(x, J1, &nerror);
			Ir = mxGetIr(plhs[1]);
			memcpy(mxGetJc(plhs[1]), A_colstarts, (n+1)*sizeof(int));
			cgp = Cgrad;
			for(i = 0; i < nc; i++)
				for(cg = *cgp++; cg; cg = cg->next)
					Ir[cg->goff] = i;
			}
		return;
		}
	if (nlhs == 0 && nrhs == 3) {
		/* eval2('solution message', x, v): x = primal, v = dual */
		if (!mxIsString(prhs[0]))
			usage();
		x = sizechk(prhs[1],"x",n);
		v = sizechk(prhs[2],"v",nc);
		if (mxGetString(prhs[0], buf, sizeof(buf)))
			mexErrMsgTxt(
			 "Expected 'solution message' as first argument\n");
		write_sol(buf, x, v, 0);
		return;
		}
	if (nlhs != 1 || nrhs != 1)
		usage();
	v = sizechk(prhs[0],"v",nc);
	W = mxGetPr(plhs[0] = mxCreateSparse(n, n, nhnz, REAL));

	what = "W";
	sphes(H = Hsp, 0, 0, v);

	/* Expand the Hessian lower triangle into the full Hessian... */

	Ir = mxGetIr(plhs[0]);
	Jc = mxGetJc(plhs[0]);
	hcs = sputinfo->hcolstarts;
	hr = sputinfo->hrownos;
	for(i = 0; i <= n; i++)
		Jc[i] = hcs[i];
	He = H + hcs[n];
	while(H < He) {
		*W++ = *H++;
		*Ir++ = *hr++;
		}
	}
Exemple #7
0
/* ************************************************************
   PROCEDURE mexFunction - Entry for Matlab
   ************************************************************ */
void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[])
{
  const mxArray *L_FIELD;
  mwIndex i,j, nsuper,m, cachesiz;
  const mwIndex *ljc,*lir;
  mwIndex *xsuper, *split;
  const double *xsuperPr;
  double *splitPr;
/* ------------------------------------------------------------
   Check for proper number of arguments
   ------------------------------------------------------------ */
  mxAssert(nrhs >= NPARIN, "cholsplit requires more input arguments.");
  mxAssert(nlhs <= NPAROUT, "cholsplit produces less output arguments.");
/* ------------------------------------------------------------
   Get cachesiz, and transform from KBs into 90% of FLOATS.
   ------------------------------------------------------------ */
  cachesiz = (mwIndex) floor(0.9 * (1024 / sizeof(double)) * mxGetScalar(CACHESIZ_IN));
/* ------------------------------------------------------------
   Disassemble block Cholesky structure L
   ------------------------------------------------------------ */
  mxAssert(mxIsStruct(L_IN), "Parameter `L' should be a structure.");
  L_FIELD = mxGetField(L_IN,(mwIndex)0,"L");        /* L.L */
  mxAssert( L_FIELD != NULL, "Missing field L.L.");
  m = mxGetM(L_FIELD);
  mxAssert(m == mxGetN(L_FIELD), "L.L must be square.");
  mxAssert(mxIsSparse(L_FIELD), "L.L should be sparse.");
  ljc = mxGetJc(L_FIELD);
  lir = mxGetIr(L_FIELD);
  L_FIELD = mxGetField(L_IN,(mwIndex)0,"xsuper");          /* L.xsuper */
  mxAssert( L_FIELD != NULL, "Missing field L.xsuper.");
  nsuper = mxGetM(L_FIELD) * mxGetN(L_FIELD) - 1;
  mxAssert( nsuper <= m, "Size L.xsuper mismatch.");
  xsuperPr = mxGetPr(L_FIELD);
/* ------------------------------------------------------------
   Allocate working arrays:
   ------------------------------------------------------------ */
  xsuper    = (mwIndex *) mxCalloc(nsuper+1,sizeof(mwIndex));
  split     = (mwIndex *) mxCalloc(m,sizeof(mwIndex));
/* ------------------------------------------------------------
   Convert XSUPER to integer and C-Style
   ------------------------------------------------------------ */
  for(i = 0; i <= nsuper; i++){
    j =  (mwIndex) xsuperPr[i];
    mxAssert(j>0,"");
    xsuper[i] = --j;
  }
/* ------------------------------------------------------------
   The main job: compute (upper bound on) blkchol-split.
   ------------------------------------------------------------ */
  getsplit(split, ljc,lir,xsuper,nsuper, cachesiz);
/* ------------------------------------------------------------
   create OUTPUT variable SPLIT(m)
   ------------------------------------------------------------ */
  SPLIT_OUT = mxCreateDoubleMatrix(m, (mwSize)1, mxREAL);          /* L.split */
  splitPr = mxGetPr(SPLIT_OUT);
  for(i = 0; i < m; i += j){
    j = split[i];
    splitPr[i] = (double) j;
  }
/* ------------------------------------------------------------
   Release working arrays.
   ------------------------------------------------------------ */
  mxFree(split);
  mxFree(xsuper);
}
Exemple #8
0
/* ************************************************************
   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) */
}
void mexFunction(
      int nlhs,   mxArray  *plhs[], 
      int nrhs,   const mxArray  *prhs[] )
{    
     mxArray  *A_cell_pr;
     double   *A, *B;
     int      *irA, *jcA, *irB, *jcB; 
     double   *Btmp, *tr;
     int      isspA, isspB, iscellA, iscellB;

     int     subs[2];
     int     nsubs=2; 
     int     mA, nA, m1, n1, m2, n2, j, index;    
     int     rowidx, colidx, r, k, kstart, kend;


/* CHECK THE DIMENSIONS */

   iscellA = mxIsCell(prhs[1]); 
   mA = mxGetM(prhs[1]); 
   if (!iscellA) { mA = 1; }  
   if (nrhs < 2) {
       mexErrMsgTxt(" mexinprod: must have at least 3 inputs"); }
   if (nlhs>2) { 
       mexErrMsgTxt("mexinprod: requires 1 output argument"); }
   if (nrhs > 4) { rowidx = (int)*mxGetPr(prhs[4]); } else { rowidx = 1; }
   if (rowidx > mA) {
      mexErrMsgTxt("mexinprod: rowidx exceeds size(Avec,1)"); 
   }
   /***** assign pointers *****/
    
       iscellB = mxIsCell(prhs[2]); 
       isspB = mxIsSparse(prhs[2]);
       m2 = mxGetM(prhs[2]); 
       n2 = mxGetN(prhs[2]);            
       if ((n2 > 1) || (iscellB)) { 
 	  mexErrMsgTxt("mexinprod: 3RD input must be a column vector"); }
       if (isspB) { 
          irB = mxGetIr(prhs[2]);
          jcB = mxGetJc(prhs[2]); 
          Btmp = mxGetPr(prhs[2]); 
          /***** copy Btmp to B *****/ 
          B = mxCalloc(m2,sizeof(double)); 
          kstart = jcB[0]; kend = jcB[1]; 
          for (k=kstart; k<kend; k++) { 
	      r = irB[k]; B[r] = Btmp[k]; }
       } else {
          B = mxGetPr(prhs[2]); 
       }       
       if (iscellA) {
  	  subs[0] = rowidx-1;  /* subtract 1 to adjust for Matlab index */
          subs[1] = 0;
          index = mxCalcSingleSubscript(prhs[1],nsubs,subs); 
          A_cell_pr = mxGetCell(prhs[1],index); 
          A  = mxGetPr(A_cell_pr); 
          m1 = mxGetM(A_cell_pr); 
          n1 = mxGetN(A_cell_pr);
          isspA = mxIsSparse(A_cell_pr);               
          if (isspA) { irA = mxGetIr(A_cell_pr);
                       jcA = mxGetJc(A_cell_pr); } 
       } else {
          A = mxGetPr(prhs[1]); 
          m1 = mxGetM(prhs[1]); 
          n1 = mxGetN(prhs[1]);
          isspA = mxIsSparse(prhs[1]);
          if (isspA) { irA = mxGetIr(prhs[1]);
	               jcA = mxGetJc(prhs[1]); }
       }           
       if (nrhs > 3) { colidx = (int)*mxGetPr(prhs[3]); } else { colidx = 1; }
       if (colidx > n1) { 
          mexErrMsgTxt("mexinprod: colidx exceeds size(Avec,2)"); }
       if (m1 != m2) {
          mexErrMsgTxt("mexinprod: 2ND and 3RD input not compatible."); 
       }
       /***** create return argument *****/

       plhs[0] = mxCreateDoubleMatrix(colidx,1,mxREAL); 
       tr = mxGetPr(plhs[0]); 

       /***** compute <Aj,B> *****/
       if (isspA) { 
          for (j=0; j<colidx; j++){
	      tr[j] = realdot2(A,irA,jcA,j,B); }      
       } else {
          for (j=0; j<colidx; j++){
	      tr[j] = realdot1(A,j,B,m1); }       
       }
       if (isspB) { mxFree(B); } 
 return;
}
Exemple #10
0
/* ************************************************************
   PROCEDURE mexFunction - Entry for Matlab
   ************************************************************ */
void mexFunction(const int nlhs, mxArray *plhs[],
  const int nrhs, const mxArray *prhs[])
{
  const mxArray *L_FIELD;
  int maxnnz, i,j, nsuper,m,n;
  const int *ljc,*lir,*bjc,*bir;
  int *xjc,*xir, *snode,*snodebelow, *iwork,*xsuper;
  char *cwork;
  double *xpr;
  const double *xsuperPr;
/* ------------------------------------------------------------
   Check for proper number of arguments
   ------------------------------------------------------------ */
  mxAssert(nrhs >= NPARIN, "symbfwblk requires more input arguments");
  mxAssert(nlhs <= NPAROUT, "symbfwblk produces 1 output argument");
/* ------------------------------------------------------------
   Get rhs-input B
   ------------------------------------------------------------ */
  mxAssert(mxIsSparse(B_IN), "B must be sparse");
  m = mxGetM(B_IN);
  n = mxGetN(B_IN);
  bjc = mxGetJc(B_IN);
  bir = mxGetIr(B_IN);
/* ------------------------------------------------------------
   Disassemble block Cholesky structure L
   ------------------------------------------------------------ */
  mxAssert(mxIsStruct(L_IN), "Parameter `L' should be a structure.");
  L_FIELD = mxGetField(L_IN,0,"L"); 
  mxAssert( L_FIELD != NULL, "Missing field L.L.");           /* L.L */
  mxAssert( m == mxGetM(L_FIELD) && m == mxGetN(L_FIELD), "Size L.L mismatch.");
  mxAssert(mxIsSparse(L_FIELD), "L.L should be sparse.");
  ljc = mxGetJc(L_FIELD);
  lir = mxGetIr(L_FIELD);
  L_FIELD = mxGetField(L_IN,0,"xsuper"); 
  mxAssert( L_FIELD != NULL, "Missing field L.xsuper.");      /* L.xsuper */
  nsuper = mxGetM(L_FIELD) * mxGetN(L_FIELD) - 1;
  mxAssert( nsuper <= m, "Size L.xsuper mismatch.");
  xsuperPr = mxGetPr(L_FIELD);
/* ------------------------------------------------------------
   Allocate int-part of sparse output matrix X(m x n)
   Heuristically set nnz to nnz(B) + 4*m.
   ------------------------------------------------------------ */
  maxnnz = bjc[n] + 4 * m;
  xjc = (int *) mxCalloc(n + 1, sizeof(int));
  xir = (int *) mxCalloc(maxnnz, sizeof(int));
/* ------------------------------------------------------------
   Allocate working arrays:
   int snode(m), xsuper(nsuper+1), snodebelow(nsuper),
   iwork(nsuper).
   char cwork(nsuper+1).
   ------------------------------------------------------------ */
  snode     = (int *) mxCalloc(m,sizeof(int)); 
  xsuper    = (int *) mxCalloc(nsuper+1,sizeof(int));
  snodebelow = (int *) mxCalloc(nsuper,sizeof(int));
  iwork = (int *) mxCalloc(nsuper, sizeof(int));
  cwork = (char *) mxCalloc(nsuper+1, sizeof(char));
/* ------------------------------------------------------------
   Convert XSUPER to integer and C-Style
   ------------------------------------------------------------ */
  for(i = 0; i <= nsuper; i++){
    j =  xsuperPr[i];
    xsuper[i] = --j;
  }
/* ------------------------------------------------------------
   Create "snode" from xsuper, and get "first-below-diag" 
   supernodal subscript snodebelow (snodebelow[j]==nsuper means none).
   This is enough to determine the nz-pattern of the backward-solve.
   ------------------------------------------------------------ */
  getSnodeBelow(snodebelow,snode, ljc,lir,xsuper,nsuper);
/* ------------------------------------------------------------
   Compute nz structure after backward solve
   ------------------------------------------------------------ */
  symbbwmat(xjc, &xir, &maxnnz, bjc, bir, snode, xsuper,
            snodebelow, nsuper, m, n, iwork, cwork);
/* ------------------------------------------------------------
   Create output matrix x
   ------------------------------------------------------------ */
  X_OUT = mxCreateSparse(m,n, 1,mxREAL);
  mxFree(mxGetJc(X_OUT));                    /* jc */
  mxFree(mxGetIr(X_OUT));                    /* ir */
  mxFree(mxGetPr(X_OUT));                    /* pr */
  xpr = (double *) mxCalloc(maxnnz,sizeof(double));
  mxSetJc(X_OUT, xjc);
  mxSetIr(X_OUT, xir);
  mxSetPr(X_OUT, xpr);
  mxSetNzmax(X_OUT, maxnnz);
  for(i = 0; i < maxnnz; i++)
    xpr[i] = 1.0;
/* ------------------------------------------------------------
   Release working arrays.
   ------------------------------------------------------------ */
  mxFree(cwork);
  mxFree(iwork);
  mxFree(snodebelow);
  mxFree(xsuper);
  mxFree(snode);
}
Exemple #11
0
/* ************************************************************
   PROCEDURE mexFunction - Entry for Matlab
   ************************************************************ */
void mexFunction(const int nlhs, mxArray *plhs[],
                 const int nrhs, const mxArray *prhs[])
{
  jcir At, Ablk;
  int i,j, nblk,m, blknnz, njc, iwsize, blk0,blk1;
  int *iwork, *Ajc, *blkstart;
  const double *blkstartPr, *AjcPr;
  char *cwork;
/* ------------------------------------------------------------
   Check for proper number of arguments
   ------------------------------------------------------------ */
  mxAssert(nrhs >= NPARIN, "findblks requires more input arguments.");
  mxAssert(nlhs <= NPAROUT, "findblks produces less output arguments.");
/* --------------------------------------------------
   GET inputs At, blkstart, Ablkjc, blk0, blk1
   -------------------------------------------------- */
  mxAssert(mxIsSparse(AT_IN), "At must be a sparse matrix.");
  At.jc = mxGetJc(AT_IN);
  At.ir = mxGetIr(AT_IN);
  m = mxGetN(AT_IN);
  nblk = mxGetM(BLKSTART_IN) * mxGetN(BLKSTART_IN) - 1;
  blkstartPr = mxGetPr(BLKSTART_IN);
  AjcPr = mxGetPr(ABLKJC_IN);
  mxAssert(m == mxGetM(ABLKJC_IN), "Ablkjc size mismatch.");
  njc = mxGetN(ABLKJC_IN);
  blk0 = mxGetScalar(BLK0_IN);           /* double to int */
  --blk0;                                /* Fortran to C */
  if(mxGetM(BLK1_IN) * mxGetN(BLK1_IN) != 1)
    blk1 = njc;                           /*default to end */
  else{
    blk1 = mxGetScalar(BLK1_IN);   /* double to int (thus inf not allowed) */
    --blk1;                                /* Fortran to C */
  }
/* ------------------------------------------------------------
   Allocate working array iwork(nblk+2+log_2(1+nblk)),
   blkstart(2*nblk), Ajc(2*m)
   char cwork(nblk)
   ------------------------------------------------------------ */
  iwsize = nblk + 2 + floor(log(1+nblk)/log(2));
  iwork = (int *) mxCalloc(iwsize, sizeof(int));
  blkstart = (int *) mxCalloc(MAX(2*nblk,1), sizeof(int));
  Ajc = (int *) mxCalloc(MAX(2*m,1), sizeof(int));
  cwork = (char *) mxCalloc(MAX(nblk,1), sizeof(char));
/* ------------------------------------------------------------
   Translate blkstart from Fortran-double to C-int
   ------------------------------------------------------------ */
  for(i = 0; i < nblk; i++){                         /* to integers */
    j = blkstartPr[i];
    blkstart[i] = --j;
    blkstart[nblk+i] = --j;          /* blkstart minus 1 */
  }
/* ------------------------------------------------------------
   Convert Ajc from double to int:
   ------------------------------------------------------------ */
  mxAssert(blk0 < njc, "Ablkjc size mismatches blk0.");
  if(blk0 < 0)
    memcpy(Ajc,At.jc,m*sizeof(int));          /* default: start of column */
  else
    for(i = 0; i < m; i++){                         /* to integers */
      Ajc[i] = AjcPr[m*blk0 + i];
    }
  mxAssert(blk1 >= 0, "blk1 must be positive.");
  if(blk1 >= njc)
    memcpy(Ajc+m,At.jc+1,m*sizeof(int));      /* default: end of column */
  else
    for(i = 0; i < m; i++){                         /* to integers */
      Ajc[m+i] = AjcPr[blk1*m + i];
    }
/* ------------------------------------------------------------
   Ablk = sparse(nblk,m,blknnz);
   ------------------------------------------------------------ */
  blknnz = 0;
  for(i = 0; i < m; i++)
    blknnz += Ajc[m+i]-Ajc[i];              /* upper bound on nnz blocks */
  blknnz = MAX(blknnz,1);
  ABLK_OUT = mxCreateSparse(nblk,m, blknnz,mxREAL);
  Ablk.jc = mxGetJc(ABLK_OUT);
  Ablk.ir = mxGetIr(ABLK_OUT);
/* ------------------------------------------------------------
   The real job:
   ------------------------------------------------------------ */
  findblks(Ablk.ir,Ablk.jc, Ajc,Ajc+m,At.ir, blkstart,blkstart+nblk,
           m,nblk, iwsize,cwork,iwork);
/* ------------------------------------------------------------
   REALLOC (shrink) Ablk to Ablk.jc[m] nonzeros.
   ------------------------------------------------------------ */
  mxAssert(Ablk.jc[m] <= blknnz,"");
  blknnz = MAX(Ablk.jc[m],1);
  if((Ablk.ir = (int *) mxRealloc(Ablk.ir, blknnz * sizeof(int))) == NULL)
    mexErrMsgTxt("Memory allocation error");
  if((Ablk.pr = (double *) mxRealloc(mxGetPr(ABLK_OUT), blknnz*sizeof(double)))
     == NULL)
    mexErrMsgTxt("Memory allocation error");
  mxSetPr(ABLK_OUT,Ablk.pr);
  mxSetIr(ABLK_OUT,Ablk.ir);
  mxSetNzmax(ABLK_OUT,blknnz);
  for(i = 0; i < blknnz; i++)
    Ablk.pr[i] = 1.0;
/* ------------------------------------------------------------
   Release working arrays
   ------------------------------------------------------------ */
  mxFree(cwork);
  mxFree(iwork);
  mxFree(Ajc);
  mxFree(blkstart);
}
const char *model_to_matlab_structure(mxArray *plhs[], int num_of_feature, struct svm_model *model)
{
	int i, j, n;
	double *ptr;
	mxArray *return_model, **rhs;
	int out_id = 0;

	rhs = (mxArray **)mxMalloc(sizeof(mxArray *)*NUM_OF_RETURN_FIELD);

	// Parameters
	rhs[out_id] = mxCreateDoubleMatrix(5, 1, mxREAL);
	ptr = mxGetPr(rhs[out_id]);
	ptr[0] = model->param.svm_type;
	ptr[1] = model->param.kernel_type;
	ptr[2] = model->param.degree;
	ptr[3] = model->param.gamma;
	ptr[4] = model->param.coef0;
	out_id++;

	// nr_class
	rhs[out_id] = mxCreateDoubleMatrix(1, 1, mxREAL);
	ptr = mxGetPr(rhs[out_id]);
	ptr[0] = model->nr_class;
	out_id++;

	// total SV
	rhs[out_id] = mxCreateDoubleMatrix(1, 1, mxREAL);
	ptr = mxGetPr(rhs[out_id]);
	ptr[0] = model->l;
	out_id++;

	// rho
	n = model->nr_class*(model->nr_class-1)/2;
	rhs[out_id] = mxCreateDoubleMatrix(n, 1, mxREAL);
	ptr = mxGetPr(rhs[out_id]);
	for(i = 0; i < n; i++)
		ptr[i] = model->rho[i];
	out_id++;

	// obj
	n = model->nr_class*(model->nr_class-1)/2;
	rhs[out_id] = mxCreateDoubleMatrix(1, 1, mxREAL);
	ptr = mxGetPr(rhs[out_id]);
	for(i = 0; i < n; i++)
		ptr[i] = model->obj[i];
	out_id++;

	//radius
	rhs[out_id] = mxCreateDoubleMatrix(1, 1, mxREAL);
	ptr = mxGetPr(rhs[out_id]);
	ptr[0] = model->radius;
	out_id++;
	
	// Label
	if(model->label)
	{
		rhs[out_id] = mxCreateDoubleMatrix(model->nr_class, 1, mxREAL);
		ptr = mxGetPr(rhs[out_id]);
		for(i = 0; i < model->nr_class; i++)
			ptr[i] = model->label[i];
	}
	else
		rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL);
	out_id++;

	// probA
	if(model->probA != NULL)
	{
		rhs[out_id] = mxCreateDoubleMatrix(n, 1, mxREAL);
		ptr = mxGetPr(rhs[out_id]);
		for(i = 0; i < n; i++)
			ptr[i] = model->probA[i];
	}
	else
		rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL);
	out_id ++;

	// probB
	if(model->probB != NULL)
	{
		rhs[out_id] = mxCreateDoubleMatrix(n, 1, mxREAL);
		ptr = mxGetPr(rhs[out_id]);
		for(i = 0; i < n; i++)
			ptr[i] = model->probB[i];
	}
	else
		rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL);
	out_id++;

	// nSV
	if(model->nSV)
	{
		rhs[out_id] = mxCreateDoubleMatrix(model->nr_class, 1, mxREAL);
		ptr = mxGetPr(rhs[out_id]);
		for(i = 0; i < model->nr_class; i++)
			ptr[i] = model->nSV[i];
	}
	else
		rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL);
	out_id++;

	// sv_coef
	rhs[out_id] = mxCreateDoubleMatrix(model->l, model->nr_class-1, mxREAL);
	ptr = mxGetPr(rhs[out_id]);
	for(i = 0; i < model->nr_class-1; i++)
		for(j = 0; j < model->l; j++)
			ptr[(i*(model->l))+j] = model->sv_coef[i][j];
	out_id++;

	// SVs
	{
		int ir_index, nonzero_element;
		mwIndex *ir, *jc;
		mxArray *pprhs[1], *pplhs[1];	

		if(model->param.kernel_type == PRECOMPUTED)
		{
			nonzero_element = model->l;
			num_of_feature = 1;
		}
		else
		{
			nonzero_element = 0;
			for(i = 0; i < model->l; i++) {
				j = 0;
				while(model->SV[i][j].index != -1) 
				{
					nonzero_element++;
					j++;
				}
			}
		}

		// SV in column, easier accessing
		rhs[out_id] = mxCreateSparse(num_of_feature, model->l, nonzero_element, mxREAL);
		ir = mxGetIr(rhs[out_id]);
		jc = mxGetJc(rhs[out_id]);
		ptr = mxGetPr(rhs[out_id]);
		jc[0] = ir_index = 0;		
		for(i = 0;i < model->l; i++)
		{
			if(model->param.kernel_type == PRECOMPUTED)
			{
				// make a (1 x model->l) matrix
				ir[ir_index] = 0; 
				ptr[ir_index] = model->SV[i][0].value;
				ir_index++;
				jc[i+1] = jc[i] + 1;
			}
			else
			{
				int x_index = 0;
				while (model->SV[i][x_index].index != -1)
				{
					ir[ir_index] = model->SV[i][x_index].index - 1; 
					ptr[ir_index] = model->SV[i][x_index].value;
					ir_index++, x_index++;
				}
				jc[i+1] = jc[i] + x_index;
			}
		}
		// transpose back to SV in row
		pprhs[0] = rhs[out_id];
		if(mexCallMATLAB(1, pplhs, 1, pprhs, "transpose"))
			return "cannot transpose SV matrix";
		rhs[out_id] = pplhs[0];
		out_id++;
	}


	/* Create a struct matrix contains NUM_OF_RETURN_FIELD fields */
	return_model = mxCreateStructMatrix(1, 1, NUM_OF_RETURN_FIELD, field_names);

	/* Fill struct matrix with input arguments */
	for(i = 0; i < NUM_OF_RETURN_FIELD; i++)
		mxSetField(return_model,0,field_names[i],mxDuplicateArray(rhs[i]));
	/* return */
	plhs[0] = return_model;
	mxFree(rhs);

	return NULL;
}
struct svm_model *matlab_matrix_to_model(const mxArray *matlab_struct, const char **msg)
{
	int i, j, n, num_of_fields;
	double *ptr;
	int id = 0;
	struct svm_node *x_space;
	struct svm_model *model;
	mxArray **rhs;

	num_of_fields = mxGetNumberOfFields(matlab_struct);
	if(num_of_fields != NUM_OF_RETURN_FIELD) 
	{
		*msg = "number of return field is not correct";
		return NULL;
	}
	rhs = (mxArray **) mxMalloc(sizeof(mxArray *)*num_of_fields);

	for(i=0;i<num_of_fields;i++)
		rhs[i] = mxGetFieldByNumber(matlab_struct, 0, i);

	model = Malloc(struct svm_model, 1);
	model->rho = NULL;
	model->obj = NULL;
	model->probA = NULL;
	model->probB = NULL;
	model->label = NULL;
	model->nSV = NULL;
	model->free_sv = 1; // XXX

	ptr = mxGetPr(rhs[id]);
	model->param.svm_type = (int)ptr[0];
	model->param.kernel_type  = (int)ptr[1];
	model->param.degree	  = (int)ptr[2];
	model->param.gamma	  = ptr[3];
	model->param.coef0	  = ptr[4];
	id++;

	ptr = mxGetPr(rhs[id]);
	model->nr_class = (int)ptr[0];
	id++;

	ptr = mxGetPr(rhs[id]);
	model->l = (int)ptr[0];
	id++;

	// rho
	n = model->nr_class * (model->nr_class-1)/2;
	model->rho = (double*) malloc(n*sizeof(double));
	ptr = mxGetPr(rhs[id]);
	for(i=0;i<n;i++)
		model->rho[i] = ptr[i];
	id++;

	// obj
	n = model->nr_class * (model->nr_class-1)/2;
	model->obj = (double*) malloc(n*sizeof(double));
	ptr = mxGetPr(rhs[id]);
	for(i=0;i<n;i++)
		model->obj[i] = ptr[i];
	id++;

	//radius
	ptr = mxGetPr(rhs[id]);
	model->radius = (double)ptr[0];
	id++;
	

	// label
	if(mxIsEmpty(rhs[id]) == 0)
	{
		model->label = (int*) malloc(model->nr_class*sizeof(int));
		ptr = mxGetPr(rhs[id]);
		for(i=0;i<model->nr_class;i++)
			model->label[i] = (int)ptr[i];
	}
	id++;

	// probA
	if(mxIsEmpty(rhs[id]) == 0)
	{
		model->probA = (double*) malloc(n*sizeof(double));
		ptr = mxGetPr(rhs[id]);
		for(i=0;i<n;i++)
			model->probA[i] = ptr[i];
	}
	id++;

	// probB
	if(mxIsEmpty(rhs[id]) == 0)
	{
		model->probB = (double*) malloc(n*sizeof(double));
		ptr = mxGetPr(rhs[id]);
		for(i=0;i<n;i++)
			model->probB[i] = ptr[i];
	}
	id++;

	// nSV
	if(mxIsEmpty(rhs[id]) == 0)
	{
		model->nSV = (int*) malloc(model->nr_class*sizeof(int));
		ptr = mxGetPr(rhs[id]);
		for(i=0;i<model->nr_class;i++)
			model->nSV[i] = (int)ptr[i];
	}
	id++;

	// sv_coef
	ptr = mxGetPr(rhs[id]);
	model->sv_coef = (double**) malloc((model->nr_class-1)*sizeof(double));
	for( i=0 ; i< model->nr_class -1 ; i++ )
		model->sv_coef[i] = (double*) malloc((model->l)*sizeof(double));
	for(i = 0; i < model->nr_class - 1; i++)
		for(j = 0; j < model->l; j++)
			model->sv_coef[i][j] = ptr[i*(model->l)+j];
	id++;

	// SV
	{
		int sr, sc, elements;
		int num_samples;
		mwIndex *ir, *jc;
		mxArray *pprhs[1], *pplhs[1];

		// transpose SV
		pprhs[0] = rhs[id];
		if(mexCallMATLAB(1, pplhs, 1, pprhs, "transpose")) 
		{
			svm_free_and_destroy_model(&model);
			*msg = "cannot transpose SV matrix";
			return NULL;
		}
		rhs[id] = pplhs[0];

		sr = (int)mxGetN(rhs[id]);
		sc = (int)mxGetM(rhs[id]);

		ptr = mxGetPr(rhs[id]);
		ir = mxGetIr(rhs[id]);
		jc = mxGetJc(rhs[id]);

		num_samples = (int)mxGetNzmax(rhs[id]);

		elements = num_samples + sr;

		model->SV = (struct svm_node **) malloc(sr * sizeof(struct svm_node *));
		x_space = (struct svm_node *)malloc(elements * sizeof(struct svm_node));

		// SV is in column
		for(i=0;i<sr;i++)
		{
			int low = (int)jc[i], high = (int)jc[i+1];
			int x_index = 0;
			model->SV[i] = &x_space[low+i];
			for(j=low;j<high;j++)
			{
				model->SV[i][x_index].index = (int)ir[j] + 1; 
				model->SV[i][x_index].value = ptr[j];
				x_index++;
			}
			model->SV[i][x_index].index = -1;
		}

		id++;
	}
	
	mxFree(rhs);

	return model;
}
Exemple #14
0
SparseMatrix::SparseMatrix (const mxArray* ptr, bool iscomplex, 
			    bool useconjtrans) 
  : iscomplex(iscomplex), ia(0), ja(0), ar(0), ac(0) {
  double* pr = mxGetPr(ptr);
  double* pi = mxGetPi(ptr);

  // Get the height and width of the sparse matrix, the number of
  // nonzeros, and the values of the nonzero entries.
  n   = mxGetM(ptr);
  nnz = mxGetNzmax(ptr);

  // Allocate memory for the nonzero entries, then initialize the
  // complex entries to zero.
  if (!iscomplex)
    ar = new double[nnz];
  else {
    ac = new complex[nnz];
    for (int i = 0; i < nnz; i++) {
      ac[i].re = 0;
      ac[i].im = 0;
    }
  }

  // Copy the values of the nonzero entries.
  if (!mxIsComplex(ptr)) {

    // Copy the real matrix entries.
    if (!iscomplex)
      copymemory<double>(pr,ar,nnz);
    else
      for (int i = 0; i < nnz; i++)
	ac[i].re = pr[i];
  } else {
    if (iscomplex) {

      // Copy the real matrix entries.
      for (int i = 0; i < nnz; i++)
	ac[i].re = pr[i];

      // Copy the complex matrix entries. Note that sometimes we take
      // the complex conjugate of each entry.
      if (useconjtrans)
	for (int i = 0; i < nnz; i++)
	  ac[i].im = -pi[i];
      else
	for (int i = 0; i < nnz; i++)
	  ac[i].im = pi[i];
    } else
      mexErrMsgTxt("PARDISO was initialized to handle real matrices, but \
you provided a sparse matrix with complex entries");
  }

  // Copy the row and column indices of the nonzero entries,
  // converting the matrix from 0-based C++ notation to Fortran
  // 1-based notation. Note that in the process of doing this, we
  // transpose the matrix.
  mwIndex* jc = mxGetJc(ptr);
  mwIndex* ir = mxGetIr(ptr);
  ia          = new int[n+1];
  ja          = new int[nnz];
  for (int i = 0; i < n + 1; i++)
    ia[i] = (int) jc[i] + 1;
  for (int i = 0; i < nnz; i++)
    ja[i] = (int) ir[i] + 1;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs,
                 const mxArray *prhs[])
{
  double *srwp, *srdp, *probs, *Z, *X, *WS, *DS, *ZIN, *XIN;
  double ALPHA, BETA0, BETA1, BETA2, GAMMA1, GAMMA0, GAMMA2;
  int *irwp, *jcwp, *irdp, *jcdp;
  int *z,*d,*w, *x, *xcounts0, *xcounts1, *xcounts2, *order, *wp, *dp, *sumdp, *ztot;
  int W,T,T2,D,NN,SEED,OUTPUT, nzmax, nzmaxwp, nzmaxdp, ntokens;
  int i,j,c,n,nt,wi,di, startcond;
  
  /* Check for proper number of arguments. */
  if (nrhs < 13) {
    mexErrMsgTxt("At least 13 input arguments required");
  } else if (nlhs < 4) {
    mexErrMsgTxt("4 output arguments required");
  }
  
  startcond = 0;
  if (nrhs >= 14) startcond = 1;
  
  /* process the input arguments */
  if (mxIsDouble( prhs[ 0 ] ) != 1) mexErrMsgTxt("WS input vector must be a double precision matrix");
  if (mxIsDouble( prhs[ 1 ] ) != 1) mexErrMsgTxt("DS input vector must be a double precision matrix");
  
  // pointer to word indices
  WS = mxGetPr( prhs[ 0 ] );
     
  // pointer to document indices
  DS = mxGetPr( prhs[ 1 ] );
  
  // get the number of tokens
  ntokens = mxGetM( prhs[ 0 ] ) * mxGetN( prhs[ 0 ] );
  
  
  if (ntokens == 0) mexErrMsgTxt("WS vector is empty"); 
  if (ntokens != ( mxGetM( prhs[ 1 ] ) * mxGetN( prhs[ 1 ] ))) mexErrMsgTxt("WS and DS vectors should have same number of entries");
  
  T    = (int) mxGetScalar(prhs[2]);
  if (T<=0) mexErrMsgTxt("Number of topics must be greater than zero");
  
  NN    = (int) mxGetScalar(prhs[3]);
  if (NN<0) mexErrMsgTxt("Number of iterations must be positive");
  
  ALPHA = (double) mxGetScalar(prhs[4]);
  if (ALPHA<=0) mexErrMsgTxt("ALPHA0 must be greater than zero");

  BETA0 = (double) mxGetScalar(prhs[5]);
  if (BETA0<=0) mexErrMsgTxt("BETA0 must be greater than zero");

  BETA1 = (double) mxGetScalar(prhs[6]);
  if (BETA1<=0) mexErrMsgTxt("BETA1 must be greater than zero");

  BETA2 = (double) mxGetScalar(prhs[7]);
  if (BETA2<=0) mexErrMsgTxt("BETA2 must be greater than zero");

  GAMMA0 = (double) mxGetScalar(prhs[8]);
  if (GAMMA0<=0) mexErrMsgTxt("GAMMA0 must be greater than zero");

  GAMMA1 = (double) mxGetScalar(prhs[9]);
  if (GAMMA1<=0) mexErrMsgTxt("GAMMA1 must be greater than zero");

  GAMMA2 = (double) mxGetScalar(prhs[10]);
  if (GAMMA2<=0) mexErrMsgTxt("GAMMA2 must be greater than zero");
  
  SEED = (int) mxGetScalar(prhs[11]);
  
  OUTPUT = (int) mxGetScalar(prhs[12]);
  
  if (startcond == 1) {
      ZIN = mxGetPr( prhs[ 13 ] );
      if (ntokens != ( mxGetM( prhs[ 13 ] ) * mxGetN( prhs[ 13 ] ))) mexErrMsgTxt("WS and ZIN vectors should have same number of entries");
      
      XIN = mxGetPr( prhs[ 14 ] );
      if (ntokens != ( mxGetM( prhs[ 14 ] ) * mxGetN( prhs[ 14 ] ))) mexErrMsgTxt("WS and XIN vectors should have same number of entries");
  }
  
  // seeding
  seedMT( 1 + SEED * 2 ); // seeding only works on uneven numbers
  
   
  
  /* allocate memory */
  z  = (int *) mxCalloc( ntokens , sizeof( int ));
  x  = (int *) mxCalloc( ntokens , sizeof( int ));
  
  if (startcond == 1) {
     for (i=0; i<ntokens; i++) z[ i ] = (int) ZIN[ i ] - 1;
     for (i=0; i<ntokens; i++) x[ i ] = (int) XIN[ i ]; // 0 = normal topic assignment 1 = special document topic 2 = background distribution
  }
  
  d  = (int *) mxCalloc( ntokens , sizeof( int ));
  w  = (int *) mxCalloc( ntokens , sizeof( int ));
  order  = (int *) mxCalloc( ntokens , sizeof( int ));  
  
  
  // copy over the word and document indices into internal format
  for (i=0; i<ntokens; i++) {
     w[ i ] = (int) WS[ i ] - 1;
     d[ i ] = (int) DS[ i ] - 1;
  }
  
  n = ntokens;
  
  W = 0;
  D = 0;
  for (i=0; i<n; i++) {
     if (w[ i ] > W) W = w[ i ];
     if (d[ i ] > D) D = d[ i ];
  }
  W = W + 1;
  D = D + 1;
  
  // NOTE: the wp matrix has T+D+1 topics for T regular topics, D special word topics and 1 background distribution
  T2 = T + D + 1;
  wp  = (int *) mxCalloc( T2*W , sizeof( int ));
  
  // NOTE: the last two topic probabilities are for the special word topic and background topic
  dp  = (int *) mxCalloc( (T+2)*D , sizeof( int ));
  
  sumdp  = (int *) mxCalloc( D , sizeof( int ));
  
  ztot  = (int *) mxCalloc( T2 , sizeof( int ));
  probs  = (double *) mxCalloc( T+2 , sizeof( double ));
  xcounts0 = (int *) mxCalloc( D , sizeof( int ));
  xcounts1 = (int *) mxCalloc( D , sizeof( int ));
  xcounts2 = (int *) mxCalloc( D , sizeof( int ));
  
  //mexPrintf( "N=%d  T=%d W=%d D=%d\n" , ntokens , T , W , D );
  
  if (OUTPUT==2) {
      mexPrintf( "Running SWB LDA Gibbs Sampler\n" );
      if (startcond==1) mexPrintf( "Starting from previous state ZIN\n" );
      mexPrintf( "Arguments:\n" );
      mexPrintf( "\tNumber of words      W = %d\n"    , W );
      mexPrintf( "\tNumber of docs       D = %d\n"    , D );
      mexPrintf( "\tNumber of topics     T = %d\n"    , T );
      mexPrintf( "\tNumber of iterations N = %d\n"    , NN );
      mexPrintf( "\tHyperparameter   ALPHA = %4.4f\n" , ALPHA );
      mexPrintf( "\tHyperparameter   BETA0 = %4.4f\n" , BETA0 );
      mexPrintf( "\tHyperparameter   BETA1 = %4.4f\n" , BETA1 );
      mexPrintf( "\tHyperparameter   BETA2 = %4.4f\n" , BETA2 );
      mexPrintf( "\tHyperparameter  GAMMA0 = %4.4f\n" , GAMMA0 );
      mexPrintf( "\tHyperparameter  GAMMA1 = %4.4f\n" , GAMMA1 );
      mexPrintf( "\tHyperparameter  GAMMA2 = %4.4f\n" , GAMMA2 );
      mexPrintf( "\tSeed number            = %d\n"    , SEED );
      mexPrintf( "\tNumber of tokens       = %d\n"    , ntokens );
  }
  
  /* run the model */
  GibbsSampler( ALPHA, BETA0 , BETA1, BETA2, GAMMA0, GAMMA1, GAMMA2, 
                W, T, D, NN, OUTPUT, n, z, x, d, w, wp, dp, sumdp, ztot, 
                xcounts0, xcounts1, xcounts2, order, probs, startcond );
  
  /* convert the full wp matrix into a sparse matrix */
  nzmaxwp = 0;
  for (i=0; i<W; i++) {
     for (j=0; j<T2; j++)
         nzmaxwp += (int) ( *( wp + j + i*T2 )) > 0;
  }  
  /*if (OUTPUT==2) {
      mexPrintf( "Constructing sparse output matrix wp\n" );
      mexPrintf( "Number of nonzero entries for WP = %d\n" , nzmaxwp );
  }*/
  
  // MAKE THE WP SPARSE MATRIX
  plhs[0] = mxCreateSparse( W,T2,nzmaxwp,mxREAL);
  srwp  = mxGetPr(plhs[0]);
  irwp = mxGetIr(plhs[0]);
  jcwp = mxGetJc(plhs[0]);  
  n = 0;
  for (j=0; j<T2; j++) {
      *( jcwp + j ) = n;
      for (i=0; i<W; i++) {
         c = (int) *( wp + i*T2 + j );
         if (c >0) {
             *( srwp + n ) = c;
             *( irwp + n ) = i;
             n++;
         }
      }    
  }  
  *( jcwp + T2 ) = n;    
   
  // MAKE THE DP SPARSE MATRIX
  nzmaxdp = 0;
  for (i=0; i<D; i++) {
      for (j=0; j<(T+2); j++)
          nzmaxdp += (int) ( *( dp + j + i*(T+2) )) > 0;
  }  
  /*if (OUTPUT==2) {
      mexPrintf( "Constructing sparse output matrix dp\n" );
      mexPrintf( "Number of nonzero entries for DP = %d\n" , nzmaxdp );
  } */ 
  plhs[1] = mxCreateSparse( D,T+2,nzmaxdp,mxREAL);
  srdp  = mxGetPr(plhs[1]);
  irdp = mxGetIr(plhs[1]);
  jcdp = mxGetJc(plhs[1]);
  n = 0;
  for (j=0; j<T+2; j++) {
      *( jcdp + j ) = n;
      for (i=0; i<D; i++) {
          c = (int) *( dp + i*(T+2) + j );
          if (c >0) {
              *( srdp + n ) = c;
              *( irdp + n ) = i;
              n++;
          }
      }
  }
  *( jcdp + (T+2) ) = n;
  
  plhs[ 2 ] = mxCreateDoubleMatrix( 1,ntokens , mxREAL );
  Z = mxGetPr( plhs[ 2 ] );
  for (i=0; i<ntokens; i++) Z[ i ] = (double) z[ i ] + 1;
  
  plhs[ 3 ] = mxCreateDoubleMatrix( 1,ntokens , mxREAL );
  X = mxGetPr( plhs[ 3 ] );
  for (i=0; i<ntokens; i++) X[ i ] = (double) x[ i ];
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    mwSize *ir, *jc, *ir_out, *jc_out;
    int nnz=0, M, N, D, i, j, 
            row, column;
    double *U, *V, *out, *data;
    mxArray *Ut, *Vt, *RHS[1], *LHS[1];
    
    if (nrhs != 3) 
        mexErrMsgTxt("Input error: Expected sparse mask, U, V, 1 output");
    if (!mxIsSparse(prhs[0]))
        mexErrMsgTxt("Error: Mask must be sparse\n");
    if (mxIsSparse(prhs[1]) || mxIsSparse(prhs[2]))
        mexErrMsgTxt("Error: sparse U or V is not implemented yet");
    
    /* load input */
    ir = mxGetIr(prhs[0]);
    jc = mxGetJc(prhs[0]);
    M = mxGetM(prhs[0]);
    N = mxGetN(prhs[0]);
    nnz = jc[N];
    
    if (mxGetM(prhs[1]) == M && mxGetM(prhs[2]) == N) {
        /* transpose U and V for faster memory access */
        RHS[0] = prhs[1];
        mexCallMATLAB(1, LHS, 1, RHS, "transpose");
        Ut = LHS[0];
        RHS[0] = prhs[2];
        mexCallMATLAB(1, LHS, 1, RHS, "transpose");
        Vt = LHS[0];
        U = mxGetData(Ut);
        V = mxGetData(Vt);
        
        D = mxGetN(prhs[1]);
    } else if (mxGetN(prhs[1])==M && mxGetN(prhs[2])==N) {
        D = mxGetM(prhs[1]);
        U = mxGetPr(prhs[1]);
        V = mxGetPr(prhs[2]);
    } else 
        mexErrMsgTxt("Error: Matrix sizes are incorrect");
    
    /* open output */
    
    plhs[0] = mxCreateSparse(M, N, nnz, 0);
    out = mxGetPr(plhs[0]);
    
    ir_out = mxGetIr(plhs[0]);
    jc_out = mxGetJc(plhs[0]);
    
    column=0;
    jc_out[0] = jc[0]; 
    for (i=0; i<nnz; i++) {
        row = ir[i];
        ir_out[i] = ir[i];        
        
        while (i>=jc[column+1]) {
            column++;
        }
        
        /* printf("Nonzero at %d, %d\n", row,column); */
        
        out[i] = 0;
        for (j=0; j<D; j++) {
            out[i] += U[D*row+j]*V[D*column+j];
        }
        if (out[i]>1e128)
            out[i] = 1e128;
    }
    
    for (i=0; i<N; i++) {
        jc_out[i] = jc[i];
    }
    jc_out[N] = nnz;

}
inline void callFunction(mxArray* plhs[], const mxArray*prhs[]) {
   
   if (!mexCheckType<T>(prhs[0])) 
      mexErrMsgTxt("type of argument 1 is not consistent");
   if (mxIsSparse(prhs[0])) 
      mexErrMsgTxt("argument 1 should be full");
   if (!mexCheckType<T>(prhs[1])) 
      mexErrMsgTxt("type of argument 2 is not consistent");
   if (mxIsSparse(prhs[1])) mexErrMsgTxt("argument 2 should be full");
   if (mxIsSparse(prhs[2])) mexErrMsgTxt("argument 3 should be full");
   if (!mexCheckType<long>(prhs[2])) 
      mexErrMsgTxt("type of argument 3 is not consistent");

   if (!mxIsStruct(prhs[3])) 
      mexErrMsgTxt("argument 4 should be struct");
      
   T* prX=reinterpret_cast<T*>(mxGetPr(prhs[0]));
   const mwSize* dims=mxGetDimensions(prhs[0]);
   long n=static_cast<long>(dims[0]);
   long M=static_cast<long>(dims[1]);

   T * prD = reinterpret_cast<T*>(mxGetPr(prhs[1]));
   const mwSize* dimsD=mxGetDimensions(prhs[1]);
   long nD=static_cast<long>(dimsD[0]);
   if (nD != n) mexErrMsgTxt("wrong size for argument 2");
   long K=static_cast<long>(dimsD[1]);

   const mwSize* dimsList = mxGetDimensions(prhs[2]);
   long Ng = static_cast<long>(dimsList[0]*dimsList[1]);
   long* list_groups=reinterpret_cast<long*>(mxGetPr(prhs[2]));

   long L= getScalarStruct<long>(prhs[3],"L");
   T eps= getScalarStructDef<T>(prhs[3],"eps",0);
   long numThreads = getScalarStructDef<long>(prhs[3],"numThreads",-1);

   Matrix<T> D(prD,n,K);
   Matrix<T>* X = new Matrix<T>[Ng];
   if (list_groups[0] != 0)
      mexErrMsgTxt("First group index should be zero");
   for (long i = 0; i<Ng-1; ++i) {
      if (list_groups[i] >= M) 
         mexErrMsgTxt("Size of groups is not consistent");
      if (list_groups[i] >= list_groups[i+1]) 
         mexErrMsgTxt("Group indices should be a strictly non-decreasing sequence");
      X[i].setData(prX+list_groups[i]*n,n,list_groups[i+1]-list_groups[i]);
   }
   X[Ng-1].setData(prX+list_groups[Ng-1]*n,n,M-list_groups[Ng-1]);
   SpMatrix<T>* spAlpha = new SpMatrix<T>[Ng];

   somp(X,D,spAlpha,Ng,L,eps,numThreads);

   long nzmax=0;
   for (long i = 0; i<Ng; ++i) {
      nzmax += spAlpha[i].nzmax();
   }
   plhs[0]=mxCreateSparse(K,M,nzmax,mxREAL);
   double* Pr = mxGetPr(plhs[0]);
   mwSize* Ir = mxGetIr(plhs[0]);
   mwSize* Jc = mxGetJc(plhs[0]);
   long count=0;
   long countcol=0;
   long offset=0;
   for (long i = 0; i<Ng; ++i) {
      const T* v = spAlpha[i].v();
      const long* r = spAlpha[i].r();
      const long* pB = spAlpha[i].pB();
      long nn = spAlpha[i].n();
      nzmax = spAlpha[i].nzmax();
      if (nn != 0) {
         for (long j = 0; j<pB[nn]; ++j) {
            Pr[count]=static_cast<double>(v[j]);
            Ir[count++]=static_cast<mwSize>(r[j]);
         }
         for (long j = 0; j<=nn; ++j) 
            Jc[countcol++]=static_cast<mwSize>(offset+pB[j]);
         --countcol;
         offset = Jc[countcol];
      }
   }

   delete[](X);
   delete[](spAlpha);
}
/**
 *  @brief Y = predict_fastnb(model, X) performs predictions using a multinomial Naive Bayes classifier
 *  @param model A model generated using train_fastnb
 *  @param X MxN Matrix of observations, where columns are observations (ie. X is transposed!)
 *  @return Y NxK Matrix of log probabilities, where K is the number of labels in the model
 *  @note This method is about 100x faster than Matlab's NaiveBayes.predict
 *  @see train_fastnb
 */
void mexFunction( int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[] )
{
    //  check inputs
    if(nrhs != 2)
    {
        mexErrMsgIdAndTxt("predict_fastnb:invalidNumInputs",
                          "Two inputs required.");
    }
    else if (nlhs != 1)
    {
        mexErrMsgIdAndTxt("predict_fastnb:invalidNumOutputs",
                          "One output required.");
    }
    else if(!mxIsStruct(prhs[0]))
    {
        mexErrMsgIdAndTxt("predict_fastnb:inputNotStruct",
                          "First input must be struct.");
    }
    else if (!mxIsDouble(prhs[1]) || !mxIsSparse(prhs[1]))
    {
        mexErrMsgIdAndTxt("predict_fastnb:inputNotSparse",
                          "Second input must be sparse double!");
    }
    
    const mxArray * model = prhs[0];
    const mxArray * X = prhs[1];    //  this input should be transposed!
    
    const mxArray * featureProbs = mxGetField(model, 0, "feature_prob");
    const mxArray * classProbs = mxGetField(model, 0, "class_prob");
    const mxArray * classes = mxGetField(model, 0, "classes");
    if (!featureProbs || !classProbs || !classes) {
        mexErrMsgIdAndTxt("predict_fast_nb:missingField", "One or more fields is missing from the model!");
    }
    
    //  TODO: Check data types and sizes here!
    float * wp = static_cast<float*>( mxGetData(featureProbs) );
    float * cp = static_cast<float*>( mxGetData(classProbs) );
    
    const mwSize M = mxGetM(X);
    const mwSize N = mxGetN(X);
    
    //  check dimensions
    if (M == 0 || N == 0) {
        mexErrMsgIdAndTxt("predict_fastnb:invalidInputDimensions", "X must have non-zero dimensions");
    }
    
    if (mxGetN(featureProbs) != M) {
        mexErrMsgIdAndTxt("predict_fastnb:invalidInputDimensions",
                          "X does not have the same number of features as the model. Did you remember to transpose X?");
    }
    
    //  feature space data
    const mwIndex * xIR = mxGetIr(X);
    const mwIndex * xJC = mxGetJc(X);
    const double * xVals = mxGetPr(X);
    
    //  label data
    const mwSize K = mxGetN(classes);
    
    //  output is N x K, with probabilities of each class
    mxArray * yProbs = mxCreateNumericMatrix(N,K, mxDOUBLE_CLASS, mxREAL);
    mxSetM(yProbs, N);
    mxSetN(yProbs, K);
    double * yp = static_cast<double *>( mxMalloc(N * K * sizeof(double)) );
    mxSetData(yProbs, yp);
    
    //  iterate over observations, which are in columns now
    for (mwIndex n=0; n < N; n++)
    {
        mwIndex rowStart = xJC[n];
        mwIndex rowEnd = xJC[n+1];
        
        if (rowStart == rowEnd) {
            //  observation with no features - predict class probabilies
            for (mwIndex k=0; k < K; k++)
            {
                yp[k*N + n] = static_cast<double>(cp[k]);
            }
            continue;
        }
        rowEnd--;
        
        std::vector<double> log_prob_n_given_k(K, 0.0);     //  log probability of seeing observation n, given class k
        std::vector<double> log_prob_n_and_k(K, 0.0);
        
        //  iterate over features, which are in rows now
        for (mwIndex i=rowStart; i <= rowEnd; i++)
        {
            const mwIndex m = xIR[i];               //   m is index of feature
            const double word_count = xVals[i];     //   number of times word appears
            
            //  get probability of word for each class
            for (mwIndex k=0; k < K; k++)
            {
                double log_p_word = static_cast<double>(wp[m*K + k]);       //  P(word)
                log_p_word *= word_count;                                   //  P(word)^count
                log_prob_n_given_k[k] += log_p_word;                        //  P(word1)^count1 * P(word2)^count2 * ...
            }
        }
        
        //  calculate probability of observation itself using handy formula
        for (mwIndex k=0; k < K; k++) {
            log_prob_n_and_k[k] = cp[k] + log_prob_n_given_k[k];    //  log(P(c) * P(n|c))
        }
        
        double sum=0.0f;
        for (mwIndex k=1; k < K; k++) {
            sum += exp(log_prob_n_and_k[k] - log_prob_n_and_k[0]);
        }
        sum = log_prob_n_and_k[0] + log(1.0f + sum);
        
        //  calculate class probabilities
        for (mwIndex k=0; k < K; k++) {
            yp[k*N + n] = exp( static_cast<double>( cp[k] ) + log_prob_n_given_k[k] - sum );
        }
    }
    
    //  done
    plhs[0] = yProbs;
}
void mexFunction(int nlhs, mxArray *plhs[],
		 int nrhs, const mxArray *prhs[]) {
  
  mwSize sizeWm,sizeWn;
  mxArray * v;
  mwSize nzmax;
  mwIndex *ir, *jc, *irs, *jcs;
  double *weights,*sr;
  double * p;
  mwIndex currentEntryIndex,currentColumnIndex,numColumnEntries;
  mwIndex i;
             
  // Test number of parameters.
  if (nrhs != 2 || nlhs != 1) {
    mexWarnMsgTxt("Usage: K = computePower(W,p)");
    return;
  }
  
  // Parse parameters
  if (!mxIsSparse(prhs[0])) {
    mexWarnMsgTxt("Error: Expects sparse matrix W.");
    return;
  }
  sizeWm=mxGetM(prhs[0]);
  sizeWn=mxGetN(prhs[0]);
    
  nzmax = mxGetNzmax(prhs[0]); // number of nonzero elements of sparse matrix
  ir = mxGetIr(prhs[0]);
  jc = mxGetJc(prhs[0]);
  weights = mxGetPr(prhs[0]);
    
  p = mxGetPr(prhs[1]);
  // Allocate memory for output (sparse real matrix)
  v = mxCreateSparse(sizeWm, sizeWn, nzmax, mxREAL);
  sr = mxGetPr(v);
  irs = mxGetIr(v);
  jcs = mxGetJc(v);
  
  
  currentEntryIndex=0;
  currentColumnIndex=0;
  numColumnEntries=0;
  
  jcs[0]=0;
 
  
  #pragma omp parallel for schedule(static)
  for (i=0;i<nzmax;i++)
  {
      if (i<sizeWn+1)
          jcs[i]=jc[i];
      irs[i]=ir[i];
      sr[i]=pow(fabs(weights[i]),*p);
  }
  
  // if we have less than sizeWn entries
  if (nzmax < sizeWn+1)
  {
      for (i=nzmax;i<sizeWn+1;i++)
          jcs[i]=jc[i];
  }
      
  
   plhs[0]=v; 
 }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{
	double *mu, *MUIN, *phi, *theta, *sr;
	double ALPHA, BETA;
	mwIndex *ir, *jc;
	int W, J, D, NN, SEED, OUTPUT, nzmax, i, j, wi, di, startcond;

	/* Check for proper number of arguments. */
	if (nrhs < 7) {
		mexErrMsgTxt("At least 7 input arguments required");
	} else if (nlhs < 2) {
		mexErrMsgTxt("At least 2 output arguments required");
	}

	startcond = 0;
	if (nrhs == 8) startcond = 1;

	/* dealing with sparse array WD */
	if (mxIsDouble(prhs[0]) != 1) mexErrMsgTxt("WD must be a double precision matrix");
	sr = mxGetPr(prhs[0]);
	ir = mxGetIr(prhs[0]);
	jc = mxGetJc(prhs[0]);
	nzmax = (int) mxGetNzmax(prhs[0]);
	W = (int) mxGetM(prhs[0]);
	D = (int) mxGetN(prhs[0]);

	J = (int) mxGetScalar(prhs[1]);
	if (J<=0) mexErrMsgTxt("Number of topics must be greater than zero");

	NN = (int) mxGetScalar(prhs[2]);
	if (NN<0) mexErrMsgTxt("Number of iterations must be positive");

	ALPHA = (double) mxGetScalar(prhs[3]);
	if (ALPHA<0) mexErrMsgTxt("ALPHA must be greater than zero");

	BETA = (double) mxGetScalar(prhs[4]);
	if (BETA<0) mexErrMsgTxt("BETA must be greater than zero");

	SEED = (int) mxGetScalar(prhs[5]);

	OUTPUT = (int) mxGetScalar(prhs[6]);

	if (startcond == 1) {
		MUIN = mxGetPr(prhs[7]);
		if (nzmax != (mxGetN(prhs[7]))) mexErrMsgTxt("WD and MUIN mismatch");
		if (J != (mxGetM(prhs[7]))) mexErrMsgTxt("J and MUIN mismatch");
	}

	/* seeding */
	seedMT(1 + SEED*2); // seeding only works on uneven numbers

	/* allocate memory */
	mu  = dvec(J*nzmax);
	if (startcond == 1) {
		for (i=0; i<J*nzmax; i++) mu[i] = (double) MUIN[i];   
	}

	phi = dvec(J*W);
	theta = dvec(J*D);

	/* run the learning algorithm */
	asiBP(ALPHA, BETA, W, J, D, NN, OUTPUT, sr, ir, jc, phi, theta, mu, startcond);

	/* output */
	plhs[0] = mxCreateDoubleMatrix(J, W, mxREAL);
	mxSetPr(plhs[0], phi);

	plhs[1] = mxCreateDoubleMatrix(J, D, mxREAL );
	mxSetPr(plhs[1], theta);

	plhs[2] = mxCreateDoubleMatrix(J, nzmax, mxREAL );
	mxSetPr(plhs[2], mu);
}
Exemple #21
0
int read_problem_sparse(const mxArray *label_vec, const mxArray *instance_mat)
{
	mwIndex *ir, *jc, low, high, k;
	// using size_t due to the output type of matlab functions
	size_t i, j, l, elements, max_index, label_vector_row_num;
	mwSize num_samples;
	double *samples, *labels;
	mxArray *instance_mat_col; // instance sparse matrix in column format

	prob.x = NULL;
	prob.y = NULL;
	x_space = NULL;

	if(col_format_flag)
		instance_mat_col = (mxArray *)instance_mat;
	else
	{
		// transpose instance matrix
		mxArray *prhs[1], *plhs[1];
		prhs[0] = mxDuplicateArray(instance_mat);
		if(mexCallMATLAB(1, plhs, 1, prhs, "transpose"))
		{
			mexPrintf("Error: cannot transpose training instance matrix\n");
			return -1;
		}
		instance_mat_col = plhs[0];
		mxDestroyArray(prhs[0]);
	}

	// the number of instance
	l = mxGetN(instance_mat_col);
	label_vector_row_num = mxGetM(label_vec);
	prob.l = (int) l;

	if(label_vector_row_num!=l)
	{
		mexPrintf("Length of label vector does not match # of instances.\n");
		return -1;
	}
	
	// each column is one instance
	labels = mxGetPr(label_vec);
	samples = mxGetPr(instance_mat_col);
	ir = mxGetIr(instance_mat_col);
	jc = mxGetJc(instance_mat_col);

	num_samples = mxGetNzmax(instance_mat_col);

	elements = num_samples + l*2;
	max_index = mxGetM(instance_mat_col);

	prob.y = Malloc(double, l);
	prob.x = Malloc(struct feature_node*, l);
	x_space = Malloc(struct feature_node, elements);

	prob.bias=bias;

	j = 0;
	for(i=0;i<l;i++)
	{
		prob.x[i] = &x_space[j];
		prob.y[i] = labels[i];
		low = jc[i], high = jc[i+1];
		for(k=low;k<high;k++)
		{
			x_space[j].index = (int) ir[k]+1;
			x_space[j].value = samples[k];
			j++;
	 	}
		if(prob.bias>=0)
		{
			x_space[j].index = (int) max_index+1;
			x_space[j].value = prob.bias;
			j++;
		}
		x_space[j++].index = -1;
	}

	if(prob.bias>=0)
		prob.n = (int) max_index+1;
	else
		prob.n = (int) max_index;

	return 0;
}
Exemple #22
0
// read in a problem (in svmlight format)
void read_problem(const char *filename, mxArray *plhs[])
{
	int max_index, min_index, inst_max_index, i;
	long elements, k;
	FILE *fp = fopen(filename,"r");
	int l = 0;
	char *endptr;
	mwIndex *ir, *jc;
	double *labels, *samples;
	
	if(fp == NULL)
	{
		mexPrintf("can't open input file %s\n",filename);
		fake_answer(plhs);
		return;
	}

	max_line_len = 1024;
	line = (char *) malloc(max_line_len*sizeof(char));

	max_index = 0;
	min_index = 1; // our index starts from 1
	elements = 0;
	while(readline(fp) != NULL)
	{
		char *idx, *val;
		// features
		int index = 0;

		inst_max_index = -1; // strtol gives 0 if wrong format, and precomputed kernel has <index> start from 0
		strtok(line," \t"); // label
		while (1)
		{
			idx = strtok(NULL,":"); // index:value
			val = strtok(NULL," \t");
			if(val == NULL)
				break;

			errno = 0;
			index = (int) strtol(idx,&endptr,10);
			if(endptr == idx || errno != 0 || *endptr != '\0' || index <= inst_max_index)
			{
				mexPrintf("Wrong input format at line %d\n",l+1);
				fake_answer(plhs);
				return;
			}
			else
				inst_max_index = index;

			min_index = min(min_index, index);
			elements++;
		}
		max_index = max(max_index, inst_max_index);
		l++;
	}
	rewind(fp);

	// y
	plhs[0] = mxCreateDoubleMatrix(l, 1, mxREAL);
	// x^T
	if (min_index <= 0)
		plhs[1] = mxCreateSparse(max_index-min_index+1, l, elements, mxREAL);
	else
		plhs[1] = mxCreateSparse(max_index, l, elements, mxREAL);

	labels = mxGetPr(plhs[0]);
	samples = mxGetPr(plhs[1]);
	ir = mxGetIr(plhs[1]);
	jc = mxGetJc(plhs[1]);

	k=0;
	for(i=0;i<l;i++)
	{
		char *idx, *val, *label;
		jc[i] = k;

		readline(fp);

		label = strtok(line," \t");
		labels[i] = (int)strtol(label,&endptr,10);
		if(endptr == label)
		{
			mexPrintf("Wrong input format at line %d\n",i+1);
			fake_answer(plhs);
			return;
		}

		// features
		while(1)
		{
			idx = strtok(NULL,":");
			val = strtok(NULL," \t");
			if(val == NULL)
				break;

			ir[k] = (mwIndex) (strtol(idx,&endptr,10) - min_index); // precomputed kernel has <index> start from 0

			errno = 0;
			samples[k] = strtod(val,&endptr);
			if (endptr == val || errno != 0 || (*endptr != '\0' && !isspace(*endptr)))
			{
				mexPrintf("Wrong input format at line %d\n",i+1);
				fake_answer(plhs);
				return;
			}
			++k;
		}
	}
	jc[l] = k;

	fclose(fp);
	free(line);

	{
		mxArray *rhs[1], *lhs[1];
		rhs[0] = plhs[1];
		if(mexCallMATLAB(1, lhs, 1, rhs, "transpose"))
		{
			mexPrintf("Error: cannot transpose problem\n");
			fake_answer(plhs);
			return;
		}
		plhs[1] = lhs[0];
	}
}
Exemple #23
0
void mexFunction(
      int nlhs,   mxArray  *plhs[], 
      int nrhs,   const mxArray  *prhs[] )

{    
     mxArray  *rhs[2]; 
     mxArray  *blk_cell_pr, *A_cell_pr;
     double   *A,  *B,  *blksize;
     int      *irA, *jcA, *irB, *jcB;
     int      *cumblksize, *blknnz;
     int      iscellA, mblk, mA, nA, m1, n1, rowidx, colidx, isspA, isspB;

     int   subs[2];
     int   nsubs=2; 
     int   n, n2, k, nsub, index, numblk, NZmax;
     double  ir2=1/sqrt(2); 

/* CHECK FOR PROPER NUMBER OF ARGUMENTS */

     if (nrhs < 2){
         mexErrMsgTxt("mexsmat: requires at least 2 input arguments."); }
     else if (nlhs>1){ 
         mexErrMsgTxt("mexsmat: requires 1 output argument."); }

/* CHECK THE DIMENSIONS */

     iscellA = mxIsCell(prhs[1]); 
     if (iscellA) { mA = mxGetM(prhs[1]); nA = mxGetN(prhs[1]); }
     else         { mA = 1; nA = 1; }
     if (mxGetM(prhs[0]) != mA) {
         mexErrMsgTxt("mexsmat: blk and Avec not compatible"); }

/***** main body *****/ 
       
     if (nrhs > 3) {rowidx = (int)*mxGetPr(prhs[3]); } else {rowidx = 1;}  
     if (rowidx > mA) {
         mexErrMsgTxt("mexsmat: rowidx exceeds size(Avec,1)."); }
     subs[0] = rowidx-1;  /* subtract 1 to adjust for Matlab index */
     subs[1] = 1;
     index = mxCalcSingleSubscript(prhs[0],nsubs,subs); 
     blk_cell_pr = mxGetCell(prhs[0],index);
     if (blk_cell_pr == NULL) { 
        mexErrMsgTxt("mexsmat: blk not properly specified"); }    
     numblk  = mxGetN(blk_cell_pr);            
     blksize = mxGetPr(blk_cell_pr);
     cumblksize = mxCalloc(numblk+1,sizeof(int)); 
     blknnz = mxCalloc(numblk+1,sizeof(int)); 
     cumblksize[0] = 0; blknnz[0] = 0; 
     n = 0;  n2 = 0; 
     for (k=0; k<numblk; ++k) {
          nsub = (int) blksize[k];
          n  += nsub; 
          n2 += nsub*(nsub+1)/2;  
          cumblksize[k+1] = n; 
          blknnz[k+1] = n2;
     }
     /***** assign pointers *****/
     if (iscellA) { 
         subs[0] = rowidx-1; 
         subs[1] = 0;
         index = mxCalcSingleSubscript(prhs[1],nsubs,subs); 
         A_cell_pr = mxGetCell(prhs[1],index); 
         A  = mxGetPr(A_cell_pr); 
         m1 = mxGetM(A_cell_pr); 
         n1 = mxGetN(A_cell_pr);
         isspA = mxIsSparse(A_cell_pr);
         if (isspA) { irA = mxGetIr(A_cell_pr);
                      jcA = mxGetJc(A_cell_pr); } 
     }
     else { 
         A  = mxGetPr(prhs[1]); 
         m1 = mxGetM(prhs[1]); 
         n1 = mxGetN(prhs[1]); 
         isspA = mxIsSparse(prhs[1]); 
         if (isspA) {  irA = mxGetIr(prhs[1]); 
                       jcA = mxGetJc(prhs[1]); }
     }
     if (numblk > 1) 
        { isspB = 1; }
     else { 
        if (nrhs > 2) {isspB = (int)*mxGetPr(prhs[2]);} else {isspB = isspA;} 
     }
     if (nrhs > 4) {colidx = (int)*mxGetPr(prhs[4]) -1;} else {colidx = 0;} 
     if (colidx > n1) { 
         mexErrMsgTxt("mexsmat: colidx exceeds size(Avec,2)."); 
     }    
     /***** create return argument *****/
     if (isspB) {
	 if (isspA) { NZmax = jcA[colidx+1]-jcA[colidx]; } 
         else       { NZmax = blknnz[numblk]; } 
	 rhs[0] = mxCreateSparse(n,n,2*NZmax,mxREAL); 
	 B = mxGetPr(rhs[0]); irB = mxGetIr(rhs[0]); jcB = mxGetJc(rhs[0]);
     }
     else {
         plhs[0] = mxCreateDoubleMatrix(n,n,mxREAL); 
         B = mxGetPr(plhs[0]); 
     }
     /***** Do the computations in a subroutine *****/
     if (numblk == 1) { 
         smat1(n,ir2,A,irA,jcA,isspA,m1,colidx,B,irB,jcB,isspB);  }
     else { 
         smat2(n,numblk,cumblksize,blknnz,ir2,A,irA,jcA,isspA,m1,colidx,B,irB,jcB,isspB);  
     }
     if (isspB) {
        /*** if isspB, (actual B) = B+B' ****/ 
        mexCallMATLAB(1, &rhs[1], 1, &rhs[0], "transpose"); 
        mexCallMATLAB(1, &plhs[0],2, rhs, "+");  
        mxDestroyArray(*rhs); 
     }
     mxFree(blknnz); 
     mxFree(cumblksize);
 return;
 }
Exemple #24
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[])
{

  if(strcmp(glp_version(),"4.36")<0){
	mexErrMsgTxt("This MEX interface is compatible only with GLPK version 4.36 or higher.");
	}

  if (nrhs != 9){
      mexPrintf("MEX interface to GLPK Version %s\n",glp_version());
      mexPrintf("Internal interface for the GNU GLPK library.\n");
      mexPrintf("You should use the 'glpk' function instead.\n\n");
      mexPrintf("SYNTAX: [xopt, fmin, status, extra] = glpk(c, a, b, lb, ub, ctype, vartype, sense, param)\n");
      return;
  }

  //-- 1nd Input. A column array containing the objective function
  //--            coefficients.
  int mrowsc = mxGetM(C_IN);

  double *c=mxGetPr(C_IN);
  if (c == NULL) mexErrMsgTxt("glpk: invalid value of C");


  //-- 2nd Input. A matrix containing the constraints coefficients.
  // If matrix A is NOT a sparse matrix
  double *A = mxGetPr(A_IN); // get the matrix
  if(A==NULL) mexErrMsgTxt("glpk: invalid value of A");

  int mrowsA = mxGetM(A_IN);

  int *rn;
  int *cn;
  double *a;
  int nz = 0;

  if(!mxIsSparse(A_IN)){
     rn=(int *)mxCalloc(mrowsA*mrowsc+1,sizeof(int));
     cn=(int *)mxCalloc(mrowsA*mrowsc+1,sizeof(int));
	   a=(double *)mxCalloc(mrowsA*mrowsc+1,sizeof(double));

     for (int i = 0; i < mrowsA; i++){
      for (int j = 0; j < mrowsc; j++){
	     if (A[i+j*mrowsA] != 0){
	      nz++;
	      rn[nz] = i + 1;
	      cn[nz] = j + 1;
	      a[nz] = A[i+j*mrowsA];
	    }
	   }
     }
  }else{
	  /* NOTE: nnz is the actual number of nonzeros and is stored as the
         last element of the jc array where the size of the jc array is the
         number of columns + 1 */
	  nz = *(mxGetJc(A_IN) + mrowsc);

      mwIndex *jc = mxGetJc(A_IN);
      mwIndex *ir = mxGetIr(A_IN);

      double *pr = mxGetPr(A_IN);

      rn=(int *)mxCalloc(nz+1,sizeof(int));
	  cn=(int *)mxCalloc(nz+1,sizeof(int));
	  a=(double *)mxCalloc(nz+1,sizeof(double));

      int nelc,count,row;
      count=0; row=0;
	    for(int i=1;i<=mrowsc;i++){
	      nelc=jc[i]-jc[i-1];
	      for(int j=0;j<nelc;j++){
		      count++;
		      rn[count]=ir[row]+1;
		      cn[count]=i;
		      a[count]=pr[row];
		      row++;
	      }
	    }
  }

  //-- 3rd Input. A column array containing the right-hand side value
  //	           for each constraint in the constraint matrix.
  double *b = mxGetPr(B_IN);

  if (b==NULL) mexErrMsgTxt("glpk: invalid value of b");


  //-- 4th Input. An array of length mrowsc containing the lower
  //--            bound on each of the variables.
  double *lb = mxGetPr(LB_IN);

  if (lb==NULL) mexErrMsgTxt("glpk: invalid value of lb");


  //-- LB argument, default: Free
  int *freeLB=(int *)mxCalloc(mrowsc,sizeof(int));
  for (int i = 0; i < mrowsc; i++) {
    if (lb[i]==-mxGetInf()){
      freeLB[i] = 1;
	 	}else freeLB[i] = 0;
  }

  //-- 5th Input. An array of at least length numcols containing the upper
  //--            bound on each of the variables.
  double *ub = mxGetPr(UB_IN);

  if (ub==NULL) mexErrMsgTxt("glpk: invalid value of ub");

  int *freeUB=(int *)mxCalloc(mrowsc,sizeof(int));
  for (int i = 0; i < mrowsc; i++)
  {
    if (ub[i]==mxGetInf())
		{
	     freeUB[i] = 1;
	  }else freeUB[i] = 0;
  }

  //-- 6th Input. A column array containing the sense of each constraint
  //--            in the constraint matrix.
  int size = mxGetNumberOfElements(CTYPE_IN) + 1;
  if (size==0) mexErrMsgTxt("glpk: invalid value of ctype");

  /* Allocate enough memory to hold the converted string. */
  char *ctype =(char *)mxCalloc(size, sizeof (char));

  /* Copy the string data from string_array_ptr and place it into buf. */
  if (mxGetString(CTYPE_IN, ctype, size) != 0)  mexErrMsgTxt("Could not convert string data.");


  //-- 7th Input. A column array containing the types of the variables.
  size = mxGetNumberOfElements(VARTYPE_IN)+1;

  char *vtype = (char *)mxCalloc(size, sizeof (char));
  int *vartype = (int *)mxCalloc(size, sizeof (int));

  if (size==0) mexErrMsgTxt("glpk: invalid value of vartype");

  // Copy the string data from string_array_ptr and place it into buf.
  if (mxGetString(VARTYPE_IN, vtype, size) != 0)
	  mexErrMsgTxt("Could not convert string data.");

  int isMIP = 0;
  for (int i = 0; i < mrowsc ; i++)
  {
    switch (vtype[i]){
      case 'I': vartype[i] = GLP_IV; isMIP = 1; break;
      case 'B': vartype[i] = GLP_BV; isMIP = 1; break;
      default: vartype[i] = GLP_CV;
    }
  }

  //-- 8th Input. Sense of optimization.
  int sense;

  double *tmp = mxGetPr(SENSE_IN);

  if (*tmp >= 0) sense = 1;
  else sense = -1;

  //-- 9th Input. A structure containing the control parameters.

  //-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  //-- Integer parameters
  //-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  //-- Level of messages output by the solver
  GLPK_GET_INT_PARAM (PARAM, "msglev", glpIntParam[0]);
  if (glpIntParam[0] < 0 || glpIntParam[0] > 3)
    {
      mexErrMsgTxt("glpk: param.msglev must be 0 (no output [default]) or 1 (error messages only) or 2 (normal output) or 3 (full output)");
    }

  //-- scaling option
  GLPK_GET_INT_PARAM (PARAM, "scale", glpIntParam[1]);
  if (glpIntParam[1] < 0 || glpIntParam[1] > 4)
    {
      mexErrMsgTxt("glpk: param.scale must be 0 (no scaling) or 1 (equilibration scaling [default]) or 2 (geometric mean scaling) or 3 (geometric then equilibration scaling) or 4 (rounds scale factors to nearest power of 2)");
    }

  //-- Dual dimplex option
  GLPK_GET_INT_PARAM (PARAM, "dual", glpIntParam[2]);
  if (glpIntParam[2] < 0 || glpIntParam[2] > 2)
    {
      mexErrMsgTxt("glpk: param.dual must be 0 (do NOT use dual simplex [default]) or 1 (use dual simplex) or 2 (two phase dual simplex, switch to primal simplexi if it fails");
    }

  //-- Pricing option
  GLPK_GET_INT_PARAM (PARAM, "price", glpIntParam[3]);
  if (glpIntParam[3] < 0 || glpIntParam[3] > 1)
    {
      mexErrMsgTxt("glpk: param.price must be 0 (textbook pricing) or 1 (steepest edge pricing [default])");
    }

  //-- Ratio test option
  GLPK_GET_INT_PARAM (PARAM, "r_test", glpIntParam[20]);
  if (glpIntParam[20] < 0 || glpIntParam[20] > 1)
    {
      mexErrMsgTxt("glpk: param.r_test must be 0 (textbook) or 1 (Harris's Two pass ratio test)");
    }

  //-- Solution rounding option
  GLPK_GET_INT_PARAM (PARAM, "round", glpIntParam[4]);
  if (glpIntParam[4] < 0 || glpIntParam[4] > 1)
    {
      mexErrMsgTxt("glpk: param.round must be 0 (report all primal and dual values [default]) or 1 (replace tiny primal and dual values by exact zero)");
    }

  //-- Simplex iterations limit
  GLPK_GET_INT_PARAM (PARAM, "itlim", glpIntParam[5]);

  //-- Simplex iterations count
  GLPK_GET_INT_PARAM (PARAM, "itcnt", glpIntParam[6]);

  //-- Output frequency, in iterations
  GLPK_GET_INT_PARAM (PARAM, "outfrq", glpIntParam[7]);

  //-- Branching heuristic option
  GLPK_GET_INT_PARAM (PARAM, "branch", glpIntParam[14]);
  if (glpIntParam[14] < 0 || glpIntParam[14] > 3)
    {
      mexErrMsgTxt("glpk: param.branch must be (MIP only) 0 (branch on first variable) or 1 (branch on last variable) or 2 (most fractional variable)  or 3 (branch using a heuristic by Driebeck and Tomlin [default]");
    }

  //-- Backtracking heuristic option
  GLPK_GET_INT_PARAM (PARAM, "btrack", glpIntParam[15]);
  if (glpIntParam[15] < 0 || glpIntParam[15] > 3)
    {
      mexErrMsgTxt("glpk: param.btrack must be (MIP only) 0 (depth first search) or 1 (breadth first search) or 2 ( best local bound ) or 3 (backtrack using the best projection heuristic [default]");
    }

  //-- Presolver option
  GLPK_GET_INT_PARAM (PARAM, "presol", glpIntParam[16]);
  if (glpIntParam[16] < 0 || glpIntParam[16] > 1)
    {
      mexErrMsgTxt("glpk: param.presol must be 0 (do NOT use LP presolver) or 1 (use LP presolver [default])");
    }

  //-- Generating cuts
  GLPK_GET_INT_PARAM (PARAM, "usecuts", glpIntParam[17]);
  if (glpIntParam[17] < 0 || glpIntParam[17] > 5)
    {
      mexErrMsgTxt("glpk: param.usecuts must be 0 (do NOT generate cuts), 1 (generate Gomory's cuts [default]), 2 (mir), 3 (cov) or 4 (clq cuts), 5( all cuts)");
    }

 //-- PrePocessing
 GLPK_GET_INT_PARAM (PARAM, "pprocess", glpIntParam[18]);
  if (glpIntParam[18] < 0 || glpIntParam[18] > 2)
    {
      mexErrMsgTxt("glpk: param.pprocess must be 0 (disable preprocessing), 1 (preprocess root only) or 2 (preprocess all levels)");
    }

 //-- Binarize
 GLPK_GET_INT_PARAM (PARAM, "binarize", glpIntParam[19]);
  if (glpIntParam[19] < 0 || glpIntParam[19] > 1)
    {
      mexErrMsgTxt("glpk: param.binarize must be 0 (do use binarization) or 1 (replace general integer variable by binary ones)");
    }

  //-- LPsolver option
  int lpsolver = 1;
  GLPK_GET_INT_PARAM (PARAM, "lpsolver", lpsolver);
  if (lpsolver < 1 || lpsolver > 3)
    {
      mexErrMsgTxt("glpk: param.lpsolver must be 1 (simplex method) or 2 (interior point method) or 3 (LP in exact arithmetic)");
    }

  //-- Save option
  int save_pb = 0;
  char *save_filename = NULL;
  char *filetype = NULL;
  GLPK_GET_INT_PARAM (PARAM, "save", save_pb);
  save_pb = (save_pb != 0);
  if (save_pb){
    // -- Look for the name --
    mxArray *mxtmp=mxGetField(PARAM,0,"savefilename");
    if ( mxtmp != NULL ){
      int nl=mxGetNumberOfElements(mxtmp)+1;
      nl=nl+4; // increase size to consider then extension .xxx
      save_filename=(char *)mxCalloc(nl,sizeof(char));
      if (mxGetString(mxtmp, save_filename, nl) != 0)
        mexErrMsgTxt("glpk: Could not load file name to save.");
    }else{
      // Default file name
      save_filename= (char *)mxCalloc(9, sizeof(char));
      strcpy(save_filename,"outpb");
    }

    // -- Look for the type --
    char save_filetype[5];
    mxArray *txtmp=mxGetField(PARAM,0,"savefiletype");
    if ( txtmp != NULL ){
      int nl=mxGetNumberOfElements(txtmp)+1;
      filetype=(char *)mxCalloc(nl,sizeof(char));
      if (mxGetString(txtmp, filetype, nl) != 0)
        mexErrMsgTxt("glpk: Could not load file type.");
      if (!strcmp(filetype,"fixedmps") || !strcmp(filetype,"freemps")){
        strcpy(save_filetype,".mps");
      } else {
        if (!strcmp(filetype,"cplex")) strcpy(save_filetype,".lp");
        else {
          if (!strcmp(filetype,"plain")) strcpy(save_filetype,".txt");
        }
      }
    }else{
      filetype= (char *)mxCalloc(5, sizeof(char));
      strcpy(filetype,"cplex");
      strcpy(save_filetype,".lp"); // Default file type
    }
    strcat(save_filename,save_filetype); // name.extension
  }

  // MPS parameters
  //-- mpsinfo
  GLPK_GET_INT_PARAM (PARAM, "mpsinfo", glpIntParam[8]);
  //-- mpsobj
  GLPK_GET_INT_PARAM (PARAM, "mpsobj", glpIntParam[9]);
  if (glpIntParam[9] < 0 || glpIntParam[9] > 2)
  {
    mexErrMsgTxt("glpk: param.mpsobj must be 0 (never output objective function row) or 1 (always output objective function row ) or 2 [default](output objective function row if the problem has no free rows)");
  }
  //-- mpsorig
  GLPK_GET_INT_PARAM (PARAM, "mpsorig", glpIntParam[10]);
  //-- mpswide
  GLPK_GET_INT_PARAM (PARAM, "mpswide", glpIntParam[11]);
  //-- mpsfree
  GLPK_GET_INT_PARAM (PARAM, "mpsfree", glpIntParam[12]);



  //-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  //-- Real parameters
  //-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  //-- Ratio test option
  GLPK_GET_REAL_PARAM (PARAM, "relax", 0);

  //-- Relative tolerance used to check if the current basic solution
  //-- is primal feasible
  GLPK_GET_REAL_PARAM (PARAM, "tolbnd", 1);

  //-- Absolute tolerance used to check if the current basic solution
  //-- is dual feasible
  GLPK_GET_REAL_PARAM (PARAM, "toldj", 2);

  //-- Relative tolerance used to choose eligible pivotal elements of
  //--	the simplex table in the ratio test
  GLPK_GET_REAL_PARAM (PARAM, "tolpiv", 3);

  GLPK_GET_REAL_PARAM (PARAM, "objll", 4);

  GLPK_GET_REAL_PARAM (PARAM, "objul", 5);

  GLPK_GET_REAL_PARAM (PARAM, "tmlim", 6);

  GLPK_GET_REAL_PARAM (PARAM, "outdly", 7);

  GLPK_GET_REAL_PARAM (PARAM, "tolint", 8);

  GLPK_GET_REAL_PARAM (PARAM, "tolobj", 9);

  GLPK_GET_REAL_PARAM (PARAM, "mipgap", 10);

  //-- Assign pointers to the output parameters
  const char **extranames=(const char **)mxCalloc(4,sizeof(*extranames));
  extranames[0]="lambda";
  extranames[1]="redcosts";
  extranames[2]="time";
  extranames[3]="memory";

  XMIN_OUT   = mxCreateDoubleMatrix(mrowsc, 1, mxREAL);
  FMIN_OUT   = mxCreateDoubleMatrix(1, 1, mxREAL);
  STATUS_OUT = mxCreateDoubleMatrix(1, 1, mxREAL);

  double *xmin   = mxGetPr(XMIN_OUT);
  double *fmin   = mxGetPr(FMIN_OUT);
  double *status = mxGetPr(STATUS_OUT);

  EXTRA_OUT  = mxCreateStructMatrix(1, 1, 4, extranames);
  mxArray *mxlambda   = mxCreateDoubleMatrix(mrowsA, 1, mxREAL);
  mxArray *mxredcosts = mxCreateDoubleMatrix(mrowsc, 1, mxREAL);
  mxArray *mxtime     = mxCreateDoubleMatrix(1, 1, mxREAL);
  mxArray *mxmem      = mxCreateDoubleMatrix(1, 1, mxREAL);

  double *lambda = mxGetPr(mxlambda);
  double *redcosts= mxGetPr(mxredcosts);
  double *time   = mxGetPr(mxtime);
  double *mem    = mxGetPr(mxmem);

  int jmpret = setjmp (mark);

  if (jmpret == 0)
    glpk (sense, mrowsc, mrowsA, c, nz, rn,
	       cn, a, b, ctype, freeLB, lb, freeUB,
	       ub, vartype, isMIP, lpsolver, save_pb, save_filename, filetype,
	       xmin, fmin, status, lambda,
	       redcosts, time, mem);

  if (! isMIP)
    {
      mxSetField(EXTRA_OUT,0,extranames[0],mxlambda);
      mxSetField(EXTRA_OUT,0,extranames[1],mxredcosts);
    }

  mxSetField(EXTRA_OUT,0,extranames[2],mxtime);
  mxSetField(EXTRA_OUT,0,extranames[3],mxmem);

  mxFree(rn);
  mxFree(cn);
  mxFree(a);
  mxFree(freeLB);
  mxFree(freeUB);
  mxFree(ctype);
  mxFree(vartype);
  mxFree(vtype);
  mxFree(extranames);
  mxFree(save_filename);
  mxFree(filetype);

  return;
}
/*  the gateway routine.  */
void mexFunction( int nlhs, mxArray *plhs[],
        int nrhs, const mxArray *prhs[] )
{
    
    /* create a pointer to the real data in the input matrix  */
    int nfields = mxGetNumberOfFields(prhs[0]); // number of fields in each constraint
    mwSize NStructElems = mxGetNumberOfElements(prhs[0]); // number of constraints
    const char **fnames = (const char **)mxCalloc(nfields, sizeof(*fnames)); /* pointers to field names */
    double *sw = mxGetPr(prhs[1]); /* switch vector */ 
    double *xs = mxGetPr(prhs[2]); /* linearisation point */
    long unsigned int nrow = mxGetM(prhs[2]);
    double *ptr = mxGetPr(prhs[3]); /* number of cameras */
    int ncams = ptr[0];
    
    /* initialise a PwgOptimiser object */
    PwgOptimiser *Object; // pointer initialisation
    Object = new PwgOptimiser (ncams, nrow-6*ncams) ; // pointer initialisation
    
    /* get constraints from Matlab to C++ and initialise a constraint */
    double *pr;
    mxArray *tmp;
    int cam, kpt;
    std::vector<double> p1(2), z(2), R(4,0.0);//, Y(49,0.0), y(7,0.0);
    std::string str1 ("cam");
    std::string str2 ("kpt");
    std::string str3 ("p1");
    std::string str4 ("z");
    std::string str5 ("R");
    std::string str6 ("y");
    std::string str7 ("Y");
    Eigen::MatrixXd yz = Eigen::MatrixXd::Zero(7,1);
    Eigen::VectorXd Yz = Eigen::MatrixXd::Zero(7,7);
    for (mwIndex jstruct = 0; jstruct < NStructElems; jstruct++) { /* loop the constraints */
        for (int ifield = 0; ifield < nfields; ifield++) {  /* loop the fields */
            fnames[ifield] = mxGetFieldNameByNumber(prhs[0],ifield); // get field name
            tmp = mxGetFieldByNumber(prhs[0], jstruct, ifield); // get field
            pr = (double *)mxGetData(tmp); // get the field data pointer
            if (str1.compare(fnames[ifield]) == 0) // cam
                cam = pr[0];
            if (str2.compare(fnames[ifield]) == 0) // kpt
                kpt = pr[0];
            if (str3.compare(fnames[ifield]) == 0){ // p1
                p1[0] = pr[0]; p1[1] = pr[1];}
            if (str4.compare(fnames[ifield]) == 0){ // z
                z[0] = pr[0]; z[1] = pr[1];}
            if (str5.compare(fnames[ifield]) == 0){ // R
                R[0] = pr[0]; R[3] = pr[3];}
        } // end of nfields loop
        Object->initialise_a_constraint(cam, kpt, p1, z, R, Yz, yz, (int)sw[jstruct]) ; // using pointer to object
    } // end of NStructElems loop
    
    // optimise constraints information
    Object->optimise_constraints_image_inverse_depth_Mviews( xs ) ;
            
    /* get output state vector */
    int ncol = (Object->xhat).size();
    plhs[0] = mxCreateDoubleMatrix(ncol, 1, mxREAL);
    double *vec_out = mxGetPr(plhs[0]);
    for (int i=0; i<ncol; i++)
        vec_out[i] = (Object->xhat).coeffRef(i);
    
    /* get output sparse covariance matrix */
    ncol = (Object->Phat).outerSize();
    long unsigned int nzmax = (Object->Phat).nonZeros();
    plhs[1] = mxCreateSparse(ncol, ncol, nzmax, mxREAL);
    double *mat_out = mxGetPr(plhs[1]);
    long unsigned int *ir2 = mxGetIr(plhs[1]);
    long unsigned int *jc2 = mxGetJc(plhs[1]);
    int index=0;
    for (int k=0; k < (Object->Phat).outerSize(); ++k)
    {
        jc2[k] = index;
        for (Eigen::SparseMatrix<double>::InnerIterator it(Object->Phat,k); it; ++it)
        {
            ir2[index] = it.row();
            mat_out[index] = it.value();
            index++;
        }
    }
    jc2[(Object->Phat).outerSize()] = index;
    
    /* Free memory */
    mxFree((void *)fnames);
    delete Object; // delete class pointer
    //mxFree(tmp);
}
    void mexFunction(int nlhs, mxArray *plhs[], int nrhs,
                     const mxArray *prhs[])
    {
      double *srwp, *srdp, *probs, *Z, *WS, *DS, *ZIN;
      double ALPHA,BETA;
      mwIndex *irwp, *jcwp, *irdp, *jcdp;
      int *z,*d,*w, *order, *wp, *dp, *ztot;
      int W,T,D,NN,SEED,OUTPUT, nzmax, nzmaxwp, nzmaxdp, ntokens;
      int i,j,c,n,nt,wi,di, startcond;

      /* Check for proper number of arguments. */
      if (nrhs < 8) {
          mexPrintf("1");
        mexErrMsgTxt("At least 8 input arguments required");
      } else if (nlhs < 3) {
          mexPrintf("2");
        mexErrMsgTxt("3 output arguments required");
      }

      startcond = 0;
      if (nrhs == 9) {
          mexPrintf("3");
          startcond = 1;
      }

      /* process the input arguments */
      if (mxIsDouble( prhs[ 0 ] ) != 1) mexErrMsgTxt("WS input vector must be a double precision matrix");
      if (mxIsDouble( prhs[ 1 ] ) != 1) mexErrMsgTxt("DS input vector must be a double precision matrix");

      // pointer to word indices
      WS = mxGetPr( prhs[ 0 ] );

      // pointer to document indices
      DS = mxGetPr( prhs[ 1 ] );

      // get the number of tokens
      ntokens = mxGetM( prhs[ 0 ] ) * mxGetN( prhs[ 0 ] );


      if (ntokens == 0){
          mexPrintf("4");
          mexErrMsgTxt("WS vector is empty");
      }
      if (ntokens != ( mxGetM( prhs[ 1 ] ) * mxGetN( prhs[ 1 ] ))) mexErrMsgTxt("WS and DS vectors should have same number of entries");

      T    = (int) mxGetScalar(prhs[2]);
      if (T<=0){
          mexPrintf("5");
          mexErrMsgTxt("Number of topics must be greater than zero");
      }

      NN    = (int) mxGetScalar(prhs[3]);
      if (NN<0) mexErrMsgTxt("Number of iterations must be positive");

      ALPHA = (double) mxGetScalar(prhs[4]);
      if (ALPHA<=0) mexErrMsgTxt("ALPHA must be greater than zero");

      BETA = (double) mxGetScalar(prhs[5]);
      if (BETA<=0) mexErrMsgTxt("BETA must be greater than zero");

      SEED = (int) mxGetScalar(prhs[6]);

      OUTPUT = (int) mxGetScalar(prhs[7]);
        mexPrintf("ok");
      if (startcond == 1) {
          mexPrintf("6");
          ZIN = mxGetPr( prhs[ 8 ] );
          if (ntokens != ( mxGetM( prhs[ 8 ] ) * mxGetN( prhs[ 8 ] ))) mexErrMsgTxt("WS and ZIN vectors should have same number of entries");
      }

      // seeding
      seedMT( 1 + SEED * 2 ); // seeding only works on uneven numbers



    /* allocate memory */
      z  = (int *) mxCalloc( ntokens , sizeof( int ));

      if (startcond == 1) {
         for (i=0; i<ntokens; i++) z[ i ] = (int) ZIN[ i ] - 1;
      }

      d  = (int *) mxCalloc( ntokens , sizeof( int ));
      w  = (int *) mxCalloc( ntokens , sizeof( int ));
      order  = (int *) mxCalloc( ntokens , sizeof( int ));
      ztot  = (int *) mxCalloc( T , sizeof( int ));
      probs  = (double *) mxCalloc( T , sizeof( double ));

      // copy over the word and document indices into internal format
      for (i=0; i<ntokens; i++) {
         w[ i ] = (int) WS[ i ] - 1;
         d[ i ] = (int) DS[ i ] - 1;
      }

      n = ntokens;

      W = 0;
      D = 0;
      for (i=0; i<n; i++) {
         if (w[ i ] > W) W = w[ i ];
         if (d[ i ] > D) D = d[ i ];
      }
      W = W + 1;
      D = D + 1;

      wp  = (int *) mxCalloc( T*W , sizeof( int ));
      dp  = (int *) mxCalloc( T*D , sizeof( int ));

      //mexPrintf( "N=%d  T=%d W=%d D=%d\n" , ntokens , T , W , D );

      if (OUTPUT==2) {
          mexPrintf("7");
          mexPrintf( "Running LDA Gibbs Sampler Version 1.0\n" );
          if (startcond==1) mexPrintf( "Starting from previous state ZIN\n" );
          mexPrintf( "Arguments:\n" );
          mexPrintf( "\tNumber of words      W = %d\n"    , W );
          mexPrintf( "\tNumber of docs       D = %d\n"    , D );
          mexPrintf( "\tNumber of topics     T = %d\n"    , T );
          mexPrintf( "\tNumber of iterations N = %d\n"    , NN );
          mexPrintf( "\tHyperparameter   ALPHA = %4.4f\n" , ALPHA );
          mexPrintf( "\tHyperparameter    BETA = %4.4f\n" , BETA );
          mexPrintf( "\tSeed number            = %d\n"    , SEED );
          mexPrintf( "\tNumber of tokens       = %d\n"    , ntokens );
          mexPrintf( "Internal Memory Allocation\n" );
          mexPrintf( "\tw,d,z,order indices combined = %d bytes\n" , 4 * sizeof( int) * ntokens );
          mexPrintf( "\twp (full) matrix = %d bytes\n" , sizeof( int ) * W * T  );
          mexPrintf( "\tdp (full) matrix = %d bytes\n" , sizeof( int ) * D * T  );
          //mexPrintf( "Checking: sizeof(int)=%d sizeof(long)=%d sizeof(double)=%d\n" , sizeof(int) , sizeof(long) , sizeof(double));
      }

      /* run the model */
      GibbsSamplerLDA( ALPHA, BETA, W, T, D, NN, OUTPUT, n, z, d, w, wp, dp, ztot, order, probs, startcond );

      /* convert the full wp matrix into a sparse matrix */
      nzmaxwp = 0;
      for (i=0; i<W; i++) {
         for (j=0; j<T; j++)
             nzmaxwp += (int) ( *( wp + j + i*T )) > 0;
      }
      /*if (OUTPUT==2) {
          mexPrintf( "Constructing sparse output matrix wp\n" );
          mexPrintf( "Number of nonzero entries for WP = %d\n" , nzmaxwp );
      }*/

      // MAKE THE WP SPARSE MATRIX
      plhs[0] = mxCreateSparse( W,T,nzmaxwp,mxREAL);
      srwp  = mxGetPr(plhs[0]);
      irwp = mxGetIr(plhs[0]);
      jcwp = mxGetJc(plhs[0]);
      n = 0;
      for (j=0; j<T; j++) {
          *( jcwp + j ) = n;
          for (i=0; i<W; i++) {
             c = (int) *( wp + i*T + j );
             if (c >0) {
                 *( srwp + n ) = c;
                 *( irwp + n ) = i;
                 n++;
             }
          }
      }
      *( jcwp + T ) = n;

      // MAKE THE DP SPARSE MATRIX
      nzmaxdp = 0;
      for (i=0; i<D; i++) {
          for (j=0; j<T; j++)
              nzmaxdp += (int) ( *( dp + j + i*T )) > 0;
      }
      /*if (OUTPUT==2) {
          mexPrintf( "Constructing sparse output matrix dp\n" );
          mexPrintf( "Number of nonzero entries for DP = %d\n" , nzmaxdp );
      } */
      plhs[1] = mxCreateSparse( D,T,nzmaxdp,mxREAL);
      srdp  = mxGetPr(plhs[1]);
      irdp = mxGetIr(plhs[1]);
      jcdp = mxGetJc(plhs[1]);
      n = 0;
      for (j=0; j<T; j++) {
          *( jcdp + j ) = n;
          for (i=0; i<D; i++) {
              c = (int) *( dp + i*T + j );
              if (c >0) {
                  *( srdp + n ) = c;
                  *( irdp + n ) = i;
                  n++;
              }
          }
      }
      *( jcdp + T ) = n;

      plhs[ 2 ] = mxCreateDoubleMatrix( 1,ntokens , mxREAL );
      Z = mxGetPr( plhs[ 2 ] );
      for (i=0; i<ntokens; i++) Z[ i ] = (double) z[ i ] + 1;
    }
void mexFunction
(
    int nargout,
    mxArray *pargout [ ],
    int nargin,
    const mxArray *pargin [ ]
)
{
    double dummy = 0, *Px, *Xsetx ;
    Long *Lp, *Lnz, *Xp, *Xi, xnz, *Perm, *Lprev, *Lnext, *Xsetp ;
    cholmod_sparse *Bset, Bmatrix, *Xset ;
    cholmod_dense *Bdense, *X, *Y, *E ;
    cholmod_factor *L ;
    cholmod_common Common, *cm ;
    Long k, j, n, head, tail, xsetlen ;
    int sys, kind ;

    /* ---------------------------------------------------------------------- */
    /* start CHOLMOD and set parameters */ 
    /* ---------------------------------------------------------------------- */

    cm = &Common ;
    cholmod_l_start (cm) ;
    sputil_config (SPUMONI, cm) ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    if (nargin != 5 || nargout > 2)
    {
	mexErrMsgTxt ("usage: [x xset] = lsubsolve (L,kind,P,b,system)") ;
    }

    n = mxGetN (pargin [0]) ;
    if (!mxIsSparse (pargin [0]) || n != mxGetM (pargin [0]))
    {
	mexErrMsgTxt ("lsubsolve: L must be sparse and square") ;
    }
    if (mxGetNumberOfElements (pargin [1]) != 1)
    {
	mexErrMsgTxt ("lsubsolve: kind must be a scalar") ;
    }

    if (mxIsSparse (pargin [2]) ||
       !(mxIsEmpty (pargin [2]) || mxGetNumberOfElements (pargin [2]) == n))
    {
	mexErrMsgTxt ("lsubsolve: P must be size n, or empty") ;
    }

    if (mxGetM (pargin [3]) != n || mxGetN (pargin [3]) != 1)
    {
	mexErrMsgTxt ("lsubsolve: b wrong dimension") ;
    }
    if (!mxIsSparse (pargin [3]))
    {
	mexErrMsgTxt ("lxbpattern: b must be sparse") ;
    }
    if (mxGetNumberOfElements (pargin [4]) != 1)
    {
	mexErrMsgTxt ("lsubsolve: system must be a scalar") ;
    }

    /* ---------------------------------------------------------------------- */
    /* get the inputs */
    /* ---------------------------------------------------------------------- */

    kind = (int) sputil_get_integer (pargin [1], FALSE, 0) ;
    sys  = (int) sputil_get_integer (pargin [4], FALSE, 0) ;

    /* ---------------------------------------------------------------------- */
    /* get the sparse b */
    /* ---------------------------------------------------------------------- */

    /* get sparse matrix B (unsymmetric) */
    Bset = sputil_get_sparse (pargin [3], &Bmatrix, &dummy, 0) ;
    Bdense = cholmod_l_sparse_to_dense (Bset, cm) ;
    Bset->x = NULL ;
    Bset->z = NULL ;
    Bset->xtype = CHOLMOD_PATTERN ;

    /* ---------------------------------------------------------------------- */
    /* construct a shallow copy of the input sparse matrix L */
    /* ---------------------------------------------------------------------- */

    /* the construction of the CHOLMOD takes O(n) time and memory */

    /* allocate the CHOLMOD symbolic L */
    L = cholmod_l_allocate_factor (n, cm) ;
    L->ordering = CHOLMOD_NATURAL ;

    /* get the MATLAB L */
    L->p = mxGetJc (pargin [0]) ;
    L->i = mxGetIr (pargin [0]) ;
    L->x = mxGetPr (pargin [0]) ;
    L->z = mxGetPi (pargin [0]) ;

    /* allocate and initialize the rest of L */
    L->nz = cholmod_l_malloc (n, sizeof (Long), cm) ;
    Lp = L->p ;
    Lnz = L->nz ;
    for (j = 0 ; j < n ; j++)
    {
	Lnz [j] = Lp [j+1] - Lp [j] ;
    }

    /* these pointers are not accessed in cholmod_solve2 */
    L->prev = cholmod_l_malloc (n+2, sizeof (Long), cm) ;
    L->next = cholmod_l_malloc (n+2, sizeof (Long), cm) ;
    Lprev = L->prev ;
    Lnext = L->next ;

    head = n+1 ;
    tail = n ;
    Lnext [head] = 0 ;
    Lprev [head] = -1 ;
    Lnext [tail] = -1 ;
    Lprev [tail] = n-1 ;
    for (j = 0 ; j < n ; j++)
    {
	Lnext [j] = j+1 ;
	Lprev [j] = j-1 ;
    }
    Lprev [0] = head ;

    L->xtype = (mxIsComplex (pargin [0])) ? CHOLMOD_ZOMPLEX : CHOLMOD_REAL ;
    L->nzmax = Lp [n] ;

    /* get the permutation */
    if (mxIsEmpty (pargin [2]))
    {
        L->Perm = NULL ;
        Perm = NULL ;
    }
    else
    {
        L->ordering = CHOLMOD_GIVEN ;
        L->Perm = cholmod_l_malloc (n, sizeof (Long), cm) ;
        Perm = L->Perm ;
        Px = mxGetPr (pargin [2]) ;
        for (k = 0 ; k < n ; k++)
        {
            Perm [k] = ((Long) Px [k]) - 1 ;
        }
    }

    /* set the kind, LL' or LDL' */
    L->is_ll = (kind == 0) ;
    /*
    cholmod_l_print_factor (L, "L", cm) ;
    */

    /* ---------------------------------------------------------------------- */
    /* solve the system */
    /* ---------------------------------------------------------------------- */

    X = cholmod_l_zeros (n, 1, L->xtype, cm) ;
    Xset = NULL ;
    Y = NULL ;
    E = NULL ;

    cholmod_l_solve2 (sys, L, Bdense, Bset, &X, &Xset, &Y, &E, cm) ;

    cholmod_l_free_dense (&Y, cm) ;
    cholmod_l_free_dense (&E, cm) ;

    /* ---------------------------------------------------------------------- */
    /* return result */
    /* ---------------------------------------------------------------------- */

    pargout [0] = sputil_put_dense (&X, cm) ;

    /* fill numerical values of Xset with one's */
    Xsetp = Xset->p ;
    xsetlen = Xsetp [1] ;
    Xset->x = cholmod_l_malloc (xsetlen, sizeof (double), cm) ;
    Xsetx = Xset->x ;
    for (k = 0 ; k < xsetlen ; k++)
    {
        Xsetx [k] = 1 ;
    }
    Xset->xtype = CHOLMOD_REAL ;

    pargout [1] = sputil_put_sparse (&Xset, cm) ;

    /* ---------------------------------------------------------------------- */
    /* free workspace and the CHOLMOD L, except for what is copied to MATLAB */
    /* ---------------------------------------------------------------------- */

    L->p = NULL ;
    L->i = NULL ;
    L->x = NULL ;
    L->z = NULL ;
    cholmod_l_free_factor (&L, cm) ;
    cholmod_l_finish (cm) ;
    cholmod_l_print_common (" ", cm) ;
}
void mexFunction
(
    /* === Parameters ======================================================= */

    int nlhs,			/* number of left-hand sides */
    mxArray *plhs [],		/* left-hand side matrices */
    int nrhs,			/* number of right--hand sides */
    const mxArray *prhs []	/* right-hand side matrices */
)
{
    /* === Local variables ================================================== */

    Long *perm ;                /* column ordering of M and ordering of A */
    Long *A ;                   /* row indices of input matrix A */
    Long *p ;                   /* column pointers of input matrix A */
    Long n_col ;                /* number of columns of A */
    Long n_row ;                /* number of rows of A */
    Long full ;                 /* TRUE if input matrix full, FALSE if sparse */
    double knobs [COLAMD_KNOBS] ; /* colamd user-controllable parameters */
    double *out_perm ;          /* output permutation vector */
    double *out_stats ;         /* output stats vector */
    double *in_knobs ;          /* input knobs vector */
    Long i ;                    /* loop counter */
    mxArray *Ainput ;           /* input matrix handle */
    Long spumoni ;              /* verbosity variable */
    Long stats2 [COLAMD_STATS] ;/* stats for symamd */

    Long *cp, *cp_end, result, nnz, col, length ;
    Long *stats ;
    stats = stats2 ;

    /* === Check inputs ===================================================== */

    if (nrhs < 1 || nrhs > 2 || nlhs < 0 || nlhs > 2)
    {
	mexErrMsgTxt (
	"symamd: incorrect number of input and/or output arguments.") ;
    }

    if (nrhs != 2)
    {
	mexErrMsgTxt ("symamdtest: knobs are required") ;
    }
    /* for testing we require all 3 knobs */
    if (mxGetNumberOfElements (prhs [1]) != 3)
    {
	mexErrMsgTxt ("symamdtest: must have all 3 knobs for testing") ;
    }

    /* === Get knobs ======================================================== */

    colamd_l_set_defaults (knobs) ;
    spumoni = 0 ;

    /* check for user-passed knobs */
    if (nrhs == 2)
    {
	in_knobs = mxGetPr (prhs [1]) ;
	i = mxGetNumberOfElements (prhs [1]) ;
	if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [0] ;
	if (i > 1) spumoni = (Long) in_knobs [1] ;
    }

    /* print knob settings if spumoni is set */
    if (spumoni)
    {
	mexPrintf ("\nsymamd version %d.%d, %s:\n",
	    COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION, COLAMD_DATE) ;
	if (knobs [COLAMD_DENSE_ROW] >= 0)
	{
	    mexPrintf ("knobs(1): %g, rows/cols with > "
		"max(16,%g*sqrt(size(A,2))) entries removed\n",
		in_knobs [0], knobs [COLAMD_DENSE_ROW]) ;
	}
	else
	{
	    mexPrintf ("knobs(1): %g, no dense rows removed\n", in_knobs [0]) ;
	}
	mexPrintf ("knobs(2): %g, statistics and knobs printed\n",
	    in_knobs [1]) ;
	mexPrintf ("Testing %d\n", in_knobs [2]) ;
    }

    /* === If A is full, convert to a sparse matrix ========================= */

    Ainput = (mxArray *) prhs [0] ;
    if (mxGetNumberOfDimensions (Ainput) != 2)
    {
	mexErrMsgTxt ("symamd: input matrix must be 2-dimensional.") ;
    }
    full = !mxIsSparse (Ainput) ;
    if (full)
    {
	mexCallMATLAB (1, &Ainput, 1, (mxArray **) prhs, "sparse") ;
    }

    /* === Allocate workspace for symamd ==================================== */

    /* get size of matrix */
    n_row = mxGetM (Ainput) ;
    n_col = mxGetN (Ainput) ;
    if (n_col != n_row)
    {
	mexErrMsgTxt ("symamd: matrix must be square.") ;
    }

    /* p = mxGetJc (Ainput) ; */
    p = (Long *) mxCalloc (n_col+1, sizeof (Long)) ;
    (void) memcpy (p, mxGetJc (Ainput), (n_col+1)*sizeof (Long)) ;

    nnz = p [n_col] ;
    if (spumoni > 0)
    {
	mexPrintf ("symamdtest: nnz %d\n", nnz) ;
    }

    /* A = mxGetIr (Ainput) ; */
    A = (Long *) mxCalloc (nnz+1, sizeof (Long)) ;
    (void) memcpy (A, mxGetIr (Ainput), nnz*sizeof (Long)) ;

    perm = (Long *) mxCalloc (n_col+1, sizeof (Long)) ;

/* === Jumble matrix ======================================================== */


/*
	knobs [2]	FOR TESTING ONLY: Specifies how to jumble matrix
			0 : No jumbling
			1 : (no errors)
			2 : Make first pointer non-zero
			3 : Make column pointers not non-decreasing
			4 : (no errors)
			5 : Make row indices not strictly increasing
			6 : Make a row index greater or equal to n_row
			7 : Set A = NULL
			8 : Set p = NULL
			9 : Repeat row index
			10: make row indices not sorted
			11: jumble columns massively (note this changes
				the pattern of the matrix A.)
			12: Set stats = NULL
			13: Make n_col less than zero
*/

    /* jumble appropriately */
    switch ((Long) in_knobs [2])
    {

	case 0 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: no errors expected\n") ;
	    }
	    result = 1 ;		/* no errors */
	    break ;

	case 1 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: no errors expected (1)\n") ;
	    }
	    result = 1 ;
	    break ;

	case 2 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: p [0] nonzero\n") ;
	    }
	    result = 0 ;		/* p [0] must be zero */
	    p [0] = 1 ;
	    break ;

	case 3 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: negative length last column\n") ;
	    }
	    result = (n_col == 0) ;	/* p must be monotonically inc. */
	    p [n_col] = p [0] ;
	    break ;

	case 4 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: no errors expected (4)\n") ;
	    }
	    result = 1 ;
	    break ;

	case 5 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: row index out of range (-1)\n") ;
	    }
	    if (nnz > 0)		/* row index out of range */
	    {
		result = 0 ;
		A [nnz-1] = -1 ;
	    }
	    else
	    {
	        if (spumoni > 0)
		{
		    mexPrintf ("Note: no row indices to put out of range\n") ;
		}
		result = 1 ;
	    }
	    break ;

	case 6 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: row index out of range (ncol)\n") ;
	    }
	    if (nnz > 0)		/* row index out of range */
	    {
		result = 0 ;
		A [nnz-1] = n_col ;
	    }
	    else
	    {
	        if (spumoni > 0)
		{
		    mexPrintf ("Note: no row indices to put out of range\n") ;
		}
		result = 1 ;
	    }
	    break ;

	case 7 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: A not present\n") ;
	    }
	    result = 0 ;		/* A not present */
	    A = (Long *) NULL ;
	    break ;

	case 8 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: p not present\n") ;
	    }
	    result = 0 ;		/* p not present */
	    p = (Long *) NULL ;
	    break ;

	case 9 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: duplicate row index\n") ;
	    }
	    result = 1 ;		/* duplicate row index */

	    for (col = 0 ; col < n_col ; col++)
	    {
		length = p [col+1] - p [col] ;
	    	if (length > 1)
		{
		    A [p [col+1]-2] = A [p [col+1] - 1] ;
		    if (spumoni > 0)
		    {
			mexPrintf ("Made duplicate row %d in col %d\n",
		    	 A [p [col+1] - 1], col) ;
		    }
		    break ;
		}
	    }

	    if (spumoni > 1)
	    {
		dump_matrix (A, p, n_row, n_col, nnz, col+2) ;
	    }
	    break ;

	case 10 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: unsorted column\n") ;
	    }
	    result = 1 ;		/* jumbled columns */

	    for (col = 0 ; col < n_col ; col++)
	    {
		length = p [col+1] - p [col] ;
	    	if (length > 1)
		{
		    i = A[p [col]] ;
		    A [p [col]] = A[p [col] + 1] ;
		    A [p [col] + 1] = i ;
		    if (spumoni > 0)
		    {
			mexPrintf ("Unsorted column %d \n", col) ;
		    }
		    break ;
		}
	    }

	    if (spumoni > 1)
	    {
		dump_matrix (A, p, n_row, n_col, nnz, col+2) ;
	    }
	    break ;

	case 11 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: massive jumbling\n") ;
	    }
	    result = 1 ;		/* massive jumbling, but no errors */
	    srand (1) ;
	    for (i = 0 ; i < n_col ; i++)
	    {
		cp = &A [p [i]] ;
		cp_end = &A [p [i+1]] ;
		while (cp < cp_end)
		{
		    *cp++ = rand() % n_row ;
		}
	    }
	    if (spumoni > 1)
	    {
		dump_matrix (A, p, n_row, n_col, nnz, n_col) ;
	    }
	    break ;

	case 12 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: stats not present\n") ;
	    }
	    result = 0 ;		/* stats not present */
	    stats = (Long *) NULL ;
	    break ;

	case 13 :
	    if (spumoni > 0)
	    {
		mexPrintf ("symamdtest: ncol out of range\n") ;
	    }
	    result = 0 ;		/* ncol out of range */
	    n_col = -1 ;
	    break ;

    }

    /* === Order the rows and columns of A (does not destroy A) ============= */

    if (!symamd_l (n_col, A, p, perm, knobs, stats, &mxCalloc, &mxFree))
    {

	/* return p = -1 if colamd failed */
	plhs [0] = mxCreateDoubleMatrix (1, 1, mxREAL) ;
	out_perm = mxGetPr (plhs [0]) ;
	out_perm [0] = -1 ;
	mxFree (p) ;
	mxFree (A) ;

	if (spumoni > 0 || result)
	{
	    symamd_l_report (stats) ;
	}

	if (result)
	{
	    mexErrMsgTxt ("symamd should have returned TRUE\n") ;
	}

	return ;
	/* mexErrMsgTxt ("symamd error!") ; */
    }

    if (!result)
    {
	symamd_l_report (stats) ;
	mexErrMsgTxt ("symamd should have returned FALSE\n") ;
    }

    if (full)
    {
	mxDestroyArray (Ainput) ;
    }

    /* === Return the permutation vector ==================================== */

    plhs [0] = mxCreateDoubleMatrix (1, n_col, mxREAL) ;
    out_perm = mxGetPr (plhs [0]) ;
    for (i = 0 ; i < n_col ; i++)
    {
	/* symamd is 0-based, but MATLAB expects this to be 1-based */
	out_perm [i] = perm [i] + 1 ;
    }
    mxFree (perm) ;

    /* === Return the stats vector ========================================== */

    /* print stats if spumoni > 0 */
    if (spumoni > 0)
    {
	symamd_l_report (stats) ;
    }

    if (nlhs == 2)
    {
	plhs [1] = mxCreateDoubleMatrix (1, COLAMD_STATS, mxREAL) ;
	out_stats = mxGetPr (plhs [1]) ;
	for (i = 0 ; i < COLAMD_STATS ; i++)
	{
	    out_stats [i] = stats [i] ;
	}

	/* fix stats (5) and (6), for 1-based information on jumbled matrix. */
	/* note that this correction doesn't occur if symamd returns FALSE */
	out_stats [COLAMD_INFO1] ++ ; 
	out_stats [COLAMD_INFO2] ++ ; 
    }
}
Exemple #29
0
mxArray *sfmult_AN_XN_YT    // y = (A*x)'
(
    const mxArray *A,
    const mxArray *X,
    int ac,		// if true: conj(A)   if false: A. ignored if A real
    int xc,		// if true: conj(x)   if false: x. ignored if x real
    int yc		// if true: conj(y)   if false: y. ignored if y real
)
{
    mxArray *Y ;
    double *Ax, *Az, *Xx, *Xz, *Yx, *Yz, *Wx, *Wz ;
    Int *Ap, *Ai ;
    Int m, n, k, k1, i ;
    int Acomplex, Xcomplex, Ycomplex ;

    //--------------------------------------------------------------------------
    // get inputs
    //--------------------------------------------------------------------------

    m = mxGetM (A) ;
    n = mxGetN (A) ;
    k = mxGetN (X) ;
    if (n != mxGetM (X)) sfmult_invalid ( ) ;
    Acomplex = mxIsComplex (A) ;
    Xcomplex = mxIsComplex (X) ;
    Ap = mxGetJc (A) ;
    Ai = mxGetIr (A) ;
    Ax = mxGetPr (A) ;
    Az = mxGetPi (A) ;
    Xx = mxGetPr (X) ;
    Xz = mxGetPi (X) ;

    //--------------------------------------------------------------------------
    // allocate result
    //--------------------------------------------------------------------------

    Ycomplex = Acomplex || Xcomplex ;
    Y = sfmult_yalloc (k, m, Ycomplex) ;
    Yx = mxGetPr (Y) ;
    Yz = mxGetPi (Y) ;

    //--------------------------------------------------------------------------
    // special cases
    //--------------------------------------------------------------------------

    if (k == 0 || m == 0 || n == 0 || Ap [n] == 0)
    {
	// Y = 0
	return (sfmult_yzero (Y)) ;
    }
    if (k == 1)
    {
	// Y = A*X
	sfmult_AN_x_1 (Yx, Yz, Ap, Ai, Ax, Az, m, n, Xx, Xz, ac, xc, yc) ;
	return (Y) ;
    }
    if (k == 2)
    {
	// Y = (A * X)'
	sfmult_AN_XN_YT_2 (Yx, Yz, Ap, Ai, Ax, Az, m, n, Xx, Xz, ac, xc, yc) ;
	return (Y) ;
    }
    if (k == 4)
    {
	// Y = (A * X)'
	sfmult_AN_XN_YT_4 (Yx, Yz, Ap, Ai, Ax, Az, m, n, Xx, Xz, ac, xc, yc) ;
	return (Y) ;
    }

    //--------------------------------------------------------------------------
    // allocate workspace
    //--------------------------------------------------------------------------

    sfmult_walloc (4, m, &Wx, &Wz) ;

    //--------------------------------------------------------------------------
    // Y = (A*X)', in blocks of up to 4 columns of X, using sfmult_anxnyt
    //--------------------------------------------------------------------------

    k1 = k % 4 ;
    if (k1 == 1)
    {
	// W = A * X(:,1)
	sfmult_AN_x_1 (Wx, Wz, Ap, Ai, Ax, Az, m, n, Xx, Xz, ac, xc, yc) ;
	// Y (1,:) = W
	for (i = 0 ; i < m ; i++)
	{
	    Yx [k*i] = Wx [i] ;
	}
	Yx += 1 ;
	Yz += 1 ;
	Xx += n ;
	Xz += n ;
    }
    else if (k1 == 2)
    {
	// W = (A * X(:,1:2))'
	sfmult_AN_XN_YT_2 (Wx, Wz, Ap, Ai, Ax, Az, m, n, Xx, Xz, ac, xc, yc) ;
	// Y (1:2,:) = W
	for (i = 0 ; i < m ; i++)
	{
	    Yx [k*i  ] = Wx [2*i  ] ;
	    Yx [k*i+1] = Wx [2*i+1] ;
	}
	Yx += 2 ;
	Yz += 2 ;
	Xx += 2*n ;
	Xz += 2*n ;
    }
    else if (k1 == 3)
    {
	// W = (A * X(:,1:3))'
	sfmult_AN_XN_YT_3 (Wx, Wz, Ap, Ai, Ax, Az, m, n, Xx, Xz, ac, xc, yc) ;
	// Y (1:3,:) = W
	for (i = 0 ; i < m ; i++)
	{
	    Yx [k*i  ] = Wx [4*i  ] ;
	    Yx [k*i+1] = Wx [4*i+1] ;
	    Yx [k*i+2] = Wx [4*i+2] ;
	}
	Yx += 3 ;
	Yz += 3 ;
	Xx += 3*n ;
	Xz += 3*n ;
    }
    for ( ; k1 < k ; k1 += 4)
    {
	// W = (A*X(:,1:4))'
	sfmult_AN_XN_YT_4 (Wx, Wz, Ap, Ai, Ax, Az, m, n, Xx, Xz, ac, xc, yc) ;
	// Y (k1+(1:4),:) = W
	for (i = 0 ; i < m ; i++)
	{
	    Yx [k*i  ] = Wx [4*i  ] ;
	    Yx [k*i+1] = Wx [4*i+1] ;
	    Yx [k*i+2] = Wx [4*i+2] ;
	    Yx [k*i+3] = Wx [4*i+3] ;
	}
	Yx += 4 ;
	Yz += 4 ;
	Xx += 4*n ;
	Xz += 4*n ;
    }

    //--------------------------------------------------------------------------
    // free workspace and return result
    //--------------------------------------------------------------------------

    mxFree (Wx) ;
    return (Y) ;
}
mxArray *sfmult_AT_XT_YT    // y = (A'*x')'
(
    const mxArray *A,
    const mxArray *X,
    int ac,		// if true: conj(A)   if false: A. ignored if A real
    int xc,		// if true: conj(x)   if false: x. ignored if x real
    int yc		// if true: conj(y)   if false: y. ignored if y real
)
{
    mxArray *Y ;
    double *Ax, *Az, *Xx, *Xz, *Yx, *Yz, *Wx, *Wz ;
    Int *Ap, *Ai ;
    Int m, n, k, k1, i ;
    int Acomplex, Xcomplex, Ycomplex ;

    //--------------------------------------------------------------------------
    // get inputs
    //--------------------------------------------------------------------------

    m = mxGetM (A) ;
    n = mxGetN (A) ;
    k = mxGetM (X) ;
    if (m != mxGetN (X)) sfmult_invalid ( ) ;
    Acomplex = mxIsComplex (A) ;
    Xcomplex = mxIsComplex (X) ;
    Ap = mxGetJc (A) ;
    Ai = mxGetIr (A) ;
    Ax = mxGetPr (A) ;
    Az = mxGetPi (A) ;
    Xx = mxGetPr (X) ;
    Xz = mxGetPi (X) ;

    //--------------------------------------------------------------------------
    // allocate result
    //--------------------------------------------------------------------------

    Ycomplex = Acomplex || Xcomplex ;
    Y = sfmult_yalloc (k, n, Ycomplex) ;
    Yx = mxGetPr (Y) ;
    Yz = mxGetPi (Y) ;

    //--------------------------------------------------------------------------
    // special cases
    //--------------------------------------------------------------------------

    if (k == 0 || m == 0 || n == 0 || Ap [n] == 0)
    {
	// Y = 0
	return (sfmult_yzero (Y)) ;
    }
    if (k == 1)
    {
	// Y = A' * X
	sfmult_AT_x_1 (Yx, Yz, Ap, Ai, Ax, Az, m, n, Xx, Xz, ac, xc, yc) ;
	return (Y) ;
    }
    if (k == 2)
    {
	// Y = (A' * X')'
	sfmult_AT_XT_YT_2 (Yx, Yz, Ap, Ai, Ax, Az, m, n, Xx, Xz, ac, xc, yc, k);
	return (Y) ;
    }
    if (k == 4)
    {
	// Y = (A' * X')'
	sfmult_AT_XT_YT_4 (Yx, Yz, Ap, Ai, Ax, Az, m, n, Xx, Xz, ac, xc, yc, k);
	return (Y) ;
    }

    if (k > 8 && Ap [n] < 8 * MAX (m,n))
    {
	// Y = (A' * X')' when A is moderately sparse and X is large
	sfmult_xA (Yx, Yz, Ap, Ai, Ax, Az, m, n, Xx, Xz, ac, xc, yc, k) ;
	return (Y) ;
    }

    //--------------------------------------------------------------------------
    // allocate workspace
    //--------------------------------------------------------------------------

    sfmult_walloc (4, m, &Wx, &Wz) ;

    //--------------------------------------------------------------------------
    // Y = (A'*X')', in blocks of up to 4 columns of X, using sfmult_atxtyt
    //--------------------------------------------------------------------------

    k1 = k % 4 ;
    if (k1 == 1)
    {
	// W = X (1,:)'
	for (i = 0 ; i < m ; i++)
	{
	    Wx [i] = Xx [k*i] ;
	}
	// Y (1,:) = (A' * W)'
	sfmult_AT_xk_1 (Yx, Yz, Ap, Ai, Ax, Az, m, n, Wx, Wz, ac, xc, yc, k) ;
	Yx += 1 ;
	Yz += 1 ;
	Xx += 1 ;
	Xz += 1 ;
    }
    else if (k1 == 2)
    {
	// W = X (1:2,:)
	for (i = 0 ; i < m ; i++)
	{
	    Wx [2*i  ] = Xx [k*i  ] ;
	    Wx [2*i+1] = Xx [k*i+1] ;
	}
	// Y (1:2,:) = (A' * W')'
	sfmult_AT_XT_YT_2 (Yx, Yz, Ap, Ai, Ax, Az, m, n, Wx, Wz, ac, xc, yc, k);
	Yx += 2 ;
	Yz += 2 ;
	Xx += 2 ;
	Xz += 2 ;
    }
    else if (k1 == 3)
    {
	// W = X (1:3,:)
	for (i = 0 ; i < m ; i++)
	{
	    Wx [4*i  ] = Xx [k*i  ] ;
	    Wx [4*i+1] = Xx [k*i+1] ;
	    Wx [4*i+2] = Xx [k*i+2] ;
	}
	// Y (1:3,:) = (A' * W')'
	sfmult_AT_XT_YT_3 (Yx, Yz, Ap, Ai, Ax, Az, m, n, Wx, Wz, ac, xc, yc, k);
	Yx += 3 ;
	Yz += 3 ;
	Xx += 3 ;
	Xz += 3 ;
    }
    for ( ; k1 < k ; k1 += 4)
    {
	// W = X (1:4,:)
	for (i = 0 ; i < m ; i++)
	{
	    Wx [4*i  ] = Xx [k*i  ] ;
	    Wx [4*i+1] = Xx [k*i+1] ;
	    Wx [4*i+2] = Xx [k*i+2] ;
	    Wx [4*i+3] = Xx [k*i+3] ;
	}
	// Y (k1+(1:4),:) = (A' * W')'
	sfmult_AT_XT_YT_4 (Yx, Yz, Ap, Ai, Ax, Az, m, n, Wx, Wz, ac, xc, yc, k);
	Yx += 4 ;
	Yz += 4 ;
	Xx += 4 ;
	Xz += 4 ;
    }

    //--------------------------------------------------------------------------
    // free workspace and return result
    //--------------------------------------------------------------------------

    mxFree (Wx) ;
    return (Y) ;
}