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.

Complex object can be created as literal, and also by using Kernel#Complex, ::rect, ::polar or #to_c method.

``````2+1i                 #=> (2+1i)
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)
``````
Namespace
Methods
#
A
C
D
F
I
J
M
N
P
Q
R
T
#
Constants
 I = f_complex_new_bang2(rb_cComplex, ZERO, ONE) The imaginary unit.
Class Public methods
json_create(object)

Deserializes JSON string by converting Real value `r`, imaginary value `i`, to a Complex object.

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

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);
if (canonicalization) return abs;
return nucomp_s_new_internal(klass, abs, ZERO);
default:
nucomp_real_check(abs);
nucomp_real_check(arg);
break;
}
return f_complex_polar(klass, abs, arg);
}```
Complex.rect(real[, imag]) → complex
Complex.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);
}```
Complex.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);
}```
Instance Public methods
cmp * numeric → complex

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)
``````
```VALUE
rb_nucomp_mul(VALUE self, VALUE other)
{
if (k_complex_p(other)) {
VALUE real, imag;
VALUE areal, aimag, breal, bimag;
int arzero, aizero, brzero, bizero;

get_dat2(self, other);

brzero = !!f_zero_p(breal = bdat->real);
bizero = !!f_zero_p(bimag = bdat->imag);
real = f_sub(safe_mul(areal, breal, arzero, brzero),
safe_mul(aimag, bimag, aizero, bizero));
imag = f_add(safe_mul(areal, bimag, arzero, bizero),
safe_mul(aimag, breal, aizero, brzero));

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

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)));
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

``````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)
``````
```VALUE
{
}```
cmp - numeric → complex

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)
{
}```
-cmp → complex

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
cmp.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

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);

}
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);
}```
cmp.abs → real

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);
}```
cmp.abs2 → real

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);
f_mul(dat->imag, dat->imag));
}```
cmp.angle → float

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);
}```
cmp.arg → float

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(*)

Returns a hash, that will be turned into a JSON object and represent this object.

```# File ext/json/lib/json/add/complex.rb, line 17
def as_json(*)
{
JSON.create_id => self.class.name,
'r'            => real,
'i'            => imag,
}
end```
cmp.conj → complex
cmp.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));
}```
cmp.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));
}```
cmp.denominator → integer

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));
}```
cmp.fdiv(numeric) → complex

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);
}```
cmp.imag → real
cmp.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;
}```
cmp.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;
}```
cmp.inspect → string

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, rb_inspect));
rb_str_cat2(s, ")");

return s;
}```
cmp.magnitude → real

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);
}```
cmp.numerator → numeric

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))));
}```
cmp.phase → float

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);
}```
cmp.polar → array

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
cmp.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.rationalize([eps]) → rational

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_exact_zero_p(dat->imag)) {
rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
self);
}
return rb_funcall2(dat->real, rb_intern("rationalize"), argc, argv);
}```
cmp.real → real

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;
}```
cmp.real? → false

Returns false.

```static VALUE
nucomp_false(VALUE self)
{
return Qfalse;
}```
cmp.rect → array
cmp.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);
}```
cmp.rect → array
cmp.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);
}```
complex.to_c → self

Returns self.

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

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_exact_zero_p(dat->imag)) {
rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Float",
self);
}
return f_to_f(dat->real);
}```
cmp.to_i → integer

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_exact_zero_p(dat->imag)) {
rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Integer",
self);
}
return f_to_i(dat->real);
}```
to_json(*)

Stores class name (Complex) along with real value `r` and imaginary value `i` as JSON string

```# File ext/json/lib/json/add/complex.rb, line 26
def to_json(*)
as_json.to_json
end```
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  # RangeError
Complex(1, 2).to_r    # RangeError
``````

See rationalize.

```static VALUE
nucomp_to_r(VALUE self)
{
get_dat1(self);

if (!k_exact_zero_p(dat->imag)) {
rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
self);
}
return f_to_r(dat->real);
}```
cmp.to_s → string

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, rb_String);
}```
cmp.conj → complex
cmp.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));
}```