@@ -52,6 +52,8 @@ pub trait Float: Copy + Sized + cmp::PartialOrd
52
52
53
53
/// Take the tangent of self
54
54
fn tan ( self ) -> Self ;
55
+ /// Take the logarithm of the gamma function of self
56
+ fn log_gamma ( self ) -> Self ;
55
57
}
56
58
57
59
impl Float for f32 {
@@ -84,6 +86,13 @@ impl Float for f32 {
84
86
85
87
#[ inline]
86
88
fn tan ( self ) -> Self { self . tan ( ) }
89
+ #[ inline]
90
+ fn log_gamma ( self ) -> Self {
91
+ let result = log_gamma ( self as f64 ) ;
92
+ assert ! ( result <= :: core:: f32 :: MAX as f64 ) ;
93
+ assert ! ( result >= :: core:: f32 :: MIN as f64 ) ;
94
+ result as f32
95
+ }
87
96
}
88
97
89
98
impl Float for f64 {
@@ -116,6 +125,8 @@ impl Float for f64 {
116
125
117
126
#[ inline]
118
127
fn tan ( self ) -> Self { self . tan ( ) }
128
+ #[ inline]
129
+ fn log_gamma ( self ) -> Self { log_gamma ( self ) }
119
130
}
120
131
121
132
/// Calculates ln(gamma(x)) (natural logarithm of the gamma
@@ -131,33 +142,33 @@ impl Float for f64 {
131
142
/// `Ag(z)` is an infinite series with coefficients that can be calculated
132
143
/// ahead of time - we use just the first 6 terms, which is good enough
133
144
/// for most purposes.
134
- pub ( crate ) fn log_gamma < N : Float > ( x : N ) -> N {
145
+ pub ( crate ) fn log_gamma ( x : f64 ) -> f64 {
135
146
// precalculated 6 coefficients for the first 6 terms of the series
136
- let coefficients: [ N ; 6 ] = [
137
- N :: from ( 76.18009172947146 ) ,
138
- N :: from ( -86.50532032941677 ) ,
139
- N :: from ( 24.01409824083091 ) ,
140
- N :: from ( -1.231739572450155 ) ,
141
- N :: from ( 0.1208650973866179e-2 ) ,
142
- N :: from ( -0.5395239384953e-5 ) ,
147
+ let coefficients: [ f64 ; 6 ] = [
148
+ 76.18009172947146 ,
149
+ -86.50532032941677 ,
150
+ 24.01409824083091 ,
151
+ -1.231739572450155 ,
152
+ 0.1208650973866179e-2 ,
153
+ -0.5395239384953e-5 ,
143
154
] ;
144
155
145
156
// (x+0.5)*ln(x+g+0.5)-(x+g+0.5)
146
- let tmp = x + N :: from ( 5.5 ) ;
147
- let log = ( x + N :: from ( 0.5 ) ) * tmp. ln ( ) - tmp;
157
+ let tmp = x + 5.5 ;
158
+ let log = ( x + 0.5 ) * tmp. ln ( ) - tmp;
148
159
149
160
// the first few terms of the series for Ag(x)
150
- let mut a = N :: from ( 1.000000000190015 ) ;
161
+ let mut a = 1.000000000190015 ;
151
162
let mut denom = x;
152
163
for & coeff in & coefficients {
153
- denom += N :: from ( 1.0 ) ;
164
+ denom += 1.0 ;
154
165
a += coeff / denom;
155
166
}
156
167
157
168
// get everything together
158
169
// a is Ag(x)
159
170
// 2.5066... is sqrt(2pi)
160
- log + ( N :: from ( 2.5066282746310005 ) * a / x) . ln ( )
171
+ log + ( 2.5066282746310005 * a / x) . ln ( )
161
172
}
162
173
163
174
/// Sample a random number using the Ziggurat method (specifically the
0 commit comments