WPILibC++ 2023.4.3-108-ge5452e3
lgamma.hpp
Go to the documentation of this file.
1/*################################################################################
2 ##
3 ## Copyright (C) 2016-2022 Keith O'Hara
4 ##
5 ## This file is part of the GCE-Math C++ library.
6 ##
7 ## Licensed under the Apache License, Version 2.0 (the "License");
8 ## you may not use this file except in compliance with the License.
9 ## You may obtain a copy of the License at
10 ##
11 ## http://www.apache.org/licenses/LICENSE-2.0
12 ##
13 ## Unless required by applicable law or agreed to in writing, software
14 ## distributed under the License is distributed on an "AS IS" BASIS,
15 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 ## See the License for the specific language governing permissions and
17 ## limitations under the License.
18 ##
19 ################################################################################*/
20
21/*
22 * compile-time log-gamma function
23 *
24 * for coefficient values, see:
25 * http://my.fit.edu/~gabdo/gamma.txt
26 */
27
28#ifndef _gcem_lgamma_HPP
29#define _gcem_lgamma_HPP
30
31namespace internal
32{
33
34// P. Godfrey's coefficients:
35//
36// 0.99999999999999709182
37// 57.156235665862923517
38// -59.597960355475491248
39// 14.136097974741747174
40// -0.49191381609762019978
41// .33994649984811888699e-4
42// .46523628927048575665e-4
43// -.98374475304879564677e-4
44// .15808870322491248884e-3
45// -.21026444172410488319e-3
46// .21743961811521264320e-3
47// -.16431810653676389022e-3
48// .84418223983852743293e-4
49// -.26190838401581408670e-4
50// .36899182659531622704e-5
51
52constexpr
53long double
54lgamma_coef_term(const long double x)
55noexcept
56{
57 return( 0.99999999999999709182L + 57.156235665862923517L / (x+1) \
58 - 59.597960355475491248L / (x+2) + 14.136097974741747174L / (x+3) \
59 - 0.49191381609762019978L / (x+4) + .33994649984811888699e-4L / (x+5) \
60 + .46523628927048575665e-4L / (x+6) - .98374475304879564677e-4L / (x+7) \
61 + .15808870322491248884e-3L / (x+8) - .21026444172410488319e-3L / (x+9) \
62 + .21743961811521264320e-3L / (x+10) - .16431810653676389022e-3L / (x+11) \
63 + .84418223983852743293e-4L / (x+12) - .26190838401581408670e-4L / (x+13) \
64 + .36899182659531622704e-5L / (x+14) );
65}
66
67template<typename T>
68constexpr
69T
70lgamma_term_2(const T x)
71noexcept
72{ //
73 return( T(GCEM_LOG_SQRT_2PI) + log(T(lgamma_coef_term(x))) );
74}
75
76template<typename T>
77constexpr
78T
79lgamma_term_1(const T x)
80noexcept
81{ // note: 607/128 + 0.5 = 5.2421875
82 return( (x + T(0.5))*log(x + T(5.2421875L)) - (x + T(5.2421875L)) );
83}
84
85template<typename T>
86constexpr
87T
88lgamma_begin(const T x)
89noexcept
90{ // returns lngamma(x+1)
91 return( lgamma_term_1(x) + lgamma_term_2(x) );
92}
93
94template<typename T>
95constexpr
96T
97lgamma_check(const T x)
98noexcept
99{
100 return( // NaN check
101 is_nan(x) ? \
102 GCLIM<T>::quiet_NaN() :
103 // indistinguishable from one or <= zero
104 GCLIM<T>::min() > abs(x - T(1)) ? \
105 T(0) :
106 GCLIM<T>::min() > x ? \
107 GCLIM<T>::infinity() :
108 // else
109 lgamma_begin(x - T(1)) );
110}
111
112}
113
114/**
115 * Compile-time log-gamma function
116 *
117 * @param x a real-valued input.
118 * @return computes the log-gamma function
119 * \f[ \ln \Gamma(x) = \ln \int_0^\infty y^{x-1} \exp(-y) dy \f]
120 * using a polynomial form:
121 * \f[ \Gamma(x+1) \approx (x+g+0.5)^{x+0.5} \exp(-x-g-0.5) \sqrt{2 \pi} \left[ c_0 + \frac{c_1}{x+1} + \frac{c_2}{x+2} + \cdots + \frac{c_n}{x+n} \right] \f]
122 * where the value \f$ g \f$ and the coefficients \f$ (c_0, c_1, \ldots, c_n) \f$
123 * are taken from Paul Godfrey, whose note can be found here: http://my.fit.edu/~gabdo/gamma.txt
124 */
125
126template<typename T>
127constexpr
128return_t<T>
129lgamma(const T x)
130noexcept
131{
132 return internal::lgamma_check( static_cast<return_t<T>>(x) );
133}
134
135#endif
#define GCEM_LOG_SQRT_2PI
Definition: gcem_options.hpp:110
UnitType abs(const UnitType x) noexcept
Compute absolute value.
Definition: math.h:721
dimensionless::scalar_t log(const ScalarUnit x) noexcept
Compute natural logarithm.
Definition: math.h:349
constexpr return_t< T > lgamma(const T x) noexcept
Compile-time log-gamma function.
Definition: lgamma.hpp:129
constexpr common_t< T1, T2 > min(const T1 x, const T2 y) noexcept
Compile-time pairwise minimum function.
Definition: min.hpp:35
Definition: Eigen_Colamd.h:50
constexpr T lgamma_check(const T x) noexcept
Definition: lgamma.hpp:97
constexpr T lgamma_begin(const T x) noexcept
Definition: lgamma.hpp:88
constexpr bool is_nan(const T x) noexcept
Definition: is_nan.hpp:36
constexpr T lgamma_term_1(const T x) noexcept
Definition: lgamma.hpp:79
constexpr long double lgamma_coef_term(const long double x) noexcept
Definition: lgamma.hpp:54
constexpr T lgamma_term_2(const T x) noexcept
Definition: lgamma.hpp:70