#include "BSprivate.h"

/*+ BSrow_err_check - Check the sparse matrix for error

    Input Parameters:
.   A - the sparse matrix
.   procinfo - the usual processor stuff

    Returns:
    void

    Notes:
    This routine checks for many common errors in a sparse matrix
    data structure.  It can be used for checking the initial user
    input as well as for checking matrices generated within BSmain_perm.

 +*/
void BSrow_err_check(BSspmat *A, BSprocinfo *procinfo)
{
	int	i, j, k;
	BSsprow *row, *trow;
	void (*lmap)(int,int *,int *,BSprocinfo *,BSmapping *);
	void (*gmap)(int,int *,int *,BSprocinfo *,BSmapping *);
	void (*pmap)(int,int *,int *,BSprocinfo *,BSmapping *);
	int	gval, lval, pval;
	int	found;

	if (A == NULL) {
		MY_SETERRC(MATRIX_ERROR0,"Null matrix pointer\n");
	}
	if (A->num_rows <= 0) {
		MY_SETERRC(MATRIX_ERROR1,"Non-positive number of local rows\n");
	}
	if (A->global_num_rows <= 0) {
		MY_SETERRC(MATRIX_ERROR2,"Non-positive number of global rows\n");
	}
	/* check for consistent mapping */
	if (A->map == NULL) {
		MY_SETERRC(MATRIX_ERROR3,"Null matrix map pointer\n");
	}
	lmap = A->map->flocal2global;
	if (lmap == NULL) {
		MY_SETERRC(MATRIX_ERROR4,"No local to global map\n");
	}
	gmap = A->map->fglobal2local;
	if (gmap == NULL) {
		MY_SETERRC(MATRIX_ERROR5,"No global to local map\n");
	}
	pmap = A->map->fglobal2proc;
	if (pmap == NULL) {
		MY_SETERRC(MATRIX_ERROR6,"No global to processor map\n");
	}
	for (i=0;i<A->num_rows;i++) {
		(*lmap)(1,&i,&gval,procinfo,A->map); CHKERR(0);
		if ((gval < 0) || (gval >= A->global_num_rows)) {
			MY_SETERRC(MATRIX_ERROR7,"Bad local to global mapping\n");
		}
		(*gmap)(1,&gval,&lval,procinfo,A->map); CHKERR(0);
		if (lval != i) {
			MY_SETERRC(MATRIX_ERROR8,"Bad global to local mapping\n");
		}
		(*pmap)(1,&gval,&pval,procinfo,A->map); CHKERR(0);
		if (pval != procinfo->my_id) {
			MY_SETERRC(MATRIX_ERROR9,"Bad global to processor mapping\n");
		}
		row = A->rows[i];
		if (row == NULL) {
			MY_SETERRC(MATRIX_ERROR10,"Null row pointer\n");
		}
		if (row->length < 1) {
			MY_SETERRC(MATRIX_ERROR11,"Zero or Negative row length\n");
		}
		if (row->col == NULL) {
			MY_SETERRC(MATRIX_ERROR17,"Null column pointer\n");
		}
		for (j=0;j<row->length;j++) {
			if ((row->col[j] < 0) || (row->col[j] >= A->global_num_rows)) {
				MY_SETERRC(MATRIX_ERROR13,"Bad column number\n");
			}
			/* check for local symmetry */
			(*gmap)(1,&(row->col[j]),&lval,procinfo,A->map); CHKERR(0);
			if (lval >= 0) {
				trow = A->rows[lval];
				found = FALSE;
				for (k=0;k<trow->length;k++) {
					/* find someone who is connected to me */
					if (trow->col[k] == gval) {
						found = TRUE;
						break;
					}
				}
				if (!found) {
					MY_SETERRC(MATRIX_ERROR16,"Local asymmetry\n");
				}
			}
		}
		for (j=0;j<row->length-1;j++) {
			if (row->col[j] == row->col[j+1]) {
				MY_SETERRC(MATRIX_ERROR14,"Duplicate column number\n");
			}
			if (row->col[j] > row->col[j+1]) {
				MY_SETERRC(MATRIX_ERROR15,"Out of order column number\n");
			}
		}
	}
}


syntax highlighted by Code2HTML, v. 0.9.1