lanczos_approximation.sf 951 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. #!/usr/bin/ruby
  2. #
  3. ## Algorithm from Wikipedia: https://en.wikipedia.org/wiki/Lanczos_approximation#Simple_implementation
  4. #
  5. func gamma(z) {
  6. var epsilon = 0.0000001
  7. func withinepsilon(x) {
  8. abs(x - abs(x)) <= epsilon
  9. }
  10. var p = [
  11. 676.5203681218851, -1259.1392167224028,
  12. 771.32342877765313, -176.61502916214059,
  13. 12.507343278686905, -0.13857109526572012,
  14. 9.9843695780195716e-6, 1.5056327351493116e-7,
  15. ]
  16. var result
  17. const pi = Num.pi
  18. if (z.real < 0.5) {
  19. result = (pi / (sin(pi * z) * gamma(1 - z)))
  20. }
  21. else {
  22. z--
  23. var x = 0.99999999999980993
  24. p.each_kv { |i, v|
  25. x += v/(z + i + 1)
  26. }
  27. var t = (z + p.len - 0.5)
  28. result = (sqrt(pi*2) * t**(z+0.5) * exp(-t) * x)
  29. }
  30. withinepsilon(result.im) ? result.real : result
  31. }
  32. for i in [1/2,4,5,6,30,40,50] {
  33. say "gamma(%3s) =~ %s"%(i, gamma(i));
  34. }