#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, b;
	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);
	create_mpf_op(&(MPI_MPF_SUM), _mpi_mpf_add, MPI_COMM_WORLD);

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

	mpf_init_set_ui(a, myrank);
	mpf_init(b);

	buf_a = allocbuf_mpf(mpf_get_prec(a), 1);
	buf_b = allocbuf_mpf(mpf_get_prec(b), 1);

	pack_mpf(a, 1, buf_a);
	MPI_Allreduce(buf_a, buf_b, 1, MPI_MPF, MPI_MPF_SUM, MPI_COMM_WORLD);
	unpack_mpf(buf_b, b, 1);

	printf("Process %d: a = ", myrank);
	mpf_out_str(stdout, 10, 0, a);
	printf(", b = ");
	mpf_out_str(stdout, 10, 0, b);
	printf("\n");

	free(buf_a);
	free(buf_b);

	mpf_clear(a);
	mpf_clear(b);

	free_mpf_op(&(MPI_MPF_SUM));
	free_mpf(&(MPI_MPF));

	MPI_Finalize();

	return EXIT_SUCCESS;
}

