/*@ BSdepend.h - This file defines all the message-passing macros
              for the BlockSolve95 package.

	System Description:
    All the macros can MPI routines.  Note that there is blocking
    version and a nonblocking version based on whether NO_BLOCKING_SEND
    is defined.

 @*/

#ifndef __BSdependh
#define __BSdependh

/* include MPI */
#include "mpi.h"
#define MPI_Aint int

#include <stdio.h>

#if defined(PARCH_freebsd)
#include <stdlib.h>
#endif

#if defined(PARCH_sun4) && !defined(__cplusplus) && defined(_Gnu_)
extern int fprintf(FILE*,const char*,...);
extern void sscanf(char *,...);
extern int printf(const char *,...);
extern void *malloc(long unsigned int );
extern void free(void *);
extern int srand(unsigned int);
extern int rand();
#endif
#if defined(__cplusplus)
extern "C" {
extern void *malloc(long unsigned int );
extern void free(void *);
extern int  abs(int);
extern double fabs(double);
extern void srand(int);
extern int rand();
extern double drand48();
extern void srand48(long);
extern int exit(int);
}
#endif

#define DEBUG_ALL 1

#ifdef DEBUG_ALL
#define DEBUG_ACT printf("ERROR: Code %d occured at Line %d in File %s\n",__BSERROR_STATUS,__LINE__,__FILE__);

#define DEBUG_ACTC(msg) printf("ERROR: Code %d occured at Line %d in File %s: %s\n",__BSERROR_STATUS,__LINE__,__FILE__,msg);

#define SETERR(code_num) {__BSERROR_STATUS=code_num;DEBUG_ACT;}
#define SETERRC(code_num,str) {__BSERROR_STATUS=code_num;DEBUG_ACTC(str);}

#define GETERR (__BSERROR_STATUS)
#define CHKERR(code_num) {if (GETERR) {DEBUG_ACT;return;}}
#define CHKERRN(code_num) {if (GETERR) {DEBUG_ACT;return 0;}}

#else
#define SETERR(code_num)
#define SETERRC(code_num,str)
#define CHKERR(a)
#define CHKERRN(a)
#endif

#ifdef TRMALLOC
#define MALLOC(c) TrMalloc(c,__LINE__,__FILE__)
#define FREE(c) TrFree(c,__LINE__,__FILE__)
#define CHECK_MEMORY() \
{ \
	int ierr99; \
	ierr99 = TrDump(stderr); \
}
#else
#define MALLOC(c) malloc(c)
#define FREE(c) free(c)
#define CHECK_MEMORY()
#endif

#define RECVSYNCNOMEM(type,buf,length,data_type,p_info,mpistat) \
	MPI_Recv(buf,length,data_type,MPI_ANY_SOURCE,type,p_info->procset,&mpistat)

#define RECVSYNCUNSZ(type,buf,length,data_type,p_info,mpistat) \
{ \
	MPI_Aint size99; \
	MPI_Status mpistat99; \
	MPI_Probe(MPI_ANY_SOURCE,type,p_info->procset,&mpistat99); \
	MPI_Get_count(&mpistat99,data_type,&length); \
	MPI_Type_size(data_type,&size99); \
	MY_MALLOC(buf,(void *),size99*length,1); \
	MPI_Recv(buf,length,data_type,mpistat99.MPI_SOURCE, \
		mpistat99.MPI_TAG,p_info->procset,&mpistat); \
}

#define RECVSYNCUNSZN(type,buf,length,data_type,p_info,mpistat) \
{ \
	MPI_Aint size99; \
	MPI_Status mpistat99; \
	MPI_Probe(MPI_ANY_SOURCE,type,p_info->procset,&mpistat99); \
	MPI_Get_count(&mpistat99,data_type,&length); \
	MPI_Type_size(data_type,&size99); \
	MY_MALLOCN(buf,(void *),size99*length,1); \
	MPI_Recv(buf,length,data_type,mpistat99.MPI_SOURCE, \
		mpistat99.MPI_TAG,p_info->procset,&mpistat); \
}

#define MSGFREERECV(msg) MY_FREE(msg)

#define RECVASYNCNOMEMFORCE(type,buf,length,data_type,msg_id,p_info) \
	MPI_Irecv(buf,length,data_type,MPI_ANY_SOURCE,type,p_info->procset,&(msg_id))

#define SENDASYNCNOMEMFORCE(type,buf,size,to_proc,data_type,msg_id,p_info) \
	MPI_Irsend(buf,size,data_type,to_proc,type,p_info->procset,&(msg_id))

#define SENDASYNCNOMEM(type,buf,size,to_proc,data_type,msg_id,p_info) \
	MPI_Isend((void *)buf,size,data_type,to_proc,type,p_info->procset,(MPI_Request *)(&(msg_id)))

#define SENDSYNCNOMEM(type,buf,size,to_proc,data_type,p_info) \
	MPI_Send((void *)buf,size,data_type,to_proc,type,(p_info->procset))

#define SENDWAITNOMEM(type,buf,size,to_proc,data_type,msg_id) \
{ \
	MPI_Status	stat99; \
	MPI_Wait(&(msg_id),&stat99); \
}

#define GISUM(sum_vec,vec_len,work_vec,procset) \
{ \
	int	i99, *iptr1 = (int *) sum_vec, *iptr2 = (int *) work_vec; \
	for (i99=0;i99<(vec_len);i99++) { \
		(iptr2)[i99] = (iptr1)[i99]; \
	} \
	MPI_Allreduce(iptr2,iptr1,vec_len,MPI_INT,MPI_SUM,procset); \
}

#define GIOR(sum_vec,vec_len,work_vec,procset) \
{ \
	int	i99, *iptr1 = (int *) sum_vec, *iptr2 = (int *) work_vec; \
	for (i99=0;i99<(vec_len);i99++) { \
		(iptr2)[i99] = (iptr1)[i99]; \
	} \
	MPI_Allreduce(iptr2,iptr1,vec_len,MPI_INT,MPI_LOR,procset); \
}

#define GIMIN(sum_vec,vec_len,work_vec,procset) \
{ \
	int	i99, *iptr1 = (int *) sum_vec, *iptr2 = (int *) work_vec; \
	for (i99=0;i99<(vec_len);i99++) { \
		(iptr2)[i99] = (iptr1)[i99]; \
	} \
	MPI_Allreduce(iptr2,iptr1,vec_len,MPI_INT,MPI_MIN,procset); \
}

#define GIMAX(sum_vec,vec_len,work_vec,procset) \
{ \
	int	i99, *iptr1 = (int *) sum_vec, *iptr2 = (int *) work_vec; \
	for (i99=0;i99<(vec_len);i99++) { \
		(iptr2)[i99] = (iptr1)[i99]; \
	} \
	MPI_Allreduce(iptr2,iptr1,vec_len,MPI_INT,MPI_MAX,procset); \
}

#define GDMAX(sum_vec,vec_len,work_vec,procset) \
{ \
	int	i99; \
	double	*dptr1 = (double *) sum_vec, *dptr2 = (double *) work_vec; \
	for (i99=0;i99<(vec_len);i99++) { \
		(dptr2)[i99] = (dptr1)[i99]; \
	} \
	MPI_Allreduce(dptr2,dptr1,vec_len,MPI_DOUBLE,MPI_MAX,procset); \
}

#define GDMIN(sum_vec,vec_len,work_vec,procset) \
{ \
	int	i99; \
	double	*dptr1 = (double *) sum_vec, *dptr2 = (double *) work_vec; \
	for (i99=0;i99<(vec_len);i99++) { \
		(dptr2)[i99] = (dptr1)[i99]; \
	} \
	MPI_Allreduce(dptr2,dptr1,vec_len,MPI_DOUBLE,MPI_MIN,procset); \
}

#define GDSUM(sum_vec,vec_len,work_vec,procset) \
{ \
	int	i99; \
	double	*dptr1 = (double *) sum_vec, *dptr2 = (double *) work_vec; \
	for (i99=0;i99<(vec_len);i99++) { \
		(dptr2)[i99] = (dptr1)[i99]; \
	} \
	MPI_Allreduce(dptr2,dptr1,vec_len,MPI_DOUBLE,MPI_SUM,procset); \
}

#define GFSUM(sum_vec,vec_len,work_vec,procset) \
{ \
	int	i99; \
	float	*fptr1 = (float *) sum_vec, *fptr2 = (float *) work_vec; \
	for (i99=0;i99<(vec_len);i99++) { \
		(fptr2)[i99] = (fptr1)[i99]; \
	} \
	MPI_Allreduce(fptr2,fptr1,vec_len,MPI_FLOAT,MPI_SUM,procset); \
}

#define GSYNC(procset) MPI_Barrier(procset)

#define PSISROOT(procinfo) ((procinfo->my_id == 0) ? 1 : 0)

typedef MPI_Comm ProcSet;

/* the function PSNbrTree returns the parent, left child, or right child */
/* processor number is the processors are organized conceptually as a tree */
/* op_code is one of the following */
#define PS_PARENT 0
#define PS_LCHILD 1
#define PS_RCHILD 2
#define PSNbrTree(op_code,nbr_id,procset) \
{ \
	int	my_id99, np99; \
	MPI_Comm_rank(procset,&my_id99); \
	MPI_Comm_size(procset,&np99); \
	switch(op_code) { \
		case PS_PARENT: \
			if (my_id99 == 0) { \
				nbr_id = -1; \
			} else { \
				nbr_id = (my_id99-1) / 2; \
			} \
			break; \
		case PS_LCHILD: \
			nbr_id = (2*my_id99) + 1; \
			break; \
		case PS_RCHILD: \
			nbr_id = (2*my_id99) + 2; \
			break; \
	} \
	if (nbr_id >= np99) nbr_id = -1; \
}

/* PICall(procedure,argc,argv) gets things started */
#define PICall(procedure,argc,argv) \
{ \
	MPI_Init(&argc,&argv); \
	procedure(argc,argv); \
	MPI_Finalize(); \
}

/* set up the right "Fortran naming" definitions for use in BSsparse.h */
/* somehow the name of your architecture must be identified */
/* the following setup works for the *vast* majority of systems */
/* this affects only the linking of the blas and lapack routines called */
/*
       FORTRANCAPS:       Names are uppercase, no trailing underscore
       FORTRANUNDERSCORE: Names are lowercase, trailing underscore
*/
#if defined(PARCH_cray) || defined(PARCH_NCUBE) || defined(PARCH_t3d)
#define FORTRANCAPS
#elif !defined(PARCH_rs6000) && !defined(PARCH_NeXT) && !defined(PARCH_hpux)
#define FORTRANUNDERSCORE
#endif

/* ********************************************************************** */
/* this is a set of macros that retrofit the code for machines on which
   blocking sends are a bad idea.  These macros make all sends asynchronous
   by allocating buffers for the synchronous sends and cleaning up
   those buffers as we go */

/* To turn this code "on" simply define NO_BLOCKING_SEND */
/* For now, the only architecture that we know needs this is the rs6000 */
/* and, perhaps, the HPs */
#if defined(PARCH_rs6000) || defined(PARCH_hpux) || defined(PARCH_t3d) || defined(PARCH_IRIX)
#define NO_BLOCKING_SEND 1
#endif

typedef	struct __BSmsg_list {
	int	msg_type;
	char *msg_buf;
	int	msg_len;
	int	msg_to;
	MPI_Datatype msg_data_type;
	MPI_Request	msg_id;
	struct	__BSmsg_list	*next;
} BSmsg_list;

#ifdef NO_BLOCKING_SEND
#define	MY_SEND_SYNC(Mmsg_list,Mmsg_type,Mmsg,Mmsg_len,Mmsg_to,Mmsg_data_type,Mp_info) \
{ \
	BSmsg_list *node_99; \
	int i99; \
	MPI_Aint size99; \
	char *tmsg_ptr99; \
	MY_MALLOC(node_99,(BSmsg_list *),sizeof(BSmsg_list),1); \
	node_99->next = Mmsg_list; \
	Mmsg_list = node_99; \
	MPI_Type_size(Mmsg_data_type,&size99); \
	if (Mmsg_len == 0) { \
		MY_MALLOC(node_99->msg_buf,(char *),size99,2); \
	} else { \
		MY_MALLOC(node_99->msg_buf,(char *),Mmsg_len*size99,3); \
	} \
	node_99->msg_type = Mmsg_type; \
	node_99->msg_len = Mmsg_len; \
	node_99->msg_to = Mmsg_to; \
	node_99->msg_data_type = Mmsg_data_type; \
	tmsg_ptr99 = (char *) Mmsg; \
	for (i99=0;i99<Mmsg_len*size99;i99++) { \
		node_99->msg_buf[i99] = tmsg_ptr99[i99]; \
	} \
	SENDASYNCNOMEM(Mmsg_type,node_99->msg_buf,Mmsg_len,Mmsg_to,Mmsg_data_type,\
		node_99->msg_id,Mp_info); \
	CHECK_SEND_LIST(Mmsg_list); \
}
#else
#define	MY_SEND_SYNC(Mmsg_list,Mmsg_type,Mmsg,Mmsg_len,Mmsg_to,Mmsg_data_type,Mp_info) \
{ \
	SENDSYNCNOMEM(Mmsg_type,Mmsg,Mmsg_len,Mmsg_to,Mmsg_data_type,Mp_info); \
}
#endif

#define	MCHECK_SEND_LIST(Mmsg_list) \
{ \
	BSmsg_list	*node_ptr_99, *prev_node_ptr_99, *tnode_ptr_99; \
	int	fin99; \
	MPI_Status	stat99; \
	node_ptr_99 = Mmsg_list; \
	prev_node_ptr_99 = Mmsg_list; \
	while (node_ptr_99 != NULL) { \
		MPI_Test(&(node_ptr_99->msg_id),&fin99,&stat99); \
		if (fin99) { \
			tnode_ptr_99 = node_ptr_99; \
			if (node_ptr_99 == Mmsg_list) { \
				Mmsg_list = Mmsg_list->next; \
				prev_node_ptr_99 = Mmsg_list; \
				node_ptr_99 = Mmsg_list; \
			} else { \
				prev_node_ptr_99->next = node_ptr_99->next; \
				node_ptr_99 = node_ptr_99->next; \
			} \
			MY_FREE(tnode_ptr_99->msg_buf); \
			MY_FREE(tnode_ptr_99); \
		} else { \
			prev_node_ptr_99 = node_ptr_99; \
			node_ptr_99 = node_ptr_99->next; \
		} \
	} \
}
#ifdef NO_BLOCKING_SEND
#define	CHECK_SEND_LIST(Mmsg_list) MCHECK_SEND_LIST(Mmsg_list)
#else
#define	CHECK_SEND_LIST(Mmsg_list)
#endif

#define MFINISH_SEND_LIST(Mmsg_list) \
{ \
	BSmsg_list	*tnode99; \
	while(Mmsg_list != NULL) { \
		tnode99 = Mmsg_list; \
		Mmsg_list = Mmsg_list->next; \
		SENDWAITNOMEM(tnode99->msg_type,tnode99->msg_buf,tnode99->msg_len, \
			tnode99->msg_to,tnode99->msg_data_type,tnode99->msg_id); \
		MY_FREE(tnode99->msg_buf); \
		MY_FREE(tnode99); \
	} \
}
#ifdef NO_BLOCKING_SEND
#define FINISH_SEND_LIST(Mmsg_list) MFINISH_SEND_LIST(Mmsg_list)
#else
#define FINISH_SEND_LIST(Mmsg_list)
#endif

#endif


syntax highlighted by Code2HTML, v. 0.9.1