Module: Distribution::MathExtension::ApproxFactorial

Defined in:
lib/distribution/math_extension.rb

Overview

Module to calculate approximated factorial

Based (again) on Luschny formula, with 16 digits of precision

  • http://www.luschny.de/math/factorial/approx/SimpleCases.html

Class Method Summary collapse

Class Method Details

.stieltjes_factorial(x) ⇒ Object

Valid upto 11 digits


140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/distribution/math_extension.rb', line 140

def stieltjes_factorial(x)
  y = x
  _p = 1

  _p *= y; y += 1 while y < 8

  lr = stieltjes_ln_factorial(y)
  r = Math.exp(lr)

  if r.infinite?
    r = BigMath.exp(BigDecimal(lr.to_s), 20)
    r = (r * x) / (_p * y) if x < 8
    r = r.to_i
  else
    r = (r * x) / (_p * y) if x < 8
  end
  r
end

.stieltjes_ln_factorial(z) ⇒ Object


118
119
120
121
122
123
124
125
126
# File 'lib/distribution/math_extension.rb', line 118

def stieltjes_ln_factorial(z)
  a0 = 1.quo(12); a1 = 1.quo(30); a2 = 53.quo(210); a3 = 195.quo(371)
  a4 = 22_999.quo(22_737); a5 = 29_944_523.quo(19_733_142)
  a6 = 109_535_241_009.quo(48_264_275_462)
  zz = z + 1

  (1.quo(2)) * Math.log(2 * Math::PI) + (zz - 1.quo(2)) * Math.log(zz) - zz +
    a0.quo(zz + a1.quo(zz + a2.quo(zz + a3.quo(zz + a4.quo(zz + a5.quo(zz + a6.quo(zz)))))))
end

.stieltjes_ln_factorial_big(z) ⇒ Object


128
129
130
131
132
133
134
135
136
137
# File 'lib/distribution/math_extension.rb', line 128

def stieltjes_ln_factorial_big(z)
  a0 = 1 / 12.0; a1 = 1 / 30.0; a2 = 53 / 210.0; a3 = 195 / 371.0
  a4 = 22_999 / 22_737.0; a5 = 29_944_523 / 19_733_142.0
  a6 = 109_535_241_009 / 48_264_275_462.0
  zz = z + 1

  BigDecimal('0.5') * BigMath.log(BigDecimal('2') * BigMath::PI(20), 20) + BigDecimal((zz - 0.5).to_s) * BigMath.log(BigDecimal(zz.to_s), 20) - BigDecimal(zz.to_s) + BigDecimal((
    a0 / (zz + a1 / (zz + a2 / (zz + a3 / (zz + a4 / (zz + a5 / (zz + a6 / zz))))))
  ).to_s)
end