#include "mex.h"


void attributesSimilarity(mwIndex* ir, mwIndex* jc, double* commonAtts, 
        double *numAtts, mwSize n, double threshold, 
        mwIndex* ir_out, mwIndex* jc_out, double* outSimAtts)
{

	double numTotalAtts, numCommon;
	int currCol = 0, startIdx, stopIdx, i, j, currRow;
	int nnz_in = jc[n];
    int nnz_out = 0;
	
	printf("attributesSimilarity: nnz = %d\n", nnz_in);
    
	for (currCol = 0; currCol < n; currCol++)
	{
   		jc_out[currCol] = nnz_out;

        startIdx = jc[currCol];
		stopIdx = jc[currCol + 1];
		
		for(i = startIdx; i < stopIdx; i++)
		{
			currRow = ir[i];
			numCommon = commonAtts[i];
            numTotalAtts = numAtts[currRow]+numAtts[currCol]-numCommon;
//            // debugging
//            if (currCol<30 && currRow<30) {
//                printf("(i,j)=(%d,%d): common=%f, total=%f\n", currRow,currCol,numCommon,numTotalAtts);
//            }
            if (numTotalAtts > 0 && numCommon/numTotalAtts > threshold)
            {
                outSimAtts[nnz_out] = numCommon/numTotalAtts;
                ir_out[nnz_out] = ir[i];
                nnz_out++;
//             } else
//             {
//                 outSimAtts[i] = 0;
//                 ir_out[i] = ir[i];
            }
		}
        

	} 
	jc_out[n] = nnz_out;
    
}


/* The gateway function 
//this function accepts two parameters:
//1. a sparse affinity matrix (should be the number of common attributes between nodes i and j
//2. an array with the number of attributes of each node
*/
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[])
{
    /* variable declarations here */
    mwIndex* ir;
    mwIndex* jc;
    double* commonAtts;
    double* numAtts;
    mwSize n,m,n2,m2;
    double threshold;
    

    mwIndex* ir_out;
    mwIndex* jc_out;
    double* outSimAtts;
    int i;
    
    
    printf("nlhs = %d, nrhs = %d\n", nlhs, nrhs);
    
    /* Check for the correct number of inputs */
    if(nrhs != 3){
        mexErrMsgIdAndTxt( "MATLAB:attributesSimilarity:wrongrhs",
                "Wrong number of input arguments.");
    }
    
    commonAtts = mxGetPr(prhs[0]);  /* pointer to first input  */
    ir = mxGetIr(prhs[0]);
    jc = mxGetJc(prhs[0]);
    
    numAtts = mxGetPr(prhs[1]);     /* pointer to second input  */
    
    threshold = mxGetScalar(prhs[2]);  /* pointer to thrid input matrix */
    printf("threshold = %f\n", threshold);
    
    /* dimensions of input matrices */
    m = mxGetM(prhs[0]);
    n = mxGetN(prhs[0]);
    m2 = mxGetM(prhs[1]);
    n2 = mxGetN(prhs[1]);
    
    printf("dimensions: m=%d, n=%d, m2=%d, n2=%d\n", m, n, m2, n2);
    if (m != m2) {
        mexErrMsgIdAndTxt("MATLAB:attributesSimilarity:matchdims",
            "Inner dimensions of matrices do not match.");
    }
    if (n != m) {
        mexErrMsgIdAndTxt("MATLAB:attributesSimilarity:square",
            "Function requires input matrix 1 must be square.");
    }
    if (n2 != 1) {
        mexErrMsgIdAndTxt("MATLAB:attributesSimilarity:zerodivide",
            "Function requires input matrix 2 must be a column vector.");  
    }
    
    plhs[0] = mxCreateSparse(n,n, jc[n], mxREAL);
    outSimAtts = mxGetPr(plhs[0]);
    ir_out = mxGetIr(plhs[0]);
    jc_out = mxGetJc(plhs[0]);
    
    attributesSimilarity(ir, jc, commonAtts, numAtts, n, threshold, ir_out, jc_out, outSimAtts);


}


