# viltrum VILTRUM: Varied Integration Layouts for arbiTRary integrals in a Unified Manner - A C++17 header-only library that provides a set of numerical integration routines. This library was generated during research for our paper:

Primary-Space Adaptive Control Variates using Piecewise-Polynomial Approximations

Logo

ACM Transactions on Graphics - 2021
Miguel Crespo · Adrian Jarabo · Adolfo Muñoz

Paper PDF Project Page

## Installation `viltrum` is a header-only library and has no external dependencies, so installation is rather simple (it does not require any compilation process). You just need to download the library in a specific folder: ``` folder> git clone https://github.com/adolfomunoz/viltrum.git ``` Then make sure `folder` is within the included directories (`-Ifolder` parameter in g++, `include_directories("folder")` in CMake) and include it from C++. ```cpp #include ``` That would be enough to use all the features of the library. There are other alternatives that might be more comfortable for you, see them [here](doc/installation.md). There is a CMake-based building system for several example and test executable files that automatically downloads external dependencies and compiles all executables but it is not needed for the libray's usage. ## Usage Integrating a function in a specific n-dimensional range is rather simple. You need the following information: - An *integrator*, a numerical integration method, for which there are [several to choose from](doc/integrators.md). - An *integrand*, a function to be integrated. It's only parameter has to be a `std::array`, where `F` is a floating point number and `N` is the number of dimensions. There are [several ways in which such integrand can be defined](doc/integrands.md). The integrand can return any numeric value, or, in general, any data type that supports addition and multiplication by a scalar (tested with [Eigen arrays](https://eigen.tuxfamily.org/dox/group__TutorialArrayClass.html) ). - A *range*, the integration domain, that is composed on two `std::array` marking the limits of the potentially multidimensional integration domain, which [can be defined in different ways](doc/ranges.md). Example: ```cpp float sphere(const std::array& x) { return (x[0]*x[0]+x[1]*x[1]+x[2]*x[2])<=1.0f?1.0f:0.0f; } int main() { unsigned long samples = 1024; auto method = viltrum::integrator_monte_carlo_uniform(samples); auto range = viltrum::range(std::array{-1.0f,-1.0f,-1.0f},std::array{1.0f,1.0f,1.0f}); std::cout<<"Sphere volume = "<& x) { return (x[1]{0,0},std::array{1,1}); float output_array[16]; //... } ``` bin integrators can be used as follows (1D example): ```cpp auto output_array_access = [&output_array] (const std::array& i) -> float& { return output_array[i[0]]; }; integrator_bins.integrate(output_array_access,std::array{16},slope,range); for (float f : output_array) std::cout<& i) -> float& { return output_array[4*i[0]+i[1]]; }; integrator_bins.integrate(output_array_access_2d,std::array{4,4},slope,range); ``` Additionally, the `viltrum` library offers a functional version of the same method: ```cpp integrate_bins(integrator_bins,output_array_access,std::array{16},slope,range); integrate_bins(integrator_bins,output_array_access_2d,std::array{4,4},slope,range); ``` This functional version is able to deduce the bin accesor as well as the resolution for `std::vector` data types, in which there is only one parameter defining the binning structure: ```cpp std::vector output_vector(16); integrate_bins(integrator_bins, output_vector, slope, range); for (float f : output_vector) std::cout<> output_matrix(4,std::vector(4)); integrate_bins(integrator_bins, output_matrix, slope, range); std::cout<& row : output_matrix) { for (float f : row) std::cout<