Module: Math
- Defined in:
- lib/math.rb
Class Method Summary collapse
- .beta_function(x, y) ⇒ Object
- .combination(n, r) ⇒ Object
- .factorial(n) ⇒ Object
-
.incomplete_beta_function(x, alp, bet) ⇒ Object
This implementation is an adaptation of the incomplete beta function made in C by Lewis Van Winkle, which released the code under the zlib license.
- .lower_incomplete_gamma_function(s, x) ⇒ Object
-
.normalised_lower_incomplete_gamma_function(s, x) ⇒ Object
Algorithm implementation translated from the ASA147 C++ version people.sc.fsu.edu/~jburkardt/cpp_src/asa147/asa147.html translated from FORTRAN by John Burkardt.
- .permutation(n, k) ⇒ Object
-
.simpson_rule(a, b, n, &block) ⇒ Object
Function adapted from the python implementation that exists in en.wikipedia.org/wiki/Simpson%27s_rule#Sample_implementation Finite integral in the interval [a, b] split up in n-intervals.
Class Method Details
.beta_function(x, y) ⇒ Object
107 108 109 110 111 |
# File 'lib/math.rb', line 107 def self.beta_function(x, y) return 1 if x == 1 && y == 1 (Math.gamma(x) * Math.gamma(y))/Math.gamma(x + y) end |
.combination(n, r) ⇒ Object
11 12 13 |
# File 'lib/math.rb', line 11 def self.combination(n, r) self.factorial(n)/(self.factorial(r) * self.factorial(n - r)).to_r # n!/(r! * [n - r]!) end |
.factorial(n) ⇒ Object
2 3 4 5 6 7 8 9 |
# File 'lib/math.rb', line 2 def self.factorial(n) return if n < 0 n = n.to_i # Only integers. return 1 if n == 0 || n == 1 Math.gamma(n + 1) # Math.gamma(x) == (n - 1)! for integer values end |
.incomplete_beta_function(x, alp, bet) ⇒ Object
This implementation is an adaptation of the incomplete beta function made in C by Lewis Van Winkle, which released the code under the zlib license. The whole math behind this code is described in the following post: codeplea.com/incomplete-beta-function-c
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/math.rb', line 116 def self.incomplete_beta_function(x, alp, bet) return if x < 0.0 return 1.0 if x > 1.0 tiny = 1.0E-50 if x > ((alp + 1.0)/(alp + bet + 2.0)) return 1.0 - self.incomplete_beta_function(1.0 - x, bet, alp) end # To avoid overflow problems, the implementation applies the logarithm properties # to calculate in a faster and safer way the values. lbet_ab = (Math.lgamma(alp)[0] + Math.lgamma(bet)[0] - Math.lgamma(alp + bet)[0]).freeze front = (Math.exp(Math.log(x) * alp + Math.log(1.0 - x) * bet - lbet_ab) / alp.to_r).freeze # This is the non-log version of the left part of the formula (before the continuous fraction) # down_left = alp * self.beta_function(alp, bet) # upper_left = (x ** alp) * ((1.0 - x) ** bet) # front = upper_left/down_left f, c, d = 1.0, 1.0, 0.0 returned_value = nil # Let's do more iterations than the proposed implementation (200 iters) (0..500).each do |number| m = number/2 numerator = if number == 0 1.0 elsif number % 2 == 0 (m * (bet - m) * x)/((alp + 2.0 * m - 1.0)* (alp + 2.0 * m)) else top = -((alp + m) * (alp + bet + m) * x) down = ((alp + 2.0 * m) * (alp + 2.0 * m + 1.0)) top/down end d = 1.0 + numerator * d d = tiny if d.abs < tiny d = 1.0 / d.to_r c = 1.0 + numerator / c.to_r c = tiny if c.abs < tiny cd = (c*d).freeze f = f * cd if (1.0 - cd).abs < 1.0E-10 returned_value = front * (f - 1.0) break end end returned_value end |
.lower_incomplete_gamma_function(s, x) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/math.rb', line 47 def self.lower_incomplete_gamma_function(s, x) base_iterator = x.round(1) base_iterator += 1 if x < 1.0 && !x.zero? # The greater the iterations, the better. That's why we are iterating 10_000 * x times iterator = (10_000 * base_iterator).round iterator = 100_000 if iterator.zero? self.simpson_rule(0, x.to_r, iterator) do |t| (t ** (s - 1)) * Math.exp(-t) end end |
.normalised_lower_incomplete_gamma_function(s, x) ⇒ Object
Algorithm implementation translated from the ASA147 C++ version people.sc.fsu.edu/~jburkardt/cpp_src/asa147/asa147.html translated from FORTRAN by John Burkardt. Original algorithm written by Chi Leung Lau. It contains a modification on the error and underflow parameters to use maximum available float number and it performs the series using ‘Rational` objects to avoid memory exhaustion and reducing precision errors.
This algorithm is licensed with MIT license.
Reference:
Chi Leung Lau,
Algorithm AS 147:
A Simple Series for the Incomplete Gamma Integral,
Applied Statistics,
Volume 29, Number 1, 1980, pages 113-114.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/math.rb', line 74 def self.normalised_lower_incomplete_gamma_function(s, x) return 0.0 if s.negative? || x.zero? || x.negative? # e = 1.0e-308 # uflo = 1.0e-47 e = Float::MIN uflo = Float::MIN lgamma, sign = Math.lgamma(s + 1.0) arg = s * Math.log(x) - (sign * lgamma) - x return 0.0 if arg < Math.log(uflo) f = Math.exp(arg).to_r return 0.0 if f.zero? c = 1r value = 1r a = s.to_r rational_x = x.to_r loop do a += 1r c = c * (rational_x / a) value += c break if c <= (e * value) end (value * f).to_f end |
.permutation(n, k) ⇒ Object
15 16 17 |
# File 'lib/math.rb', line 15 def self.permutation(n, k) self.factorial(n)/self.factorial(n - k).to_r end |
.simpson_rule(a, b, n, &block) ⇒ Object
Function adapted from the python implementation that exists in en.wikipedia.org/wiki/Simpson%27s_rule#Sample_implementation Finite integral in the interval [a, b] split up in n-intervals
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/math.rb', line 21 def self.simpson_rule(a, b, n, &block) unless n.even? puts "The composite simpson's rule needs even intervals!" return end h = (b - a)/n.to_r resA = yield(a) resB = yield(b) sum = resA + resB (1..n).step(2).each do |number| res = yield(a + number * h) sum += 4 * res end (1..(n-1)).step(2).each do |number| res = yield(a + number * h) sum += 2 * res end return sum * h / 3.0 end |