#include "BSprivate.h"

/*+ BSpack_n_send - Pack and Send messages for the coloring

	Input Parameters: 
.   n_msg_queue - the number of messages to send
.   msg_queue - the queue of messages
.   A - the sparse matrix
.   procinfo - the usual processor info
.   local_color - the local coloring
.   local_ptr - array of pointers indicating which neighbors in
.               each row are local neighbors (on this processor)
.   global_ptr - array of pointers indicating which neighbors in
.                each row are global neighbors (not on this processor)
.   msg_buffer - space in which to pack messages
.   msg_buffer_size - the size of the message buffer
.   type - the message type to use

+*/
void BSpack_n_send(BSmsg_list *msg_list, int n_msg_queue, int *msg_queue,
	BSspmat *A, BSprocinfo *procinfo, int *local_color, int *local_ptr,
	int *global_ptr, int *msg_buffer, int msg_buffer_size, int type)
{
	BSsprow	**local_col_array;
	int i, l_vtx, p1;
	BSsprow	*t_node;
	int	*row_ptr;
	int	*msg_proc_num;
	int	*msg_queue_ptr;
	int	proc_num, next_proc_num, msg_buffer_ptr;
	int	owner;

	local_col_array = A->rows;
	MY_MALLOC(msg_proc_num,(int *),sizeof(int)*n_msg_queue,1);
	MY_MALLOC(msg_queue_ptr,(int *),sizeof(int)*n_msg_queue,2);

	proc_num = INT_MAX; 

	for (i=0; i<n_msg_queue; i++) {
		l_vtx = msg_queue[i];
		msg_queue_ptr[i] = global_ptr[l_vtx];
		t_node = local_col_array[l_vtx];
		row_ptr = t_node->col;
		(*A->map->fglobal2proc) (1,&(row_ptr[msg_queue_ptr[i]]),
			&(msg_proc_num[i]),procinfo,A->map); CHKERR(0);
		if (msg_proc_num[i] < proc_num) 
			proc_num = msg_proc_num[i];
	}

	while (proc_num < INT_MAX) {

		next_proc_num = INT_MAX;
		msg_buffer[0] = 0;
		msg_buffer_ptr = 1;
		for (i=0; i<n_msg_queue; i++) {
			if(msg_proc_num[i] == proc_num) {
				if ((msg_buffer_ptr+4) > msg_buffer_size) {
					MY_SEND_SYNC(msg_list,type,&(msg_buffer[0]),msg_buffer_ptr,
						proc_num,MPI_INT,procinfo);
					msg_buffer[0] = 0;
					msg_buffer_ptr = 1;
				}
				l_vtx = msg_queue[i];
				t_node = local_col_array[l_vtx];
				row_ptr = t_node->col;
				msg_buffer[0]++;
				p1 = msg_buffer_ptr;
				(*A->map->flocal2global) (1,&l_vtx,&(msg_buffer[p1]),
					procinfo,A->map); CHKERR(0);
				msg_buffer[p1+1] = local_color[l_vtx];
				msg_buffer[p1+2] = 1;
				msg_buffer[p1+3] = row_ptr[msg_queue_ptr[i]];
				p1 = msg_buffer_ptr+2;
				msg_queue_ptr[i]++;
				msg_buffer_ptr += 4;
				(*A->map->fglobal2proc)(1,&(row_ptr[msg_queue_ptr[i]]),
					&owner,procinfo,A->map); CHKERR(0);
				while (owner == proc_num) {
					if (msg_buffer_ptr >= msg_buffer_size) {
						MY_SEND_SYNC(msg_list,type,&(msg_buffer[0]),
							msg_buffer_ptr,proc_num,MPI_INT,procinfo);
						msg_buffer[0] = 1;
						(*A->map->flocal2global) (1,&l_vtx,
							&(msg_buffer[1]),procinfo,A->map); CHKERR(0);
						msg_buffer[2] = local_color[l_vtx];
						msg_buffer[3] = 0;
						p1 = 3;
						msg_buffer_ptr = 4;
					}
					msg_buffer[p1]++;
					msg_buffer[msg_buffer_ptr]
						= row_ptr[msg_queue_ptr[i]];
					msg_queue_ptr[i]++;
					msg_buffer_ptr++;
					(*A->map->fglobal2proc)
						(1,&(row_ptr[msg_queue_ptr[i]]),
						&owner,procinfo,A->map); CHKERR(0);
				}
				if (msg_queue_ptr[i] >= local_ptr[l_vtx]) {
					msg_proc_num[i] = INT_MAX;
				}
				else {
					(*A->map->fglobal2proc) 
						(1,&(row_ptr[msg_queue_ptr[i]]),
						&(msg_proc_num[i]),procinfo,A->map); CHKERR(0);
				}
			}
			if (msg_proc_num[i] < next_proc_num)
				next_proc_num = msg_proc_num[i];
		}
		MY_SEND_SYNC(msg_list,type,&(msg_buffer[0]),msg_buffer_ptr,proc_num,
			MPI_INT,procinfo);
		proc_num = next_proc_num;
	}
	MY_FREE(msg_proc_num);
	MY_FREE(msg_queue_ptr);
}



syntax highlighted by Code2HTML, v. 0.9.1