#ifndef _COMDEFS_H
#define _COMDEFS_H
/************************ comdefs.h *************************************
*									*
*  Macros and declarations for communications routines com_*.c          *
*  MIMD version 6 							*
*									*
*/
#include "../include/su3.h"
#include "../include/complex.h"
#include "../include/macros.h"
#include "../include/lattice.h"		/* Needed ONLY for "site" in this header */
#include "../include/machine.h"

#ifdef COMM_MPI
#include <mpi.h>
#endif

#define MAX_GATHERS 32		/* Maximum number of gather tables */

/* arguments to the make_gather() routine */
#define FORWARDS 1
#define BACKWARDS (-1)		/* BACKWARDS = -FORWARDS */
#define OWN_INVERSE 0
#define WANT_INVERSE 1
#define NO_INVERSE 2
#define ALLOW_EVEN_ODD 0
#define NO_EVEN_ODD 1
#define SAME_PARITY 0
#define SWITCH_PARITY 1
#define SCRAMBLE_PARITY 2

#ifdef COMM_GB
/* communication types */
#define COMM_CPU1 0
#define COMM_CPU2 1
#define COMM_ROW 2
#define COMM_COL 3
#define COMM_ROWCOL 4
#endif

/* Structure to keep track of outstanding sends and receives */
typedef struct
{
    int size;			/* size of each element of the field */
    int n;			/* number of sites to be sent/received */
    char *sbuf;			/* send buffer */
    char *rbuf;			/* receive buffer */
    char *rbuf_temp;		/* temporary receive buffer */
    char **ptr;			/* pointers to fields to speed up restart_gather */
#ifdef COMM_MPI
    MPI_Request srequest, rrequest;
#endif
    int done;
} msg_tag;




/**********************************************************************/
/* Declarations for all routines called in the com_*.c files */

__targetHost__ void start_handlers(  );

/* JuBE: no args needed */
__targetHost__ void initialize_machine_KE();

__targetHost__ void make_nn_gathers(  );
__targetHost__ void sort_eight_special( void **pt );

__targetHost__ void neighbor_coords_special( int x, int y, int z, int t,	/* coordinates of site */
			      int *dirpt,	/* direction (eg XUP) */
			      int fb,	/* "forwards/backwards"  */
			      int *x2p, int *y2p, int *z2p, int *t2p );
			  /* pointers to coordinates of neighbor */
__targetHost__ int make_gather( void ( *func ) ( int, int, int, int, int *, int, int *, int *, int *, int * ),
		 /* function which defines sites to gather from */
		 int *args,	/* list of arguments, to be passed to function */
		 int inverse,	/* OWN_INVERSE, WANT_INVERSE, or NO_INVERSE */
		 int want_even_odd,	/* ALLOW_EVEN_ODD or NO_EVEN_ODD */
		 int parity_conserve );	/* {SAME,SWITCH,SCRAMBLE}_PARITY */

__targetHost__ void neighbor_coords( int x, int y, int z, int t,	/* coordinates of site */
		      int dir,	/* direction (eg XUP) */
		      int *x2p, int *y2p, int *z2p, int *t2p );
			     /* pointers to coordinates of neighbor */
__targetHost__ msg_tag *start_gather_from_temp(
				    /* arguments */
				    void *field,	/* which field? pointer returned by malloc() */
				    int size,	/* size in bytes of the field (eg sizeof(su3_vector)) */
				    int dist, int index,	/* direction to gather from. eg XUP - index into
								   neighbor tables */
				    int parity,	/* parity of sites whose neighbors we gather.
						   one of EVEN, ODD or EVENANDODD. */
				    char **dest );	/* one of the vectors of pointers */

__targetHost__ void restart_gather_from_temp(
				  /* arguments */
				  void *field,	/* which field? pointer returned by malloc() */
				  int size,	/* size in bytes of the field (eg sizeof(su3_vector)) */
				  int dist, int index,	/* direction to gather from. eg XUP - index into
							   neighbor tables */
				  int parity,	/* parity of sites whose neighbors we gather.
						   one of EVEN, ODD or EVENANDODD. */
				  char **dest,	/* one of the vectors of pointers */
				  msg_tag * mbuf );	/* previously returned by start_gather */

__targetHost__ void wait_gather_KE( msg_tag * mbuf );
__targetHost__ void cleanup_gather( msg_tag * mbuf );

__targetHost__ msg_tag *start_general_gather_from_temp(
					    /* arguments */
					    void *field,	/* which field? Some member of structure "site" */
					    int size,	/* size in bytes of the field (eg sizeof(su3_vector)) */
					    int dist,	/* separation */
					    int *displacement,	/* displacement to gather from. four components */
					    int parity,	/* parity of sites to which we gather.
							   one of EVEN, ODD or EVENANDODD. */
					    char **dest );	/* one of the vectors of pointers */

__targetHost__ void wait_general_gather( msg_tag * mbuf );
__targetHost__ void cleanup_general_gather( msg_tag * mbuf );

__targetHost__ void node0_printf( const char *fmt, ... );
__targetHost__ void verbose_fprintf( FILE * file, const char *fmt, ... );
__targetHost__ void node0_fprintf( FILE * file, const char *fmt, ... );

__targetHost__ char *machine_type_KE(  );
__targetHost__ int mynode_KE(  );
__targetHost__ int numnodes_KE(  );
__targetHost__ void numnodes2( int *x, int *y );
__targetHost__ void numnodes3( int *x, int *y, int *z );
#ifdef COMM_GB
__targetHost__ void mynode3( int *n_x, int *n_y, int *n_z );
#endif

__targetHost__ void g_sync_KE(  );
__targetHost__ void g_doublesum_KE( double *dpt );
__targetHost__ void g_vecdoublesum( double *dpt, int ndoubles );
__targetHost__ void g_complexsum( complex * cpt );
__targetHost__ void g_veccomplexsum( complex * cpt, int ncomplex );
__targetHost__ void g_wvectorsum( wilson_vector * wvpt );
__targetHost__ void g_doublemax_KE( double *dpt );
__targetHost__ void broadcast_double_KE( double *dpt );
__targetHost__ void broadcast_char( char *buf, int size );
__targetHost__ void broadcast_bytes( char *buf, int size );
__targetHost__ void broadcast_int_KE( int *buf );
__targetHost__ void collect_bytes( char *buf, char *res, int size );
__targetHost__ void gen_broadcast_bytes( char *buf, int size, int node );
__targetHost__ void send_integer( int tonode, int *address );
__targetHost__ void receive_integer( int *address );

/* On the Paragon dclock is a library routine with the
   same functionality as ours */
/* Either way, it needs to be declared double */
__targetHost__ double dclock(  );
__targetHost__ void time_stamp( char *msg );

__targetHost__ void terminate_KE( int status );
__targetHost__ long long get_totcomm(  );

#endif /* _COMDEFS_H */
