#include <stdint.h>
#include <iostream>
#include <string>
#include "mex.h"

void dijkstra(double* d, double* p, size_t* jc, size_t* ir, double* cost, int64_t src, int64_t n);

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
	// validating # of input/output args
    if(nrhs < 2) {
		mexErrMsgTxt("Not enough arguments.");
		return;
	}
    if(nlhs < 1) {
        mexErrMsgTxt("This implementation must have at least one output argument.");
        return;
    }
    
    // validating adjmat
    if(!mxIsDouble(prhs[0]) || !mxIsSparse(prhs[0]) || mxGetM(prhs[0]) != mxGetN(prhs[0])) {
        mexErrMsgTxt("Invalid adjmat; a real-valued square sparse matrix is expected.");
        return;
    }
    int64_t nnodes = (int64_t)mxGetN(prhs[0]);

    // validating source node index
    if(!mxIsDouble(prhs[1]) || mxGetN(prhs[1]) > 1 || mxGetM(prhs[1]) > 1) {
        mexErrMsgTxt("Invalid source.");
        return;
    }
    int64_t isrc = (int64_t)mxGetScalar(prhs[1]) - 1;
    if(isrc < 0 || isrc >= nnodes) {
        mexErrMsgTxt("Source index is out of range.");
        return;
    }
    
    plhs[0] = mxCreateDoubleMatrix(nnodes, 1, mxREAL);
    plhs[1] = mxCreateDoubleMatrix(nnodes, 1, mxREAL);
    
    dijkstra(mxGetPr(plhs[0]), mxGetPr(plhs[1]),
            mxGetJc(prhs[0]), mxGetIr(prhs[0]), mxGetPr(prhs[0]), isrc, nnodes);
}
