#include "BSprivate.h"

/*+ BStrans_perm_cl - Find the complete mapping from clique to i-node

    Input Parameters:
.   A - a sparse matrix
.   gnum - the global numbering
.   procinfo - the usual processor stuff

    Returns:
    the mapping from clique to i-node

 +*/

#define __TREE_RETURN
#include "BStree.h"

BScl_2_inode *BStrans_perm_cl(BSspmat *A, BSnumbering *gnum, 
			BSprocinfo *procinfo)
{
	BStree	tree;
	BStree_ptr	node_ptr;
	int	*iptr;
	BSbb *row_bb;
	int	i, j;
	int	count;
	BSsprow *row;
	int	*colptr;
	int	*addrs, *answs;
	void    (*map)(int,int *,int *,BSprocinfo *,BSmapping *);
	void    (*glmap)(int,int *,int *,BSprocinfo *,BSmapping *);
	int	num_cols;
	int	num_nz;
	int	cval, lval, row_gval;
	int	found;
	BScl_2_inode *trans;
	int	max_row_len;
	int	*map_work;

	/* initialize BB */
	row_bb = BSinit_bb(A->num_rows,A->map); CHKERRN(0);
	BSpost_noaddr_bb(row_bb,A->num_rows,gnum->numbers); CHKERRN(0);

	/* set up requests */
	num_nz = BSnonlocalnz(A,&max_row_len,procinfo); CHKERRN(0);
	MY_MALLOCN(addrs,(int *),sizeof(int)*num_nz,1);
	MY_MALLOCN(answs,(int *),sizeof(int)*num_nz,2);
	MY_MALLOCN(map_work,(int *),sizeof(int)*max_row_len,2);
	count = 0;
	map = A->map->fglobal2proc;
	for (i=0;i<A->num_rows;i++) {
		row = A->rows[i];
		colptr = row->col;
     	(*map)(row->length,colptr,map_work,procinfo,A->map); CHKERRN(0);
		for (j=0;j<row->length;j++) {
			if (map_work[j] != procinfo->my_id) {
				addrs[count] = colptr[j];
				count++;
			}
		}
	}

	/* query BB */
	BSquery_match_bb(row_bb,count,addrs,answs,procinfo); CHKERRN(0);
	MY_FREEN(addrs);
	BSfree_bb(row_bb); CHKERRN(0);

	count = 0;
	map = A->map->fglobal2proc;
	glmap = A->map->fglobal2local;
	num_cols = 0;
	MY_INIT_TREE(tree,sizeof(int));
	for (i=0;i<A->num_rows;i++) {
		row = A->rows[i];
		colptr = row->col;
		row_gval = gnum->numbers[i];
     	(*map)(row->length,colptr,map_work,procinfo,A->map); CHKERRN(0);
		for (j=0;j<row->length;j++) {
			if (map_work[j] != procinfo->my_id) {
				cval = answs[count];
				count++;
			} else {
				(*glmap)(1,&(colptr[j]),&lval,procinfo,A->map); CHKERRN(0);
				cval = gnum->numbers[lval];
			}
			if(A->icc_storage) {
				if (row_gval >= cval) {
					MY_INSERT_TREE_NODE(tree,cval,found,node_ptr,num_cols);
					if (!found) {
						iptr = (int *) MY_GET_TREE_DATA(node_ptr);
						(*iptr) = map_work[j];
					}
				}
			} else {
				/* Do not need row_gval >= cval check for nonsymmetric case */
				MY_INSERT_TREE_NODE(tree,cval,found,node_ptr,num_cols);
				if (!found) {
					iptr = (int *) MY_GET_TREE_DATA(node_ptr);
					(*iptr) = map_work[j];
				}
			}
		}
	}
	MY_FREEN(answs);
	MY_FREEN(map_work);

	/* copy the linked list into the array structure */
	MY_MALLOCN(trans,(BScl_2_inode *),sizeof(BScl_2_inode),5);
	MY_MALLOCN(trans->g_offset,(int *),sizeof(int)*(num_cols+1),6);
	MY_MALLOCN(trans->proc,(int *),sizeof(int)*(num_cols+1),6);
	MY_MALLOCN(trans->inode_index,(int *),sizeof(int)*(num_cols+1),6);
	MY_MALLOCN(trans->d_mats,(BSdense *),sizeof(BSdense)*(num_cols+1),6);
	trans->num_cols = num_cols;
	trans->g_offset[num_cols] = INT_MAX;
	count = 0;
	MY_FIRST_IN_TREE(tree,node_ptr);
	while (! IS_TREE_PTR_NULL(node_ptr)) {
		trans->g_offset[count] = MY_GET_TREE_KEY(node_ptr);
		iptr = (int *) MY_GET_TREE_DATA(node_ptr);
		trans->proc[count] = (*iptr);
		count++;
		MY_NEXT_IN_TREE(node_ptr);
	}
	MY_FREE_TREE(tree);
	return(trans);
}


syntax highlighted by Code2HTML, v. 0.9.1