(t, m, s)-nets generator  3.0.1
Tutorial 4. Handler functions
Warning
This tutorial is the first tutorial of the intermediate level. It might require a greater understanding of C++.

This tutorial introduces one of the features of the library, namely, handler functions. Handler function is basically any user-defined function with the following signature:

void (tms::Point const &, tms::CountInt)
std::vector< Real > Point
Represents a point of a (t, m, s)-net.
Definition: common.hpp:25
uintmax_t CountInt
A type for integer counting values, (e.g. number of net's point)
Definition: common.hpp:17

The main idea behind this is that one can use these functions to receive points directly from the generator and immediately perform some sort of processing.

1. Basic example

Each \((t, m, s)\)-net has a for_each_point method with the following signature:

void tms::DigitalNet::for_each_point(std::function<void(Point const &, CountInt)> handler, CountInt amount, CountInt pos = 0) const
void for_each_point(std::function< void(Point const &, CountInt)> handler, CountInt amount, CountInt pos=0) const

Its execution initiates a sequential generation of amount points on a net starting with a point number pos.

Let us now create a simple handler that calculates the second norm \(\|\overrightarrow{x}\|_2\) for each point of the net and prints it.

#include "libraries/tms-nets/tms-nets.hpp"
#include <cmath>
#include <iostream>
void norm(tms::Point const &x, tms::CountInt x_i)
{
long double d = 0;
for (auto coordinate : x)
d += coordinate * coordinate;
d = sqrt(d);
std::cout << '#' << x_i << ": 2-norm = " << d << '\n';
return;
}
int main()
{
// We use a 4-dimensional Sobol net with 8 points
tms::Sobol my_net(3, 4);
my_net.for_each_point(norm, 8, 0);
return 0;
}
Definition: sobol.hpp:11

The expected output is:

#0: 2-norm = 0
#1: 2-norm = 1
#2: 2-norm = 1.11803
#3: 2-norm = 1.11803
#4: 2-norm = 1.19896
#5: 2-norm = 1.29904
#6: 2-norm = 1.08972
#7: 2-norm = 0.968246

2. Lambda as a handler

Using lambdas as handlers might end up handy to reduce the amount of code needed to perform certain mathematical operations.

Let us demonstrate a calculation of integral

\[\int_{I^4} \|\overrightarrow{x}\|_2 d\overrightarrow{x}\]

#include "lib/tms-nets/tms-nets.hpp"
#include <cmath>
#include <cstdint> // needed for uint*_t types
#include <iostream>
long double norm(tms::Point const &x)
{
long double d = 0;
for (auto coordinate : x)
d += coordinate * coordinate;
d = sqrt(d);
return d;
}
int main()
{
tms::Sobol my_net(3, 4);
long double integral = 0;
// All calculations occupy just a single line
my_net.for_each_point([&integral](tms::Point const &x, tms::CountInt x_i){integral += norm(x) / 8;}, 8, 0);
std::cout << "Integral = " << integral << '\n';
return 0;
}

The expected output is:

Integral = 0.974004