From: Masahiro TANAKA Date: 2003-07-25T19:55:17+09:00 Subject: [ruby-dev:20900] Re: complex.rb At Tue, 22 Jul 2003 17:30:31 +0900, Yukihiro Matsumoto wrote: > |あと、ここには含まれていませんが、complex.rb 中の Fixnum#** の再定義は、 > |Complex とは関係ないだけでなく、(-2)**2 => Complex(4, 0) という副作用 > |があるので、削除して欲しいです。(というのも合意してもらったはず) > > 石塚さん、作業しますか。それとも私がやりましょうか? 石塚さんがお忙しそうなので、complex.rb のパッチを作りました。 ** の再定義を削除する他に、以下の変更も含みます。 * Complex.new を public にする * Complex.new の引数が Complex であったときに例外を上げる * Math.atan2 の再定義の削除 * Complex版 cosh,sinh,tanh,acos,asin,atan,acosh,asinh,atanh の追加 * 別名の追加 ( arg -> angle, conjugate -> conj ) あと Complex(real,imag) をもっと単純にしたほうがいいと思いますが、 とりあえず問題ではないのでそのままにしてあります。 田中昌宏 Index: complex.rb =================================================================== RCS file: /ruby/ruby/lib/complex.rb,v retrieving revision 1.16 diff -u -r1.16 complex.rb --- complex.rb 22 Jul 2003 08:42:47 -0000 1.16 +++ complex.rb 25 Jul 2003 10:41:28 -0000 @@ -21,7 +21,8 @@ # # The following +Math+ module methods are redefined to handle Complex arguments. # They will work as normal with non-Complex arguments. -# sqrt exp cos sin tan log log10 atan2 +# sqrt exp cos sin tan log log10 +# cosh sinh tanh acos asin atan acosh asinh atanh # @@ -66,7 +67,6 @@ Complex(r*Math.cos(theta), r*Math.sin(theta)) end - private_class_method :new # # Creates a +Complex+ number a+bi. # @@ -76,7 +76,9 @@ def initialize(a, b) raise "non numeric 1st arg `#{a.inspect}'" if !a.kind_of? Numeric + raise "`#{a.inspect}' for 1st arg" if a.kind_of? Complex raise "non numeric 2nd arg `#{b.inspect}'" if !b.kind_of? Numeric + raise "`#{b.inspect}' for 2nd arg" if b.kind_of? Complex @real = a @image = b end @@ -181,7 +183,7 @@ end elsif Complex.generic?(other) r, theta = polar - Complex.polar(r.power!(other), theta * other) + Complex.polar(r**other, theta*other) else x, y = other.coerce(self) x**y @@ -238,6 +240,7 @@ def arg Math.atan2(@image.to_f, @real.to_f) end + alias angle arg # # Returns the absolute value _and_ the argument. @@ -252,6 +255,7 @@ def conjugate Complex(@real, -@image) end + alias conj conjugate # # Compares the absolute values of the two numbers. @@ -395,6 +399,7 @@ return Math::PI end end + alias angle arg # # See Complex#polar. @@ -409,47 +414,27 @@ def conjugate self end + alias conj conjugate end -class Fixnum - unless defined? 1.power! - alias power! ** - p [__FILE__, defined? 1.power!] - end - - # Redefined to handle a Complex argument. - def ** (other) - if self < 0 - Complex.new!(self, 0) ** other - else - if defined? self.rpower - self.rpower(other) - else - self.power!(other) - end - end - end -end - -class Bignum - alias power! ** -end - -class Float - alias power! ** -end - module Math alias sqrt! sqrt alias exp! exp + alias log! log + alias log10! log10 alias cos! cos alias sin! sin alias tan! tan - alias log! log - alias atan! atan - alias log10! log10 - alias atan2! atan2 + alias cosh! cosh + alias sinh! sinh + alias tanh! tanh + alias acos! acos + alias asin! asin + alias atan! atan + alias acosh! acosh + alias asinh! asinh + alias atanh! atanh # Redefined to handle a Complex argument. def sqrt(z) @@ -479,20 +464,6 @@ end end - # - # Hyperbolic cosine. - # - def cosh!(x) - (exp!(x) + exp!(-x))/2.0 - end - - # - # Hyperbolic sine. - # - def sinh!(x) - (exp!(x) - exp!(-x))/2.0 - end - # Redefined to handle a Complex argument. def cos(z) if Complex.generic?(z) @@ -521,6 +492,30 @@ sin(z)/cos(z) end end + + def sinh(z) + if Complex.generic?(z) + sinh!(z) + else + Complex( sinh!(z.real)*cos!(z.image), cosh!(z.real)*sin!(z.image) ) + end + end + + def cosh(z) + if Complex.generic?(z) + cosh!(z) + else + Complex( cosh!(z.real)*cos!(z.image), sinh!(z.real)*sin!(z.image) ) + end + end + + def tanh(z) + if Complex.generic?(z) + tanh!(z) + else + sinh(z)/cosh(z) + end + end # Redefined to handle a Complex argument. def log(z) @@ -540,69 +535,92 @@ log(z)/log!(10) end end - - # FIXME: I don't know what the point of this is. If you give it Complex - # arguments, it will fail. - def atan2(x, y) - if Complex.generic?(x) and Complex.generic?(y) - atan2!(x, y) + + def acos(z) + if Complex.generic?(z) + acos!(z) else - fail "Not yet implemented." + -1.0.im * log( z + 1.0.im * sqrt(1.0-z*z) ) end end - - # - # Hyperbolic arctangent. - # - def atanh!(x) - log((1.0 + x.to_f) / ( 1.0 - x.to_f)) / 2.0 + + def asin(z) + if Complex.generic?(z) + asin!(z) + else + -1.0.im * log( 1.0.im * z + sqrt(1.0-z*z) ) + end end - - # Redefined to handle a Complex argument. + def atan(z) if Complex.generic?(z) - atan2!(z, 1) - elsif z.image == 0 - atan2(z.real,1) - else - a = z.real - b = z.image - - c = (a*a + b*b - 1.0) - d = (a*a + b*b + 1.0) + atan!(z) + else + 1.0.im * log( (1.0.im+z) / (1.0.im-z) ) / 2.0 + end + end - Complex(atan2!((c + sqrt(c*c + 4.0*a*a)), 2.0*a), - atanh!((-d + sqrt(d*d - 4.0*b*b))/(2.0*b))) + def acosh(z) + if Complex.generic?(z) + acosh!(z) + else + log( z + sqrt(z*z-1.0) ) end end - - module_function :sqrt + + def asinh(z) + if Complex.generic?(z) + asinh!(z) + else + log( z + sqrt(1.0+z*z) ) + end + end + + def atanh(z) + if Complex.generic?(z) + atanh!(z) + else + log( (1.0+z) / (1.0-z) ) / 2.0 + end + end + module_function :sqrt! + module_function :sqrt module_function :exp! module_function :exp + module_function :log! + module_function :log + module_function :log10! + module_function :log10 module_function :cosh! + module_function :cosh module_function :cos! module_function :cos module_function :sinh! + module_function :sinh module_function :sin! module_function :sin module_function :tan! module_function :tan - module_function :log! - module_function :log - module_function :log10! - module_function :log - module_function :atan2! - module_function :atan2 -# module_function :atan! + module_function :tanh! + module_function :tanh + module_function :acos! + module_function :acos + module_function :asin! + module_function :asin + module_function :atan! module_function :atan + module_function :acosh! + module_function :acosh + module_function :asinh! + module_function :asinh module_function :atanh! + module_function :atanh end # Documentation comments: # - source: original (researched from pickaxe) # - a couple of fixme's -# - Math module methods sinh! etc. a bit fuzzy. What exactly is the intention? # - RDoc output for Bignum etc. is a bit short, with nothing but an # (undocumented) alias. No big deal.