int main()
{
    std::system("rm -rf timing.txt");
    std::ofstream outfile;
    outfile.open("timing.txt",std::ios::app);

    double *matrixArray=new double[9]; //Transformation Matrix array
    for(int i=0; i<9; i++)
    {
        *(matrixArray+i)=2.5;
    }
//Creating a Matrix using Blaze
    DynamicMatrix<double,rowMajor> A(3,3,matrixArray);
    std::cout<<A<<std::endl;
//Creating Matrix using Sandro's Library
    FastTransformationMatrix Av;
    Av.SetRotation(matrixArray);

//Actual Benchmarking stuff (doing transformation of dense Vector of N dimension using transformation matrix)
    int n=10000,N=0;
    int iter=20;
    int store=1,doValidation=1;
    int scalar=0.001;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


    for(int i=1; i<=iter; i++)
    {
        time_t t;
        time(&t);
        srand((double)t);

        N=n*i;
        double *testArray=new double[N*3];
        double *Vector3DFastArray=new double[N*3];
        double *BlazeArray=new double[N*3];
//double *denseBlazeArray=new double[N*3];
        for(int k=0 ; k<3*N ; k++)
        {
//testArray[k]=1.2;
            testArray[k]=rand()%100; //Assigning random number between 0 and 100   // previous giving 1.2
        }

        StopWatch tmr;
        double Tacc=0.0;

        double sum=0;
        int ent=10;
//for(int s=0 ; s<ent ; s++)

        {
            tmr.getOverhead(100);
            Tacc=0.0;
            tmr.Start();
            for(int j=0; j<N; j++)
            {
                Vector3DFast av(testArray+(3*j));
                Vector3DFast bv;
                Av.MasterToLocal<0,1>(av,bv); //Multiplying Matrix with Vector
                if(store)
                {
                    *(Vector3DFastArray+(3*j)+0)=bv.GetX();
                    *(Vector3DFastArray+(3*j)+1)=bv.GetY();
                    *(Vector3DFastArray+(3*j)+2)=bv.GetZ();
                }
            }
            tmr.Stop();
            Tacc=tmr.getDeltaSecs();
//sum+=Tacc;
        }
        std::cout<<"Execution Time N="<<N<<"  :  "<<Tacc<< " :::: ";
//outfile<<N*3<<"\t"<<sum/ent<<"\t";
        outfile<<N<<"\t"<<Tacc<<"\t";

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Below code uses Blaze and utilizing its 3D vectors to do dense vector addition
        sum=0;
//for(int s=0 ; s<ent ; s++)
        {
            tmr.getOverhead(100);
            Tacc=0.0;
            tmr.Start();
            for(int j=0; j<N; j++)
            {
//DynamicVector<double> a( 3 ), b( 3 ), c( 3 );
                StaticVector<double,3UL> a(3UL, testArray+(3*j));
//DynamicVector<double,rowVector> a(3UL, testArray+(3*j));
//StaticVector<double,3UL> a( 0, 0, 0 );
                StaticVector<double,3UL> b( 0, 0, 0 );
                b = A * a;
                if(store)
                {
                    *(BlazeArray+(3*j)+0)=b[0];
                    *(BlazeArray+(3*j)+1)=b[1];
                    *(BlazeArray+(3*j)+2)=b[2];
                }
            }
            tmr.Stop();
            Tacc=tmr.getDeltaSecs();
//sum+=Tacc;
        }
//std::cout<<Tacc<<std::endl;
        std::cout<<Tacc<<" :::: "<<std::endl;
//std::cout<<sumv<<"  ::  "<<sv;//<<std::endl;
//outfile<<sum/ent<<std::endl;
        outfile<<Tacc<<std::endl;



//Validating the results.
        if(doValidation)
        {
            for(int k=0 ; k<3*N ; k++)
            {
                if( (Vector3DFastArray[k]-BlazeArray[k]) )
                    std::cout<<"Value Differs"<<std::endl;
            }
        }

    }

    outfile.close();
    std::cout<<"******* Finished ********"<<std::endl;

}
int main()
{
std::system("rm -rf timingVectorAddition.txt");
std::ofstream outfile;
outfile.open("timingVectorAddition.txt",std::ios::app);

int n=10000,N=0;
int iter=20;
int store=1,doValidation=1;

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

for(int i=1;i<=iter;i++)
{
//-------------------------------
//For generating random numbers
time_t t;
time(&t);
srand((double)t);
//-------------------------------
N=n*i;
double *testArray=new double[N*3];
double *Vector3DFastArray=new double[N*3];
double *BlazeArray=new double[N*3];

for(int k=0 ; k<3*N ; k++)
{
 testArray[k]=rand()%100; //Assigning random number between 0 and 100   // previous giving 1.2
 Vector3DFastArray[k]=0.0;
 BlazeArray[k]=0.0;
}

StopWatch tmr;
double Tacc=0.0;
tmr.getOverhead(100);
Tacc=0.0;
tmr.Start();
for(int j=0;j<N;j++)
{
//For testing purpose filling same array in both av and bv
Vector3DFast av(testArray+(3*j));
Vector3DFast bv(testArray+(3*j));
Vector3DFast cv;
cv=av+bv;
if(store)  //requires for data Validation
{
*(Vector3DFastArray+(3*j)+0)=cv.GetX();
*(Vector3DFastArray+(3*j)+1)=cv.GetY();
*(Vector3DFastArray+(3*j)+2)=cv.GetZ();
}
//sumv+=cv;
}
tmr.Stop();
Tacc=tmr.getDeltaSecs();
std::cout<<"Execution Time N="<<N*3<<"  :  "<<Tacc<< " :::: ";
outfile<<N<<"\t"<<Tacc<<"\t";

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Below code uses Blaze and utilizing its 3D vectors to do dense vector addition
Tacc=0.0;
tmr.getOverhead(100);
Tacc=0.0;
tmr.Start();
for(int j=0;j<N;j++)
{
//DynamicVector<double> a( 3 ), b( 3 ), c( 3 );
StaticVector<double,3UL,rowVector> a(3UL, testArray+(3*j));

//StaticVector<double,3UL> b( 2, 5, -3 );
StaticVector<double,3UL,rowVector> b( 3UL, testArray+(3*j) );

StaticVector<double,3UL,rowVector> c;
c=a+b;
//sv+=c;
if(store)  //requires for data Validation
{
*(BlazeArray+(3*j)+0)=c[0];
*(BlazeArray+(3*j)+1)=c[1];
*(BlazeArray+(3*j)+2)=c[2];
}
}
tmr.Stop();
Tacc=tmr.getDeltaSecs();
std::cout<<Tacc<<" :::: "<<std::endl;
outfile<<Tacc<<std::endl;

//Validating the results.
if(doValidation)
for(int k=0 ; k<3*N ; k++)
  {
	if( (Vector3DFastArray[k]-BlazeArray[k]) )
	    std::cout<<"Value Differs"<<std::endl;
  }
}

outfile.close();
std::cout<<"******* Finished ********"<<std::endl;


}
int main(int argc, char * argv[])
{
   bool iterative=true;
   if(argc>1) iterative=false;
   Vectors3DSOA points, dirs, intermediatepoints, intermediatedirs;

   int np=1024;
   int NREPS = 1000;

   points.alloc(np);
   dirs.alloc(np);

   // generate benchmark cases
   TransformationMatrix const * identity = new TransformationMatrix(0,0,0,0,0,0);

   double L = 10.;
   double Lz = 10.;
   const double Sqrt2 = sqrt(2.);

   BoxParameters *   worldp =  new BoxParameters(L, L, Lz );
   PhysicalVolume * world = GeoManager::MakePlacedBox( worldp , identity );
   double volworld = worldp->GetVolume();

   BoxParameters * boxlevel2 = new BoxParameters( Sqrt2*L/2./2., Sqrt2*L/2./2., Lz );
   BoxParameters * boxlevel3 = new BoxParameters( L/2./2. ,L/2./2., Lz);
   BoxParameters * boxlevel1 = new BoxParameters( L/2., L/2., Lz );

   PhysicalVolume * box2 = GeoManager::MakePlacedBox(boxlevel2, new TransformationMatrix(0,0,0,0,0,45));
   PhysicalVolume * box3 = GeoManager::MakePlacedBox( boxlevel3, new TransformationMatrix(0,0,0,0,0,-45));
   box2->AddDaughter( box3 ); // rotated 45 degree around z axis

   PhysicalVolume * box1 = GeoManager::MakePlacedBox(boxlevel1, identity);
   box1->AddDaughter( box2 );

   PhysicalVolume const * box1left  = world->PlaceDaughter(GeoManager::MakePlacedBox(boxlevel1, new TransformationMatrix(-L/2.,0.,0.,0.,0.,0)), box1->GetDaughters());
   PhysicalVolume const * box1right = world->PlaceDaughter(GeoManager::MakePlacedBox(boxlevel1, new TransformationMatrix(+L/2.,0.,0.,0.,0.,0)), box1->GetDaughters());


    // perform basic tests
   SimpleVecNavigator nav(1, world);

   StopWatch timer;
   // some object which are expensive to create
   FastTransformationMatrix * m = new FastTransformationMatrix();
   VolumePath path(4);
   VolumePath newpath(4);

   timer.Start();
   int stepsdone=0;
   for(int n=0;n<1000;n++)
     {
   for(int i=0;i<100000;i++)
   // testing the NavigationAndStepInterface
   {
      int localstepsdone=0;
      double distancetravelled=0.;
      Vector3DFast p;
      PhysicalVolume::samplePoint( p, worldp->GetDX(), worldp->GetDY(), worldp->GetDZ(), 1. );
#ifdef DEBUG
      std::cerr << p << " " << worldp->GetDX()-p.GetX() << " ";
#endif

      // setup point in world
      Vector3DFast d(1,0,0);
      Vector3DFast resultpoint;

      m->SetToIdentity();
      PhysicalVolume const * vol;
#ifdef ITERATIVE
         vol = nav.LocatePoint_iterative( world, p, resultpoint, path, m );
#else
         vol = nav.LocatePoint( world, p, resultpoint, path, m );
#endif
         while( vol!=NULL )
      {
         localstepsdone++;
         // do one step
         double step;
#ifdef ITERATIVE
         nav.FindNextBoundaryAndStep_iterative(m, p, d, path, newpath, resultpoint, step);
#else
         nav.FindNextBoundaryAndStep(m, p, d, path, newpath, resultpoint, step);
#endif
         distancetravelled+=step;
#ifdef DEBUG
         std::cerr << "  proposed step: " << step << std::endl;
         std::cerr << "  next point " << resultpoint << std::endl;
         std::cerr << "  in vol " << newpath.Top() << std::endl;
#endif

         // go on with navigation
         p = resultpoint;
         path=newpath;
         vol=path.Top();
      }
#ifdef DEBUG
         std::cerr << localstepsdone << " " << distancetravelled << std::endl;
#endif
         stepsdone+=localstepsdone;
   }
     }
   timer.Stop();
   std::cout << " time for 100000 particles " << timer.getDeltaSecs( ) << std::endl;
   std::cout << " average steps done " << stepsdone / 100000. << std::endl;
   std::cout << " time per step " << timer.getDeltaSecs()/stepsdone << std::endl;

   delete m;
}