#include<stdlib.h>
#include "parlib.h"

// -------------------------------------------------------------------------- //
#ifdef FORTRANUNDERSCORE
void p_bexchange_init_ ( ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_init__ ( ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, bexchange, ierr )
#else
void p_bexchange_init ( ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, bexchange, ierr )
#endif

	MPI_Fint *datatype, *ndims, *stride, *blklen, *bdim, *overlap,
		*period, *ierr, *comm;
	BExchange **bexchange;
{
	*bexchange = (BExchange *) malloc ( sizeof (BExchange) );
	*ierr = P_BExchange_init ( (int)*ndims, (int *)stride, (int *)blklen,
		(int)*bdim, (int *)overlap, MPI_Type_f2c(*datatype), 
		MPI_Comm_f2c(*comm), (int)*period, *bexchange );
}

#ifdef FORTRANUNDERSCORE
void p_bexchange_start_ ( a, bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_start__ ( a, bexchange, ierr )
#else
void p_bexchange_start ( a, bexchange, ierr )
#endif

	void *a;
	BExchange **bexchange;
	MPI_Fint *ierr;
{
	*ierr = P_BExchange_start(a, *bexchange);
}

#ifdef FORTRANUNDERSCORE
void p_bexchange_end_ ( bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_end__ ( bexchange, ierr )
#else
void p_bexchange_end ( bexchange, ierr )
#endif

	BExchange **bexchange;
	MPI_Fint *ierr;
{
	*ierr = P_BExchange_end(*bexchange);
}

#ifdef FORTRANUNDERSCORE
void p_bexchange_free_ ( bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_free__ ( bexchange, ierr )
#else
void p_bexchange_free ( bexchange, ierr )
#endif

	BExchange **bexchange;
	MPI_Fint *ierr;
{
	P_BExchange_free(*bexchange);
	free(*bexchange);
}

#ifdef FORTRANUNDERSCORE
void p_bexchange_ ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange__ ( a, ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, ierr )
#else
void p_bexchange ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, ierr )
#endif

	void *a;
	MPI_Fint *ndims, *stride, *blklen, *bdim, *overlap, *period, *ierr;
	MPI_Fint *datatype;
	MPI_Fint *comm;
{
	*ierr = P_BExchange(a, (int)*ndims, (int *)stride, (int *)blklen,
		(int)*bdim, (int *)overlap, MPI_Type_f2c(*datatype),
		MPI_Comm_f2c(*comm), (int)*period);
}
// -------------------------------------------------------------------------- //

// v.1.3 - persistent exchanges //
// -------------------------------------------------------------------------- //
#ifdef FORTRANUNDERSCORE
void pst_bexchange_init_ ( a, ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void pst_bexchange_init__ ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, bexchange, ierr )
#else
void pst_bexchange_init(a, ndims, stride, blklen, bdim, overlap, datatype,
	    comm, period, bexchange, ierr)
#endif

	void *a;
	MPI_Fint *datatype, *ndims, *stride, *blklen, *bdim, *overlap, 
		*period, *ierr, *comm; 
	BExchange **bexchange;
{
	*bexchange = (BExchange *) malloc ( sizeof (BExchange) );
	*ierr = PST_BExchange_init ( a, (int)*ndims, (int *)stride, (int *)blklen,
		(int)*bdim, (int *)overlap, MPI_Type_f2c(*datatype), 
		MPI_Comm_f2c(*comm), (int)*period, *bexchange );
}

#ifdef FORTRANUNDERSCORE
void pst_bexchange_start_ ( bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void pst_bexchange_start__ ( bexchange, ierr )
#else
void pst_bexchange_start ( bexchange, ierr )
#endif

	BExchange **bexchange;
	MPI_Fint *ierr;
{
	*ierr = PST_BExchange_start(*bexchange);
}

#ifdef FORTRANUNDERSCORE
void pst_bexchange_end_ ( bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void pst_bexchange_end__ ( bexchange, ierr )
#else
void pst_bexchange_end ( bexchange, ierr )
#endif

	BExchange **bexchange;
	MPI_Fint *ierr;
{
	*ierr = PST_BExchange_end(*bexchange);
}

#ifdef FORTRANUNDERSCORE
void pst_bexchange_free_ ( bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void pst_bexchange_free__ ( bexchange, ierr )
#else
void pst_bexchange_free ( bexchange, ierr )
#endif

	BExchange **bexchange;
	MPI_Fint *ierr;
{
	PST_BExchange_free(*bexchange);
	free(*bexchange);
}

#ifdef FORTRANUNDERSCORE
void pst_bexchange_ ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void pst_bexchange__ ( a, ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, ierr )
#else
void pst_bexchange ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, ierr )
#endif
	
	void *a;
	MPI_Fint *ndims, *stride, *blklen, *bdim, *overlap, *period, *ierr;
	MPI_Fint *datatype;
	MPI_Fint *comm;
{
	*ierr = PST_BExchange(a, (int)*ndims, (int *)stride, (int *)blklen,
		(int)*bdim, (int *)overlap, MPI_Type_f2c(*datatype),
		MPI_Comm_f2c(*comm), (int)*period);
}
// -------------------------------------------------------------------------- //

// v.1.4 - manual packing //
// -------------------------------------------------------------------------- //
#ifdef FORTRANUNDERSCORE
void p_bexchange_mp_init_ ( ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_mp_init__ ( ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, bexchange, ierr )
#else
void p_bexchange_mp_init ( ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, bexchange, ierr )
#endif

	MPI_Fint *datatype, *ndims, *stride, *blklen, *bdim, *overlap,
		*period, *ierr, *comm;
	BExchange **bexchange;
{
	*bexchange = (BExchange *)malloc(sizeof (BExchange));
	*ierr = P_BExchange_mp_init((int)*ndims, (int *)stride, (int *)blklen,
		(int)*bdim, (int *)overlap, MPI_Type_f2c(*datatype),
		MPI_Comm_f2c(*comm), (int)*period, *bexchange);
}

#ifdef FORTRANUNDERSCORE
void p_bexchange_mp_start_ ( a, bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_mp_start__ ( a, bexchange, ierr )
#else
void p_bexchange_mp_start ( a, bexchange, ierr )
#endif

	void *a;
	BExchange **bexchange;
	MPI_Fint *ierr;
{
	*ierr = P_BExchange_mp_start(a, *bexchange);
}

#ifdef FORTRANUNDERSCORE
void p_bexchange_mp_end_ ( a, bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_mp_end__ ( a, bexchange, ierr )
#else
void p_bexchange_mp_end(a, bexchange, ierr)
#endif

	void *a;
	BExchange **bexchange;
	MPI_Fint *ierr;
{
	*ierr = P_BExchange_mp_end(a, *bexchange);
}

#ifdef FORTRANUNDERSCORE
void p_bexchange_mp_free_ ( bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_mp_free__ ( bexchange, ierr )
#else
void p_bexchange_mp_free ( bexchange, ierr )
#endif

	BExchange **bexchange;
	MPI_Fint *ierr;
{
	P_BExchange_mp_free(*bexchange);
	free(*bexchange);
}

#ifdef FORTRANUNDERSCORE
void p_bexchange_mp_ ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_mp__ ( a, ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, ierr )
#else
void p_bexchange_mp ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, ierr )
#endif

	void *a;
	MPI_Fint *ndims, *stride, *blklen, *bdim, *overlap, *period, *ierr;
	MPI_Fint *datatype;
	MPI_Fint *comm;
{
	*ierr = P_BExchange_mp(a, (int)*ndims, (int *)stride, (int *)blklen,
		(int)*bdim, (int *)overlap, MPI_Type_f2c(*datatype),
		MPI_Comm_f2c(*comm), (int)*period);
}
// -------------------------------------------------------------------------- //

// v.1.4 - persistent exchanges for manual packing //
// -------------------------------------------------------------------------- //
#ifdef FORTRANUNDERSCORE
void pst_bexchange_mp_init_ ( ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void pst_bexchange_mp_init__ ( ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, bexchange, ierr )
#else
void pst_bexchange_mp_init ( ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, bexchange, ierr )
#endif

	MPI_Fint *datatype, *ndims, *stride, *blklen, *bdim, *overlap,
		*period, *ierr, *comm;
	BExchange **bexchange;
{
	*bexchange = (BExchange *)malloc(sizeof (BExchange));
	*ierr = PST_BExchange_mp_init((int)*ndims, (int *)stride, (int *)blklen,
		(int)*bdim, (int *)overlap, MPI_Type_f2c(*datatype),
		MPI_Comm_f2c(*comm), (int)*period, *bexchange);
}

#ifdef FORTRANUNDERSCORE
void pst_bexchange_mp_start_ ( a, bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void pst_bexchange_mp_start__ ( a, bexchange, ierr )
#else
void pst_bexchange_mp_start ( a, bexchange, ierr )
#endif

	void *a;
	BExchange **bexchange;
	MPI_Fint *ierr;
{
	*ierr = PST_BExchange_mp_start(a, *bexchange);
}

#ifdef FORTRANUNDERSCORE
void pst_bexchange_mp_end_ ( a, bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void pst_bexchange_mp_end__ ( a, bexchange, ierr )
#else
void pst_bexchange_mp_end(a, bexchange, ierr)
#endif

	void *a;
	BExchange **bexchange;
	MPI_Fint *ierr;
{
	*ierr = PST_BExchange_mp_end(a, *bexchange);
}

#ifdef FORTRANUNDERSCORE
void pst_bexchange_mp_free_ ( bexchange, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void pst_bexchange_mp_free__ ( bexchange, ierr )
#else
void pst_bexchange_mp_free ( bexchange, ierr )
#endif

	BExchange **bexchange;
	MPI_Fint *ierr;
{
	PST_BExchange_mp_free(*bexchange);
	free(*bexchange);
}

#ifdef FORTRANUNDERSCORE
void pst_bexchange_mp_ ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void pst_bexchange_mp__ ( a, ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, ierr )
#else
void pst_bexchange_mp ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, ierr )
#endif

	void *a;
	MPI_Fint *ndims, *stride, *blklen, *bdim, *overlap, *period, *ierr;
	MPI_Fint *datatype;
	MPI_Fint *comm;
{
	*ierr = PST_BExchange_mp(a, (int)*ndims, (int *)stride, (int *)blklen,
		(int)*bdim, (int *)overlap, MPI_Type_f2c(*datatype),
		MPI_Comm_f2c(*comm), (int)*period);
}
// -------------------------------------------------------------------------- //

// v.1.95 - choice subroutines //
// -------------------------------------------------------------------------- //
#ifdef FORTRANUNDERSCORE
void p_bexchange_opt_init_ ( a, ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, bexchange, exch_mode, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_opt_init__ ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, bexchange, exch_mode, ierr )
#else
void p_bexchange_opt_init ( a, ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, bexchange, exch_mode, ierr )
#endif

	void *a;
	MPI_Fint *datatype, *ndims, *stride, *blklen, *bdim, *overlap,
		*period, *ierr, *comm, *exch_mode;
	BExchange **bexchange;
{
	*bexchange = (BExchange *) malloc ( sizeof (BExchange) );
	*ierr = P_BExchange_opt_init ( a, (int)*ndims, (int *)stride, (int *)blklen,
		(int)*bdim, (int *)overlap, MPI_Type_f2c(*datatype), 
		MPI_Comm_f2c(*comm), (int)*period, *bexchange, (int)*exch_mode );
}

#ifdef FORTRANUNDERSCORE
void p_bexchange_opt_start_ ( a, bexchange, exch_mode, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_opt_start__ ( a, bexchange, exch_mode, ierr )
#else
void p_bexchange_opt_start ( a, bexchange, exch_mode, ierr )
#endif

	void *a;
	BExchange **bexchange;
	MPI_Fint *ierr, *exch_mode;
{
	*ierr = P_BExchange_opt_start(a, *bexchange, (int)*exch_mode);
}

#ifdef FORTRANUNDERSCORE
void p_bexchange_opt_end_ ( a, bexchange, exch_mode, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_opt_end__ ( a, bexchange, exch_mode, ierr )
#else
void p_bexchange_opt_end ( a, bexchange, exch_mode, ierr )
#endif

	void *a;
	BExchange **bexchange;
	MPI_Fint *ierr, *exch_mode;
{
	*ierr = P_BExchange_opt_end(a, *bexchange, (int)*exch_mode);
}

#ifdef FORTRANUNDERSCORE
void p_bexchange_opt_free_ ( bexchange, exch_mode, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_opt_free__ ( bexchange, exch_mode, ierr )
#else
void p_bexchange_opt_free ( bexchange, exch_mode, ierr )
#endif

	BExchange **bexchange;
	MPI_Fint *ierr, *exch_mode;
{
	P_BExchange_opt_free(*bexchange, (int)*exch_mode);
	free(*bexchange);
}

#ifdef FORTRANUNDERSCORE
void p_bexchange_opt_ ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, exch_mode, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_opt__ ( a, ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, exch_mode, ierr )
#else
void p_bexchange_opt ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, exch_mode, ierr )
#endif

	void *a;
	MPI_Fint *ndims, *stride, *blklen, *bdim, *overlap, *period, *ierr;
	MPI_Fint *datatype;
	MPI_Fint *comm;
	MPI_Fint *exch_mode;
{
	*ierr = P_BExchange_opt(a, (int)*ndims, (int *)stride, (int *)blklen,
		(int)*bdim, (int *)overlap, MPI_Type_f2c(*datatype),
		MPI_Comm_f2c(*comm), (int)*period, (int)*exch_mode);
}

// v.2.2: periodicity conditions only
#ifdef FORTRANUNDERSCORE
void p_bexchange_period_opt_ ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, exch_mode, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void p_bexchange_period_opt__ ( a, ndims, stride, blklen, bdim, overlap, datatype, 
		comm, exch_mode, ierr )
#else
void p_bexchange_period_opt ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, exch_mode, ierr )
#endif

	void *a;
	MPI_Fint *ndims, *stride, *blklen, *bdim, *overlap, *ierr;
	MPI_Fint *datatype;
	MPI_Fint *comm;
	MPI_Fint *exch_mode;
{
	*ierr = P_BExchange_period_opt(a, (int)*ndims, (int *)stride, (int *)blklen,
		(int)*bdim, (int *)overlap, MPI_Type_f2c(*datatype),
		MPI_Comm_f2c(*comm), (int)*exch_mode);
}
// -------------------------------------------------------------------------- //


// v.2.0 - regular communications [removed only on correct program exit] //
// -------------------------------------------------------------------------- //
#ifdef FORTRANUNDERSCORE
void reg_bexchange_ ( a, ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, exch_id, exch_mode, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void reg_bexchange__ ( a, ndims, stride, blklen, bdim, overlap, datatype,
		comm, period, exch_id, exch_mode, ierr )
#else
void reg_bexchange ( a, ndims, stride, blklen, bdim, overlap, datatype, 
		comm, period, exch_id, exch_mode, ierr )
#endif

	void *a;
	MPI_Fint *datatype, *ndims, *stride, *blklen, *bdim, *overlap,
		*period, *ierr, *comm, *exch_id, *exch_mode;
{
	BExchange *bexchange;
	bexchange = (BExchange *) malloc ( sizeof (BExchange) );
	
	*ierr = P_BExchange_opt_init ( a, (int)*ndims, (int *)stride, (int *)blklen,
		(int)*bdim, (int *)overlap, MPI_Type_f2c(*datatype), 
		MPI_Comm_f2c(*comm), (int)*period, bexchange, (int)*exch_mode );
	if ((int)*ierr != 0) return;

	*exch_id = save_bexch_handle(bexchange, (int)*exch_mode);
}

#ifdef FORTRANUNDERSCORE
void start_bexchange_ ( a, exch_id, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void start_bexchange__ ( a, exch_id, ierr )
#else
void start_bexchange ( a, exch_id, ierr )
#endif

	void *a;
	MPI_Fint *ierr, *exch_id;
{
	int exch_mode;
	BExchange *bexchange;

	get_bexch_handle(&bexchange, &exch_mode, (int)*exch_id);

	*ierr = P_BExchange_opt_start(a, bexchange, exch_mode);
}

#ifdef FORTRANUNDERSCORE
void end_bexchange_ ( a, exch_id, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void end_bexchange__ ( a, exch_id, ierr )
#else
void end_bexchange ( a, exch_id, ierr )
#endif

	void *a;
	MPI_Fint *ierr, *exch_id;
{
	int exch_mode;
	BExchange *bexchange;
	
	get_bexch_handle(&bexchange, &exch_mode, (int)*exch_id);

	*ierr = P_BExchange_opt_end(a, bexchange, exch_mode);
}

#ifdef FORTRANUNDERSCORE
void run_bexchange_ ( a, exch_id, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void run_bexchange__ ( a, exch_id, ierr )
#else
void run_bexchange ( a, exch_id, ierr )
#endif

	void *a;
	MPI_Fint *ierr, *exch_id;
{
	int exch_mode;
	BExchange *bexchange;
	
	get_bexch_handle(&bexchange, &exch_mode, (int)*exch_id);

	*ierr = P_BExchange_opt_start(a, bexchange, exch_mode);
	if ((int)*ierr != 0) return;

	*ierr = P_BExchange_opt_end(a, bexchange, exch_mode);
}

#ifdef FORTRANUNDERSCORE
void unreg_bexchange_ ( exch_id, ierr )
#elif defined(FORTRANDOUBLEUNDERSCORE)
void unreg_bexchange__ ( exch_id, ierr )
#else
void unreg_bexchange ( exch_id, ierr )
#endif

	MPI_Fint *ierr, *exch_id;
{
	int exch_mode;
	BExchange *bexchange;

	get_bexch_handle(&bexchange, &exch_mode, (int)*exch_id);

	*ierr = P_BExchange_opt_free(bexchange, exch_mode);
	if ((int)*ierr != 0) return;
	free(bexchange);

	remove_bexch_handle((int)*exch_id);
}
// -------------------------------------------------------------------------- //