/rust/registry/src/index.crates.io-1949cf8c6b5b557f/pxfm-0.1.27/src/gamma/digamma.rs
Line | Count | Source |
1 | | /* |
2 | | * // Copyright (c) Radzivon Bartoshyk 8/2025. All rights reserved. |
3 | | * // |
4 | | * // Redistribution and use in source and binary forms, with or without modification, |
5 | | * // are permitted provided that the following conditions are met: |
6 | | * // |
7 | | * // 1. Redistributions of source code must retain the above copyright notice, this |
8 | | * // list of conditions and the following disclaimer. |
9 | | * // |
10 | | * // 2. Redistributions in binary form must reproduce the above copyright notice, |
11 | | * // this list of conditions and the following disclaimer in the documentation |
12 | | * // and/or other materials provided with the distribution. |
13 | | * // |
14 | | * // 3. Neither the name of the copyright holder nor the names of its |
15 | | * // contributors may be used to endorse or promote products derived from |
16 | | * // this software without specific prior written permission. |
17 | | * // |
18 | | * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
19 | | * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
20 | | * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
21 | | * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
22 | | * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
23 | | * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
24 | | * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
25 | | * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
26 | | * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
27 | | * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | | */ |
29 | | use crate::common::is_integer; |
30 | | use crate::double_double::DoubleDouble; |
31 | | use crate::gamma::digamma_coeffs::digamma_coeefs; |
32 | | use crate::logs::fast_log_d_to_dd; |
33 | | use crate::tangent::cotpi_core; |
34 | | |
35 | | #[inline] |
36 | 0 | fn approx_digamma_hard(x: f64) -> DoubleDouble { |
37 | 0 | if x <= 12. { |
38 | 0 | let x2 = DoubleDouble::from_exact_mult(x, x); |
39 | 0 | let x4 = DoubleDouble::quick_mult(x2, x2); |
40 | 0 | let x8 = DoubleDouble::quick_mult(x4, x4); |
41 | 0 | let (p, q) = digamma_coeefs(x); |
42 | | |
43 | 0 | let e0 = DoubleDouble::mul_f64_add( |
44 | 0 | DoubleDouble::from_bit_pair(p[1]), |
45 | 0 | x, |
46 | 0 | DoubleDouble::from_bit_pair(p[0]), |
47 | | ); |
48 | 0 | let e1 = DoubleDouble::mul_f64_add( |
49 | 0 | DoubleDouble::from_bit_pair(p[3]), |
50 | 0 | x, |
51 | 0 | DoubleDouble::from_bit_pair(p[2]), |
52 | | ); |
53 | 0 | let e2 = DoubleDouble::mul_f64_add( |
54 | 0 | DoubleDouble::from_bit_pair(p[5]), |
55 | 0 | x, |
56 | 0 | DoubleDouble::from_bit_pair(p[4]), |
57 | | ); |
58 | 0 | let e3 = DoubleDouble::mul_f64_add( |
59 | 0 | DoubleDouble::from_bit_pair(p[7]), |
60 | 0 | x, |
61 | 0 | DoubleDouble::from_bit_pair(p[6]), |
62 | | ); |
63 | 0 | let e4 = DoubleDouble::mul_f64_add( |
64 | 0 | DoubleDouble::from_bit_pair(p[9]), |
65 | 0 | x, |
66 | 0 | DoubleDouble::from_bit_pair(p[8]), |
67 | | ); |
68 | 0 | let e5 = DoubleDouble::mul_f64_add( |
69 | 0 | DoubleDouble::from_bit_pair(p[11]), |
70 | 0 | x, |
71 | 0 | DoubleDouble::from_bit_pair(p[10]), |
72 | | ); |
73 | | |
74 | 0 | let f0 = DoubleDouble::mul_add(x2, e1, e0); |
75 | 0 | let f1 = DoubleDouble::mul_add(x2, e3, e2); |
76 | 0 | let f2 = DoubleDouble::mul_add(x2, e5, e4); |
77 | | |
78 | 0 | let g0 = DoubleDouble::mul_add(x4, f1, f0); |
79 | | |
80 | 0 | let p_num = DoubleDouble::mul_add(x8, f2, g0); |
81 | | |
82 | 0 | let rcp = DoubleDouble::from_quick_recip(x); |
83 | | |
84 | 0 | let e0 = DoubleDouble::mul_f64_add_f64( |
85 | 0 | DoubleDouble::from_bit_pair(q[1]), |
86 | 0 | x, |
87 | 0 | f64::from_bits(0x3ff0000000000000), |
88 | | ); |
89 | 0 | let e1 = DoubleDouble::mul_f64_add( |
90 | 0 | DoubleDouble::from_bit_pair(q[3]), |
91 | 0 | x, |
92 | 0 | DoubleDouble::from_bit_pair(q[2]), |
93 | | ); |
94 | 0 | let e2 = DoubleDouble::mul_f64_add( |
95 | 0 | DoubleDouble::from_bit_pair(q[5]), |
96 | 0 | x, |
97 | 0 | DoubleDouble::from_bit_pair(q[4]), |
98 | | ); |
99 | 0 | let e3 = DoubleDouble::mul_f64_add( |
100 | 0 | DoubleDouble::from_bit_pair(q[7]), |
101 | 0 | x, |
102 | 0 | DoubleDouble::from_bit_pair(q[6]), |
103 | | ); |
104 | 0 | let e4 = DoubleDouble::mul_f64_add( |
105 | 0 | DoubleDouble::from_bit_pair(q[9]), |
106 | 0 | x, |
107 | 0 | DoubleDouble::from_bit_pair(q[8]), |
108 | | ); |
109 | 0 | let e5 = DoubleDouble::mul_f64_add( |
110 | 0 | DoubleDouble::from_bit_pair(q[11]), |
111 | 0 | x, |
112 | 0 | DoubleDouble::from_bit_pair(q[10]), |
113 | | ); |
114 | | |
115 | 0 | let f0 = DoubleDouble::mul_add(x2, e1, e0); |
116 | 0 | let f1 = DoubleDouble::mul_add(x2, e3, e2); |
117 | 0 | let f2 = DoubleDouble::mul_add(x2, e5, e4); |
118 | | |
119 | 0 | let g0 = DoubleDouble::mul_add(x4, f1, f0); |
120 | | |
121 | 0 | let p_den = DoubleDouble::mul_add(x8, f2, g0); |
122 | | |
123 | 0 | let q = DoubleDouble::div(p_num, p_den); |
124 | 0 | let r = DoubleDouble::quick_dd_sub(q, rcp); |
125 | 0 | return r; |
126 | 0 | } |
127 | | // digamma asymptotic expansion |
128 | | // digamma(x) ~ ln(z)+1/(2z)-sum_(n=1)^(infty)(Bernoulli(2n))/(2nz^(2n)) |
129 | | // Generated in SageMath: |
130 | | // var('x') |
131 | | // |
132 | | // def bernoulli_terms(x, N): |
133 | | // S = 0 |
134 | | // S += QQ(1)/QQ(2)/x |
135 | | // for k in range(1, N+1): |
136 | | // B = bernoulli(2*k) |
137 | | // term = (B / QQ(2*k))*x**(-2*k) |
138 | | // S += term |
139 | | // return S |
140 | | // |
141 | | // terms = bernoulli_terms(x, 9) |
142 | | // |
143 | | // coeffs = [RealField(150)(terms.coefficient(x, n)) for n in range(0, terms.degree(x)+1, 1)] |
144 | | // for k in range(1, 13): |
145 | | // c = terms.coefficient(x, -k) # coefficient of x^(-k) |
146 | | // if c == 0: |
147 | | // continue |
148 | | // print("f64::from_bits(" + double_to_hex(c) + "),") |
149 | | const C: [(u64, u64); 10] = [ |
150 | | (0x3c55555555555555, 0x3fb5555555555555), |
151 | | (0xbc01111111111111, 0xbf81111111111111), |
152 | | (0x3c10410410410410, 0x3f70410410410410), |
153 | | (0xbbf1111111111111, 0xbf71111111111111), |
154 | | (0xbc0f07c1f07c1f08, 0x3f7f07c1f07c1f08), |
155 | | (0x3c39a99a99a99a9a, 0xbf95995995995996), |
156 | | (0x3c55555555555555, 0x3fb5555555555555), |
157 | | (0xbc77979797979798, 0xbfdc5e5e5e5e5e5e), |
158 | | (0xbc69180646019180, 0x40086e7f9b9fe6e8), |
159 | | (0x3ccad759ad759ad7, 0xc03a74ca514ca515), |
160 | | ]; |
161 | | |
162 | 0 | let rcp = DoubleDouble::from_quick_recip(x); |
163 | 0 | let rcp_sqr = DoubleDouble::quick_mult(rcp, rcp); |
164 | | |
165 | 0 | let rx = rcp_sqr; |
166 | 0 | let x2 = DoubleDouble::quick_mult(rx, rx); |
167 | 0 | let x4 = DoubleDouble::quick_mult(x2, x2); |
168 | 0 | let x8 = DoubleDouble::quick_mult(x4, x4); |
169 | | |
170 | 0 | let q0 = DoubleDouble::quick_mul_add( |
171 | 0 | DoubleDouble::from_bit_pair(C[1]), |
172 | 0 | rx, |
173 | 0 | DoubleDouble::from_bit_pair(C[0]), |
174 | | ); |
175 | 0 | let q1 = DoubleDouble::quick_mul_add( |
176 | 0 | DoubleDouble::from_bit_pair(C[3]), |
177 | 0 | rx, |
178 | 0 | DoubleDouble::from_bit_pair(C[2]), |
179 | | ); |
180 | 0 | let q2 = DoubleDouble::quick_mul_add( |
181 | 0 | DoubleDouble::from_bit_pair(C[5]), |
182 | 0 | rx, |
183 | 0 | DoubleDouble::from_bit_pair(C[4]), |
184 | | ); |
185 | 0 | let q3 = DoubleDouble::quick_mul_add( |
186 | 0 | DoubleDouble::from_bit_pair(C[7]), |
187 | 0 | rx, |
188 | 0 | DoubleDouble::from_bit_pair(C[6]), |
189 | | ); |
190 | 0 | let q4 = DoubleDouble::quick_mul_add( |
191 | 0 | DoubleDouble::from_bit_pair(C[9]), |
192 | 0 | rx, |
193 | 0 | DoubleDouble::from_bit_pair(C[8]), |
194 | | ); |
195 | | |
196 | 0 | let q0 = DoubleDouble::quick_mul_add(x2, q1, q0); |
197 | 0 | let q1 = DoubleDouble::quick_mul_add(x2, q3, q2); |
198 | | |
199 | 0 | let r0 = DoubleDouble::quick_mul_add(x4, q1, q0); |
200 | 0 | let mut p = DoubleDouble::quick_mul_add(x8, q4, r0); |
201 | 0 | p = DoubleDouble::quick_mul_f64_add( |
202 | 0 | rcp, |
203 | 0 | f64::from_bits(0x3fe0000000000000), |
204 | 0 | DoubleDouble::quick_mult(p, rcp_sqr), |
205 | 0 | ); |
206 | | |
207 | 0 | let v_log = fast_log_d_to_dd(x); |
208 | 0 | DoubleDouble::quick_dd_sub(v_log, p) |
209 | 0 | } |
210 | | |
211 | | #[inline] |
212 | 0 | fn approx_digamma_hard_dd(x: DoubleDouble) -> DoubleDouble { |
213 | 0 | if x.hi <= 12. { |
214 | 0 | let x2 = DoubleDouble::quick_mult(x, x); |
215 | 0 | let x4 = DoubleDouble::quick_mult(x2, x2); |
216 | 0 | let x8 = DoubleDouble::quick_mult(x4, x4); |
217 | 0 | let (p, q) = digamma_coeefs(x.hi); |
218 | | |
219 | 0 | let e0 = DoubleDouble::mul_add( |
220 | 0 | DoubleDouble::from_bit_pair(p[1]), |
221 | 0 | x, |
222 | 0 | DoubleDouble::from_bit_pair(p[0]), |
223 | | ); |
224 | 0 | let e1 = DoubleDouble::mul_add( |
225 | 0 | DoubleDouble::from_bit_pair(p[3]), |
226 | 0 | x, |
227 | 0 | DoubleDouble::from_bit_pair(p[2]), |
228 | | ); |
229 | 0 | let e2 = DoubleDouble::mul_add( |
230 | 0 | DoubleDouble::from_bit_pair(p[5]), |
231 | 0 | x, |
232 | 0 | DoubleDouble::from_bit_pair(p[4]), |
233 | | ); |
234 | 0 | let e3 = DoubleDouble::mul_add( |
235 | 0 | DoubleDouble::from_bit_pair(p[7]), |
236 | 0 | x, |
237 | 0 | DoubleDouble::from_bit_pair(p[6]), |
238 | | ); |
239 | 0 | let e4 = DoubleDouble::mul_add( |
240 | 0 | DoubleDouble::from_bit_pair(p[9]), |
241 | 0 | x, |
242 | 0 | DoubleDouble::from_bit_pair(p[8]), |
243 | | ); |
244 | 0 | let e5 = DoubleDouble::mul_add( |
245 | 0 | DoubleDouble::from_bit_pair(p[11]), |
246 | 0 | x, |
247 | 0 | DoubleDouble::from_bit_pair(p[10]), |
248 | | ); |
249 | | |
250 | 0 | let f0 = DoubleDouble::mul_add(x2, e1, e0); |
251 | 0 | let f1 = DoubleDouble::mul_add(x2, e3, e2); |
252 | 0 | let f2 = DoubleDouble::mul_add(x2, e5, e4); |
253 | | |
254 | 0 | let g0 = DoubleDouble::mul_add(x4, f1, f0); |
255 | | |
256 | 0 | let p_num = DoubleDouble::mul_add(x8, f2, g0); |
257 | | |
258 | 0 | let rcp = x.recip(); |
259 | | |
260 | 0 | let e0 = DoubleDouble::mul_add_f64( |
261 | 0 | DoubleDouble::from_bit_pair(q[1]), |
262 | 0 | x, |
263 | 0 | f64::from_bits(0x3ff0000000000000), |
264 | | ); |
265 | 0 | let e1 = DoubleDouble::mul_add( |
266 | 0 | DoubleDouble::from_bit_pair(q[3]), |
267 | 0 | x, |
268 | 0 | DoubleDouble::from_bit_pair(q[2]), |
269 | | ); |
270 | 0 | let e2 = DoubleDouble::mul_add( |
271 | 0 | DoubleDouble::from_bit_pair(q[5]), |
272 | 0 | x, |
273 | 0 | DoubleDouble::from_bit_pair(q[4]), |
274 | | ); |
275 | 0 | let e3 = DoubleDouble::mul_add( |
276 | 0 | DoubleDouble::from_bit_pair(q[7]), |
277 | 0 | x, |
278 | 0 | DoubleDouble::from_bit_pair(q[6]), |
279 | | ); |
280 | 0 | let e4 = DoubleDouble::mul_add( |
281 | 0 | DoubleDouble::from_bit_pair(q[9]), |
282 | 0 | x, |
283 | 0 | DoubleDouble::from_bit_pair(q[8]), |
284 | | ); |
285 | 0 | let e5 = DoubleDouble::mul_add( |
286 | 0 | DoubleDouble::from_bit_pair(q[11]), |
287 | 0 | x, |
288 | 0 | DoubleDouble::from_bit_pair(q[10]), |
289 | | ); |
290 | | |
291 | 0 | let f0 = DoubleDouble::mul_add(x2, e1, e0); |
292 | 0 | let f1 = DoubleDouble::mul_add(x2, e3, e2); |
293 | 0 | let f2 = DoubleDouble::mul_add(x2, e5, e4); |
294 | | |
295 | 0 | let g0 = DoubleDouble::mul_add(x4, f1, f0); |
296 | | |
297 | 0 | let p_den = DoubleDouble::mul_add(x8, f2, g0); |
298 | | |
299 | 0 | let q = DoubleDouble::div(p_num, p_den); |
300 | 0 | let r = DoubleDouble::quick_dd_sub(q, rcp); |
301 | 0 | return r; |
302 | 0 | } |
303 | | // digamma asymptotic expansion |
304 | | // digamma(x) ~ ln(z)+1/(2z)-sum_(n=1)^(infty)(Bernoulli(2n))/(2nz^(2n)) |
305 | | // Generated in SageMath: |
306 | | // var('x') |
307 | | // |
308 | | // def bernoulli_terms(x, N): |
309 | | // S = 0 |
310 | | // S += QQ(1)/QQ(2)/x |
311 | | // for k in range(1, N+1): |
312 | | // B = bernoulli(2*k) |
313 | | // term = (B / QQ(2*k))*x**(-2*k) |
314 | | // S += term |
315 | | // return S |
316 | | // |
317 | | // terms = bernoulli_terms(x, 9) |
318 | | // |
319 | | // coeffs = [RealField(150)(terms.coefficient(x, n)) for n in range(0, terms.degree(x)+1, 1)] |
320 | | // for k in range(1, 13): |
321 | | // c = terms.coefficient(x, -k) # coefficient of x^(-k) |
322 | | // if c == 0: |
323 | | // continue |
324 | | // print("f64::from_bits(" + double_to_hex(c) + "),") |
325 | | const C: [(u64, u64); 10] = [ |
326 | | (0x3c55555555555555, 0x3fb5555555555555), |
327 | | (0xbc01111111111111, 0xbf81111111111111), |
328 | | (0x3c10410410410410, 0x3f70410410410410), |
329 | | (0xbbf1111111111111, 0xbf71111111111111), |
330 | | (0xbc0f07c1f07c1f08, 0x3f7f07c1f07c1f08), |
331 | | (0x3c39a99a99a99a9a, 0xbf95995995995996), |
332 | | (0x3c55555555555555, 0x3fb5555555555555), |
333 | | (0xbc77979797979798, 0xbfdc5e5e5e5e5e5e), |
334 | | (0xbc69180646019180, 0x40086e7f9b9fe6e8), |
335 | | (0x3ccad759ad759ad7, 0xc03a74ca514ca515), |
336 | | ]; |
337 | | |
338 | 0 | let rcp = x.recip(); |
339 | 0 | let rcp_sqr = DoubleDouble::quick_mult(rcp, rcp); |
340 | | |
341 | 0 | let rx = rcp_sqr; |
342 | 0 | let x2 = DoubleDouble::quick_mult(rx, rx); |
343 | 0 | let x4 = DoubleDouble::quick_mult(x2, x2); |
344 | 0 | let x8 = DoubleDouble::quick_mult(x4, x4); |
345 | | |
346 | 0 | let q0 = DoubleDouble::quick_mul_add( |
347 | 0 | DoubleDouble::from_bit_pair(C[1]), |
348 | 0 | rx, |
349 | 0 | DoubleDouble::from_bit_pair(C[0]), |
350 | | ); |
351 | 0 | let q1 = DoubleDouble::quick_mul_add( |
352 | 0 | DoubleDouble::from_bit_pair(C[3]), |
353 | 0 | rx, |
354 | 0 | DoubleDouble::from_bit_pair(C[2]), |
355 | | ); |
356 | 0 | let q2 = DoubleDouble::quick_mul_add( |
357 | 0 | DoubleDouble::from_bit_pair(C[5]), |
358 | 0 | rx, |
359 | 0 | DoubleDouble::from_bit_pair(C[4]), |
360 | | ); |
361 | 0 | let q3 = DoubleDouble::quick_mul_add( |
362 | 0 | DoubleDouble::from_bit_pair(C[7]), |
363 | 0 | rx, |
364 | 0 | DoubleDouble::from_bit_pair(C[6]), |
365 | | ); |
366 | 0 | let q4 = DoubleDouble::quick_mul_add( |
367 | 0 | DoubleDouble::from_bit_pair(C[9]), |
368 | 0 | rx, |
369 | 0 | DoubleDouble::from_bit_pair(C[8]), |
370 | | ); |
371 | | |
372 | 0 | let q0 = DoubleDouble::quick_mul_add(x2, q1, q0); |
373 | 0 | let q1 = DoubleDouble::quick_mul_add(x2, q3, q2); |
374 | | |
375 | 0 | let r0 = DoubleDouble::quick_mul_add(x4, q1, q0); |
376 | 0 | let mut p = DoubleDouble::quick_mul_add(x8, q4, r0); |
377 | 0 | p = DoubleDouble::quick_mul_f64_add( |
378 | 0 | rcp, |
379 | 0 | f64::from_bits(0x3fe0000000000000), |
380 | 0 | DoubleDouble::quick_mult(p, rcp_sqr), |
381 | 0 | ); |
382 | | |
383 | 0 | let mut v_log = fast_log_d_to_dd(x.hi); |
384 | 0 | v_log.lo += x.lo / x.hi; |
385 | 0 | DoubleDouble::quick_dd_sub(v_log, p) |
386 | 0 | } |
387 | | |
388 | | /// Computes digamma(x) |
389 | | /// |
390 | 0 | pub fn f_digamma(x: f64) -> f64 { |
391 | 0 | let xb = x.to_bits(); |
392 | 0 | if !x.is_normal() { |
393 | 0 | if x.is_infinite() { |
394 | 0 | return if x.is_sign_negative() { |
395 | 0 | f64::NAN |
396 | | } else { |
397 | 0 | f64::INFINITY |
398 | | }; |
399 | 0 | } |
400 | 0 | if x.is_nan() { |
401 | 0 | return f64::NAN; |
402 | 0 | } |
403 | 0 | if xb.wrapping_shl(1) == 0 { |
404 | | // |x| == 0 |
405 | 0 | return f64::INFINITY; |
406 | 0 | } |
407 | 0 | } |
408 | | |
409 | 0 | let dx = x; |
410 | | |
411 | 0 | if x.abs() <= f64::EPSILON { |
412 | | // |x| < ulp(1) |
413 | | // digamma near where x -> 1 ~ Digamma[x] = -euler + O(x) |
414 | | // considering identity Digamma[x+1] = Digamma[x] + 1/x, |
415 | | // hence x < ulp(1) then x+1 ~= 1 that gives |
416 | | // Digamma[x] = Digamma[x+1] - 1/x = -euler - 1/x |
417 | | // euler is dropped since 1/x >> euler |
418 | | // that gives: |
419 | | // Digamma[x] = Digamma[x+1] - 1/x = -1/x |
420 | 0 | return -1. / x; |
421 | 0 | } |
422 | | |
423 | 0 | if x < 0. { |
424 | | // at negative integers it's inf |
425 | 0 | if is_integer(x) { |
426 | 0 | return f64::NAN; |
427 | 0 | } |
428 | | |
429 | | // reflection Gamma(1-x) + Gamma(x) = Pi/tan(PI*x) |
430 | | const PI: DoubleDouble = |
431 | | DoubleDouble::from_bit_pair((0x3ca1a62633145c07, 0x400921fb54442d18)); |
432 | 0 | let r = DoubleDouble::from_full_exact_sub(1., x); |
433 | 0 | let mut result = PI * cotpi_core(-x); |
434 | 0 | let app = approx_digamma_hard_dd(r); |
435 | 0 | result = DoubleDouble::quick_dd_add(result, app); |
436 | 0 | result.to_f64() |
437 | | } else { |
438 | 0 | let app = approx_digamma_hard(dx); |
439 | 0 | app.to_f64() |
440 | | } |
441 | 0 | } |
442 | | |
443 | | #[cfg(test)] |
444 | | mod tests { |
445 | | use super::*; |
446 | | #[test] |
447 | | fn test_digamma() { |
448 | | assert_eq!(f_digamma(0.0019531200000040207), -512.5753182109892); |
449 | | assert_eq!(f_digamma(-13.999000000012591), -997.3224450000563); |
450 | | assert_eq!(f_digamma(13.999000000453323), 2.602844047257257); |
451 | | assert_eq!(f_digamma(0.), f64::INFINITY); |
452 | | assert_eq!(f_digamma(-0.), f64::INFINITY); |
453 | | assert!(f_digamma(f64::NAN).is_nan()); |
454 | | } |
455 | | } |