/****Copyright (c) 2001-2003  Alexandros V. Gerbessiotis.
 **** All rights reserved.
 ****Permission to use, copy, modify, and distribute this software,
 ****and to incorporate it, in whole or in part, into
 ****other software,is hereby granted without fee, provided that
 ****  (1) the above copyright notice and this permission
 ****      notice appear in all copies of the source code, and
 ****      the above copyright notice appear in clearly visible
 ****      form on all supporting documentation and distribution
 ****      media, and
 ****     (2) any redistribution of the software, in original
 ****         or modified form, be without fee and subject to
 ****         these same conditions.
 ****   No guarantee, whatsoever, is offered that the code works as
 ****   advertised or is absent of any, even damaging,
 ****   side-effects. Use this code at your own personal risk.
 ****/

#define MPILIB
#undef  MPILIB
#define BSPLIB
#undef  BSPLIB
#undef  PUBLIB
#define PUBLIB

/**** BSP lib related definitions */
#ifdef BSPLIB
#include "bsp.h"
#endif
#ifdef PUBLIB
#include "bspww.h"
#endif
#ifndef MPILIB
#define AIBEGIN     bsp_begin
#define AIEND       bsp_end
#define AIABORT     bsp_abort
#define AIPID       bsp_pid
#define AINPROCS    bsp_nprocs
#define AITIME      bsp_time

#define AIL()       (bsp_l())
#define AIG()       (bsp_g())
#define AISETL(X)   {}
#define AISETG(X)   {}

#define AIGET       bsp_get
#define AIOGET      bsp_get
#define AIHPGET     bsp_hpget
#define AIOHPGET    bsp_hpget
#define AIPUT       bsp_put
#define AIOPUT      bsp_put
#define AIHPPUT     bsp_hpput
#define AIOHPPUT    bsp_hpput

#define AIREGISTER    bsp_pushregister
#define AIOREGISTER   bsp_pushregister
#define AIDEREGISTER  bsp_popregister
#define AIODEREGISTER bsp_popregister
#define AIOINIT(X)    {;}
#define AIINIT()      {;}
#define AICOMMIT()    bsp_sync()
#define AIOCOMMIT()   bsp_sync()
#define AISYNC()      {;}
#define AIOSYNC(X)    {;}

#define AIBARRIER()   bsp_sync()
#define AIOBARRIER()  {;}
#endif


/* MPI related definitions (MPI-2 MPI_Put and MPI_Get must be supported*/
#ifdef   MPILIB
#include <mpi.h>
#define AIBEGIN(X)    (MPI_Init(&argc,&argv),mpi_basetime=MPI_Wtime())
#define AIEND()       MPI_Barrier(MPI_COMM_WORLD),MPI_Finalize()
#define AIABORT(X)    MPI_Abort(MPI_COMM_WORLD, __LINE__ )
#define AIPID() ((mpi_pid==-1)?(MPI_Comm_rank(MPI_COMM_WORLD,&mpi_pid),\
                mpi_pid):mpi_pid)
#define AINPROCS()  ((mpi_nprocs==-1)?(MPI_Comm_size(MPI_COMM_WORLD,\
                    &mpi_nprocs),mpi_nprocs):mpi_nprocs)    
#define AITIME()      (MPI_Wtime()-mpi_basetime)      


#define AIL()               (mpi_bsp_l)
#define AIG()               (mpi_bsp_g)
#define AISETL(X)           (mpi_bsp_l=(X))
#define AISETG(X)           (mpi_bsp_g=(X))

#define AIGET(X,Y,W,Z,R)    MPI_Get(\
                       (char *)(Z),(R),MPI_CHAR,(X),(W),(R),MPI_CHAR,win)
#define AIHPGET(X,Y,W,Z,R)  MPI_Get(\
                       (char *)(Z),(R),MPI_CHAR,(X),(W),(R),MPI_CHAR,win)
#define AIPUT(X,Y,Z,W,R)    MPI_Put(\
                       (char *)(Y),(R),MPI_CHAR,(X),(W),(R),MPI_CHAR,win)
#define AIHPPUT(X,Y,Z,W,R)  MPI_Put(\
                       (char *)(Y),(R),MPI_CHAR,(X),(W),(R),MPI_CHAR,win)
#define AIOGET(X,Y,W,Z,R)   MPI_Get((char *)(Z),(R),MPI_CHAR,\
                       (X),(W),(R),MPI_CHAR,aiwin[aisearch((void *)Y)])
#define AIOHPGET(X,Y,W,Z,R) MPI_Get((char *)(Z),(R),MPI_CHAR,\
                       (X),(W),(R),MPI_CHAR,aiwin[aisearch((void *)Y)])
#define AIOPUT(X,Y,Z,W,R)   MPI_Put((char *)(Y),(R),MPI_CHAR,\
                       (X),(W),(R),MPI_CHAR,aiwin[aisearch((void *)Z)])
#define AIOHPPUT(X,Y,Z,W,R) MPI_Put((char *)(Y),(R),MPI_CHAR,\
                       (X),(W),(R),MPI_CHAR,aiwin[aisearch((void *)Z)]) 
#define AIOOHPPUT(X,Y,Z,W,R,Q) MPI_Put((char *)(Y),(R),MPI_CHAR,\
                       (X),(W),(R),MPI_CHAR,aiwin[aisearch((void *)Q)]) 


#define AIREGISTER(X,Y)  MPI_Win_create((char *)(X),(Y),1,MPI_INFO_NULL\
                                        ,MPI_COMM_WORLD,&win)  
#define AIOREGISTER(X,Y) MPI_Win_create((char *)(X),(Y),1,MPI_INFO_NULL\
                             ,MPI_COMM_WORLD,&aiwin[aiinsert((void*)X)]) 
#define AIDEREGISTER(X)     {;}  
#define AIODEREGISTER(X)    {MPI_Win_free(&aiwin[aidelete(X)]);} 
#define AIINIT()            MPI_Win_fence(0,win)
#define AIOINIT(Z)          MPI_Win_fence(0,aiwin[aisearch((void *)Z)])
#define AICOMMIT()	    {;}
#define AIOCOMMIT()	    {;}
#define AISYNC()            MPI_Win_fence(0,win)
#define AIOSYNC(Z)          MPI_Win_fence(0,aiwin[aisearch((void *)Z)])

#define AIBARRIER()         MPI_Barrier(MPI_COMM_WORLD)
#define AIOBARRIER()        MPI_Barrier(MPI_COMM_WORLD)

extern MPI_Comm comm;
extern MPI_Win  win;
extern MPI_Win  aiwin[];
extern void*    bspmpi[];
extern int bspmpi_max ;
extern int bspmpi_first;
extern int bspmpicur_max ;
extern int mpi_pid ;
extern int mpi_nprocs ;
extern double mpi_bsp_l ;
extern double mpi_bsp_g ;
extern double mpi_basetime;
#endif
