calog/vendor/mruby/mrbgems/mruby-complex/mrblib/complex.rb
2026-07-04 20:25:00 -05:00

259 lines
5 KiB
Ruby
Vendored

class Complex < Numeric
#
# call-seq:
# Complex.polar(abs [, arg]) -> complex
#
# Returns a complex number in terms of its polar coordinates.
# abs is the absolute value (magnitude) and arg is the argument (angle).
#
# Complex.polar(3, 0) #=> (3+0i)
# Complex.polar(3, Math::PI/2) #=> (1.836909530733566e-16+3.0i)
# Complex.polar(3, Math::PI) #=> (-3.0+3.673819061467132e-16i)
#
def self.polar(abs, arg = 0)
Complex(abs * Math.cos(arg), abs * Math.sin(arg))
end
#
# call-seq:
# cmp.inspect -> string
#
# Returns the value as a string for inspection.
#
# Complex(2).inspect #=> "(2+0i)"
# Complex(-8, 6).inspect #=> "(-8+6i)"
# Complex(1, 2).inspect #=> "(1+2i)"
#
def inspect
"(#{to_s})"
end
#
# call-seq:
# cmp.to_s -> string
#
# Returns the value as a string.
#
# Complex(2).to_s #=> "2+0i"
# Complex(-8, 6).to_s #=> "-8+6i"
# Complex(1, -2).to_s #=> "1-2i"
#
def to_s
"#{real}#{'+' unless imaginary < 0}#{imaginary}#{'*' unless imaginary.finite?}i"
end
#
# call-seq:
# +cmp -> cmp
#
# Returns self.
#
# +Complex(1, 2) #=> (1+2i)
#
def +@
self
end
#
# call-seq:
# -cmp -> complex
#
# Returns the negation of self.
#
# -Complex(1, 2) #=> (-1-2i)
# -Complex(-1, 2) #=> (1-2i)
#
def -@
Complex(-real, -imaginary)
end
#
# call-seq:
# cmp <=> numeric -> -1, 0, +1, or nil
#
# Returns -1, 0, or +1 depending on whether cmp is less than, equal to,
# or greater than numeric. This is the basis for the tests in the Comparable module.
# Returns nil if the two values are incomparable.
#
# Complex(2, 3) <=> Complex(2, 3) #=> 0
# Complex(5) <=> 5 #=> 0
# Complex(2, 3) <=> 1 #=> 1
#
def <=>(other)
return nil unless other.kind_of?(Numeric)
self.to_f <=> other.to_f
rescue
nil
end
#
# call-seq:
# cmp.abs -> real
# cmp.magnitude -> real
#
# Returns the absolute part of its polar form.
#
# Complex(-1).abs #=> 1.0
# Complex(3.0, -4.0).abs #=> 5.0
#
def abs
Math.hypot(imaginary, real)
end
alias_method :magnitude, :abs
#
# call-seq:
# cmp.abs2 -> real
#
# Returns square of the absolute value.
#
# Complex(-1).abs2 #=> 1
# Complex(3.0, -4.0).abs2 #=> 25.0
#
def abs2
real * real + imaginary * imaginary
end
#
# call-seq:
# cmp.arg -> float
# cmp.angle -> float
# cmp.phase -> float
#
# Returns the angle part of its polar form.
#
# Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
#
def arg
Math.atan2(imaginary, real)
end
alias_method :angle, :arg
alias_method :phase, :arg
#
# call-seq:
# cmp.conjugate -> complex
# cmp.conj -> complex
#
# Returns the complex conjugate.
#
# Complex(1, 2).conjugate #=> (1-2i)
#
def conjugate
Complex(real, -imaginary)
end
alias_method :conj, :conjugate
#
# call-seq:
# cmp.fdiv(numeric) -> complex
#
# Performs division as each part is a float, even if the parts are not floats.
#
# Complex(11, 22).fdiv(3) #=> (3.6666666666666665+7.333333333333333i)
#
def fdiv(numeric)
Complex(real / numeric, imaginary / numeric)
end
#
# call-seq:
# cmp.polar -> array
#
# Returns an array; [cmp.abs, cmp.arg].
#
# Complex(1, 2).polar #=> [2.23606797749979, 1.1071487177940904]
#
def polar
[abs, arg]
end
#
# call-seq:
# cmp.real? -> false
#
# Returns false.
#
# Complex(1).real? #=> false
#
def real?
false
end
#
# call-seq:
# cmp.rectangular -> array
# cmp.rect -> array
#
# Returns an array; [cmp.real, cmp.imag].
#
# Complex(1, 2).rectangular #=> [1, 2]
#
def rectangular
[real, imaginary]
end
alias_method :rect, :rectangular
#
# call-seq:
# cmp.to_c -> cmp
#
# Returns self.
#
# Complex(2).to_c #=> (2+0i)
# Complex(-8, 6).to_c #=> (-8+6i)
#
def to_c
self
end
#
# call-seq:
# cmp.to_r -> rational
#
# Returns the value as a rational if possible (the imaginary part should be exactly zero).
#
# Complex(1, 0).to_r #=> (1/1)
# Complex(1, 0.0).to_r #=> (1/1)
# Complex(1, 2).to_r #=> RangeError
#
def to_r
raise RangeError.new "can't convert #{to_s} into Rational" unless imaginary.zero?
Rational(real, 1)
end
alias_method :imag, :imaginary
Numeric.class_eval do
#
# call-seq:
# num.i -> complex
#
# Returns the Complex object created from this number and i (0+num*i).
#
# -42.i #=> (0-42i)
# 2.0.i #=> (0+2.0i)
#
def i
Complex(0, self)
end
end
undef i
end
class Numeric
#
# call-seq:
# num.to_c -> complex
#
# Returns the value as a complex.
#
# 1.to_c #=> (1+0i)
# -1.to_c #=> (-1+0i)
# 1.0.to_c #=> (1.0+0i)
# 3.14159.to_c #=> (3.14159+0i)
#
def to_c
Complex(self, 0)
end
end