#include "util.h"

template<typename ComplexOrRealType>
void coord2csr(const int nrow_A,
               const int ncol_A,
               const int nnz,
               const int ilist[],
               const int jlist[],
               const ComplexOrRealType alist[],
               int arowptr[],
               int acol[],
               ComplexOrRealType aval[] )
{
	/*
 * --------------------------------------
 * convert from coordinate storage format
 * "i j aij"
 * to compressed sparse row format
 *
 * need arowptr[] to have size nrow_A + 1
 * need acol[] to have size nnz
 * need aval[] to have size nnz
 * --------------------------------------
 */

	int* nnz_row = new int[nrow_A];


	{
		int ia = 0;
		for(ia=0; ia < nrow_A; ia++) {
			nnz_row[ia] = 0;
		};
	}

	/*
  * ------------------------
  * check ilist(:), jlist(:)
  * ------------------------
  */
#ifndef NDEBUG
	{
		int k = 0;
		for(k = 0; k < nnz; k++) {
			int ia = ilist[k];
			int ja = jlist[k];


			int isok_ia = (0 <= ia) && (ia < nrow_A);
			int isok_ja = (0 <= ja) && (ja < ncol_A);

			assert( isok_ia );
			assert( isok_ja );
		};
	}
#endif


	/*
  * -------------------------------------------------
  * first pass to compute number of non-zeros per row
  * -------------------------------------------------
  */
	{
		int k = 0;
		for(k=0; k < nnz; k++) {
			int ia = ilist[k];
			nnz_row[ia] += 1;
		};
	}

	/*
  * ------------------------------
  * prefix sum to setup row poiner
  * ------------------------------
  */
	{
		int ia = 0;

		arowptr[0] = 0;
		for(ia=0; ia < nrow_A; ia++) {
			arowptr[ia+1] = arowptr[ia] + nnz_row[ia];
		};

		for(ia=0; ia < nrow_A; ia++) {
			nnz_row[ia] = 0;
		};

	}

	/*
  * -------------------------------------------------------------
  * second pass to fill in data into compressed sparse row format
  * -------------------------------------------------------------
  */
	{
		int k = 0;

		for(k=0; k < nnz; k++) {
			int ia = ilist[k];
			int ja = jlist[k];
			ComplexOrRealType aij = alist[k];

			int ipos = arowptr[ia] + nnz_row[ia];

			acol[ipos] = ja;
			aval[ipos] = aij;

			nnz_row[ia] += 1;
		};
	}

	delete[] nnz_row;
}
