田中です。

complex.rb に少し問題と思われる点があるので、以下のような修正を
提案します。最後にパッチをつけます。ruby-dev に流そうかとも思い
ましたが、内容が ruby-math 寄りなので、こっちに流します。


1. Fixnum#**の再定義取消と、Float#**の再定義追加

complex.rb で Fixnum#** が再定義されているのですが、その結果

    (-2)**2     #=> Complex(4, 0)

となってしまいます。負の整数の冪乗を Complex として計算するよう
ですが、整数の整数乗は整数または整数分の1となり、複素数とはなら
ないので、complex.rb では Fixnum#** の再定義をしないほうがよいと
思いますがいかがでしょう。

代わりに Float#** を再定義し、self<0 かつ 冪指数が Integer でな
いときに Complex として計算することを提案します。そうすれば、
Fixnum#** でも冪指数が Float なら coerce されるので、

    (-2)**0.5   #=> Complex(8.659560562e-17, 1.414213562)

となります。

ただしこれだけでは Bignum#** が違う動作になります。Bignum#** は、
冪指数が Float のとき、自前で Float に変換するので、再定義した 
Float#** を使いません。そのため、

    (-10000000000)**0.5  #=> NaN

となってしまいます。Bignum#** も Fixnum#** のように coerce に任
せてはどうでしょうか。


2. Math.sqrt(z) の修正

complex.rb で Math.sqrt(z) も再定義されていますが、z が Complex 
のとき、

    z**Rational(1,2)

と計算しています。これは rational.rb を require していないと
エラーになりますし、しかも多くの場合この結果は有理数ではありません。
下のパッチでは Float の Complex として計算するように修正しています。


3. imag

imaginary part の略語として image というのは違和感があるので、^^;;
    alias imag image
とさせてもらえるとありがたいです。


以下パッチです。できれば 1.6 にも当てて欲しいです。

田中昌宏

--- lib/complex.rb~	Mon Aug  7 01:02:10 2000
+++ lib/complex.rb	Sat Aug 11 19:22:20 2001
@@ -302,6 +302,7 @@
   
   attr :real
   attr :image
+  alias imag image
   
 end
 
@@ -340,21 +341,21 @@
     alias power! **
   end
   
-  def ** (other)
-    if self < 0
-      Complex.new(self) ** other
-    else
-      if defined? Rational
-	if other >= 0
-	  self.power!(other)
-	else
-	  Rational.new!(self,1)**other
-	end
-      else
-	self.power!(other)
-      end
-    end
-  end
+#  def ** (other)
+#    if self < 0
+#      Complex.new(self) ** other
+#    else
+#      if defined? Rational
+#	 if other >= 0
+#	   self.power!(other)
+#	 else
+#	   Rational.new!(self,1)**other
+#	 end
+#      else
+#	 self.power!(other)
+#      end
+#    end
+#  end
 end
 
 class Bignum
@@ -365,6 +366,14 @@
 
 class Float
   alias power! **
+
+  def ** (other)
+    if self >= 0 || other.kind_of?(Integer)
+      self.power!(other)
+    else
+      Complex.new(self) ** other
+    end
+  end
 end
 
 module Math
@@ -385,7 +394,18 @@
 	Complex(0,sqrt!(-z))
       end
     else
-      z**Rational(1,2)
+      if z.real >= 0
+	x = sqrt!( 0.5*(z.abs+z.real) )
+	if x==0
+	  Complex( 0.0, 0.0 )
+	else
+	  Complex( x, 0.5*z.image/x )
+	end
+      else
+	x = sqrt!( 0.5*(z.abs-z.real) )
+	x = -x if z.image<0
+	Complex( 0.5*z.image/x, x )
+      end
     end
   end