WPILibC++ 2024.3.2
lgamma.hpp
Go to the documentation of this file.
1/*################################################################################
2 ##
3 ## Copyright (C) 2016-2023 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
31#include <cmath>
32#include <type_traits>
33
34namespace gcem
35{
36
37namespace internal
38{
39
40// P. Godfrey's coefficients:
41//
42// 0.99999999999999709182
43// 57.156235665862923517
44// -59.597960355475491248
45// 14.136097974741747174
46// -0.49191381609762019978
47// .33994649984811888699e-4
48// .46523628927048575665e-4
49// -.98374475304879564677e-4
50// .15808870322491248884e-3
51// -.21026444172410488319e-3
52// .21743961811521264320e-3
53// -.16431810653676389022e-3
54// .84418223983852743293e-4
55// -.26190838401581408670e-4
56// .36899182659531622704e-5
57
58constexpr
59long double
60lgamma_coef_term(const long double x)
61noexcept
62{
63 return( 0.99999999999999709182L + 57.156235665862923517L / (x+1) \
64 - 59.597960355475491248L / (x+2) + 14.136097974741747174L / (x+3) \
65 - 0.49191381609762019978L / (x+4) + .33994649984811888699e-4L / (x+5) \
66 + .46523628927048575665e-4L / (x+6) - .98374475304879564677e-4L / (x+7) \
67 + .15808870322491248884e-3L / (x+8) - .21026444172410488319e-3L / (x+9) \
68 + .21743961811521264320e-3L / (x+10) - .16431810653676389022e-3L / (x+11) \
69 + .84418223983852743293e-4L / (x+12) - .26190838401581408670e-4L / (x+13) \
70 + .36899182659531622704e-5L / (x+14) );
71}
72
73template<typename T>
74constexpr
75T
76lgamma_term_2(const T x)
77noexcept
78{ //
79 return( T(GCEM_LOG_SQRT_2PI) + log(T(lgamma_coef_term(x))) );
80}
81
82template<typename T>
83constexpr
84T
85lgamma_term_1(const T x)
86noexcept
87{ // note: 607/128 + 0.5 = 5.2421875
88 return( (x + T(0.5))*log(x + T(5.2421875L)) - (x + T(5.2421875L)) );
89}
90
91template<typename T>
92constexpr
93T
94lgamma_begin(const T x)
95noexcept
96{ // returns lngamma(x+1)
97 return( lgamma_term_1(x) + lgamma_term_2(x) );
98}
99
100template<typename T>
101constexpr
102T
103lgamma_check(const T x)
104noexcept
105{
106 return( // NaN check
107 is_nan(x) ? \
109 // indistinguishable from one or <= zero
110 GCLIM<T>::min() > abs(x - T(1)) ? \
111 T(0) :
112 GCLIM<T>::min() > x ? \
114 // else
115 lgamma_begin(x - T(1)) );
116}
117
118}
119
120/**
121 * Compile-time log-gamma function
122 *
123 * @param x a real-valued input.
124 * @return computes the log-gamma function
125 * \f[ \ln \Gamma(x) = \ln \int_0^\infty y^{x-1} \exp(-y) dy \f]
126 * using a polynomial form:
127 * \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]
128 * where the value \f$ g \f$ and the coefficients \f$ (c_0, c_1, \ldots, c_n) \f$
129 * are taken from Paul Godfrey, whose note can be found here: http://my.fit.edu/~gabdo/gamma.txt
130 */
131
132template<typename T>
133constexpr
134return_t<T>
135lgamma(const T x)
136noexcept
137{
139 return internal::lgamma_check( static_cast<return_t<T>>(x) );
140 } else {
141 return std::lgamma(x);
142 }
143}
144
145}
146
147#endif
#define GCEM_LOG_SQRT_2PI
Definition: gcem_options.hpp:110
constexpr FMT_INLINE auto is_constant_evaluated(bool default_value=false) noexcept -> bool
Definition: core.h:304
constexpr T lgamma_term_2(const T x) noexcept
Definition: lgamma.hpp:76
constexpr long double lgamma_coef_term(const long double x) noexcept
Definition: lgamma.hpp:60
constexpr bool is_nan(const T x) noexcept
Definition: is_nan.hpp:39
constexpr T lgamma_begin(const T x) noexcept
Definition: lgamma.hpp:94
constexpr T lgamma_check(const T x) noexcept
Definition: lgamma.hpp:103
constexpr T lgamma_term_1(const T x) noexcept
Definition: lgamma.hpp:85
Definition: is_even.hpp:29
constexpr T abs(const T x) noexcept
Compile-time absolute value function.
Definition: abs.hpp:40
constexpr return_t< T > lgamma(const T x) noexcept
Compile-time log-gamma function.
Definition: lgamma.hpp:135
constexpr return_t< T > log(const T x) noexcept
Compile-time natural logarithm function.
Definition: log.hpp:186
std::numeric_limits< T > GCLIM
Definition: gcem_options.hpp:74
typename std::conditional< std::is_integral< T >::value, double, T >::type return_t
Definition: gcem_options.hpp:77