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

@ This is {\tt quasi\_mcarlo.cpp} file.

@c
#include "quasi_mcarlo.h"

#include <cmath>

@<|RadicalInverse| constructor code@>;
@<|RadicalInverse::eval| code@>;
@<|RadicalInverse::increase| code@>;
@<|RadicalInverse::print| code@>;
@<|HaltonSequence| static data@>;
@<|HaltonSequence| constructor code@>;
@<|HaltonSequence::operator=| code@>;
@<|HaltonSequence::increase| code@>;
@<|HaltonSequence::eval| code@>;
@<|HaltonSequence::print| code@>;
@<|qmcpit| empty constructor code@>;
@<|qmcpit| regular constructor code@>;
@<|qmcpit| copy constructor code@>;
@<|qmcpit| destructor@>;
@<|qmcpit::operator==| code@>;
@<|qmcpit::operator=| code@>;
@<|qmcpit::operator++| code@>;
@<|qmcpit::weight| code@>;
@<|qmcnpit| empty constructor code@>;
@<|qmcnpit| regular constructor code@>;
@<|qmcnpit| copy constructor code@>;
@<|qmcnpit| destructor@>;
@<|qmcnpit::operator=| code@>;
@<|qmcnpit::operator++| code@>;
@<|WarnockPerScheme::permute| code@>;
@<|ReversePerScheme::permute| code@>;

@ Here in the constructor, we have to calculate a maximum length of
|coeff| array for a given |base| and given maximum |maxn|. After
allocation, we calculate the coefficients.

@<|RadicalInverse| constructor code@>=
RadicalInverse::RadicalInverse(int n, int b, int mxn)
	: num(n), base(b), maxn(mxn),
	  coeff((int)(floor(log((double)maxn)/log((double)b))+2), 0)
{
	int nr = num;
	j = -1;
	do {
		j++;
		coeff[j] = nr % base;
		nr = nr / base;
	} while (nr > 0);
}

@ This evaluates the radical inverse. If there was no permutation, we have to calculate
$$
{c_0\over b}+{c_1\over b^2}+\ldots+{c_j\over b^{j+1}}
$$
which is evaluated as
$$
\left(\ldots\left(\left({c_j\over b}\cdot{1\over b}+{c_{j-1}\over b}\right)
\cdot{1\over b}+{c_{j-2}\over b}\right)
\ldots\right)\cdot{1\over b}+{c_0\over b}
$$
Now with permutation $\pi$, we have
$$
\left(\ldots\left(\left({\pi(c_j)\over b}\cdot{1\over b}+
{\pi(c_{j-1})\over b}\right)\cdot{1\over b}+
{\pi(c_{j-2})\over b}\right)
\ldots\right)\cdot{1\over b}+{\pi(c_0)\over b}
$$


@<|RadicalInverse::eval| code@>=
double RadicalInverse::eval(const PermutationScheme& p) const
{
	double res = 0;
	for (int i = j; i >= 0; i--) {
		int cper = p.permute(i, base, coeff[i]);
		res = (cper + res)/base;
	}
	return res;
}

@ We just add 1 to the lowest coefficient and check for overflow with respect to the base.
@<|RadicalInverse::increase| code@>=
void RadicalInverse::increase()
{
	// todo: raise if |num+1 > maxn|
	num++;
	int i = 0;
	coeff[i]++;
	while (coeff[i] == base) {
		coeff[i] = 0;
		coeff[++i]++;
	}
	if (i > j)
		j = i;
}

@ Debug print.
@<|RadicalInverse::print| code@>=
void RadicalInverse::print() const
{
	printf("n=%d b=%d c=", num, base);
	coeff.print();
}

@ Here we have the first 170 primes. This means that we are not able
to integrate dimensions greater than 170.

@<|HaltonSequence| static data@>=
int HaltonSequence::num_primes = 170;
int HaltonSequence::primes[] = {
      2,     3,     5,     7,    11,    13,    17,    19,    23,    29,
     31,    37,    41,    43,    47,    53,    59,    61,    67,    71,
     73,    79,    83,    89,    97,   101,   103,   107,   109,   113,
    127,   131,   137,   139,   149,   151,   157,   163,   167,   173,
    179,   181,   191,   193,   197,   199,   211,   223,   227,   229,
    233,   239,   241,   251,   257,   263,   269,   271,   277,   281,
    283,   293,   307,   311,   313,   317,   331,   337,   347,   349,
    353,   359,   367,   373,   379,   383,   389,   397,   401,   409,
    419,   421,   431,   433,   439,   443,   449,   457,   461,   463,
    467,   479,   487,   491,   499,   503,   509,   521,   523,   541,
    547,   557,   563,   569,   571,   577,   587,   593,   599,   601,
    607,   613,   617,   619,   631,   641,   643,   647,   653,   659,
    661,   673,   677,   683,   691,   701,   709,   719,   727,   733,
    739,   743,   751,   757,   761,   769,   773,   787,   797,   809,
    811,   821,   823,   827,   829,   839,   853,   857,   859,   863,
    877,   881,   883,   887,   907,   911,   919,   929,   937,   941,
    947,   953,   967,   971,   977,   983,   991,   997,  1009,  1013
};


@ This takes first |dim| primes and constructs |dim| radical inverses
and calls |eval|.

@<|HaltonSequence| constructor code@>=
HaltonSequence::HaltonSequence(int n, int mxn, int dim, const PermutationScheme& p)
	: num(n), maxn(mxn), per(p), pt(dim)
{
	// todo: raise if |dim > num_primes|
	// todo: raise if |n > mxn|
	for (int i = 0; i < dim; i++)
		ri.push_back(RadicalInverse(num, primes[i], maxn));
	eval();
}

@ 
@<|HaltonSequence::operator=| code@>=
const HaltonSequence& HaltonSequence::operator=(const HaltonSequence& hs)
{
	num = hs.num;
	maxn = hs.maxn;
	ri.clear();
	for (unsigned int i = 0; i < hs.ri.size(); i++)
		ri.push_back(RadicalInverse(hs.ri[i]));
	pt = hs.pt;
	return *this;
}



@ This calls |RadicalInverse::increase| for all radical inverses and
calls |eval|.

@<|HaltonSequence::increase| code@>=
void HaltonSequence::increase()
{
	for (unsigned int i = 0; i < ri.size(); i++)
		ri[i].increase();
	num++;
	if (num <= maxn)
		eval();
}

@ This sets point |pt| to radical inverse evaluations in each dimension.
@<|HaltonSequence::eval| code@>=
void HaltonSequence::eval()
{
	for (unsigned int i = 0; i < ri.size(); i++)
		pt[i] = ri[i].eval(per);
}

@ Debug print.
@<|HaltonSequence::print| code@>=
void HaltonSequence::print() const
{
	for (unsigned int i = 0; i < ri.size(); i++)
		ri[i].print();
	printf("point=[ ");
	for (unsigned int i = 0; i < ri.size(); i++)
		printf("%7.6f ", pt[i]);
	printf("]\n");
}

@ 
@<|qmcpit| empty constructor code@>=
qmcpit::qmcpit()
	: spec(NULL), halton(NULL), sig(NULL)@+ {}

@ 
@<|qmcpit| regular constructor code@>=
qmcpit::qmcpit(const QMCSpecification& s, int n)
	: spec(&s), halton(new HaltonSequence(n, s.level(), s.dimen(), s.getPerScheme())),
	  sig(new ParameterSignal(s.dimen()))
{
}

@ 
@<|qmcpit| copy constructor code@>=
qmcpit::qmcpit(const qmcpit& qpit)
	: spec(qpit.spec), halton(NULL), sig(NULL)
{
	if (qpit.halton)
		halton = new HaltonSequence(*(qpit.halton));
	if (qpit.sig)
		sig = new ParameterSignal(qpit.spec->dimen());
}

@ 
@<|qmcpit| destructor@>=
qmcpit::~qmcpit()
{
	if (halton)
		delete halton;
	if (sig)
		delete sig;
}

@ 
@<|qmcpit::operator==| code@>=
bool qmcpit::operator==(const qmcpit& qpit) const
{
	return (spec == qpit.spec) &&
		((halton == NULL && qpit.halton == NULL) ||
		 (halton != NULL && qpit.halton != NULL && halton->getNum() == qpit.halton->getNum())); 
}

@ 
@<|qmcpit::operator=| code@>=
const qmcpit& qmcpit::operator=(const qmcpit& qpit)
{
	spec = qpit.spec;
	if (halton)
		delete halton;
	if (qpit.halton)
		halton = new HaltonSequence(*(qpit.halton));
	else
		halton = NULL;
	return *this;
}


@ 
@<|qmcpit::operator++| code@>=
qmcpit& qmcpit::operator++()
{
	// todo: raise if |halton == null || qmcq == NULL|
	halton->increase();
	return *this;
}

@ 
@<|qmcpit::weight| code@>=
double qmcpit::weight() const
{
	return 1.0/spec->level();
}

@ 
@<|qmcnpit| empty constructor code@>=
qmcnpit::qmcnpit()
	: qmcpit(), pnt(NULL)@+ {}

@ 
@<|qmcnpit| regular constructor code@>=
qmcnpit::qmcnpit(const QMCSpecification& s, int n)
	: qmcpit(s, n), pnt(new Vector(s.dimen()))
{
}

@ 
@<|qmcnpit| copy constructor code@>=
qmcnpit::qmcnpit(const qmcnpit& qpit)
	: qmcpit(qpit), pnt(NULL)
{
	if (qpit.pnt)
		pnt = new Vector(*(qpit.pnt));
}

@ 
@<|qmcnpit| destructor@>=
qmcnpit::~qmcnpit()
{
	if (pnt)
		delete pnt;
}

@ 
@<|qmcnpit::operator=| code@>=
const qmcnpit& qmcnpit::operator=(const qmcnpit& qpit)
{
	qmcpit::operator=(qpit);
	if (pnt)
		delete pnt;
	if (qpit.pnt)
		pnt = new Vector(*(qpit.pnt));
	else
		pnt = NULL;
	return *this;
}

@ Here we inccrease a point in Halton sequence ant then store images
of the points in |NormalICDF| function.

@<|qmcnpit::operator++| code@>=
qmcnpit& qmcnpit::operator++()
{
	qmcpit::operator++();
	for (int i = 0; i < halton->point().length(); i++)
		(*pnt)[i] = NormalICDF::get(halton->point()[i]);
	return *this;
}

@ Clear from code.
@<|WarnockPerScheme::permute| code@>=
int WarnockPerScheme::permute(int i, int base, int c) const
{
	return (c+i) % base;
}

@ Clear from code.
@<|ReversePerScheme::permute| code@>=
int ReversePerScheme::permute(int i, int base, int c) const
{
	return (base-c) % base;
}

@ End of {\tt quasi\_mcarlo.cpp} file.