Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Math::gamma fix and spec improvements #1700

Merged
merged 13 commits into from

3 participants

@r-stu31

This fixes a bug in Rubinius implementation of Math::gamma for integral arguments in range 24..171 and improves Math::gamma specs.

@travisbot

This pull request fails (merged 724f16d into c4fe2ec).

@r-stu31

Please wait with the pull, I'll fix the errors reported by travisbot.

@travisbot

This pull request fails (merged 2d5a833 into c4fe2ec).

@travisbot

This pull request passes (merged e2ca816 into c4fe2ec).

@travisbot

This pull request passes (merged 8bade74 into c4fe2ec).

@travisbot

This pull request passes (merged 013f7bd into c4fe2ec).

@r-stu31

I think I'm done. :)
Besides the original issue, I've included the fix and test case for Math::gamma(-0.0) == -Float::INFINITY, thanks brixen for the tip how to do it neatly.

Please pull.

@brixen brixen merged commit a0d398a into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 3, 2012
  1. @r-stu31

    Remove false comment and test wider range of integers: it reveals a b…

    r-stu31 authored
    …ug in Rubinius implementation of Math::gamma.
  2. @r-stu31
  3. @r-stu31

    Clean up whitespace.

    r-stu31 authored
  4. @r-stu31

    Remove cases guarded by incorrect Ruby versions and doubled guards: M…

    r-stu31 authored
    …ath::gamma is only in 1.9 and up and the cases are already enclosed in this guard.
  5. @r-stu31

    Compare to Float::INFINITY instead of using 'infinite?' method to bet…

    r-stu31 authored
    …ter match labels of the cases.
  6. @r-stu31

    Add a test for gamma(-0).

    r-stu31 authored
  7. @r-stu31
  8. @r-stu31

    Fix tests: for n in 2..23 should the gamma(n) give exact results, for…

    r-stu31 authored
    … n in 24..30 the tolerance must be much bigger.
  9. @r-stu31
  10. @r-stu31
  11. @r-stu31
  12. @r-stu31

    Return -infinity for Math::gamma(n) in case of n being negative zero.…

    r-stu31 authored
    … That's what ISO C99 tgamma does.
  13. @r-stu31

    Remove tag for passing spec.

    r-stu31 authored
This page is out of date. Refresh to see the latest.
Showing with 31 additions and 29 deletions.
  1. +3 −1 kernel/common/math19.rb
  2. +28 −28 spec/ruby/core/math/gamma_spec.rb
View
4 kernel/common/math19.rb
@@ -34,6 +34,8 @@ def cbrt(x)
def gamma(x)
x = Rubinius::Type.coerce_to_float x
+ # if x is negative zero, return -infinity
+ return -Float::INFINITY if (1 / x) == -Float::INFINITY
return Float::INFINITY if x == 0.0
return Float::NAN if x.nan?
@@ -49,7 +51,7 @@ def gamma(x)
if fractional == 0.0
raise DomainError, "gamma" if int < 0
- return FactorialTable[int - 1]
+ return FactorialTable[int - 1] if int <= FactorialTable.size
end
end
View
56 spec/ruby/core/math/gamma_spec.rb
@@ -2,24 +2,41 @@
ruby_version_is "1.9" do
describe "Math.gamma" do
+ before :all do
+ @factorial1 = 1
+ @factorial2 = 1124000727777607680000 # 22!
+ end
+
it "returns +infinity given 0" do
- Math.gamma(0).infinite?.should == 1
+ Math.gamma(0).should == Float::INFINITY
+ end
+
+ it "returns -infinity given -0.0" do
+ Math.gamma(-0.0).should == -Float::INFINITY
end
it "returns Math.sqrt(Math::PI) given 0.5" do
Math.gamma(0.5).should be_close(Math.sqrt(Math::PI), TOLERANCE)
end
- # stop at n=23 because 23! is too big to fit in a IEEE 754 double
- f = 1
+ # stop at n == 23 because 23! cannot be exactly represented by IEEE 754 double
2.upto(23) do |n|
- it "returns #{n-1}! given #{n}" do
- Math.gamma(n).should be_close(f*=(n-1), TOLERANCE)
+ it "returns exactly #{n-1}! given #{n}" do
+ @factorial1 *= n - 1
+ Math.gamma(n).should == @factorial1
+ end
+ end
+
+ 24.upto(30) do |n|
+ it "returns approximately #{n-1}! given #{n}" do
+ @factorial2 *= n - 1
+ # compare only the first 12 places, tolerate the rest
+ Math.gamma(n).should be_close(@factorial2, @factorial2.to_s[12..-1].to_i)
end
end
it "returns good numerical approximation for gamma(3.2)" do
- Math.gamma(3.2) .should be_close(2.423965, TOLERANCE)
+ Math.gamma(3.2).should be_close(2.423965, TOLERANCE)
end
it "returns good numerical approximation for gamma(-2.15)" do
@@ -34,38 +51,21 @@
Math.gamma(-0.00001).should be_close(-100000.577225, TOLERANCE)
end
- ruby_version_is ""..."1.9" do
- it "raises Domain Error given -1" do
- lambda { Math.gamma(-1) }.should raise_error(Errno::EDOM)
- end
- end
-
- ruby_version_is "1.9" do
- it "raises Math::DomainError given -1" do
- lambda { Math.gamma(-1) }.should raise_error(Math::DomainError)
- end
+ it "raises Math::DomainError given -1" do
+ lambda { Math.gamma(-1) }.should raise_error(Math::DomainError)
end
# See http://redmine.ruby-lang.org/issues/show/2189
it "returns +infinity given +infinity" do
- Math.gamma(infinity_value).infinite?.should == 1
- end
-
- ruby_version_is ""..."1.9" do
- it "raises Domain Error given negative infinity" do
- lambda { Math.gamma(-infinity_value) }.should raise_error(Errno::EDOM)
- end
+ Math.gamma(Float::INFINITY).should == Float::INFINITY
end
- ruby_version_is "1.9" do
- it "raises Math::DomainError given negative infinity" do
- lambda { Math.gamma(-infinity_value) }.should raise_error(Math::DomainError)
- end
+ it "raises Math::DomainError given negative infinity" do
+ lambda { Math.gamma(-Float::INFINITY) }.should raise_error(Math::DomainError)
end
it "returns NaN given NaN" do
Math.gamma(nan_value).nan?.should be_true
end
-
end
end
Something went wrong with that request. Please try again.