/*1:*/
#line 41 "./quadrature.hweb"

#ifndef QUADRATURE_H
#define QUADRATURE_H

#include <cstdlib> 
#include "vector_function.h"
#include "int_sequence.h"
#include "sthread.h"

/*2:*/
#line 66 "./quadrature.hweb"

class OneDQuadrature{
public:
virtual~OneDQuadrature(){}
virtual int numLevels()const= 0;
virtual int numPoints(int level)const= 0;
virtual double point(int level,int i)const= 0;
virtual double weight(int lelel,int i)const= 0;
};

/*:2*/
#line 50 "./quadrature.hweb"
;
/*3:*/
#line 89 "./quadrature.hweb"

class Quadrature{
protected:
int dim;
public:
Quadrature(int d):dim(d){}
virtual~Quadrature(){}
int dimen()const
{return dim;}
virtual void integrate(const VectorFunction&func,int level,
int tn,Vector&out)const= 0;
virtual void integrate(VectorFunctionSet&fs,int level,Vector&out)const= 0;
virtual int numEvals(int level)const= 0;
};

/*:3*/
#line 51 "./quadrature.hweb"
;
/*4:*/
#line 110 "./quadrature.hweb"

template<typename _Tpit> 
class QuadratureImpl;

template<typename _Tpit> 
class IntegrationWorker:public THREAD{
const QuadratureImpl<_Tpit> &quad;
VectorFunction&func;
int level;
int ti;
int tn;
Vector&outvec;
public:
IntegrationWorker(const QuadratureImpl<_Tpit> &q,VectorFunction&f,int l,
int tii,int tnn,Vector&out)
:quad(q),func(f),level(l),ti(tii),tn(tnn),outvec(out){}
/*5:*/
#line 139 "./quadrature.hweb"

void operator()(){
_Tpit beg= quad.begin(ti,tn,level);
_Tpit end= quad.begin(ti+1,tn,level);
Vector tmpall(outvec.length());
tmpall.zeros();
Vector tmp(outvec.length());



for(_Tpit run= beg;run!=end;++run){
func.eval(run.point(),run.signal(),tmp);
tmpall.add(run.weight(),tmp);
}

{
SYNCHRO syn(&outvec,"IntegrationWorker");
outvec.add(1.0,tmpall);
}
}


/*:5*/
#line 126 "./quadrature.hweb"
;
};


/*:4*/
#line 52 "./quadrature.hweb"
;
/*6:*/
#line 169 "./quadrature.hweb"

template<typename _Tpit> 
class QuadratureImpl:public Quadrature{
friend class IntegrationWorker<_Tpit> ;
public:
QuadratureImpl(int d):Quadrature(d){}
/*7:*/
#line 191 "./quadrature.hweb"

void integrate(VectorFunctionSet&fs,int level,Vector&out)const{


out.zeros();
THREAD_GROUP gr;
for(int ti= 0;ti<fs.getNum();ti++){
gr.insert(new IntegrationWorker<_Tpit> (*this,fs.getFunc(ti),
level,ti,fs.getNum(),out));
}
gr.run();
}


/*:7*/
#line 175 "./quadrature.hweb"
;
void integrate(const VectorFunction&func,
int level,int tn,Vector&out)const{
VectorFunctionSet fs(func,tn);
integrate(fs,level,out);
}
/*8:*/
#line 206 "./quadrature.hweb"

void savePoints(const char*fname,int level)const
{
FILE*fd;
if(NULL==(fd= fopen(fname,"w"))){

fprintf(stderr,"Cannot open file %s for writing.\n",fname);
exit(1);
}
_Tpit beg= begin(0,1,level);
_Tpit end= begin(1,1,level);
for(_Tpit run= beg;run!=end;++run){
fprintf(fd,"%16.12g",run.weight());
for(int i= 0;i<dimen();i++)
fprintf(fd,"\t%16.12g",run.point()[i]);
fprintf(fd,"\n");
}
fclose(fd);
}


/*:8*/
#line 181 "./quadrature.hweb"
;
_Tpit start(int level)const
{return begin(0,1,level);}
_Tpit end(int level)const
{return begin(1,1,level);}
protected:
virtual _Tpit begin(int ti,int tn,int level)const= 0;
};

/*:6*/
#line 53 "./quadrature.hweb"
;
/*9:*/
#line 238 "./quadrature.hweb"

class OneDPrecalcQuadrature:public OneDQuadrature{
int num_levels;
const int*num_points;
const double*weights;
const double*points;
IntSequence offsets;
public:
OneDPrecalcQuadrature(int nlevels,const int*npoints,
const double*wts,const double*pts)
:num_levels(nlevels),num_points(npoints),
weights(wts),points(pts),offsets(num_levels)
{calcOffsets();}
virtual~OneDPrecalcQuadrature(){}
int numLevels()const
{return num_levels;}
int numPoints(int level)const
{return num_points[level-1];}
double point(int level,int i)const
{return points[offsets[level-1]+i];}
double weight(int level,int i)const
{return weights[offsets[level-1]+i];}
protected:
void calcOffsets();
};

/*:9*/
#line 54 "./quadrature.hweb"
;
/*10:*/
#line 276 "./quadrature.hweb"

class GaussHermite:public OneDPrecalcQuadrature{
public:
GaussHermite();
};

/*:10*/
#line 55 "./quadrature.hweb"
;
/*11:*/
#line 288 "./quadrature.hweb"

class GaussLegendre:public OneDPrecalcQuadrature{
public:
GaussLegendre();
};

/*:11*/
#line 56 "./quadrature.hweb"
;
/*12:*/
#line 305 "./quadrature.hweb"

class NormalICDF{
public:
static double get(double x);
};

/*:12*/
#line 57 "./quadrature.hweb"
;

#endif

/*:1*/
