@q $Id: quadrature.cweb 431 2005-08-16 15:41:01Z kamenik $ @>
@q Copyright 2005, Ondra Kamenik @>

@ This is {\tt quadrature.cpp} file.

@c
#include "quadrature.h"
#include "precalc_quadrature.dat"

#include <cmath>

@<|OneDPrecalcQuadrature::calcOffsets| code@>;
@<|GaussHermite| constructor code@>;
@<|GaussLegendre| constructor code@>;
@<|NormalICDF| get code@>;

@ 
@<|OneDPrecalcQuadrature::calcOffsets| code@>=
void OneDPrecalcQuadrature::calcOffsets()
{
	offsets[0] = 0;
	for (int i = 1; i < num_levels; i++)
		offsets[i] = offsets[i-1] + num_points[i-1];
}

@ 
@<|GaussHermite| constructor code@>=
GaussHermite::GaussHermite()
	: OneDPrecalcQuadrature(gh_num_levels, gh_num_points, gh_weights, gh_points)@+ {}

@ 
@<|GaussLegendre| constructor code@>=
GaussLegendre::GaussLegendre()
	: OneDPrecalcQuadrature(gl_num_levels, gl_num_points, gl_weights, gl_points)@+ {}

@ Here we transform a draw from univariate $\langle 0,1\rangle$ to the
draw from Gaussina $N(0,1)$. This is done by a table lookup, the table
is given by |normal_icdf_step|, |normal_icfd_data|, |normal_icdf_num|,
and a number |normal_icdf_end|. In order to avoid wrong tails for lookups close
to zero or one, we rescale input |x| by $(1-2*(1-end))=2*end-1$.

@<|NormalICDF| get code@>=
double NormalICDF::get(double x)
{
	double xx = (2*normal_icdf_end-1)*std::abs(x-0.5);
	int i = (int)floor(xx/normal_icdf_step);
	double xx1 = normal_icdf_step*i;
	double yy1 = normal_icdf_data[i];
	double y;
	if (i < normal_icdf_num-1) {
		double yy2 = normal_icdf_data[i+1];
		y = yy1 + (yy2-yy1)*(xx-xx1)/normal_icdf_step;
	} else { // this should never happen
		y = yy1;
	}
	if (x > 0.5)
		return y;
	else
		return -y;
}


@ End of {\tt quadrature.cpp} file
