From: Yusuke Endoh Date: 2010-04-12T23:01:41+09:00 Subject: [ruby-dev:40961] [Bug #3137] complex.rb changes exceptions of Math Bug #3137: complex.rb changes exceptions of Math http://redmine.ruby-lang.org/issues/show/3137 起票者: Yusuke Endoh ステータス: Open, 優先度: Normal 担当者: Keiju Ishitsuka, カテゴリ: lib, Target version: 1.9.2 ruby -v: ruby 1.9.2dev (2010-04-12 trunk 27317) [i686-linux] いしつかさん 遠藤です。 [ruby-core:28204] にて Brian Ford が「complex を require すると Math.atan(nil) で投げられる例外が変わる」という報告をしています。 $ ./ruby -e 'p Math.atanh(nil)' -e:1:in `atanh': can't convert nil into Float (TypeError) from -e:1:in `
' $ ./ruby -rcomplex -e 'p Math.atanh(nil)' /home/mame/work/ruby-trunk-local/lib/ruby/1.9.1/cmath.rb:196:in `atanh': undefined method `real?' for nil:NilClass (NoMethodError) from -e:1:in `
' Ruby レベルのライブラリは duck typing のためにむやみに型チェック すべきでないとはいえ、CMath は組み込みの Math クラスの置き換えを 前提としているので、なるべく Math クラスの挙動を尊重した方がよい と思いました。 以下のパッチをコミットしてもいいでしょうか。 # ついでですが、[ruby-dev:40953] も見てください。 diff --git a/lib/cmath.rb b/lib/cmath.rb index b23dac2..aa2d9bb 100644 --- a/lib/cmath.rb +++ b/lib/cmath.rb @@ -27,6 +27,7 @@ module CMath alias atanh! atanh def exp(z) + z = Float(z) if z.real? exp!(z) else @@ -36,9 +37,9 @@ module CMath end end - def log(*args) - z, b = args - if z.real? and z >= 0 and (b.nil? or b >= 0) + def log(z, b = nil) + z = Float(z) + if z.real? and z >= 0 and (b.nil? or (b = Float(b); b >= 0)) log!(*args) else a = Complex(log!(z.abs), z.arg) @@ -50,6 +51,7 @@ module CMath end def log2(z) + z = Float(z) if z.real? and z >= 0 log2!(z) else @@ -58,6 +60,7 @@ module CMath end def log10(z) + z = Float(z) if z.real? and z >= 0 log10!(z) else @@ -66,6 +69,7 @@ module CMath end def sqrt(z) + z = Float(z) if z.real? if z < 0 Complex(0, sqrt!(-z)) @@ -85,6 +89,7 @@ module CMath end def cbrt(z) + z = Float(z) if z.real? and z >= 0 cbrt!(z) else @@ -93,6 +98,7 @@ module CMath end def sin(z) + z = Float(z) if z.real? sin!(z) else @@ -102,6 +108,7 @@ module CMath end def cos(z) + z = Float(z) if z.real? cos!(z) else @@ -111,6 +118,7 @@ module CMath end def tan(z) + z = Float(z) if z.real? tan!(z) else @@ -119,6 +127,7 @@ module CMath end def sinh(z) + z = Float(z) if z.real? sinh!(z) else @@ -128,6 +137,7 @@ module CMath end def cosh(z) + z = Float(z) if z.real? cosh!(z) else @@ -137,6 +147,7 @@ module CMath end def tanh(z) + z = Float(z) if z.real? tanh!(z) else @@ -145,6 +156,7 @@ module CMath end def asin(z) + z = Float(z) if z.real? and z >= -1 and z <= 1 asin!(z) else @@ -153,6 +165,7 @@ module CMath end def acos(z) + z = Float(z) if z.real? and z >= -1 and z <= 1 acos!(z) else @@ -161,6 +174,7 @@ module CMath end def atan(z) + z = Float(z) if z.real? atan!(z) else @@ -169,6 +183,7 @@ module CMath end def atan2(y,x) + x, y = Float(x), Float(y) if y.real? and x.real? atan2!(y,x) else @@ -177,6 +192,7 @@ module CMath end def asinh(z) + z = Float(z) if z.real? asinh!(z) else @@ -185,6 +201,7 @@ module CMath end def acosh(z) + z = Float(z) if z.real? and z >= 1 acosh!(z) else @@ -193,6 +210,7 @@ module CMath end def atanh(z) + z = Float(z) if z.real? and z >= -1 and z <= 1 atanh!(z) else -- Yusuke Endoh ---------------------------------------- http://redmine.ruby-lang.org