Gamma and Related Functions
Labels: feature, triaged, module: special

# Gamma and Related Functions

A brief proposal for providing a complete suite of gamma and related functions as PyTorch operators. Enjoy!

One of a five-part series of special functions issues:

- Gamma and Related Functions (#78065)
- Bessel and Related Functions (#76324)
- Orthogonal Polynomials (#80152)
- Elliptic Functions and Integrals (#80157)
-

## Operators

- [ ] `barnes_g`
- [ ] `beta`
- [ ] `binomial_coefficient`
- [ ] `double_factorial`
- [ ] `factorial`
- [ ] `falling_factorial`
- [ ] `gamma`
- [ ] `log_barnes_g`
- [ ] `log_beta`
- [ ] `log_binomial`
- [ ] `log_double_factorial`
- [ ] `log_factorial`
- [ ] `log_falling_factorial`
- [ ] `log_gamma`
- [ ] `log_gamma_sign`
- [ ] `log_quadruple_factorial`
- [ ] `log_rising_factorial`
- [ ] `log_triple_factorial`
- [ ] `lower_incomplete_gamma`
- [ ] `polygamma`
- [ ] `quadruple_factorial`
- [ ] `reciprocal_gamma`
- [ ] `rising_factorial`
- [ ] `triple_factotial`
- [ ] `upper_incomplete_gamma`

## Documentation

### Beta function

```Python
beta(a, b, other, *, out=None) → Tensor
```

Beta function:

$${\displaystyle \mathrm{B}(a, b) = \int _{0}^{1}t^{a - 1}(1 - t)^{b - 1} dt}.$$

A key property of the beta function is its close relationship to the gamma function:

$${\displaystyle \mathrm{B}(a, b)={\frac{\Gamma(a)\Gamma(b)}{\Gamma(a + b)}}.}$$

The closeness of the relationship between the gamma and beta functions is frequently applied in calculus and statistics (e.g., beta and related probability distributions).

The beta function is also closely related to binomial coefficients. When $a$ or $b$ is a positive integer:

$${\displaystyle \mathrm{B}(a, b) = {\dfrac{(a - 1)! (b - 1)!}{(a + b - 1)!}} = \frac{\frac{a + b}{ab}}{\binom{a + b}{a}}.}$$

### Binomial coefficient

```Python
binomial_coefficient(input, k, *, out=None) → Tensor
```

Binomial coefficient:

$${\displaystyle {\binom {n}{k}}={\frac {n!}{k!(n-k)!}}.}$$

### Digamma function

```Python
digamma(z, *, out=None) → Tensor
```

The logarithmic derivative of the gamma function (i.e., the first of the polygamma functions):

$${\displaystyle \psi(z) = 
{\frac 
{\mathrm {d} }
{\mathrm {d} z}
}
\ln {\big (}\Gamma (z){\big )} = 
{\frac 
{\Gamma '(z)}
{\Gamma (z)}
}\sim \ln {z}-
{\frac {1}{2z}}.}$$ 

The digamma function is related to the harmonic numbers by:

$${\displaystyle \psi (n) = H_{n - 1} - \gamma ,}$$

where $H_{0} = 0$ and gamma is the Euler–Mascheroni constant.

### `double_factorial(input, *, out=None) → Tensor`

Double factorial function:

$$\text{input}!!.$$

### `factorial(input, *, out=None) → Tensor`

Factorial function:

$$\text{input}!.$$

The product of all positive integers less than or equal to $n$.

Many notable functions and number sequences are related to the factorials, e.g., binomial coefficients; double, triple, and quadruple factorials; and falling factorials and rising factorials.

### `falling_factorial(input, *, out=None) → Tensor`

Falling factorial function:

$$\begin{aligned}
(x)_{n}=x^{\underline {n}}&=\overbrace {x(x-1)(x-2)\cdots (x-n+1)} ^{n{\text{ terms}}}\\
         &=\prod _{k=1}^{n}(x-k+1)=\prod _{k=0}^{n-1}(x-k)\,.
\end{aligned}$$

The falling factorial is extended to real values of n using the gamma function provided x and x + n are real numbers that are not negative integers.

### `gamma(input, *, out=None) → Tensor`

Gamma function:

$$\Gamma(\text{input}).$$

The standard extension of the factorial function to all complex numbers except non-positive integers.

### `log_beta(input, other, *, out=None) → Tensor`

Natural logarithm of the Euler beta function:

$$\ln\text{B}(\text{input}, \text{other}).$$

### `log_double_factorial(input, *, out=None) → Tensor`

Natural logarithm of the double factorial function:

$$\text{input}!!.$$

### `log_factorial(input, *, out=None) → Tensor`

### `log_falling_factorial(input, *, out=None) → Tensor`

### `log_gamma(input, *, out=None) → Tensor`

Natural logarithm of the gamma function: 

$$\log\Gamma(\text{input}).$$

### `log_quadruple_factorial(input, *, out=None) → Tensor`

Natural logarithm of the quadruple factorial function:

$$\text{input}!!.$$

### `log_rising_factorial(input, *, out=None) → Tensor`

### `log_triple_factorial(input, *, out=None) → Tensor`

Natural logarithm of the triple factorial function:

$$\text{input}!!.$$

### `lower_incomplete_gamma(input, a, *, out=None) → Tensor`

Lower incomplete gamma function: 

$$\Gamma(a, \text{input}).$$

Incomplete gamma functions are special functions that arise as solutions to certain integrals. They are defined similarly to the gamma function but with _incomplete_ integral limits. Unlike the gamma function, defined as an integral from zero to infinity, the lower incomplete gamma function is defined as an integral from $0$ to $a$.

### `upper_incomplete_gamma(input, a, *, out=None) → Tensor`

Upper incomplete gamma function:

$$\Gamma(a, \text{input}).$$

Incomplete gamma functions are special functions that arise as solutions to certain integrals. They are defined similarly to the gamma function but with _incomplete_ integral limits. Unlike the gamma function, defined as an integral from zero to infinity, the upper incomplete gamma function is defined as an integral from $a$ to infinity.

### `polygamma(input, n, *, out=None) → Tensor` 

Polygamma function:

$$\psi^{(n)}(\text{input}).$$

### `regularized_gamma(input, *, out=None) → Tensor`

Regularized incomplete gamma function $Q(a, z)$.

### `inverse_regularized_gamma(input, *, out=None) → Tensor`

Inverse of the regularized incomplete gamma function.

### `incomplete_beta(input, other, z, *, out=None) → Tensor`

Incomplete Euler beta function $\text{B}_{z}(\text{input}, \text{other})$.

### `regularized_beta(input, *, out=None) → Tensor`

Regularized incomplete beta function $I_{z}(a, b)$.

### `inverse_regularized_beta(input, *, out=None) → Tensor`

Inverse of the regularized incomplete beta function.


### `triple_factorial(input, *, out=None) → Tensor`

Triple factorial, $\text{input}!!!$.

### `quadruple_factorial(input, *, out=None) → Tensor`

Quadruple factorial, $\text{input}!!!!$.


$${\displaystyle (x)_{n}={\frac {\Gamma (x+1)}{\Gamma (x-n+1)}}\,.}$$

### `log_falling_factorial(input, *, out=None) → Tensor`

### `rising_factorial(input, *, out=None) → Tensor`

$$
\begin{aligned}x^{(n)}=x^{\overline {n}}&=\overbrace {x(x+1)(x+2)\cdots (x+n-1)} ^{n{\text{ terms}}}\\
                                   &=\prod _{k=1}^{n}(x+k-1)=\prod _{k=0}^{n-1}(x+k)\,.
\end{aligned}$$

The rising factorial is extended to real values of n using the gamma function provided x and x + n are real numbers that are not negative integers:

$${\displaystyle x^{(n)}={\frac {\Gamma (x+n)}{\Gamma (x)}}\,.}$$

### `log_rising_factorial(input, *, out=None) → Tensor`



### `barnes_g(input, *, out=None) → Tensor`

Barnes G-function $G(z)$.

### `ln_barnes_g(input, *, out=None) → Tensor`

Natural logarithm of the Barnes G-function $\ln G(z)$.

## Notes

* multiple factorial operators are proposed (i.e., double, triple, and quadruple) to simplify differentiation;
* I’m unclear whether it’s possible to implement reentrant functions using the Jiterator;
* `incomplete_gamma` is implemented as `gammainc` and `gammaincc`.  I recommend renaming `gammainc` to `incomplete_gamma` for clarity and consistency. I also recommend removing `gammaincc` in favor of `regularized_gamma`.

cc @mruberry @kshitij12345