class Complex

A complex number can be represented as a paired real number with imaginary unit; a+bi. Where a is real part, b is imaginary part and i is imaginary unit. Real a equals complex a+0i mathematically.

In ruby, you can create complex object with Complex, ::rect, ::polar or #to_c method.

Complex(1) #=> (1+0i)
Complex(2, 3) #=> (2+3i)
Complex.polar(2, 3) #=> (-1.9799849932008908+0.2822400161197344i)
3.to_c #=> (3+0i)

You can also create complex object from floating-point numbers or strings.

Complex(0.3) #=> (0.3+0i)
Complex('0.3-0.5i') #=> (0.3-0.5i)
Complex('2/3+3/4i') #=> ((2/3)+(3/4)*i)
Complex('1@2') #=> (-0.4161468365471424+0.9092974268256817i)
0.3.to_c #=> (0.3+0i)
'0.3-0.5i'.to_c #=> (0.3-0.5i)
'2/3+3/4i'.to_c #=> ((2/3)+(3/4)*i)
'1@2'.to_c #=> (-0.4161468365471424+0.9092974268256817i)

A complex object is either an exact or an inexact number.

Complex(1, 1) / 2 #=> ((1/2)+(1/2)*i)
Complex(1, 1) / 2.0 #=> (0.5+0.5i)

Constants

I

The imaginary unit.

Public Class Methods

json_create(object) click to toggle source
# File ext/json/lib/json/add/complex.rb, line 7
def self.json_create(object)
 Complex(object['r'], object['i'])
end
polar(abs[, arg]) → complex click to toggle source

Returns a complex object which denotes the given polar form.

Complex.polar(3, 0) #=> (3.0+0.0i)
Complex.polar(3, Math::PI/2) #=> (1.836909530733566e-16+3.0i)
Complex.polar(3, Math::PI) #=> (-3.0+3.673819061467132e-16i)
Complex.polar(3, -Math::PI/2) #=> (1.836909530733566e-16-3.0i)
static VALUE
nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
{
 VALUE abs, arg;
 switch (rb_scan_args(argc, argv, "11", &abs, &arg)) {
 case 1:
 nucomp_real_check(abs);
 arg = ZERO;
 break;
 default:
 nucomp_real_check(abs);
 nucomp_real_check(arg);
 break;
 }
 return f_complex_polar(klass, abs, arg);
}
rect(real[, imag]) → complex click to toggle source
rectangular(real[, imag]) → complex

Returns a complex object which denotes the given rectangular form.

Complex.rectangular(1, 2) #=> (1+2i)
static VALUE
nucomp_s_new(int argc, VALUE *argv, VALUE klass)
{
 VALUE real, imag;
 switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
 case 1:
 nucomp_real_check(real);
 imag = ZERO;
 break;
 default:
 nucomp_real_check(real);
 nucomp_real_check(imag);
 break;
 }
 return nucomp_s_canonicalize_internal(klass, real, imag);
}
rectangular(real[, imag]) → complex click to toggle source

Returns a complex object which denotes the given rectangular form.

Complex.rectangular(1, 2) #=> (1+2i)
static VALUE
nucomp_s_new(int argc, VALUE *argv, VALUE klass)
{
 VALUE real, imag;
 switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
 case 1:
 nucomp_real_check(real);
 imag = ZERO;
 break;
 default:
 nucomp_real_check(real);
 nucomp_real_check(imag);
 break;
 }
 return nucomp_s_canonicalize_internal(klass, real, imag);
}

Public Instance Methods

cmp * numeric → complex click to toggle source

Performs multiplication.

Complex(2, 3) * Complex(2, 3) #=> (-5+12i)
Complex(900) * Complex(1) #=> (900+0i)
Complex(-2, 9) * Complex(-9, 2) #=> (0-85i)
Complex(9, 8) * 4 #=> (36+32i)
Complex(20, 9) * 9.8 #=> (196.0+88.2i)
static VALUE
nucomp_mul(VALUE self, VALUE other)
{
 if (k_complex_p(other)) {
 VALUE real, imag;
 get_dat2(self, other);
 real = f_sub(f_mul(adat->real, bdat->real),
 f_mul(adat->imag, bdat->imag));
 imag = f_add(f_mul(adat->real, bdat->imag),
 f_mul(adat->imag, bdat->real));
 return f_complex_new2(CLASS_OF(self), real, imag);
 }
 if (k_numeric_p(other) && f_real_p(other)) {
 get_dat1(self);
 return f_complex_new2(CLASS_OF(self),
 f_mul(dat->real, other),
 f_mul(dat->imag, other));
 }
 return rb_num_coerce_bin(self, other, '*');
}
cmp ** numeric → complex click to toggle source

Performs exponentiation.

Complex('i') ** 2 #=> (-1+0i)
Complex(-8) ** Rational(1, 3) #=> (1.0000000000000002+1.7320508075688772i)
static VALUE
nucomp_expt(VALUE self, VALUE other)
{
 if (k_numeric_p(other) && k_exact_zero_p(other))
 return f_complex_new_bang1(CLASS_OF(self), ONE);
 if (k_rational_p(other) && f_one_p(f_denominator(other)))
 other = f_numerator(other); /* c14n */
 if (k_complex_p(other)) {
 get_dat1(other);
 if (k_exact_zero_p(dat->imag))
 other = dat->real; /* c14n */
 }
 if (k_complex_p(other)) {
 VALUE r, theta, nr, ntheta;
 get_dat1(other);
 r = f_abs(self);
 theta = f_arg(self);
 nr = m_exp_bang(f_sub(f_mul(dat->real, m_log_bang(r)),
 f_mul(dat->imag, theta)));
 ntheta = f_add(f_mul(theta, dat->real),
 f_mul(dat->imag, m_log_bang(r)));
 return f_complex_polar(CLASS_OF(self), nr, ntheta);
 }
 if (k_fixnum_p(other)) {
 if (f_gt_p(other, ZERO)) {
 VALUE x, z;
 long n;
 x = self;
 z = x;
 n = FIX2LONG(other) - 1;
 while (n) {
 long q, r;
 while (1) {
 get_dat1(x);
 q = n / 2;
 r = n % 2;
 if (r)
 break;
 x = nucomp_s_new_internal(CLASS_OF(self),
 f_sub(f_mul(dat->real, dat->real),
 f_mul(dat->imag, dat->imag)),
 f_mul(f_mul(TWO, dat->real), dat->imag));
 n = q;
 }
 z = f_mul(z, x);
 n--;
 }
 return z;
 }
 return f_expt(f_reciprocal(self), f_negate(other));
 }
 if (k_numeric_p(other) && f_real_p(other)) {
 VALUE r, theta;
 if (k_bignum_p(other))
 rb_warn("in a**b, b may be too big");
 r = f_abs(self);
 theta = f_arg(self);
 return f_complex_polar(CLASS_OF(self), f_expt(r, other),
 f_mul(theta, other));
 }
 return rb_num_coerce_bin(self, other, id_expt);
}
cmp + numeric → complex click to toggle source

Performs addition.

Complex(2, 3) + Complex(2, 3) #=> (4+6i)
Complex(900) + Complex(1) #=> (901+0i)
Complex(-2, 9) + Complex(-9, 2) #=> (-11+11i)
Complex(9, 8) + 4 #=> (13+8i)
Complex(20, 9) + 9.8 #=> (29.8+9i)
static VALUE
nucomp_add(VALUE self, VALUE other)
{
 return f_addsub(self, other, f_add, '+');
}
cmp - numeric → complex click to toggle source

Performs subtraction.

Complex(2, 3) - Complex(2, 3) #=> (0+0i)
Complex(900) - Complex(1) #=> (899+0i)
Complex(-2, 9) - Complex(-9, 2) #=> (7+7i)
Complex(9, 8) - 4 #=> (5+8i)
Complex(20, 9) - 9.8 #=> (10.2+9i)
static VALUE
nucomp_sub(VALUE self, VALUE other)
{
 return f_addsub(self, other, f_sub, '-');
}
-cmp → complex click to toggle source

Returns negation of the value.

-Complex(1, 2) #=> (-1-2i)
static VALUE
nucomp_negate(VALUE self)
{
 get_dat1(self);
 return f_complex_new2(CLASS_OF(self),
 f_negate(dat->real), f_negate(dat->imag));
}
cmp / numeric → complex click to toggle source
quo(numeric) → complex

Performs division.

Complex(2, 3) / Complex(2, 3) #=> ((1/1)+(0/1)*i)
Complex(900) / Complex(1) #=> ((900/1)+(0/1)*i)
Complex(-2, 9) / Complex(-9, 2) #=> ((36/85)-(77/85)*i)
Complex(9, 8) / 4 #=> ((9/4)+(2/1)*i)
Complex(20, 9) / 9.8 #=> (2.0408163265306123+0.9183673469387754i)
static VALUE
nucomp_div(VALUE self, VALUE other)
{
 return f_divide(self, other, f_quo, id_quo);
}
cmp == object → true or false click to toggle source

Returns true if cmp equals object numerically.

Complex(2, 3) == Complex(2, 3) #=> true
Complex(5) == 5 #=> true
Complex(0) == 0.0 #=> true
Complex('1/3') == 0.33 #=> false
Complex('1/2') == '1/2' #=> false
static VALUE
nucomp_eqeq_p(VALUE self, VALUE other)
{
 if (k_complex_p(other)) {
 get_dat2(self, other);
 return f_boolcast(f_eqeq_p(adat->real, bdat->real) &&
 f_eqeq_p(adat->imag, bdat->imag));
 }
 if (k_numeric_p(other) && f_real_p(other)) {
 get_dat1(self);
 return f_boolcast(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
 }
 return f_eqeq_p(other, self);
}
abs → real click to toggle source

Returns the absolute part of its polar form.

Complex(-1).abs #=> 1
Complex(3.0, -4.0).abs #=> 5.0
static VALUE
nucomp_abs(VALUE self)
{
 get_dat1(self);
 if (f_zero_p(dat->real)) {
 VALUE a = f_abs(dat->imag);
 if (k_float_p(dat->real) && !k_float_p(dat->imag))
 a = f_to_f(a);
 return a;
 }
 if (f_zero_p(dat->imag)) {
 VALUE a = f_abs(dat->real);
 if (!k_float_p(dat->real) && k_float_p(dat->imag))
 a = f_to_f(a);
 return a;
 }
 return m_hypot(dat->real, dat->imag);
}
abs2 → real click to toggle source

Returns square of the absolute value.

Complex(-1).abs2 #=> 1
Complex(3.0, -4.0).abs2 #=> 25.0
static VALUE
nucomp_abs2(VALUE self)
{
 get_dat1(self);
 return f_add(f_mul(dat->real, dat->real),
 f_mul(dat->imag, dat->imag));
}
angle → float click to toggle source

Returns the angle part of its polar form.

Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
static VALUE
nucomp_arg(VALUE self)
{
 get_dat1(self);
 return m_atan2_bang(dat->imag, dat->real);
}
arg → float click to toggle source

Returns the angle part of its polar form.

Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
static VALUE
nucomp_arg(VALUE self)
{
 get_dat1(self);
 return m_atan2_bang(dat->imag, dat->real);
}
as_json(*) click to toggle source
# File ext/json/lib/json/add/complex.rb, line 11
def as_json(*)
 {
 JSON.create_id => self.class.name,
 'r' => real,
 'i' => imag,
 }
end
conj → complex click to toggle source
conjugate → complex

Returns the complex conjugate.

Complex(1, 2).conjugate #=> (1-2i)
static VALUE
nucomp_conj(VALUE self)
{
 get_dat1(self);
 return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}
conjugate → complex click to toggle source

Returns the complex conjugate.

Complex(1, 2).conjugate #=> (1-2i)
static VALUE
nucomp_conj(VALUE self)
{
 get_dat1(self);
 return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}
denominator → integer click to toggle source

Returns the denominator (lcm of both denominator - real and imag).

See numerator.

static VALUE
nucomp_denominator(VALUE self)
{
 get_dat1(self);
 return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag));
}
fdiv(numeric) → complex click to toggle source

Performs division as each part is a float, never returns a float.

Complex(11, 22).fdiv(3) #=> (3.6666666666666665+7.333333333333333i)
static VALUE
nucomp_fdiv(VALUE self, VALUE other)
{
 return f_divide(self, other, f_fdiv, id_fdiv);
}
imag → real click to toggle source
imaginary → real

Returns the imaginary part.

Complex(7).imaginary #=> 0
Complex(9, -4).imaginary #=> -4
static VALUE
nucomp_imag(VALUE self)
{
 get_dat1(self);
 return dat->imag;
}
imaginary → real click to toggle source

Returns the imaginary part.

Complex(7).imaginary #=> 0
Complex(9, -4).imaginary #=> -4
static VALUE
nucomp_imag(VALUE self)
{
 get_dat1(self);
 return dat->imag;
}
inspect → string click to toggle source

Returns the value as a string for inspection.

Complex(2).inspect #=> "(2+0i)"
Complex('-8/6').inspect #=> "((-4/3)+0i)"
Complex('1/2i').inspect #=> "(0+(1/2)*i)"
Complex(0, Float::INFINITY).inspect #=> "(0+Infinity*i)"
Complex(Float::NAN, Float::NAN).inspect #=> "(NaN+NaN*i)"
static VALUE
nucomp_inspect(VALUE self)
{
 VALUE s;
 s = rb_usascii_str_new2("(");
 rb_str_concat(s, f_format(self, f_inspect));
 rb_str_cat2(s, ")");
 return s;
}
magnitude → real click to toggle source

Returns the absolute part of its polar form.

Complex(-1).abs #=> 1
Complex(3.0, -4.0).abs #=> 5.0
static VALUE
nucomp_abs(VALUE self)
{
 get_dat1(self);
 if (f_zero_p(dat->real)) {
 VALUE a = f_abs(dat->imag);
 if (k_float_p(dat->real) && !k_float_p(dat->imag))
 a = f_to_f(a);
 return a;
 }
 if (f_zero_p(dat->imag)) {
 VALUE a = f_abs(dat->real);
 if (!k_float_p(dat->real) && k_float_p(dat->imag))
 a = f_to_f(a);
 return a;
 }
 return m_hypot(dat->real, dat->imag);
}
numerator → numeric click to toggle source

Returns the numerator.

 1 2 3+4i <- numerator
 - + -i -> ----
 2 3 6 <- denominator
c = Complex('1/2+2/3i') #=> ((1/2)+(2/3)*i)
n = c.numerator #=> (3+4i)
d = c.denominator #=> 6
n / d #=> ((1/2)+(2/3)*i)
Complex(Rational(n.real, d), Rational(n.imag, d))
 #=> ((1/2)+(2/3)*i)

See denominator.

static VALUE
nucomp_numerator(VALUE self)
{
 VALUE cd;
 get_dat1(self);
 cd = f_denominator(self);
 return f_complex_new2(CLASS_OF(self),
 f_mul(f_numerator(dat->real),
 f_div(cd, f_denominator(dat->real))),
 f_mul(f_numerator(dat->imag),
 f_div(cd, f_denominator(dat->imag))));
}
phase → float click to toggle source

Returns the angle part of its polar form.

Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
static VALUE
nucomp_arg(VALUE self)
{
 get_dat1(self);
 return m_atan2_bang(dat->imag, dat->real);
}
polar → array click to toggle source

Returns an array; [cmp.abs, cmp.arg].

Complex(1, 2).polar #=> [2.23606797749979, 1.1071487177940904]
static VALUE
nucomp_polar(VALUE self)
{
 return rb_assoc_new(f_abs(self), f_arg(self));
}
cmp / numeric → complex click to toggle source
quo(numeric) → complex

Performs division.

Complex(2, 3) / Complex(2, 3) #=> ((1/1)+(0/1)*i)
Complex(900) / Complex(1) #=> ((900/1)+(0/1)*i)
Complex(-2, 9) / Complex(-9, 2) #=> ((36/85)-(77/85)*i)
Complex(9, 8) / 4 #=> ((9/4)+(2/1)*i)
Complex(20, 9) / 9.8 #=> (2.0408163265306123+0.9183673469387754i)
static VALUE
nucomp_div(VALUE self, VALUE other)
{
 return f_divide(self, other, f_quo, id_quo);
}
rationalize([eps]) → rational click to toggle source

Returns the value as a rational if possible (the imaginary part should be exactly zero).

Complex(1.0/3, 0).rationalize #=> (1/3)
Complex(1, 0.0).rationalize # RangeError
Complex(1, 2).rationalize # RangeError

See to_r.

static VALUE
nucomp_rationalize(int argc, VALUE *argv, VALUE self)
{
 get_dat1(self);
 rb_scan_args(argc, argv, "01", NULL);
 if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
 VALUE s = f_to_s(self);
 rb_raise(rb_eRangeError, "can't convert %s into Rational",
 StringValuePtr(s));
 }
 return rb_funcall2(dat->real, rb_intern("rationalize"), argc, argv);
}
real → real click to toggle source

Returns the real part.

Complex(7).real #=> 7
Complex(9, -4).real #=> 9
static VALUE
nucomp_real(VALUE self)
{
 get_dat1(self);
 return dat->real;
}
real? → false click to toggle source

Returns false.

static VALUE
nucomp_false(VALUE self)
{
 return Qfalse;
}
rect → array click to toggle source
rectangular → array

Returns an array; [cmp.real, cmp.imag].

Complex(1, 2).rectangular #=> [1, 2]
static VALUE
nucomp_rect(VALUE self)
{
 get_dat1(self);
 return rb_assoc_new(dat->real, dat->imag);
}
rect → array click to toggle source
rectangular → array

Returns an array; [cmp.real, cmp.imag].

Complex(1, 2).rectangular #=> [1, 2]
static VALUE
nucomp_rect(VALUE self)
{
 get_dat1(self);
 return rb_assoc_new(dat->real, dat->imag);
}
to_c → self click to toggle source

Returns self.

Complex(2).to_c #=> (2+0i)
Complex(-8, 6).to_c #=> (-8+6i)
static VALUE
nucomp_to_c(VALUE self)
{
 return self;
}
to_f → float click to toggle source

Returns the value as a float if possible (the imaginary part should be exactly zero).

Complex(1, 0).to_f #=> 1.0
Complex(1, 0.0).to_f # RangeError
Complex(1, 2).to_f # RangeError
static VALUE
nucomp_to_f(VALUE self)
{
 get_dat1(self);
 if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
 VALUE s = f_to_s(self);
 rb_raise(rb_eRangeError, "can't convert %s into Float",
 StringValuePtr(s));
 }
 return f_to_f(dat->real);
}
to_i → integer click to toggle source

Returns the value as an integer if possible (the imaginary part should be exactly zero).

Complex(1, 0).to_i #=> 1
Complex(1, 0.0).to_i # RangeError
Complex(1, 2).to_i # RangeError
static VALUE
nucomp_to_i(VALUE self)
{
 get_dat1(self);
 if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
 VALUE s = f_to_s(self);
 rb_raise(rb_eRangeError, "can't convert %s into Integer",
 StringValuePtr(s));
 }
 return f_to_i(dat->real);
}
to_json(*) click to toggle source
# File ext/json/lib/json/add/complex.rb, line 19
def to_json(*)
 as_json.to_json
end
to_r → rational click to toggle source

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 # RangeError
Complex(1, 2).to_r # RangeError

See rationalize.

static VALUE
nucomp_to_r(VALUE self)
{
 get_dat1(self);
 if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
 VALUE s = f_to_s(self);
 rb_raise(rb_eRangeError, "can't convert %s into Rational",
 StringValuePtr(s));
 }
 return f_to_r(dat->real);
}
to_s → string click to toggle source

Returns the value as a string.

Complex(2).to_s #=> "2+0i"
Complex('-8/6').to_s #=> "-4/3+0i"
Complex('1/2i').to_s #=> "0+1/2i"
Complex(0, Float::INFINITY).to_s #=> "0+Infinity*i"
Complex(Float::NAN, Float::NAN).to_s #=> "NaN+NaN*i"
static VALUE
nucomp_to_s(VALUE self)
{
 return f_format(self, f_to_s);
}
conj → complex click to toggle source
conjugate → complex

Returns the complex conjugate.

Complex(1, 2).conjugate #=> (1-2i)
static VALUE
nucomp_conj(VALUE self)
{
 get_dat1(self);
 return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}