Bug #2381

Math.gammaの挙動がx86_64とia64で異なる

Added by Mitsuhiro TAKANO over 5 years ago. Updated about 4 years ago.

[ruby-dev:39709]
Status:Closed
Priority:Low
Assignee:Mitsuhiro TAKANO
ruby -v:ruby 1.9.2dev (2009-11-17 trunk 25805) Backport:

Description

=begin
x86_64とia64でMath.gamma(4294967296) の結果などが異なる。

$ ./ruby -ve 'p Math.gamma(4294967296) '
ruby 1.9.2dev (2009-11-17 trunk 25805) [x86_64-linux]
Infinity

$ ./ruby -ve 'p Math.gamma(4294967296).finite? '
ruby 1.9.2dev (2009-11-17 trunk 25805) [x86_64-linux]
false

$ ./ruby -ve 'p Math.gamma(4294967296) '
ruby 1.9.2dev (2009-11-17 trunk 25805) [ia64-linux]
9.652349077525983e-315

$ ./ruby -ve 'p Math.gamma(4294967296).finite? '
ruby 1.9.2dev (2009-11-17 trunk 25805) [ia64-linux]
true

文字列表現に変換するときに finite? 相当のチェックをしている様子だが、これがうまく機能していない。
numeric.c:flo_is_finite_p, numeric.c:flo_to_s などでの挙動が異なる。

なお、 tgamma(3) を呼び出した単体の結果ではどちらも "inf" を返却している。
=end

math.c.diff Magnifier - math_gamma の修正 (425 Bytes) Mitsuhiro TAKANO, 11/18/2009 11:29 AM

math.c.diff Magnifier (644 Bytes) Mitsuhiro TAKANO, 11/18/2009 11:50 AM

math.c.diff Magnifier (644 Bytes) Mitsuhiro TAKANO, 11/18/2009 11:58 AM

Associated revisions

Revision 25836
Added by Mitsuhiro TAKANO over 5 years ago

  • math.c (math_gamma): fix incorrect comparison expression. see also [Bug #2381]

Revision 25836
Added by Mitsuhiro TAKANO over 5 years ago

  • math.c (math_gamma): fix incorrect comparison expression. see also [Bug #2381]

History

#1 Updated by Mitsuhiro TAKANO over 5 years ago

=begin
math.cの671行目付近での 0 < intpart という条件式にて intpart が 0 よりも微妙に大きい double型であったため、意図した処理ではなくなったように思える。

該当部分のパッチを添付する。
=end

#2 Updated by Usaku NAKAMURA over 5 years ago

=begin
こんにちは、なかむら(う)です。

In message " [Bug #2381] Math.gammaの挙動がx86_64とia64で異なる"
on Nov.18,2009 11:30:57, redmine@ruby-lang.org wrote:

math.cの671行目付近での 0 < intpart という条件式にて intpart が 0 よりも微妙に大きい double型であったため、意図した処理ではなくなったように思える。

modf()の仕様的に考えて、よっぽど腐ったライブラリ実装でない限
り、intpartが0より大きく1より小さい値になることはありえないと
考えられます。

実際の問題は、その次の行で不用意にintpartをintにキャストして
いることにあります。
なので、以下のパッチが正しいでしょう。

Index: math.c
===================================================================
--- math.c (revision 25830)
+++ math.c (working copy)
@@ -672,6 +672,7 @@ math_gamma(VALUE obj, VALUE x)
fracpart = modf(d0, &intpart);
if (fracpart == 0.0 &&
0 < intpart &&
+ intpart <= INT_MAX &&
(n = (int)intpart - 1) < numberof(fact_table)) {
return DBL2NUM(fact_table[n]);
}

それでは。
--
U.Nakamura usa@garbagecollect.jp

=end

#3 Updated by Mitsuhiro TAKANO over 5 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r25836.
Mitsuhiro, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

#4 Updated by Mitsuhiro TAKANO over 5 years ago

=begin
こんにちは
高野です。

U.Nakamura さんは書きました:

こんにちは、なかむら(う)です。

In message " [Bug #2381] Math.gammaの挙動がx86_64とia64で異なる"
on Nov.18,2009 11:30:57, redmine@ruby-lang.org wrote:

math.cの671行目付近での 0 < intpart という条件式にて intpart が 0 よりも微妙に大きい double型であったため、意図した処理ではなくなったように思える。

modf()の仕様的に考えて、よっぽど腐ったライブラリ実装でない限
り、intpartが0より大きく1より小さい値になることはありえないと
考えられます。

実際の問題は、その次の行で不用意にintpartをintにキャストして
いることにあります。

IRCはいろいろ教えていただきありがとうございます。
結局、int型がでてくるのがおかしい、ということになり、
なかださん提案の以下のパッチを r25836 にてコミットしました。

ありがとうございます。 m(_ _)m

Index: math.c
===================================================================
--- math.c (revision 25834)
+++ math.c (working copy)
@@ -666,14 +666,13 @@
};
double d0, d;
double intpart, fracpart;
- int n;
Need_Float(x);
d0 = RFLOAT_VALUE(x);
fracpart = modf(d0, &intpart);
if (fracpart == 0.0 &&
0 < intpart &&
- (n = (int)intpart - 1) < numberof(fact_table)) {
- return DBL2NUM(fact_table[n]);
+ intpart - 1 < (double)numberof(fact_table)) {
+ return DBL2NUM(fact_table[(int)intpart - 1]);
}
errno = 0;
d = tgamma(d0);

=end

Also available in: Atom PDF