View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.numbers.gamma;
18  
19  /**
20   * <a href="http://en.wikipedia.org/wiki/Trigamma_function">Trigamma function</a>.
21   *
22   * It is the derivative of the {@link Digamma digamma function}:
23   * \( \psi_1(x) = \frac{d^2}{dx^2} (\ln \Gamma(x)) \).
24   */
25  public final class Trigamma {
26      /** C limit. */
27      private static final double C_LIMIT = 49;
28  
29      /** S limit. */
30      private static final double S_LIMIT = 1e-5;
31      /** Fraction. */
32      private static final double F_1_6 = 1d / 6;
33      /** Fraction. */
34      private static final double F_1_30 = 1d / 30;
35      /** Fraction. */
36      private static final double F_1_42 = 1d / 42;
37  
38      /** Private constructor. */
39      private Trigamma() {
40          // intentionally empty.
41      }
42  
43      /**
44       * Computes the trigamma function.
45       *
46       * @param x Argument.
47       * @return trigamma(x) to within {@code 1e-8} relative or absolute error whichever is larger.
48       */
49      public static double value(double x) {
50          if (!Double.isFinite(x)) {
51              return x;
52          }
53  
54          if (x > 0 && x <= S_LIMIT) {
55              return 1 / (x * x);
56          }
57  
58          double trigamma = 0;
59          while (x < C_LIMIT) {
60              trigamma += 1 / (x * x);
61              x += 1;
62          }
63  
64          final double inv = 1 / (x * x);
65          //  1    1      1       1       1
66          //  - + ---- + ---- - ----- + -----
67          //  x      2      3       5       7
68          //      2 x    6 x    30 x    42 x
69          trigamma += 1 / x + inv / 2 + inv / x * (F_1_6 - inv * (F_1_30 + F_1_42 * inv));
70  
71          return trigamma;
72      }
73  }