lib/distribution/math_extension.rb in distribution-0.2.0 vs lib/distribution/math_extension.rb in distribution-0.3.0
- old
+ new
@@ -1,6 +1,18 @@
-require 'prime'
+if RUBY_VERSION<"1.9"
+ require 'mathn'
+ def Prime.each(upper,&block)
+ @primes=Prime.new
+ @primes.each do |prime|
+ break if prime > upper.to_i
+ block.call(prime)
+ end
+ end
+else
+ require 'prime'
+end
+
require 'bigdecimal'
require 'bigdecimal/math'
# Useful additions to Math
module Distribution
@@ -36,34 +48,35 @@
end
def swing(n)
return SmallOddSwing[n] if (n<33)
sqrtN = Math.sqrt(n).floor
count=0
+
Prime.each(n/3) do |prime|
next if prime<3
if (prime<=sqrtN)
q=n
_p=1
- while((q/=prime)>0) do
- if ((q&1)==1)
+
+ while((q=(q/prime).truncate)>0) do
+ if((q%2)==1)
_p*=prime
end
end
-
if _p>1
@prime_list[count]=_p
count+=1
end
else
- if ((n/prime)&1==1)
+ if ((n/prime).truncate%2==1)
@prime_list[count]=prime
count+=1
end
end
end
- prod=get_primorial(n/2+1,n)
+ prod=get_primorial((n/2).truncate+1,n)
prod * @prime_list[0,count].inject(1) {|ac,v| ac*v}
end
def get_primorial(low,up)
prod=1;
Prime.each(up) do |prime|
@@ -150,11 +163,42 @@
# Source:
# * http://mathworld.wolfram.com/BetaFunction.html
def beta(x,y)
(gamma(x)*gamma(y)).quo(gamma(x+y))
end
+ # I_x(a,b): Regularized incomplete beta function
+ #
+ # Source:
+ #
+ def regularized_beta_function(x,a,b)
+ return 1 if x==1
+ #incomplete_beta(x,a,b).quo(beta(a,b))
+ m=a
+ n=b+a-1
+ (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
+ def incomplete_beta(x,a,b)
+ raise "Not work"
+ return beta(a,b) if x==1
+
+ ((x**a * (1-x)**b).quo(a)) * hyper_f(a+b,1,a+1,x)
+ end
+ def permutations(x,n)
+ factorial(x).quo(factorial(x-n))
+ end
+ def rising_factorial(x,n)
+ factorial(x+n-1).quo(factorial(x-1))
+ end
+
+
LOG_2PI = Math.log(2 * Math::PI)# log(2PI)
N = 8
B0 = 1.0
B1 = -1.0 / 2.0
B2 = 1.0 / 6.0
@@ -190,19 +234,57 @@
if (x < 0.0)
return Math::PI / (Math.sin(Math.PI * x) * Math.exp(loggamma(1 - x))) #/
end
Math.exp(loggamma(x))
end
+ # Binomial coeffients, or:
+ # ( n )
+ # ( k )
+ # Gives the number of different k size subsets of a set size n
+ #
+ # Replaces (n,k) for (n, n-k) if k>n-k
+ #
+ # (n) n^k' (n)..(n-k+1)
+ # ( ) = ---- = ------------
+ # (k) k! k!
+ #
+ def binomial_coefficient(n,k)
+ return 1 if (k==0 or k==n)
+ k=[k, n-k].min
+ (((n-k+1)..n).inject(1) {|ac,v| ac * v}).quo(factorial(k))
+ # Other way to calcule binomial is this:
+ # (1..k).inject(1) {|ac, i| (ac*(n-k+i).quo(i))}
+ end
+ # Approximate binomial coefficient, using gamma function.
+ # The fastest method, until we fall on BigDecimal!
+ def binomial_coefficient_gamma(n,k)
+ return 1 if (k==0 or k==n)
+ k=[k, n-k].min
+
+ val=gamma(n+1) / (gamma(k+1)*gamma(n-k+1))
+ if (val.nan?)
+ lg=lgamma(n+1) - (lgamma(k+1)+lgamma(n-k+1))
+ val=Math.exp(lg)
+ # Crash again! We require BigDecimals
+ if val.infinite?
+ val=BigMath.exp(BigDecimal(lg.to_s),16)
+ end
+ end
+
+ val
+ end
end
end
module Math
include Distribution::MathExtension
- module_function :factorial, :beta, :gamma, :gosper, :loggamma, :fast_factorial
+ alias :lgamma :loggamma
+
+ module_function :factorial, :beta, :gamma, :gosper, :loggamma, :lgamma, :binomial_coefficient, :binomial_coefficient_gamma, :regularized_beta_function, :incomplete_beta, :permutations, :rising_factorial , :fast_factorial
end
# Necessary on Ruby 1.9
module CMath # :nodoc:
include Distribution::MathExtension
- module_function :factorial, :beta, :gamma, :gosper, :loggamma, :fast_factorial
+ module_function :factorial, :beta, :gosper, :loggamma, :binomial_coefficient, :binomial_coefficient_gamma, :regularized_beta_function, :incomplete_beta, :permutations, :rising_factorial, :fast_factorial
end