/*************************************************************************
 *                                                                       *
 *  INTERPROCESSOR COLLECTIVE COMMUNICATIONS LIBRARY                     *
 *  (InterCom)                                                           *
 *                                                                       *
 *  This library is funded by a grant from the Intel Research Council    *
 *  Intel Supercomputer Systems Division and the University of Texas     *
 *  Center for High Performance Computing                                *
 *                                                                       *
 *  Satya Gupta          -- Intel Corporation SSD division               *
 *  David G. Payne       -- Intel Corporation SSD division               *
 *  Lance Shuler         -- Sandia National Laboratories                 *
 *  Robert van de Geijn  -- University of Texas at Austin                *
 *  Jerrell Watts        -- California Institue of Technology            *
 *                                                                       *
 *************************************************************************/
/*
 * GROUP BETA RELEASE 0.0.1
 */
/* Misc. global constants */
#ifndef NULL
  #define NULL 0
#endif
#ifndef TRUE
  #define TRUE 1
#endif
#ifndef FALSE
  #define FALSE 0
#endif
#ifndef YES
  #define YES 1
#endif
#ifndef NO
  #define NO 0
#endif

#define NO_VERIFY     /* Do not check that recvcounts are equal to sendcounts */

/*
** Threshold for doing the short vector approach 
** to avoid added overhead for short vectors
*/
extern long iCC_g_THRESHOLD;

/* Initialization and Debug flags */
extern long iCC_g_INIT;
extern long iCC_g_DEBUG;

/* Error Codes */
#define iCC_g_OK			(0)
#define iCC_g_ERROR_NULL		(1)
#define iCC_g_ERROR_COMM_NULL		(2)
#define iCC_g_ERROR_GROUP_NULL		(3)
#define iCC_g_ERROR_GROUP_EMPTY		(4)
#define iCC_g_ERROR_OP_NULL		(5)
#define iCC_g_ERROR_DATATYPE_NULL	(6)
#define iCC_g_ERROR_DATATYPE_MISMATCH	(7)
#define iCC_g_ERROR_INTERCOMMUNICATOR	(8)
#define iCC_g_ERROR_ROOT		(9)
#define iCC_g_ERROR_MYPOS		(10)
#define iCC_g_ERROR_MEMBERSHIP		(11)
#define iCC_g_ERROR_NO_INITIALIZATION   (12)
#define iCC_g_ERROR_MALLOC		(13)
#define iCC_g_ERROR_UNEQUAL_COUNTS	(14)
#define iCC_g_ERROR_BLOCK_SIZE		(15)


/***************************************
 *  Datatype Stuctures and definitions *
 ***************************************/

typedef enum {
  iCC_g_INTenum=1,iCC_g_LONGenum,iCC_g_FLOATenum,iCC_g_DOUBLEenum,
  iCC_g_BYTEenum,iCC_g_CHARenum,iCC_g_LOGICALenum
} iCC_g_DATATYPE_NAME;

typedef struct datatype_struct {
  iCC_g_DATATYPE_NAME  datatype_name;   /* name of datatype */
  long               size;        /* size of datatype in bytes */
} iCC_g_tDatatype;
typedef iCC_g_tDatatype *iCC_g_Datatype;

/* Global pre-assigned datatypes */
extern iCC_g_Datatype iCC_g_int_dtype;
extern iCC_g_Datatype iCC_g_long_dtype;
extern iCC_g_Datatype iCC_g_float_dtype;
extern iCC_g_Datatype iCC_g_double_dtype;
extern iCC_g_Datatype iCC_g_byte_dtype;
extern iCC_g_Datatype iCC_g_char_dtype;
extern iCC_g_Datatype iCC_g_logical_dtype;

/* datatype defines */
#define iCC_g_INT	    iCC_g_int_dtype
#define iCC_g_LONG	    iCC_g_long_dtype
#define iCC_g_FLOAT	    iCC_g_float_dtype
#define iCC_g_DOUBLE	    iCC_g_double_dtype
#define iCC_g_BYTE	    iCC_g_byte_dtype
#define iCC_g_CHAR	    iCC_g_char_dtype
#define iCC_g_LOGICAL	    iCC_g_logical_dtype

/* Fortran logicals */
extern long iCC_g_F_TRUE;
extern long iCC_g_F_FALSE;
#define iCC_g_FROM_F_LOGICAL( log )	((log) ? TRUE : FALSE)
#define iCC_g_TO_F_LOGICAL( log )	((log) ? iCC_g_F_TRUE : iCC_g_F_FALSE)

/**********************************
 *  Group/Communicator Structures *
 **********************************/

/* Global MPI-like Constants */
#define iCC_g_UNDEFINED   (-32766)
#define iCC_g_IDENT        (0)
#define iCC_g_CONGRUENT    (1)
#define iCC_g_SIMILAR      (2)
#define iCC_g_UNEQUAL      (3)
#define iCC_g_GROUP_NULL  ((iCC_g_Group) 0)
#define iCC_g_COMM_NULL   ((iCC_g_Comm) 0)
#define iCC_g_DATATYPE_NULL   ((iCC_g_Datatype) 0)

/* Group Structure */
typedef struct group_struct {
  long ref;                  /* group reference counter */
  long mypos;                /* my position in group list */
  long nlist;                /* number of members of the group */
  long *list;                /* list of members of the group */
  long ndiv;                 /* number of divisors in div[] */
  long *div;                 /* integer divisors of nlist */
  long mypos_row,mypos_col;  /* my position in rowlist and collist */
  long nrowlist,ncollist;    /* number of members in rowlist and collist */
  long *rowlist;             /* nodes in this node's physical row */
  long *collist;             /* nodes in this node's physical column */
  long nrdiv,ncdiv;          /* number of divisors in rdiv and cdiv */
  long *rdiv;                /* integer divisors of nrowlist */
  long *cdiv;                /* integer divisors of ncollist  */
} iCC_g_tgroup; 
typedef iCC_g_tgroup *iCC_g_Group;

/* Communicator Structure */
typedef struct comm_struct{
  long       inter_flag;     /* inter/intra-communicator flag */
  long       source;         /* local rank of process */
  iCC_g_Group  group;         /* intra-comm: local group or */
                             /* inter-comm: remote group   */
  iCC_g_Group  local_group;   /* inter-comm only: local group */
  void       **attrib;       /* attributes: not yet supported */
} iCC_g_tcomm;
typedef iCC_g_tcomm  *iCC_g_Comm;

/* Global MPI-like Variables */
extern iCC_g_Group iCC_g_GROUP_EMPTY;
extern iCC_g_Comm  iCC_g_COMM_WORLD;
extern iCC_g_Comm  iCC_g_COMM_SELF;


/****************************************
 *  Collective Communication Structures *
 ****************************************/

/* User provided operator function */
typedef void (iCC_g_Uop)();

/* iCC operator function structure */
typedef struct op_struct {
  iCC_g_Uop           *uop;
  iCC_g_DATATYPE_NAME  datatype_name;
  long               commute;
} iCC_g_tOp;
typedef iCC_g_tOp *iCC_g_Op;

#define iCC_g_OP_NULL ((iCC_g_Op)0)

/* Remove these declarations once groups are in the library */
extern iCC_g_Uop iCC_dhigh;
extern iCC_g_Uop iCC_dlow;
extern iCC_g_Uop iCC_dsum;
extern iCC_g_Uop iCC_dprod;
extern iCC_g_Uop iCC_ihigh;
extern iCC_g_Uop iCC_ilow;
extern iCC_g_Uop iCC_isum;
extern iCC_g_Uop iCC_iprod;
extern iCC_g_Uop iCC_shigh;
extern iCC_g_Uop iCC_slow;
extern iCC_g_Uop iCC_ssum;
extern iCC_g_Uop iCC_sprod;
extern iCC_g_Uop iCC_land;
extern iCC_g_Uop iCC_iand;
extern iCC_g_Uop iCC_lor;
extern iCC_g_Uop iCC_ior;


/* Global functions for reduction */
extern iCC_g_Op iCC_g_DMAX;
extern iCC_g_Op iCC_g_DMIN;
extern iCC_g_Op iCC_g_DSUM;
extern iCC_g_Op iCC_g_DPROD;
extern iCC_g_Op iCC_g_IMAX;
extern iCC_g_Op iCC_g_IMIN;
extern iCC_g_Op iCC_g_ISUM;
extern iCC_g_Op iCC_g_IPROD;
extern iCC_g_Op iCC_g_SMAX;
extern iCC_g_Op iCC_g_SMIN;
extern iCC_g_Op iCC_g_SSUM;
extern iCC_g_Op iCC_g_SPROD;
extern iCC_g_Op iCC_g_LAND;
extern iCC_g_Op iCC_g_BAND;
extern iCC_g_Op iCC_g_LOR;
extern iCC_g_Op iCC_g_BOR;
