Skip to content

utl::math

<- to README.md

<- to implementation.hpp

utl::math header is a collection of mathematical utils that includes:

  • Constants
  • Template math
  • Non-overflowing functions
  • Index functions
  • Conversions and etc.

All implementations template, constexpr and noexcept.

Note

For a more "complete" mathematical library check out DmitriBogdanov/GSE.

Definitions

// Constants
namespace constants {
    constexpr double pi      = 3.14159265358979323846;
    constexpr double two_pi  = 2.0 * pi;
    constexpr double half_pi = 0.5 * pi;
    constexpr double inv_pi  = 1.0 / pi;
    constexpr double e       = 2.71828182845904523536;
    constexpr double phi     = 1.61803398874989484820;
}

// Basic functions
template <class T> constexpr T       abs(T x) noexcept;
template <class T> constexpr T      sign(T x) noexcept;
template <class T> constexpr T     bsign(T x) noexcept;
template <class T> constexpr T       sqr(T x) noexcept;
template <class T> constexpr T      cube(T x) noexcept;
template <class T> constexpr T       inv(T x) noexcept;
template <class T> constexpr T heaviside(T x) noexcept;

// Non-overflowing functions
template <class T> constexpr T midpoint(T a, T b) noexcept;
template <class T> constexpr T  absdiff(T a, T b) noexcept;

// Power functions
template <class T, class U> constexpr T     pow(T x, U p) noexcept;
template <         class U> constexpr U signpow(     U p) noexcept;

// Index functions
template <class T> constexpr T kronecker_delta(T i, T j     ) noexcept;
template <class T> constexpr T     levi_civita(T i, T j, T k) noexcept;

// Conversions
template <class T> constexpr T deg_to_rad(T degrees) noexcept;
template <class T> constexpr T rad_to_deg(T radians) noexcept;

// Sequence operations
template <class Idx, class Func> constexpr auto  sum(Idx low, Idx high, Func&& func);
template <class Idx, class Func> constexpr auto prod(Idx low, Idx high, Func&& func);

Note

All methods have appropriate SFINAE-restrictions, which are omitted in documentation to reduce verbosity.

Methods

Constants

namespace constants {
    constexpr double pi      = 3.14159265358979323846;
    constexpr double two_pi  = 6.28318530717958647693;
    constexpr double half_pi = 1.57079632679489661923;
    constexpr double inv_pi  = 0.31830988618379067153;
    constexpr double sqrtpi  = 1.77245385090551602729;
    constexpr double e       = 2.71828182845904523536;
    constexpr double egamma  = 0.57721566490153286060;
    constexpr double phi     = 1.61803398874989484820;
    constexpr double ln2     = 0.69314718055994530942;
    constexpr double ln10    = 2.30258509299404568402;
    constexpr double sqrt2   = 1.41421356237309504880;
    constexpr double sqrt3   = 1.73205080756887729352;
}

Basic mathematical constants. In C++20 most of these get standardized as a part of <numbers> header.

Identifier Mathematical notation Reference
pi \(\pi\) Mathematical constant π
two_pi \(2 \pi\) -
half_pi \(\pi / 2\) -
inv_pi \(1 / \pi\) -
sqrtpi \(\sqrt{\pi}\) -
e \(e\) Euler's number
egamma \(\gamma\) Euler–Mascheroni constant
phi \(\varphi\) Golden ratio
ln2 \(\ln{2}\) -
ln10 \(\ln{10}\) -
sqrt2 \(\sqrt{2}\) -
sqrt3 \(\sqrt{3}\) -

Basic functions

template <class T> constexpr T       abs(T x) noexcept;
template <class T> constexpr T      sign(T x) noexcept;
template <class T> constexpr T     bsign(T x) noexcept;
template <class T> constexpr T       sqr(T x) noexcept;
template <class T> constexpr T      cube(T x) noexcept;
template <class T> constexpr T       inv(T x) noexcept;
template <class T> constexpr T heaviside(T x) noexcept;

Returns \(|x|\), \(\mathrm{sign} (x)\), \(x^2\), \(x^3\), \(x^{-1}\), or \(H(x)\).

T can be of any arithmetic type except bool.

To reduce integer division surprises, inv() also requires a floating point.

Note 1: sign() is a standard sign function which returns \(-1\), \(0\) or \(1\). bsign() is a binary variation that returns \(1\) instead of \(0\).

Note 2: \(H(x)\) refers to Heaviside step function.

Non-overflowing functions

template <class T> constexpr T midpoint(T a, T b) noexcept;
template <class T> constexpr T  absdiff(T a, T b) noexcept;

Computes \(\dfrac{a + b}{2}\) or \(|a - b|\) without potential overflow.

T can be of any arithmetic type except bool.

Integer midpoint() rounds down in case of a fractional result.

Note 1: Correctly computing integer / float midpoint() is trickier than it might initially seem, naive (a + b) / 2 formula suffers multiple issues when applied to values near min / max of the given type.

Note 2: Compared to integer std::midpoint() (which rounds towards a), integer math::midpoint() (which rounds down) is commutative and faster to compute. Floating point behavior is the same.

Power functions

template <class T, class U> constexpr T     pow(T x, U p) noexcept;
template <         class U> constexpr U signpow(     U p) noexcept;

Returns \(x^p\) or \(-1^p\) .

T can be of any arithmetic type except bool.

U can be of any integral type.

Note: Computing signpow(p) is significantly faster than std::pow(-1, p).

Index functions

template <class T> constexpr T kronecker_delta(T i, T j) noexcept;

Computes Kronecker delta symbol: 1 if i == j, 0 otherwise.

T can be of any integral type.

template <class T> constexpr T levi_civita(T i, T j, T k) noexcept;

Computes Levi-Civita symbol: 1 if (i, j, k) form an even permutation, -1 if (i, j, k) form an odd permutation, and 0 if any the adjacent letters are equal.

T can be of any integral type.

Conversions

template <class T> constexpr T deg_to_rad(T degrees) noexcept;
template <class T> constexpr T rad_to_deg(T radians) noexcept;

Converts degrees to radians and back.

T can be of any floating point type.

Sequence operations

template <class Idx, class Func> constexpr auto  sum(Idx low, Idx high, Func&& f);
template <class Idx, class Func> constexpr auto prod(Idx low, Idx high, Func&& f);

Computes \(\sum_{i = low}^{high} f(i)\) or \(\prod_{i = low}^{high} f(i)\).

Idx can be of any integral type.

noexcept when f is non-throwing.

Examples

Template math functions

[ Run this code ]

using namespace utl;

static_assert( math::abs      (-7 ) ==  7  );
static_assert( math::sign     ( 0 ) ==  0  );
static_assert( math::bsign    ( 0 ) ==  1  );
static_assert( math::sqr      (-2 ) ==  4  );
static_assert( math::cube     (-2 ) == -8  );
static_assert( math::inv      ( 2.) == 0.5 );
static_assert( math::heaviside( 2.) ==  1  );

static_assert( math::midpoint(3, 5) == 4 );
static_assert( math::absdiff (4, 7) == 3 );

static_assert( math::pow    (2, 7) ==  128 );
static_assert( math::signpow(  -5) == -1   );

Index functions

[ Run this code ]

using namespace utl;

static_assert( math::kronecker_delta(3, 4) == 0 );
static_assert( math::kronecker_delta(3, 3) == 1 );

static_assert( math::levi_civita(3, 4, 4) ==  0 );
static_assert( math::levi_civita(3, 4, 5) ==  1 );
static_assert( math::levi_civita(5, 4, 3) == -1 );

Conversions

[ Run this code ]

using namespace utl;

static_assert( math::absdiff(math::deg_to_rad(180.), math::constants::pi) < 1e-16  );

static_assert( math::absdiff(math::rad_to_deg(math::constants::pi), 180.) < 1e-16  );

Summation & product

[ Run this code ]

using namespace utl;

constexpr auto  sum = math::sum( 1, 3, [](int i){ return math::sqr(i); }); // 1^2 + 2^2 + 3^2
constexpr auto prod = math::prod(1, 3, [](int i){ return math::sqr(i); }); // 1^2 * 2^2 * 3^2

static_assert(  sum == 1 + 4 + 9 );
static_assert( prod == 1 * 4 * 9 );

Newer standards

Some parts of this header can be replaced with std features in newer standards: