std::lgamma...std::lgammal(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… std::lgamma, std::lgammaf, std::lgammal ✨

okay so bestie, listen up β€” this is the C++ Standard Library's take on the log-gamma function, and honestly? it's giving math girlboss energy. no cap.


🌸 SYNOPSIS 🌸

so this whole situation lives in the header <cmath>, periodt:

float       lgamma ( float num );

double      lgamma ( double num );                           (until C++23)

long double lgamma ( long double num );
/* floating-point-type */                                    (since C++23)
                lgamma ( /* floating-point-type */ num
(constexpr since C++26)
);                                                   (1)
float       lgammaf( float num );                        (2) (since C++11)
                                                             (constexpr
since C++26)
long double lgammal( long double num );                  (3) (since C++11)
                                                             (constexpr
since C++26)
Additional overloads (since C++11)
Defined in header <cmath>
template< class Integer >                                (A)
(constexpr since C++26)
double      lgamma ( Integer num );

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so here's the tea:

  1. 1-3) these bad boys compute the natural logarithm of the absolute value of the gamma function of num. honestly iconic behavior.

starting since C++23, the library is like so generous and provides overloads of std::lgamma for all cv-unqualified floating-point types as the type of the parameter. we love inclusive king behavior πŸ‘‘

A) and since C++11, additional overloads are provided for all integer types, which are treated as double. it's giving "close enough" energy but make it mathematical πŸ’…


πŸŽ€ Parameters πŸŽ€

  • num β€” a floating-point or integer value. literally that's it bestie, that's the input 🫢

✨ Return value ✨

if no errors occur, you get the value of the logarithm of the gamma function of num, that is:

$$\log_{e}\left|\int_0^\infty t^{num-1} e^{-t} , \mathsf{d}t\right|$$

aka log<sub>e</sub>|∫<sub>0</sub><sup>∞</sup> t<sup>num-1</sup> e<sup>-t</sup> dt| β€” slay, the math is mathing πŸ”₯

if a pole error occurs, you get +HUGE_VAL, +HUGE_VALF, or +HUGE_VALL returned. not great, not terrible.

if a range error due to overflow occurs, you get Β±HUGE_VAL, Β±HUGE_VALF, or Β±HUGE_VALL returned. yikes but okay πŸ’€


πŸ’œ Error handling πŸ’œ

errors are reported as specified in math_errhandling. know that.

if num is zero or is an integer less than zero, a pole error may occur. so watch out babes ⚠️

if the implementation supports IEEE floating-point arithmetic (IEC 60559), here's the vibe check:

  • if the argument is 1, +0 is returned.
  • if the argument is 2, +0 is returned.
  • if the argument is Β±0, +∞ is returned and FE_DIVBYZERO is raised.
  • if the argument is a negative integer, +∞ is returned and FE_DIVBYZERO is raised.
  • if the argument is ±∞, +∞ is returned.
  • if the argument is NaN, NaN is returned.

ngl these special cases are iconic and you should memorize them πŸ’…


🌈 NOTES 🌈

okay so if num is a natural number, std::lgamma(num) is the logarithm of the factorial of num - 1. math girlies stay winning 🧚

⚠️ important tea: the POSIX version of lgamma is not thread-safe β€” each execution of the function stores the sign of the gamma function of num in the static external variable signgam. some implementations provide lgamma_r, which takes a pointer to user-provided storage for signgam as the second parameter, and is thread-safe. so like, if you're doing multithreaded stuff, be careful bestie 😭

also there's a non-standard function named gamma in various implementations, but its definition is inconsistent. for example, glibc and 4.2BSD version of gamma executes lgamma, but 4.4BSD version of gamma executes tgamma. it's giving chaotic and honestly? we don't stan πŸ’€

the additional overloads are not required to be provided exactly as (A). they only need to be sufficient to ensure that for their argument num of integer type, std::lgamma(num) has the same effect as std::lgamma(static_cast<double>(num)). so like, vibe-wise it's the same. periodt.


πŸ“ Example πŸ“

// Run this code

#include <cerrno>
#include <cfenv>
#include <cmath>
#include <cstring>
#include <iostream>

// #pragma STDC FENV_ACCESS ON

const double pi = std::acos(-1); // or std::numbers::pi since C++20

int main()
{
    std::cout << "lgamma(10) = " << std::lgamma(10)
              << ", log(9!) = " << std::log(std::tgamma(10))
              << ", exp(lgamma(10)) = " << std::exp(std::lgamma(10)) << '\n'
              << "lgamma(0.5) = " << std::lgamma(0.5)
              << ", log(sqrt(pi)) = " << std::log(std::sqrt(pi)) << '\n';

    // special values
    std::cout << "lgamma(1) = " << std::lgamma(1) << '\n'
              << "lgamma(+Inf) = " << std::lgamma(INFINITY) << '\n';

    // error handling
    errno = 0;
    std::feclearexcept(FE_ALL_EXCEPT);

    std::cout << "lgamma(0) = " << std::lgamma(0) << '\n';

    if (errno == ERANGE)
        std::cout << "    errno == ERANGE: " << std::strerror(errno) << '\n';
    if (std::fetestexcept(FE_DIVBYZERO))
        std::cout << "    FE_DIVBYZERO raised\n";
}

⭐ Output ⭐

lgamma(10) = 12.8018, log(9!) = 12.8018, exp(lgamma(10)) = 362880
lgamma(0.5) = 0.572365, log(sqrt(pi)) = 0.572365
lgamma(1) = 0
lgamma(+Inf) = inf
lgamma(0) = inf
    errno == ERANGE: Numerical result out of range
    FE_DIVBYZERO raised

πŸ‘‘ See also πŸ‘‘

  • tgamma, tgammaf, tgammal β€” gamma function, the non-log version bestie πŸ’… (C++11 function, C++11, C++11)
  • C documentation for lgamma β€” for when you need to revisit the source material ig

Weisstein, Eric W. "Log Gamma Function." From MathWorld β€” A Wolfram Web Resource. very scholarly, very demure πŸŽ€


k that's the whole page bestie, you're officially a lgamma expert now. go forth and compute those logarithms πŸ’–

source/version: cppreference.com Β· date: 2024.06.10 Β· manual: std::lgamma...std::lgammal(3) Β· mwah πŸ’‹

πŸ“¦ where this page comes from