GCE-Math (Generalized Constant Expression Math) is a templated C++ library enabling compile-time computation of mathematical functions.
constexpr
format, and is C++11/14/17 compatible.gcem::
syntax is identical to the C++ standard library (std::
).Author: Keith O'Hara
A list of features includes:
abs
, exp
, log
, max
, min
, pow
, sqrt
, gcd
, lcm
, and morecos
, sin
, tan
acos
, asin
, atan
cosh
, sinh
, tanh
, acosh
, asinh
, atanh
factorial
, binomial_coef
beta
, lbeta
, lgamma
, tgamma
, lmgamma
erf
, erf_inv
incomplete_beta
, incomplete_gamma
incomplete_beta_inv
, incomplete_gamma_inv
Full documentation is avaialble online:
To run a code cell, use shift + enter
.
// include libraries
#include <iostream> // for printing
#include "../include/gcem.hpp"
GCE-Math functions are written as C++ templates with constexpr
specifiers. For example, the Gaussian error function (erf
) is defined as:
template<typename T>
constexpr
return_t<T>
erf(const T x);
where a set of internal templated constexpr
functions will implement a continued fraction expansion to return a value of type return_t<T>
. This output type ('return_t<T>
') is generally determined by the input type, e.g., int
, float
, double
, long double
, etc. When T
is an intergral 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.
// exponential and natural logarithm functions
double exp_val_1 = gcem::exp(3);
double log_val_1 = gcem::log(2);
// compare with the standard library
double exp_val_2 = std::exp(3);
double log_val_2 = std::log(2);
std::cout << "exp(3) = " << exp_val_1 << std::endl;
std::cout << "error = " << gcem::abs(exp_val_1 - exp_val_2) << std::endl;
exp(3) = 20.0855 error = 0
// trig functions
double pi_dbl = double(GCEM_PI);
double hpi_dbl = double(GCEM_HALF_PI);
double sin_val_1 = gcem::sin(pi_dbl);
double sin_val_2 = gcem::sin(hpi_dbl);
std::cout << "sin(pi) = " << sin_val_1 << std::endl;
std::cout << "sin(pi/2) = " << sin_val_2 << std::endl;
std::cout << "gcem::tan(pi/2) = " << gcem::tan(hpi_dbl) << std::endl;
std::cout << "std::tan(pi/2) = " << std::tan(hpi_dbl) << std::endl;
std::cout << "|gcem::tan(0.9) - std::tan(0.9)| = " << gcem::abs(gcem::tan(1.5) - std::tan(1.5)) << std::endl;
sin(pi) = 0 sin(pi/2) = 1 gcem::tan(pi/2) = 1.63312e+16 std::tan(pi/2) = 1.63312e+16 |gcem::tan(0.9) - std::tan(0.9)| = 1.77636e-15
// hyperbolic functions
constexpr double cosh_val = gcem::cosh(0.3);
constexpr double inp_val = gcem::acosh(cosh_val);
std::cout << "gcem::cosh(0.3) = " << cosh_val << std::endl;
std::cout << "gcem::acosh(gcem::cosh(0.3)) = " << inp_val << std::endl;
gcem::cosh(0.3) = 1.04534 gcem::acosh(gcem::cosh(0.3)) = 0.3
Special functions are so-called because of their extensive use in mathematics, physics, and statisitcs. Simple examples include the basic trigonometric functions (tan, sin, cos, etc.) and the natural logarithm.
Of particular interest in statistics are integral equations, like the Gaussian error function and incomplete gamma and beta functions, necessary to calculate cumulative distribution functions.
// define some storage
double erf_inp_val, erf_val;
double a_par, b_par;
double ig_inp_val, bt_inp_val;
double ig_val, bt_val;
// Gaussian error function
erf_inp_val = 1.2;
erf_val = gcem::erf(erf_inp_val);
std::cout << "gcem::erf(" << erf_inp_val << ") = " << erf_val << std::endl;
// regularied lower incomplete gamma function
a_par = 3;
ig_inp_val = 4;
ig_val = gcem::incomplete_gamma(a_par,ig_inp_val);
std::cout << "gcem::incomplete_gamma(" << a_par << "," << ig_inp_val << ") = " << ig_val << std::endl;
// regularied lower incomplete beta function
a_par = 6;
b_par = 5;
bt_inp_val = 0.7;
bt_val = gcem::incomplete_beta(a_par,b_par,bt_inp_val);
std::cout << "gcem::incomplete_gamma(" << a_par << "," << b_par << "," << bt_inp_val << ") = " << bt_val << std::endl;
gcem::erf(1.2) = 0.910314 gcem::incomplete_gamma(3,4) = 0.761897 gcem::incomplete_gamma(6,5,0.7) = 0.849732