diff --git a/mrbgems/mruby-complex/mrblib/complex.rb b/mrbgems/mruby-complex/mrblib/complex.rb index 44b218024..8d58c334a 100644 --- a/mrbgems/mruby-complex/mrblib/complex.rb +++ b/mrbgems/mruby-complex/mrblib/complex.rb @@ -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 diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c index 03e058f71..e33c1f85d 100644 --- a/mrbgems/mruby-complex/src/complex.c +++ b/mrbgems/mruby-complex/src/complex.c @@ -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) {