mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Added RDoc comments. See comments at EOF for remaining issues.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3438 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
bed06ae87d
commit
c46774cdb3
1 changed files with 149 additions and 38 deletions
185
lib/complex.rb
185
lib/complex.rb
|
@ -5,48 +5,31 @@
|
||||||
# $Date: 1998/07/08 10:05:28 $
|
# $Date: 1998/07/08 10:05:28 $
|
||||||
# by Keiju ISHITSUKA(SHL Japan Inc.)
|
# by Keiju ISHITSUKA(SHL Japan Inc.)
|
||||||
#
|
#
|
||||||
# --
|
# ----
|
||||||
# Usage:
|
|
||||||
# class Complex < Numeric
|
|
||||||
#
|
#
|
||||||
# Complex(x, y) --> x + yi
|
# complex.rb implements the Complex class for complex numbers. Additionally,
|
||||||
# y.im --> 0 + yi
|
# some methods in other Numeric classes are redefined or added to allow greater
|
||||||
|
# interoperability with Complex numbers.
|
||||||
#
|
#
|
||||||
# Complex::polar
|
# Complex numbers can be created in the following manner:
|
||||||
|
# - <tt>Complex(a, b)</tt>
|
||||||
|
# - <tt>Complex.new(a, b)</tt>
|
||||||
|
# - <tt>Complex.polar(radius, theta)</tt>
|
||||||
#
|
#
|
||||||
# Complex::+
|
# Additionally, note the following:
|
||||||
# Complex::-
|
# - <tt>Complex::I</tt> (the mathematical constant <i>i</i>)
|
||||||
# Complex::*
|
# - <tt>Numeric#im</tt> (e.g. <tt>5.im -> 0+5i</tt>)
|
||||||
# Complex::/
|
|
||||||
# Complex::**
|
|
||||||
# Complex::%
|
|
||||||
# Complex::divmod -- obsolete
|
|
||||||
# Complex::abs
|
|
||||||
# Complex::abs2
|
|
||||||
# Complex::arg
|
|
||||||
# Complex::polar
|
|
||||||
# Complex::conjugate
|
|
||||||
# Complex::<=>
|
|
||||||
# Complex::==
|
|
||||||
# Complex::to_f
|
|
||||||
# Complex::to_r
|
|
||||||
# Complex::to_s
|
|
||||||
#
|
|
||||||
# Complex::I
|
|
||||||
#
|
|
||||||
# Numeric::im
|
|
||||||
#
|
|
||||||
# Math.sqrt
|
|
||||||
# Math.exp
|
|
||||||
# Math.cos
|
|
||||||
# Math.sin
|
|
||||||
# Math.tan
|
|
||||||
# Math.log
|
|
||||||
# Math.log10
|
|
||||||
# Math.atan2
|
|
||||||
#
|
#
|
||||||
|
# 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
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Creates a Complex number. +a+ and +b+ should be Numeric. The result will be
|
||||||
|
# <tt>a+bi</tt>.
|
||||||
|
#
|
||||||
def Complex(a, b = 0)
|
def Complex(a, b = 0)
|
||||||
if a.kind_of?(Complex) and b == 0
|
if a.kind_of?(Complex) and b == 0
|
||||||
a
|
a
|
||||||
|
@ -63,21 +46,30 @@ def Complex(a, b = 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# The complex number class. See complex.rb for an overview.
|
||||||
|
#
|
||||||
class Complex < Numeric
|
class Complex < Numeric
|
||||||
@RCS_ID='-$Id: complex.rb,v 1.3 1998/07/08 10:05:28 keiju Exp keiju $-'
|
@RCS_ID='-$Id: complex.rb,v 1.3 1998/07/08 10:05:28 keiju Exp keiju $-'
|
||||||
|
|
||||||
undef step
|
undef step
|
||||||
|
|
||||||
def Complex.generic?(other)
|
def Complex.generic?(other) # :nodoc:
|
||||||
other.kind_of?(Integer) or
|
other.kind_of?(Integer) or
|
||||||
other.kind_of?(Float) or
|
other.kind_of?(Float) or
|
||||||
(defined?(Rational) and other.kind_of?(Rational))
|
(defined?(Rational) and other.kind_of?(Rational))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Creates a +Complex+ number in terms of +r+ (radius) and +theta+ (angle).
|
||||||
|
#
|
||||||
def Complex.polar(r, theta)
|
def Complex.polar(r, theta)
|
||||||
Complex(r*Math.cos(theta), r*Math.sin(theta))
|
Complex(r*Math.cos(theta), r*Math.sin(theta))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Creates a +Complex+ number <tt>a</tt>+<tt>b</tt><i>i</i>.
|
||||||
|
#
|
||||||
def initialize(a, b = 0)
|
def initialize(a, b = 0)
|
||||||
raise "non numeric 1st arg `#{a.inspect}'" if !a.kind_of? Numeric
|
raise "non numeric 1st arg `#{a.inspect}'" if !a.kind_of? Numeric
|
||||||
raise "non numeric 2nd arg `#{b.inspect}'" if !b.kind_of? Numeric
|
raise "non numeric 2nd arg `#{b.inspect}'" if !b.kind_of? Numeric
|
||||||
|
@ -85,6 +77,9 @@ class Complex < Numeric
|
||||||
@image = b
|
@image = b
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Addition with real or complex number.
|
||||||
|
#
|
||||||
def + (other)
|
def + (other)
|
||||||
if other.kind_of?(Complex)
|
if other.kind_of?(Complex)
|
||||||
re = @real + other.real
|
re = @real + other.real
|
||||||
|
@ -98,6 +93,9 @@ class Complex < Numeric
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Subtraction with real or complex number.
|
||||||
|
#
|
||||||
def - (other)
|
def - (other)
|
||||||
if other.kind_of?(Complex)
|
if other.kind_of?(Complex)
|
||||||
re = @real - other.real
|
re = @real - other.real
|
||||||
|
@ -111,6 +109,9 @@ class Complex < Numeric
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Multiplication with real or complex number.
|
||||||
|
#
|
||||||
def * (other)
|
def * (other)
|
||||||
if other.kind_of?(Complex)
|
if other.kind_of?(Complex)
|
||||||
re = @real*other.real - @image*other.image
|
re = @real*other.real - @image*other.image
|
||||||
|
@ -124,6 +125,9 @@ class Complex < Numeric
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Division by real or complex number.
|
||||||
|
#
|
||||||
def / (other)
|
def / (other)
|
||||||
if other.kind_of?(Complex)
|
if other.kind_of?(Complex)
|
||||||
self*other.conjugate/other.abs2
|
self*other.conjugate/other.abs2
|
||||||
|
@ -135,6 +139,9 @@ class Complex < Numeric
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Raise this complex number to the given (real or complex) power.
|
||||||
|
#
|
||||||
def ** (other)
|
def ** (other)
|
||||||
if other == 0
|
if other == 0
|
||||||
return Complex(1)
|
return Complex(1)
|
||||||
|
@ -177,6 +184,9 @@ class Complex < Numeric
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Remainder after division by a real or complex number.
|
||||||
|
#
|
||||||
def % (other)
|
def % (other)
|
||||||
if other.kind_of?(Complex)
|
if other.kind_of?(Complex)
|
||||||
Complex(@real % other.real, @image % other.image)
|
Complex(@real % other.real, @image % other.image)
|
||||||
|
@ -188,6 +198,7 @@ class Complex < Numeric
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#--
|
||||||
# def divmod(other)
|
# def divmod(other)
|
||||||
# if other.kind_of?(Complex)
|
# if other.kind_of?(Complex)
|
||||||
# rdiv, rmod = @real.divmod(other.real)
|
# rdiv, rmod = @real.divmod(other.real)
|
||||||
|
@ -200,31 +211,54 @@ class Complex < Numeric
|
||||||
# x.divmod(y)
|
# x.divmod(y)
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
|
#++
|
||||||
|
|
||||||
|
#
|
||||||
|
# Absolute value (aka modulus): distance from the zero point on the complex
|
||||||
|
# plane.
|
||||||
|
#
|
||||||
def abs
|
def abs
|
||||||
Math.sqrt!((@real*@real + @image*@image).to_f)
|
Math.sqrt!((@real*@real + @image*@image).to_f)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Square of the absolute value.
|
||||||
|
#
|
||||||
def abs2
|
def abs2
|
||||||
@real*@real + @image*@image
|
@real*@real + @image*@image
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Argument (angle from (1,0) on the complex plane).
|
||||||
|
#
|
||||||
def arg
|
def arg
|
||||||
Math.atan2(@image.to_f, @real.to_f)
|
Math.atan2(@image.to_f, @real.to_f)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Returns the absolute value _and_ the argument.
|
||||||
|
#
|
||||||
def polar
|
def polar
|
||||||
return abs, arg
|
return abs, arg
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Complex conjugate (<tt>z + z.conjugate = 2 * z.real</tt>).
|
||||||
|
#
|
||||||
def conjugate
|
def conjugate
|
||||||
Complex(@real, -@image)
|
Complex(@real, -@image)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Compares the absolute values of the two numbers.
|
||||||
|
#
|
||||||
def <=> (other)
|
def <=> (other)
|
||||||
self.abs <=> other.abs
|
self.abs <=> other.abs
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test for numerical equality (<tt>a == a + 0<i>i</i></tt>).
|
||||||
|
#
|
||||||
def == (other)
|
def == (other)
|
||||||
if other.kind_of?(Complex)
|
if other.kind_of?(Complex)
|
||||||
@real == other.real and @image == other.image
|
@real == other.real and @image == other.image
|
||||||
|
@ -236,6 +270,9 @@ class Complex < Numeric
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Attempts to coerce +other+ to a Complex number.
|
||||||
|
#
|
||||||
def coerce(other)
|
def coerce(other)
|
||||||
if Complex.generic?(other)
|
if Complex.generic?(other)
|
||||||
return Complex.new(other), self
|
return Complex.new(other), self
|
||||||
|
@ -244,16 +281,25 @@ class Complex < Numeric
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# FIXME
|
||||||
|
#
|
||||||
def denominator
|
def denominator
|
||||||
@real.denominator.lcm(@image.denominator)
|
@real.denominator.lcm(@image.denominator)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# FIXME
|
||||||
|
#
|
||||||
def numerator
|
def numerator
|
||||||
cd = denominator
|
cd = denominator
|
||||||
Complex(@real.numerator*(cd/@real.denominator),
|
Complex(@real.numerator*(cd/@real.denominator),
|
||||||
@image.numerator*(cd/@image.denominator))
|
@image.numerator*(cd/@image.denominator))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Standard string representation of the complex number.
|
||||||
|
#
|
||||||
def to_s
|
def to_s
|
||||||
if @real != 0
|
if @real != 0
|
||||||
if defined?(Rational) and @image.kind_of?(Rational) and @image.denominator != 1
|
if defined?(Rational) and @image.kind_of?(Rational) and @image.denominator != 1
|
||||||
|
@ -278,35 +324,65 @@ class Complex < Numeric
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Returns a hash code for the complex number.
|
||||||
|
#
|
||||||
def hash
|
def hash
|
||||||
@real.hash ^ @image.hash
|
@real.hash ^ @image.hash
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Returns "<tt>Complex(<i>real</i>, <i>image</i>)</tt>".
|
||||||
|
#
|
||||||
def inspect
|
def inspect
|
||||||
sprintf("Complex(%s, %s)", @real.inspect, @image.inspect)
|
sprintf("Complex(%s, %s)", @real.inspect, @image.inspect)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# +I+ is the imaginary number. It exists at point (0,1) on the complex plane.
|
||||||
|
#
|
||||||
I = Complex(0,1)
|
I = Complex(0,1)
|
||||||
|
|
||||||
|
# The real part of a complex number.
|
||||||
attr :real
|
attr :real
|
||||||
|
|
||||||
|
# The imaginary part of a complex number.
|
||||||
attr :image
|
attr :image
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Numeric is a built-in class on which Fixnum, Bignum, etc., are based. Here
|
||||||
|
# some methods are added so that all number types can be treated to some extent
|
||||||
|
# as Complex numbers.
|
||||||
|
#
|
||||||
class Numeric
|
class Numeric
|
||||||
|
#
|
||||||
|
# Returns a Complex number <tt>(0,<i>self</i>)</tt>.
|
||||||
|
#
|
||||||
def im
|
def im
|
||||||
Complex(0, self)
|
Complex(0, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# The real part of a complex number, i.e. <i>self</i>.
|
||||||
|
#
|
||||||
def real
|
def real
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# The imaginary part of a complex number, i.e. 0.
|
||||||
|
#
|
||||||
def image
|
def image
|
||||||
0
|
0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# See Complex#arg.
|
||||||
|
#
|
||||||
def arg
|
def arg
|
||||||
if self >= 0
|
if self >= 0
|
||||||
return 0
|
return 0
|
||||||
|
@ -315,20 +391,28 @@ class Numeric
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# See Complex#polar.
|
||||||
|
#
|
||||||
def polar
|
def polar
|
||||||
return abs, arg
|
return abs, arg
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# See Complex#conjugate (short answer: returns <i>self</i>).
|
||||||
|
#
|
||||||
def conjugate
|
def conjugate
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
class Fixnum
|
class Fixnum
|
||||||
if not defined? Rational
|
if not defined? Rational
|
||||||
alias power! **
|
alias power! **
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Redefined to handle a Complex argument.
|
||||||
def ** (other)
|
def ** (other)
|
||||||
if self < 0
|
if self < 0
|
||||||
Complex.new(self) ** other
|
Complex.new(self) ** other
|
||||||
|
@ -367,6 +451,7 @@ module Math
|
||||||
alias log10! log10
|
alias log10! log10
|
||||||
alias atan2! atan2
|
alias atan2! atan2
|
||||||
|
|
||||||
|
# Redefined to handle a Complex argument.
|
||||||
def sqrt(z)
|
def sqrt(z)
|
||||||
if Complex.generic?(z)
|
if Complex.generic?(z)
|
||||||
if z >= 0
|
if z >= 0
|
||||||
|
@ -379,6 +464,7 @@ module Math
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Redefined to handle a Complex argument.
|
||||||
def exp(z)
|
def exp(z)
|
||||||
if Complex.generic?(z)
|
if Complex.generic?(z)
|
||||||
exp!(z)
|
exp!(z)
|
||||||
|
@ -387,14 +473,21 @@ module Math
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Hyperbolic cosine.
|
||||||
|
#
|
||||||
def cosh!(x)
|
def cosh!(x)
|
||||||
(exp!(x) + exp!(-x))/2.0
|
(exp!(x) + exp!(-x))/2.0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Hyperbolic sine.
|
||||||
|
#
|
||||||
def sinh!(x)
|
def sinh!(x)
|
||||||
(exp!(x) - exp!(-x))/2.0
|
(exp!(x) - exp!(-x))/2.0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Redefined to handle a Complex argument.
|
||||||
def cos(z)
|
def cos(z)
|
||||||
if Complex.generic?(z)
|
if Complex.generic?(z)
|
||||||
cos!(z)
|
cos!(z)
|
||||||
|
@ -404,6 +497,7 @@ module Math
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Redefined to handle a Complex argument.
|
||||||
def sin(z)
|
def sin(z)
|
||||||
if Complex.generic?(z)
|
if Complex.generic?(z)
|
||||||
sin!(z)
|
sin!(z)
|
||||||
|
@ -413,6 +507,7 @@ module Math
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Redefined to handle a Complex argument.
|
||||||
def tan(z)
|
def tan(z)
|
||||||
if Complex.generic?(z)
|
if Complex.generic?(z)
|
||||||
tan!(z)
|
tan!(z)
|
||||||
|
@ -421,6 +516,7 @@ module Math
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Redefined to handle a Complex argument.
|
||||||
def log(z)
|
def log(z)
|
||||||
if Complex.generic?(z) and z >= 0
|
if Complex.generic?(z) and z >= 0
|
||||||
log!(z)
|
log!(z)
|
||||||
|
@ -430,6 +526,7 @@ module Math
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Redefined to handle a Complex argument.
|
||||||
def log10(z)
|
def log10(z)
|
||||||
if Complex.generic?(z)
|
if Complex.generic?(z)
|
||||||
log10!(z)
|
log10!(z)
|
||||||
|
@ -438,6 +535,8 @@ module Math
|
||||||
end
|
end
|
||||||
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)
|
def atan2(x, y)
|
||||||
if Complex.generic?(x) and Complex.generic?(y)
|
if Complex.generic?(x) and Complex.generic?(y)
|
||||||
atan2!(x, y)
|
atan2!(x, y)
|
||||||
|
@ -446,10 +545,14 @@ module Math
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Hyperbolic arctangent.
|
||||||
|
#
|
||||||
def atanh!(x)
|
def atanh!(x)
|
||||||
log((1.0 + x.to_f) / ( 1.0 - x.to_f)) / 2.0
|
log((1.0 + x.to_f) / ( 1.0 - x.to_f)) / 2.0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Redefined to handle a Complex argument.
|
||||||
def atan(z)
|
def atan(z)
|
||||||
if Complex.generic?(z)
|
if Complex.generic?(z)
|
||||||
atan2!(z, 1)
|
atan2!(z, 1)
|
||||||
|
@ -490,3 +593,11 @@ module Math
|
||||||
module_function :atanh!
|
module_function :atanh!
|
||||||
|
|
||||||
end
|
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.
|
||||||
|
|
Loading…
Add table
Reference in a new issue