All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.librec.math.algorithm.Gamma Maven / Gradle / Ivy

// Copyright (C) 2014-2015 Guibing Guo
//
// This file is part of LibRec.
//
// LibRec is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// LibRec is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with LibRec. If not, see .
//

package net.librec.math.algorithm;

public class Gamma {

    private final static double small = 1e-6;
    private final static double large = 9.5;
    private final static double d1 = -0.5772156649015328606065121; // digamma(1)
    private final static double d2 = Math.pow(Math.PI, 2.0) / 6.0;

    private final static double s3 = 1.0 / 12.0;
    private final static double s4 = 1.0 / 120.0;
    private final static double s5 = 1.0 / 252.0;
    private final static double s6 = 1.0 / 240.0;
    private final static double s7 = 1.0 / 132.0;

    /**
     * log Gamma function: log(gamma(alpha)) for alpha bigger than 0, accurate to 10 decimal places
*

* Reference: Pike MC & Hill ID (1966) Algorithm 291: Logarithm of the gamma function. Communications of the * Association for Computing Machinery, 9:684 * * @param x parameter of the gamma function * @return the log of the gamma function of the given alpha */ public static double logGamma(double x) { double tmp = (x - 0.5) * Math.log(x + 4.5) - (x + 4.5); double ser = 1.0 + 76.18009173 / (x + 0) - 86.50532033 / (x + 1) + 24.01409822 / (x + 2) - 1.231739516 / (x + 3) + 0.00120858003 / (x + 4) - 0.00000536382 / (x + 5); return tmp + Math.log(ser * Math.sqrt(2 * Math.PI)); } /** * The Gamma function is defined by:
*

* Gamma(x) = integral( t^(x-1) e^(-t), t = 0 .. infinity)
*

* Uses Lanczos approximation formula. * * @param x parameter of the gamma function * @return gamma function of the given alpha */ public static double gamma(double x) { return Math.exp(logGamma(x)); } /** * digamma(x) = d log Gamma(x)/ dx * * @param x parameter of the gamma function * @return derivative of the gamma function */ public static double digamma(double x) { double y = 0.0; double r = 0.0; if (Double.isInfinite(x) || Double.isNaN(x)) { return 0.0 / 0.0; } if (x == 0.0) { return -1.0 / 0.0; } if (x < 0.0) { y = gamma(-x + 1) + Math.PI * (1.0 / Math.tan(-Math.PI * x)); return y; } // Use approximation if argument <= small. if (x <= small) { y = y + d1 - 1.0 / x + d2 * x; return y; } // Reduce to digamma(X + N) where (X + N) >= large. while (true) { if (x > small && x < large) { y = y - 1.0 / x; x = x + 1.0; } else { break; } } // Use de Moivre's expansion if argument >= large. // In maple: asympt(Psi(x), x); if (x >= large) { r = 1.0 / x; y = y + Math.log(x) - 0.5 * r; r = r * r; y = y - r * (s3 - r * (s4 - r * (s5 - r * (s6 - r * s7)))); } return y; } /** * Newton iteration to solve digamma(x)-y = 0. * * @param y parameter y in the function above * @return the inverse function of digamma, i.e., returns x such that digamma(x) = y adapted from Tony Minka fastfit * Matlab code */ public static double invDigamma(double y) { // Newton iteration to solve digamma(x)-y = 0 return y < -2.22 ? (-1.0 / (y - digamma(1))) : (Math.exp(y) + 0.5); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy