{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# [GCE-Math](https://github.com/kthohr/gcem)\n",
    "\n",
    "\n",
    "GCE-Math (Generalized Constant Expression Math) is a templated C++ library enabling compile-time computation of mathematical functions.\n",
    "\n",
    "* The library is written in C++11 `constexpr` format, and is C++11/14/17 compatible.\n",
    "* Continued fraction and series expansions are implemented using recursive templates.\n",
    "* The `gcem::` syntax is identical to the C++ standard library (`std::`).\n",
    "* Tested and accurate to floating-point precision against the C++ standard library.\n",
    "* Released under a permissive, non-GPL license.\n",
    "\n",
    "**Author**: Keith O'Hara\n",
    "\n",
    "<a href=\"https://travis-ci.org/kthohr/gcem/LICENSE\" target=\"_blank\"><img style=\"float: left;\" src=\"https://img.shields.io/badge/Licence-Apache%202.0-blue.svg\" alt=\"License\"></a>\n",
    "\n",
    "&nbsp;\n",
    "\n",
    "## Coverage and Documentation\n",
    "\n",
    "A list of features includes:\n",
    "\n",
    "* basic library functions:\n",
    "    - ```abs```, ```exp```, ```log```, ```max```, ```min```, ```pow```, ```sqrt```, ```gcd```, ```lcm```, and more\n",
    "* trigonometric functions:\n",
    "    - basic: ```cos```, ```sin```, ```tan```\n",
    "    - inverse: ```acos```, ```asin```, ```atan```\n",
    "    - hyperbolic (area) functions: ```cosh```, ```sinh```, ```tanh```, ```acosh```, ```asinh```, ```atanh```\n",
    "* special functions:\n",
    "    - factorials and the binomial coefficient: ```factorial```, ```binomial_coef```\n",
    "    - beta, gamma, and multivariate gamma functions: ```beta```, ```lbeta```, ```lgamma```, ```tgamma```, ```lmgamma```\n",
    "    - the Gaussian error function and inverse error function: ```erf```, ```erf_inv```\n",
    "    - (regularized) incomplete beta and incomplete gamma functions: ```incomplete_beta```, ```incomplete_gamma```\n",
    "    - inverse incomplete beta and incomplete gamma functions: ```incomplete_beta_inv```, ```incomplete_gamma_inv```\n",
    "\n",
    "Full documentation is avaialble online:\n",
    "\n",
    "<a href=\"https://gcem.readthedocs.io/en/latest/?badge=latest\" target=\"_blank\"><img style=\"float: left;\" src=\"https://readthedocs.org/projects/gcem/badge/?version=latest\" alt=\"Documentation\"></a> \n",
    "\n",
    "&nbsp;\n",
    "\n",
    "## This Notebook\n",
    "\n",
    "To run a code cell, use `shift + enter`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "// include libraries\n",
    "#include <iostream>              // for printing\n",
    "#include \"../include/gcem.hpp\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Syntax and Examples\n",
    "\n",
    "GCE-Math functions are written as C++ templates with `constexpr` specifiers. For example, the [Gaussian error function](https://en.wikipedia.org/wiki/Error_function) (```erf```) is defined as:\n",
    "```cpp\n",
    "template<typename T>\n",
    "constexpr\n",
    "return_t<T>\n",
    "erf(const T x);\n",
    "```\n",
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "exp(3) = 20.0855\n",
      "error = 0\n"
     ]
    }
   ],
   "source": [
    "// exponential and natural logarithm functions\n",
    "\n",
    "double exp_val_1 = gcem::exp(3);\n",
    "double log_val_1 = gcem::log(2);\n",
    "\n",
    "// compare with the standard library\n",
    "\n",
    "double exp_val_2 = std::exp(3);\n",
    "double log_val_2 = std::log(2);\n",
    "\n",
    "std::cout << \"exp(3) = \" << exp_val_1 << std::endl;\n",
    "std::cout << \"error = \" << gcem::abs(exp_val_1 - exp_val_2) << std::endl;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sin(pi)   = 0\n",
      "sin(pi/2) = 1\n",
      "gcem::tan(pi/2) = 1.63312e+16\n",
      "std::tan(pi/2)  = 1.63312e+16\n",
      "|gcem::tan(0.9) -  std::tan(0.9)| = 1.77636e-15\n"
     ]
    }
   ],
   "source": [
    "// trig functions\n",
    "\n",
    "double pi_dbl  = double(GCEM_PI);\n",
    "double hpi_dbl = double(GCEM_HALF_PI);\n",
    "\n",
    "double sin_val_1 = gcem::sin(pi_dbl);\n",
    "double sin_val_2 = gcem::sin(hpi_dbl);\n",
    "\n",
    "std::cout << \"sin(pi)   = \" << sin_val_1 << std::endl;\n",
    "std::cout << \"sin(pi/2) = \" << sin_val_2 << std::endl;\n",
    "\n",
    "std::cout << \"gcem::tan(pi/2) = \" << gcem::tan(hpi_dbl) << std::endl;\n",
    "std::cout << \"std::tan(pi/2)  = \" << std::tan(hpi_dbl) << std::endl;\n",
    "\n",
    "std::cout << \"|gcem::tan(0.9) -  std::tan(0.9)| = \" << gcem::abs(gcem::tan(1.5) - std::tan(1.5)) << std::endl;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gcem::cosh(0.3) = 1.04534\n",
      "gcem::acosh(gcem::cosh(0.3)) = 0.3\n"
     ]
    }
   ],
   "source": [
    "// hyperbolic functions\n",
    "\n",
    "constexpr double cosh_val = gcem::cosh(0.3);\n",
    "constexpr double inp_val  = gcem::acosh(cosh_val);\n",
    "\n",
    "std::cout << \"gcem::cosh(0.3) = \" << cosh_val << std::endl;\n",
    "std::cout << \"gcem::acosh(gcem::cosh(0.3)) = \" << inp_val << std::endl;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Special Functions\n",
    "\n",
    "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.\n",
    "\n",
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "// define some storage\n",
    "double erf_inp_val, erf_val;\n",
    "double a_par, b_par;\n",
    "double ig_inp_val, bt_inp_val;\n",
    "double ig_val, bt_val;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gcem::erf(1.2) = 0.910314\n",
      "gcem::incomplete_gamma(3,4) = 0.761897\n",
      "gcem::incomplete_gamma(6,5,0.7) = 0.849732\n"
     ]
    }
   ],
   "source": [
    "// Gaussian error function\n",
    "erf_inp_val = 1.2;\n",
    "erf_val = gcem::erf(erf_inp_val);\n",
    "\n",
    "std::cout << \"gcem::erf(\" << erf_inp_val << \") = \" << erf_val << std::endl;\n",
    "\n",
    "// regularied lower incomplete gamma function\n",
    "a_par = 3;\n",
    "ig_inp_val = 4;\n",
    "\n",
    "ig_val = gcem::incomplete_gamma(a_par,ig_inp_val);\n",
    "\n",
    "std::cout << \"gcem::incomplete_gamma(\" << a_par << \",\" << ig_inp_val << \") = \" << ig_val << std::endl;\n",
    "\n",
    "// regularied lower incomplete beta function\n",
    "a_par = 6;\n",
    "b_par = 5;\n",
    "bt_inp_val = 0.7;\n",
    "\n",
    "bt_val = gcem::incomplete_beta(a_par,b_par,bt_inp_val);\n",
    "\n",
    "std::cout << \"gcem::incomplete_gamma(\" << a_par << \",\" << b_par << \",\" << bt_inp_val << \") = \" << bt_val << std::endl;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++11",
   "language": "C++11",
   "name": "xeus-cling-cpp11"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "c++",
   "version": "-std=c++11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}