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

#include "mpi.h"

#include "mpi_bnc.h"

#define MAX_LENGTH 1024

#define DEG 20

int main(int argc, char *argv[])
{
	long int i, dtimes, mpftimes;
	FILE * dcoef, * mpfcoef;

	long int local_dim, dd_dim[MPI_GMP_MAXPROCS];
	CDArray cdans, cdinit, local_cdans, local_cdinit;
	DPoly df;
	double dabs_eps, drel_eps;
	double startwtime[2], endwtime[2];
	int myrank, num_procs;

/* for MPI */
	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
	MPI_Comm_size(MPI_COMM_WORLD, &num_procs);

/* double */

	/* init */
	dabs_eps = 1.0e-100;
	drel_eps = 1.0e-7;
	df = init_dpoly(MAX_LENGTH);

	local_dim = _mpi_divide_dim(dd_dim, DEG, num_procs);
	if(myrank == 0)
	{
//		for(i = 0; i < DEG; i++)
//			printf("%d d_dim[%d]: %d\n", local_dim, i, dd_dim[i]);
	}
	local_cdans = init_cdarray(local_dim);
	local_cdinit = init_cdarray(local_dim);

	cdans = init_cdarray(DEG);
	cdinit = init_cdarray(DEG);
	if(myrank == 0)
	{
		dcoef = fopen("polycoef20.dat", "r");
		fread_dpolycoef(dcoef, df, DEG);
		fclose(dcoef);
	}

	/* Bcast dpoly */
	_mpi_bcast_dpoly(df, MPI_COMM_WORLD);
	if(myrank == 0)
	{
		printf("rank: %d\n", myrank);
		print_dpoly(df);
	}

	/* set Aberth's initial value */
	_mpi_ddka_init(local_cdinit, df, MPI_COMM_WORLD);
//	print_cdarray(local_cdinit);

	/* DKA method */
	if(myrank == 0) startwtime[0] = MPI_Wtime();
	_mpi_ddka(&dtimes, cdans, local_cdans, cdinit, local_cdinit, df, 1000, dabs_eps, drel_eps, MPI_COMM_WORLD);
	if(myrank == 0) endwtime[0] = MPI_Wtime();

	/* print answer */
	if(myrank == 0) printf("Iterative times: %d\n", dtimes);
	_mpi_collect_cdarray(cdans, dd_dim, local_cdans, MPI_COMM_WORLD);
	if(myrank == 0) print_cdarray(cdans);

	/* clear */
	free_dpoly(df);
	free_cdarray(cdans);
	free_cdarray(cdinit);

	MPI_Finalize();
	if(myrank == 0)
	{
		printf("double_DKA     : %f sec\n", endwtime[0] - startwtime[0]);
	}

	return EXIT_SUCCESS;
}
