kthohr / gcem

A C++ compile-time math library using generalized constant expressions
https://gcem.readthedocs.io/en/latest/
Apache License 2.0
734 stars 64 forks source link
constexpr cpp cpp11 cpp14 cpp17 expression-math math special-functions

GCE-Math

Build Status Build status Coverage Status Documentation Status

GCE-Math (Generalized Constant Expression Math) is a templated C++ library enabling compile-time computation of mathematical functions.

Features:

Author: Keith O'Hara

License

Contents:

Status and Documentation

The library is actively maintained and is still being extended. A list of features includes:

Full documentation is available online:

Documentation Status

A PDF version of the documentation is available here.

Installation

GCE-Math is a header-only library and does not require any additional libraries or utilities (beyond a C++11 compatible compiler). Simply add the header files to your project using:

#include "gcem.hpp"

Conda

Anaconda-Server Badge Anaconda-Server Badge

You can install GCE-Math using the Conda package manager.

conda install -c conda-forge gcem

CMake

You can also install the library from source using CMake.

# clone gcem from GitHub
git clone https://github.com/kthohr/gcem ./gcem

# make a build directory
cd ./gcem
mkdir build
cd build

# generate Makefiles and install
cmake .. -DCMAKE_INSTALL_PREFIX=/gcem/install/location
make install

For example, /gcem/install/location could be /usr/local/.

Test Suite

There are two ways to build the test suite. On Unix-alike systems, a Makefile is available under tests/.

cd ./gcem/tests
make
./run_tests

With CMake, the option GCEM_BUILD_TESTS=1 generates the necessary Makefiles to build the test suite.

cd ./gcem
mkdir build

cd build
cmake ../ -DGCEM_BUILD_TESTS=1 -DCMAKE_INSTALL_PREFIX=/gcem/install/location
make gcem_tests

cd tests
./exp.test

Jupyter Notebook

You can test the library online using an interactive Jupyter notebook:

Binder

General Syntax

GCE-Math functions are written as C++ templates with constexpr specifiers, the format of which might appear confusing to users unfamiliar with template-based programming.

For example, the Gaussian error function (erf) is defined as:

template<typename T>
constexpr
return_t<T>
erf(const T x) noexcept;

A set of internal templated constexpr functions will implement a continued fraction expansion and return a value of type return_t<T>. The output type ('return_t<T>') is generally determined by the input type, e.g., int, float, double, long double, etc.; when T is an integral type, the output will be upgraded to return_t<T> = double, otherwise return_t<T> = T. For types not covered by std::is_integral, recasts should be used.

Examples

To calculate 10!:

#include "gcem.hpp"

int main()
{
    constexpr int x = 10;
    constexpr int res = gcem::factorial(x);

    return 0;
}

Inspecting the assembly code generated by Clang 7.0.0:

        push    rbp
        mov     rbp, rsp
        xor     eax, eax
        mov     dword ptr [rbp - 4], 0
        mov     dword ptr [rbp - 8], 10
        mov     dword ptr [rbp - 12], 3628800
        pop     rbp
        ret

We see that a function call has been replaced by a numeric value (10! = 3628800).

Similarly, to compute the log Gamma function at a point:

#include "gcem.hpp"

int main()
{
    constexpr long double x = 1.5;
    constexpr long double res = gcem::lgamma(x);

    return 0;
}

Assembly code:

.LCPI0_0:
        .long   1069547520              # float 1.5
.LCPI0_1:
        .quad   -622431863250842976     # x86_fp80 -0.120782237635245222719
        .short  49147
        .zero   6
main:                                   # @main
        push    rbp
        mov     rbp, rsp
        xor     eax, eax
        mov     dword ptr [rbp - 4], 0
        fld     dword ptr [rip + .LCPI0_0]
        fstp    tbyte ptr [rbp - 32]
        fld     tbyte ptr [rip + .LCPI0_1]
        fstp    tbyte ptr [rbp - 48]
        pop     rbp
        ret

Related libraries