#include <octave/oct.h>
#define NUM_ARG 2
#define HELP " Help della funzione"

double calc_tnorm(double first, double second);


DEFUN_DLD (spmaxmin_ST, args, nargout, HELP)
{
	if (args.length() != NUM_ARG)	
		print_usage();
	else
	{
		SparseMatrix a = args(0).sparse_matrix_value();
		SparseMatrix b = args(1).sparse_matrix_value();
		dim_vector dimsA = a.dims();
		int rowsA = dimsA(0);
		int colsA = dimsA(1);

		dim_vector dimsB = b.dims();
		int rowsB = dimsB(0);
		int colsB = dimsB(1);
	
		//il terzo parametro è il numero di elementi nonzero della matrice
		//visto che non posso saperlo al momento della creazione, lo metto al numero massimo
		//poi richiamerò una funzione che comprimerà la matrice al numero utile di elementi nonzero
		SparseMatrix c = SparseMatrix(rowsA, colsB, rowsA*colsB);
		dim_vector dimsC = c.dims();
		int rowsC = dimsC(0);
		int colsC = dimsC(1);
	
		//const SparseMatrix tmp(c);
		int i,j,k;
		double mx,mn;
		if (colsA != rowsB)
			print_usage();
		else
		{
			for (i = 0; i < rowsC; i++)
			{
				for(j = 0; j < colsC; j++)
				{
					mx = 0;
					
					// ciclo solo sugli elementi nonzero della jesima colonna di b
					for (k = b.cidx(j); k <= (b.xcidx(j+1) - 1); k++)
					{	
						// b.data(k) mi da il valore del kesimo elemento
						// del sottovettore degli elementi nonzero della
						// jesima colonna di b
						// b.ridx(k) mi da la riga del kesimo elemento
						// del sottovettore degli elementi nonzero della
						// jesima colonna di b
						mn = calc_tnorm(a(i, b.xridx(k)), b.xdata(k));
						if (mn > mx)
							mx = mn;
					}
		
					//aggiungo il controllo che l'elemento aggiunto alla matrice sparsa non sia uno 0
					//perchè altrimenti bisognerebbe comprimere la matrice sparsa con la rimozione degli 0 (molto costosa)
					if (mx != 0)
						c(i, j) = mx;
				}
			}

			//funzione che comrpime la matrice sparsa riducendo il numero di elementi nonzero
			//Se le si passa true come parametro si vuole che la funzione rimuova eventuali 0 dalla matrice sparsa
			//poiche questo è molto dispendioso computazionalmente
			//semplicemente è meglio non aggiugnere gli elementi uguali a 0 alla matrice sparsa
			c.maybe_compress();
			return octave_value(c);
		}
	}
}


double calc_tnorm(double first, double second)
{
	if(first < second)
		return first;
	else
		return second;
}
