lib/distribution/math_extension.rb in distribution-0.5.0 vs lib/distribution/math_extension.rb in distribution-0.6.0

- old
+ new

@@ -1,5 +1,17 @@ +# The next few requires eventually probably need to go in their own gem. They're all functions and constants used by +# GSL-adapted pure Ruby math functions. +require "distribution/math_extension/chebyshev_series" +require "distribution/math_extension/erfc" +require "distribution/math_extension/exponential_integral" +require "distribution/math_extension/gammastar" +require "distribution/math_extension/gsl_utilities" +require "distribution/math_extension/incomplete_gamma" +require "distribution/math_extension/incomplete_beta" +require "distribution/math_extension/log_utilities" + + if RUBY_VERSION<"1.9" require 'mathn' def Prime.each(upper,&block) @primes=Prime.new @primes.each do |prime| @@ -28,10 +40,12 @@ B8 = -1.0 / 30.0 B10 = 5.0 / 66.0 B12 = -691.0 / 2730.0 B14 = 7.0 / 6.0 B16 = -3617.0 / 510.0 + + # From statistics2 def loggamma(x) v = 1.0 while (x < N) v *= x @@ -201,46 +215,78 @@ # Source: # * http://mathworld.wolfram.com/BetaFunction.html def beta(x,y) (gamma(x)*gamma(y)).quo(gamma(x+y)) end + + # Get pure-Ruby logbeta def logbeta(x,y) - (loggamma(x)+loggamma(y))-loggamma(x+y) + Beta.log_beta(x,y).first end + + # Log beta function conforming to style of lgamma (returns sign in second array index) + def lbeta(x,y) + Beta.log_beta(x,y) + end + # I_x(a,b): Regularized incomplete beta function + # Fast version. For a exact calculation, based on factorial + # use exact_regularized_beta_function + def regularized_beta(x,a,b) + return 1 if x==1 + IncompleteBeta.evaluate(a,b,x) + end + # I_x(a,b): Regularized incomplete beta function # TODO: Find a faster version. # Source: # * http://dlmf.nist.gov/8.17 - def regularized_beta_function(x,a,b) + def exact_regularized_beta(x,a,b) return 1 if x==1 - #incomplete_beta(x,a,b).quo(beta(a,b)) m=a.to_i n=(b+a-1).to_i (m..n).inject(0) {|sum,j| sum+(binomial_coefficient(n,j)* x**j * (1-x)**(n-j)) } - end - # B_x(a,b) : Incomplete beta function - # Should be replaced by - # http://lib.stat.cmu.edu/apstat/63 + end + # + # Incomplete beta function: B(x;a,b) + # +a+ and +b+ are parameters and +x+ is + # integration upper limit. def incomplete_beta(x,a,b) - raise "Doesn't work" + IncompleteBeta.evaluate(a,b,x)*beta(a,b) + #Math::IncompleteBeta.axpy(1.0, 0.0, a,b,x) end # Rising factorial def rising_factorial(x,n) factorial(x+n-1).quo(factorial(x-1)) end # Ln of gamma def loggamma(x) - lg=Math.lgamma(x) - lg[0]*lg[1] + Math.lgamma(x).first end + + def incomplete_gamma(a, x = 0, with_error = false) + IncompleteGamma.p(a,x, with_error) + end + alias :gammp :incomplete_gamma + + def gammq(a, x, with_error = false) + IncompleteGamma.q(a,x,with_error) + end + + def unnormalized_incomplete_gamma(a, x, with_error = false) + IncompleteGamma.unnormalized(a, x, with_error) + end + + # Not the same as erfc. This is the GSL version, which may have slightly different results. + def erfc_e x, with_error = false + Erfc.evaluate(x, with_error) + end - # Sequences without repetition. n^k' # Also called 'failing factorial' def permutations(n,k) return 1 if k==0 return n if k==1 @@ -304,16 +350,16 @@ end end module Math include Distribution::MathExtension - module_function :factorial, :beta, :loggamma, :binomial_coefficient, :binomial_coefficient_gamma, :regularized_beta_function, :incomplete_beta, :permutations, :rising_factorial , :fast_factorial, :combinations, :logbeta + module_function :factorial, :beta, :loggamma, :erfc_e, :unnormalized_incomplete_gamma, :incomplete_gamma, :gammp, :gammq, :binomial_coefficient, :binomial_coefficient_gamma, :exact_regularized_beta, :incomplete_beta, :regularized_beta, :permutations, :rising_factorial , :fast_factorial, :combinations, :logbeta, :lbeta end # Necessary on Ruby 1.9 module CMath # :nodoc: include Distribution::MathExtension - module_function :factorial, :beta, :loggamma, :binomial_coefficient, :binomial_coefficient_gamma, :regularized_beta_function, :incomplete_beta, :permutations, :rising_factorial, :fast_factorial, :combinations, :logbeta + module_function :factorial, :beta, :loggamma, :unnormalized_incomplete_gamma, :incomplete_gamma, :gammp, :gammq, :erfc_e, :binomial_coefficient, :binomial_coefficient_gamma, :incomplete_beta, :exact_regularized_beta, :regularized_beta, :permutations, :rising_factorial, :fast_factorial, :combinations, :logbeta, :lbeta end if RUBY_VERSION<"1.9" module Math remove_method :loggamma