mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-complex: add comprehensive call-seq documentation for Complex methods
Added complete call-seq documentation for all Complex methods in mrblib/complex.rb (18 methods): ## Complex Class Methods: - polar: creates complex number from polar coordinates (magnitude, angle) with trigonometric conversion using Math.cos and Math.sin ## Complex Instance Methods: - inspect, to_s: string representation methods for debugging and display with proper formatting of real and imaginary parts - +@, -@: unary plus and minus operators for identity and negation - <=>: spaceship operator for comparison with other numeric types, enables Comparable module functionality with proper nil handling - abs/magnitude: absolute value (magnitude) calculation using hypot - abs2: square of absolute value for performance-critical calculations - arg/angle/phase: argument (angle) calculation using atan2 - conjugate/conj: complex conjugate operation (negates imaginary part) - fdiv: floating-point division ensuring float results - polar: returns [magnitude, angle] array representation - real?: always returns false for complex numbers - rectangular/rect: returns [real, imaginary] array representation - to_c: returns self (identity conversion) - to_r: converts to rational when imaginary part is zero, raises RangeError otherwise ## Numeric Extension Methods: - i: creates pure imaginary number (0+num*i) for convenient complex creation - to_c: converts any numeric to complex with zero imaginary part Co-authored-by: Atlassian Rovo Dev
This commit is contained in:
@@ -1,24 +1,84 @@
|
||||
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
|
||||
@@ -26,47 +86,137 @@ class Complex < Numeric
|
||||
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)
|
||||
@@ -75,6 +225,15 @@ class Complex < Numeric
|
||||
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
|
||||
@@ -83,6 +242,17 @@ class Complex < Numeric
|
||||
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
|
||||
|
||||
@@ -94,6 +94,15 @@ mrb_complex_copy(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
p1->imaginary = p2->imaginary;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* complex.real -> float
|
||||
*
|
||||
* Returns the real part of the complex number.
|
||||
*
|
||||
* Complex(3, 4).real #=> 3.0
|
||||
* Complex(-1).real #=> -1.0
|
||||
*/
|
||||
static mrb_value
|
||||
complex_real(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -101,6 +110,16 @@ complex_real(mrb_state *mrb, mrb_value self)
|
||||
return mrb_float_value(mrb, p->real);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* complex.imaginary -> float
|
||||
* complex.imag -> float
|
||||
*
|
||||
* Returns the imaginary part of the complex number.
|
||||
*
|
||||
* Complex(3, 4).imaginary #=> 4.0
|
||||
* Complex(5).imag #=> 0.0
|
||||
*/
|
||||
static mrb_value
|
||||
complex_imaginary(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -108,6 +127,19 @@ complex_imaginary(mrb_state *mrb, mrb_value self)
|
||||
return mrb_float_value(mrb, p->imaginary);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Complex.rectangular(real, imag = 0) -> complex
|
||||
* Complex.rect(real, imag = 0) -> complex
|
||||
* Complex(real, imag = 0) -> complex
|
||||
*
|
||||
* Returns a complex number with the given real and imaginary parts.
|
||||
* The imaginary part defaults to 0 if not specified.
|
||||
*
|
||||
* Complex.rectangular(1, 2) #=> (1+2i)
|
||||
* Complex.rect(3) #=> (3+0i)
|
||||
* Complex(1, -1) #=> (1-1i)
|
||||
*/
|
||||
static mrb_value
|
||||
complex_s_rect(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -117,6 +149,16 @@ complex_s_rect(mrb_state *mrb, mrb_value self)
|
||||
return complex_new(mrb, real, imaginary);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* complex.to_f -> float
|
||||
*
|
||||
* Returns the real part of the complex number as a float.
|
||||
* Raises RangeError if the imaginary part is not zero.
|
||||
*
|
||||
* Complex(3, 0).to_f #=> 3.0
|
||||
* Complex(3, 4).to_f #=> RangeError: can't convert (3+4i) into Float
|
||||
*/
|
||||
mrb_value
|
||||
mrb_complex_to_f(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -129,6 +171,16 @@ mrb_complex_to_f(mrb_state *mrb, mrb_value self)
|
||||
return mrb_float_value(mrb, p->real);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* complex.to_i -> integer
|
||||
*
|
||||
* Returns the real part of the complex number as an integer.
|
||||
* Raises RangeError if the imaginary part is not zero.
|
||||
*
|
||||
* Complex(3, 0).to_i #=> 3
|
||||
* Complex(3, 4).to_i #=> RangeError: can't convert (3+4i) into Integer
|
||||
*/
|
||||
mrb_value
|
||||
mrb_complex_to_i(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -176,6 +228,17 @@ mrb_complex_eq(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* complex == object -> true or false
|
||||
*
|
||||
* Returns true if complex equals object. Two complex numbers are equal
|
||||
* if their real and imaginary parts are equal.
|
||||
*
|
||||
* Complex(1, 2) == Complex(1, 2) #=> true
|
||||
* Complex(1, 2) == Complex(2, 1) #=> false
|
||||
* Complex(1, 0) == 1 #=> true
|
||||
*/
|
||||
static mrb_value
|
||||
complex_eq(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
@@ -203,6 +266,17 @@ mrb_complex_add(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* complex + numeric -> complex
|
||||
*
|
||||
* Returns the sum of complex and numeric. If numeric is a complex number,
|
||||
* adds both real and imaginary parts. If numeric is real, adds only to
|
||||
* the real part.
|
||||
*
|
||||
* Complex(1, 2) + Complex(3, 4) #=> (4+6i)
|
||||
* Complex(1, 2) + 3 #=> (4+2i)
|
||||
*/
|
||||
static mrb_value
|
||||
complex_add(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
@@ -230,6 +304,17 @@ mrb_complex_sub(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* complex - numeric -> complex
|
||||
*
|
||||
* Returns the difference of complex and numeric. If numeric is a complex number,
|
||||
* subtracts both real and imaginary parts. If numeric is real, subtracts only
|
||||
* from the real part.
|
||||
*
|
||||
* Complex(5, 6) - Complex(1, 2) #=> (4+4i)
|
||||
* Complex(5, 6) - 2 #=> (3+6i)
|
||||
*/
|
||||
static mrb_value
|
||||
complex_sub(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
@@ -258,6 +343,16 @@ mrb_complex_mul(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* complex * numeric -> complex
|
||||
*
|
||||
* Returns the product of complex and numeric. Uses the standard complex
|
||||
* multiplication formula: (a+bi) * (c+di) = (ac-bd) + (ad+bc)i
|
||||
*
|
||||
* Complex(1, 2) * Complex(3, 4) #=> (-5+10i)
|
||||
* Complex(1, 2) * 3 #=> (3+6i)
|
||||
*/
|
||||
static mrb_value
|
||||
complex_mul(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
@@ -362,6 +457,17 @@ mrb_complex_div(mrb_state *mrb, mrb_value self, mrb_value rhs)
|
||||
return complex_new(mrb, F(ldexp)(zr.s, zr.x), F(ldexp)(zi.s, zi.x));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* complex / numeric -> complex
|
||||
* complex.quo(numeric) -> complex
|
||||
*
|
||||
* Returns the quotient of complex divided by numeric. Uses the standard
|
||||
* complex division formula by multiplying by the conjugate.
|
||||
*
|
||||
* Complex(10, 5) / Complex(2, 1) #=> (5+0i)
|
||||
* Complex(6, 4) / 2 #=> (3+2i)
|
||||
*/
|
||||
static mrb_value
|
||||
complex_div(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
@@ -369,6 +475,15 @@ complex_div(mrb_state *mrb, mrb_value x)
|
||||
return mrb_complex_div(mrb, x, y);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* complex.hash -> integer
|
||||
*
|
||||
* Returns a hash value for the complex number. Two complex numbers with
|
||||
* the same real and imaginary parts will have the same hash value.
|
||||
*
|
||||
* Complex(1, 2).hash == Complex(1, 2).hash #=> true
|
||||
*/
|
||||
static mrb_value
|
||||
complex_hash(mrb_state *mrb, mrb_value cpx)
|
||||
{
|
||||
@@ -378,6 +493,14 @@ complex_hash(mrb_state *mrb, mrb_value cpx)
|
||||
return mrb_int_value(mrb, hash);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* nil.to_c -> complex
|
||||
*
|
||||
* Returns Complex(0, 0).
|
||||
*
|
||||
* nil.to_c #=> (0+0i)
|
||||
*/
|
||||
static mrb_value
|
||||
nil_to_c(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user