#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "mpi.h"

#define USE_GMP
#define USE_MPFR
#include "mpi_bnc.h"

int main(int argc, char *argv[])
{
	int num_procs, myrank;
	mpf_t a[128], b[128];
	void *buf_a, *buf_b;
	int tag = 0, i;
	MPI_Status status;

	MPI_Init(&argc, &argv);

	_mpi_set_bnc_default_prec_decimal(50, MPI_COMM_WORLD);
	commit_mpf(&(MPI_MPF), ceil(50/log10(2.0)), MPI_COMM_WORLD);

	MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
	MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

	for(i = 0; i < num_procs; i++)
	{
		mpf_init_set_ui(a[i], i);
		mpf_init(b[i]);
	}

	buf_a = allocbuf_mpf(mpf_get_prec(a[0]), num_procs);
	buf_b = allocbuf_mpf(mpf_get_prec(b[0]), num_procs);

	pack_mpf(a[0], num_procs, buf_a);
	MPI_Alltoall(buf_a, 1, MPI_MPF, buf_b, 1, MPI_MPF, MPI_COMM_WORLD);
	unpack_mpf(buf_b, b[0], num_procs);

	printf("Process %d:\n", myrank);
	for(i = 0; i < num_procs; i++)
	{
		printf("a[%d] = ", i);
		mpf_out_str(stdout, 10, 0, a[i]);
		printf(", b[%d] = ", i);
		mpf_out_str(stdout, 10, 0, b[i]);
		printf("\n");
	}

	free(buf_a);
	free(buf_b);

	for(i = 0; i < num_procs; i++)
	{
		mpf_clear(a[i]);
		mpf_clear(b[i]);
	}

	free_mpf(&(MPI_MPF));

	MPI_Finalize();

	return EXIT_SUCCESS;
}

