Complex.rb changes exceptions of Math

Issue #3137 has been updated by Sho H…

r32055 の修正だと、CMath.#log で底に数値以外を与える場合に Math.#log のように TypeError
が発生しませんでした。

CMath.log(8, “2”) # => ArgumentError

Bug #3137: complex.rb changes exceptions of Math

Author: Yusuke E.
Status: Assigned
Priority: Normal
Assignee: Keiju Ishitsuka
Category: lib
Target version: 1.9.x
ruby -v: -

=begin
いしつかさん
遠藤です。

[ruby-core:28204] にて Brian F. が「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 E. [email protected]
=end