#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>
#define REAL double
#define DIM 3

main(argc,argv)
int argc;
char *argv[];
{
        REAL t;
        double eps=0.01;
        FILE *inputfile,*fopen(); 
        int n,i,nn,itv,k;
        double dum,tbegin,maxerr,maxerrp,aveerr,aveerrp,maxa2,maxa2h;  
        int uniformflag,ng,nleaf;
        double theta;
/*
       int n,i,dum,idem,nout,ii,iii,npipes,nbof,ncrit,inb,nn,j,nj,xjmax,k;

        float ran1();
        double mass,radius,size,rcrit,minpot,mpart,rho200;
        double runit,munit,maxerr,aveerr,aveerrp,maxerrp;
        int ik,nk,ihalo=0,itv;
        double tbegin;
*/

/*        static REAL x[NMAX][DIM];
        static REAL v[NMAX][DIM];
        static REAL m[NMAX];
        static REAL pot[NMAX];
        static REAL a[NMAX][DIM];*/

        double (*x)[DIM];
        double (*v)[DIM];
        double *m;
        double *pot;
        double (*a)[DIM];

#ifdef PTHREAD
        initialize_force_function();
#endif

 	if(argc==5){
	  inputfile = fopen(argv[1],"r");
/*	  outputfile = fopen(argv[2],"w");*/
	  sscanf(argv[2],"%lf",&theta);
	  sscanf(argv[3],"%d",&ng);
	  sscanf(argv[4],"%d",&nleaf);
          uniformflag = 0;
	}else if(argc==6){   
	  inputfile = fopen(argv[1],"r");
/*	  outputfile = fopen(argv[2],"w");*/
	  sscanf(argv[2],"%lf",&theta);
	  sscanf(argv[3],"%d",&ng);
	  sscanf(argv[4],"%d",&nleaf);
	  sscanf(argv[5],"%d",&n);
          uniformflag = 1;
	}else{
	  printf("jcode inputfile theta ncrit nleaf\n");
	  exit(0);
	}

  if(uniformflag == 1){
      double drand48();
      fprintf(stderr,"generate uniform sphare: n: %d\n",n);
       x = (double (*)[3])malloc(sizeof(double)*n*3);
       v = (double (*)[3])malloc(sizeof(double)*n*3);
       m = (double *)malloc(sizeof(double)*n);
       pot = (double *)malloc(sizeof(double)*n);
       a = (double (*)[3])malloc(sizeof(double)*n*3);
      for(i=0;i<n;i++){
	double dist;
	do{
	  x[i][0] = 2.0*drand48()-1.0;
	  x[i][1] = 2.0*drand48()-1.0;
	  x[i][2] = 2.0*drand48()-1.0;
	  dist = x[i][0]*x[i][0]+x[i][1]*x[i][1]+x[i][2]*x[i][2];
	}while(dist>1.0);
	m[i] = 1.0/n;
      }	
    }else{
       fscanf(inputfile,"%d%lf",&n,&dum);
       x = (double (*)[3])malloc(sizeof(double)*n*3);
       v = (double (*)[3])malloc(sizeof(double)*n*3);
       m = (double *)malloc(sizeof(double)*n);
       pot = (double *)malloc(sizeof(double)*n);
       a = (double (*)[3])malloc(sizeof(double)*n*3);

	fscanf(inputfile,"%lf",&t);
	for(i=0;i<n;i++) fscanf(inputfile,"%lf",&m[i]);
	for(i=0;i<n;i++) fscanf(inputfile,"%lf%lf%lf",&x[i][0],&x[i][1],&x[i][2]);
	for(i=0;i<n;i++) fscanf(inputfile,"%lf%lf%lf",&v[i][0],&v[i][1],&v[i][2]);
	for(i=0;i<n;i++) fscanf(inputfile,"%lf",&pot[i]);
	fclose(inputfile);
        fprintf(stderr,"read file %s\n",argv[1]);
    }



        system("hostname");
        system("date");

        nbody_force_gravity_init(theta, ng, nleaf);
        nbody_force_gravity(n, eps, m, x, a, pot);

#if 1
       nn = 0;
       maxerr = maxerrp = aveerr = aveerrp = maxa2= 0;
/*       itv = (n/30000)*(n/30000) + 1;*/
       itv = (n/10000)*(n/10000) + 1;
       for(i=0;i<n;i+=itv){ 
	 double ah[3],poth,err[4],fabs(),a2,err2,relerr,relerrp;
	 int errflag=0;
         force_on_ith_particle(i,x[i],x,m,eps,ah,&poth,n);
	 for(k=0;k<3;k++){
	   err[k] = a[i][k] - ah[k];
	 }
	 err[3] = pot[i] - poth;
	 a2 = ah[0]*ah[0]+ah[1]*ah[1]+ah[2]*ah[2];
	 err2 = err[0]*err[0]+err[1]*err[1]+err[2]*err[2];

	 relerr = err2/a2;
	 aveerr += relerr;
	 relerrp = (err[3]/poth)*(err[3]/poth);
         aveerrp += relerrp;

 	 if(relerr>maxerr){
	    maxerr = relerr;
	    maxa2h = a2;
	    maxa2 = a[i][0]*a[i][0]+a[i][1]*a[i][1]+a[i][2]*a[i][2];
         }
 	 if(relerrp>maxerrp) maxerrp = relerrp;

	 if(i<0){
	   printf("tree   i %d: a %g %g %g p %g\n",i,a[i][0],a[i][1],a[i][2],pot[i]);  
	   printf("direct i %d: a %g %g %g p %g err %e %e\n",
		  i,ah[0],ah[1],ah[2],poth,sqrt(relerr),sqrt(relerrp));
	 }

	 if((relerr>3.0e-3)||(relerrp>1.0e-4)){
	   printf("tree   i %d: a %g %g %g p %g\n",i,a[i][0],a[i][1],a[i][2],pot[i]);  
	   printf("direct i %d: a %g %g %g p %g err %e %e\n",
		  i,ah[0],ah[1],ah[2],poth,sqrt(relerr),sqrt(relerrp));
	 }
	 nn++;
       }
       printf("itv %d maxerr %22.15e %g ave %22.15e %e %22.15e %22.15e\n\n",itv,sqrt(maxerr),sqrt(maxerrp),sqrt(aveerr/nn),sqrt(aveerrp/nn),maxa2,maxa2h);

#endif

}	






