# Class: Complex

Inherits:
Numeric
show all
Defined in:
complex.c

## Overview

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, Complex::rect, Complex::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('[email protected]')       #=> (-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)
'[email protected]'.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)
``````

## Constant Summary collapse

I =
`f_complex_new_bang2(rb_cComplex, ZERO, ONE)`

## Class Method Summary collapse

• Returns a complex object which denotes the given polar form.

• Returns a complex object which denotes the given rectangular form.

• Returns a complex object which denotes the given rectangular form.

## Instance Method Summary collapse

• Performs multiplication.

• Performs exponentiation.

• Performs subtraction.

• Returns negation of the value.

• Performs division.

• Returns true if cmp equals object numerically.

• Returns the absolute part of its polar form.

• Returns square of the absolute value.

• Returns the angle part of its polar form.

• Returns the angle part of its polar form.

• :nodoc:.

• :nodoc:.

• Returns the complex conjugate.

• Returns the complex conjugate.

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

• :nodoc:.

• :nodoc:.

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

• :nodoc:.

• Returns the imaginary part.

• Returns the imaginary part.

• :nodoc:.

• Returns the value as a string for inspection.

• Returns the absolute part of its polar form.

• :nodoc:.

• :nodoc:.

• Returns the numerator.

• Returns the angle part of its polar form.

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

• If the imaginary part is exactly 0, returns the real part as a Rational, otherwise a RangeError is raised.

• Returns the real part.

• Returns false.

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

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

• Returns the value as a float if possible.

• Returns the value as an integer if possible.

• If the imaginary part is exactly 0, returns the real part as a Rational, otherwise a RangeError is raised.

• Returns the value as a string.

• Returns the complex conjugate.

## Class Method Details

### .polar(abs[, arg]) ⇒ Object

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)
``````
 ``` ``` ```# File 'complex.c' 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; }```

### .rect(real[, imag]) ⇒ Object .rectangular(real[, imag]) ⇒ Object

Returns a complex object which denotes the given rectangular form.

 ``` ``` ```# File 'complex.c' 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; }```

### .rect(real[, imag]) ⇒ Object .rectangular(real[, imag]) ⇒ Object

Returns a complex object which denotes the given rectangular form.

 ``` ``` ```# File 'complex.c' 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; }```

## Instance Method Details

### #*(numeric) ⇒ Object

Performs multiplication.

 ``` ``` ```# File 'complex.c' 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); }```

### #**(numeric) ⇒ Object

Performs exponentiation.

For example:

``````Complex('i') ** 2             #=> (-1+0i)
Complex(-8) ** Rational(1,3)  #=> (1.0000000000000002+1.7320508075688772i)
``````
 ``` ``` ```# File 'complex.c' 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 */ }```

### #+(numeric) ⇒ Object

 ``` ``` ```# File 'complex.c' static VALUE nucomp_add(VALUE self, VALUE other) { return f_addsub(self, other, f_add, '+'); }```

### #-(numeric) ⇒ Object

Performs subtraction.

 ``` ``` ```# File 'complex.c' static VALUE nucomp_sub(VALUE self, VALUE other) { return f_addsub(self, other, f_sub, '-'); }```

### #- ⇒ Object

Returns negation of the value.

 ``` ``` ```# File 'complex.c' static VALUE nucomp_negate(VALUE self) { get_dat1(self); return f_complex_new2(CLASS_OF(self), f_negate(dat->real), f_negate(dat->imag)); }```

### #/(numeric) ⇒ Object #quo(numeric) ⇒ Object

Performs division.

For example:

``````Complex(10.0) / 3  #=> (3.3333333333333335+(0/1)*i)
Complex(10)   / 3  #=> ((10/3)+(0/1)*i)  # not (3+0i)
``````
 ``` ``` ```# File 'complex.c' static VALUE nucomp_div(VALUE self, VALUE other) { return f_divide(self, other, f_quo, id_quo); }```

### #==(object) ⇒ Boolean

Returns true if cmp equals object numerically.

Returns:

• (Boolean)
 ``` ``` ```# File 'complex.c' 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)); }```

### #abs ⇒ Object #magnitude ⇒ Object

Returns the absolute part of its polar form.

 ``` ``` ```# File 'complex.c' 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; }```

### #abs2 ⇒ Object

Returns square of the absolute value.

 ``` ``` ```# File 'complex.c' static VALUE nucomp_abs2(VALUE self) { get_dat1(self); return f_add(f_mul(dat->real, dat->real), f_mul(dat->imag, dat->imag)); }```

### #arg ⇒ Float #angle ⇒ Float #phase ⇒ Float

Returns the angle part of its polar form.

``````Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
``````

 ``` ``` ```# File 'complex.c' static VALUE nucomp_arg(VALUE self) { get_dat1(self); return m_atan2_bang(dat->imag, dat->real); }```

### #arg ⇒ Float #angle ⇒ Float #phase ⇒ Float

Returns the angle part of its polar form.

``````Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
``````

 ``` ``` ```# File 'complex.c' static VALUE nucomp_arg(VALUE self) { get_dat1(self); return m_atan2_bang(dat->imag, dat->real); }```

### #coerce ⇒ Object

:nodoc:

 ``` ``` ```# File 'complex.c' static VALUE nucomp_coerce(VALUE self, VALUE other) { if (k_numeric_p(other) && f_real_p(other)) return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self), other), self); if (TYPE(other) == T_COMPLEX) return rb_assoc_new(other, self); rb_raise(rb_eTypeError, "%s can't be coerced into %s", rb_obj_classname(other), rb_obj_classname(self)); return Qnil; }```

### #complex? ⇒ Object

:nodoc:

 ``` ``` ```# File 'complex.c' static VALUE nucomp_true(VALUE self) { return Qtrue; }```

### #conj ⇒ Object #conjugate ⇒ Object

Returns the complex conjugate.

 ``` ``` ```# File 'complex.c' static VALUE nucomp_conj(VALUE self) { get_dat1(self); return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag)); }```

### #conj ⇒ Object #conjugate ⇒ Object

Returns the complex conjugate.

 ``` ``` ```# File 'complex.c' static VALUE nucomp_conj(VALUE self) { get_dat1(self); return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag)); }```

### #denominator ⇒ Integer

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

See numerator.

Returns:

 ``` ``` ```# File 'complex.c' static VALUE nucomp_denominator(VALUE self) { get_dat1(self); return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag)); }```

### #eql? ⇒ Object

:nodoc:

 ``` ``` ```# File 'complex.c' static VALUE nucomp_eql_p(VALUE self, VALUE other) { if (k_complex_p(other)) { get_dat2(self, other); return f_boolcast((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) && (CLASS_OF(adat->imag) == CLASS_OF(bdat->imag)) && f_eqeq_p(self, other)); }```

### #exact? ⇒ Object

:nodoc:

 ``` ``` ```# File 'complex.c' static VALUE nucomp_exact_p(VALUE self) { get_dat1(self); return f_boolcast(k_exact_p(dat->real) && k_exact_p(dat->imag)); }```

### #fdiv(numeric) ⇒ Object

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

For example:

``````Complex(11,22).fdiv(3)  #=> (3.6666666666666665+7.333333333333333i)
``````
 ``` ``` ```# File 'complex.c' static VALUE nucomp_fdiv(VALUE self, VALUE other) { return f_divide(self, other, f_fdiv, id_fdiv); }```

### #hash ⇒ Object

:nodoc:

 ``` ``` ```# File 'complex.c' static VALUE nucomp_hash(VALUE self) { st_index_t v, h[2]; VALUE n; get_dat1(self); n = rb_hash(dat->real); h[0] = NUM2LONG(n); n = rb_hash(dat->imag); h[1] = NUM2LONG(n); v = rb_memhash(h, sizeof(h)); return LONG2FIX(v); }```

### #imag ⇒ Object #imaginary ⇒ Object

Returns the imaginary part.

 ``` ``` ```# File 'complex.c' static VALUE nucomp_imag(VALUE self) { get_dat1(self); return dat->imag; }```

### #imag ⇒ Object #imaginary ⇒ Object

Returns the imaginary part.

 ``` ``` ```# File 'complex.c' static VALUE nucomp_imag(VALUE self) { get_dat1(self); return dat->imag; }```

### #inexact? ⇒ Object

:nodoc:

 ``` ``` ```# File 'complex.c' static VALUE nucomp_inexact_p(VALUE self) { return f_boolcast(!nucomp_exact_p(self)); }```

### #inspect ⇒ String

Returns the value as a string for inspection.

Returns:

 ``` ``` ```# File 'complex.c' 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; }```

### #abs ⇒ Object #magnitude ⇒ Object

Returns the absolute part of its polar form.

 ``` ``` ```# File 'complex.c' 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; }```

### #marshal_dump ⇒ Object

:nodoc:

 ``` ``` ```# File 'complex.c' static VALUE nucomp_marshal_dump(VALUE self) { VALUE a; get_dat1(self); a = rb_assoc_new(dat->real, dat->imag); rb_copy_generic_ivar(a, self); return a; }```

### #marshal_load ⇒ Object

:nodoc:

 ``` ``` ```# File 'complex.c' static VALUE nucomp_marshal_load(VALUE self, VALUE a) { get_dat1(self); Check_Type(a, T_ARRAY); if (RARRAY_LEN(a) != 2) rb_raise(rb_eArgError, "marshaled complex must have an array whose length is 2 but %ld", RARRAY_LEN(a)); dat->real = RARRAY_PTR(a)[0]; dat->imag = RARRAY_PTR(a)[1]; rb_copy_generic_ivar(self, a); return self; }```

### #numerator ⇒ Numeric

Returns the numerator.

For example:

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

Returns:

 ``` ``` ```# File 'complex.c' 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)))); }```

### #arg ⇒ Float #angle ⇒ Float #phase ⇒ Float

Returns the angle part of its polar form.

``````Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
``````

 ``` ``` ```# File 'complex.c' static VALUE nucomp_arg(VALUE self) { get_dat1(self); return m_atan2_bang(dat->imag, dat->real); }```

### #polar ⇒ Array

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

Returns:

 ``` ``` ```# File 'complex.c' static VALUE nucomp_polar(VALUE self) { return rb_assoc_new(f_abs(self), f_arg(self)); }```

### #rationalize([eps]) ⇒ Object

If the imaginary part is exactly 0, returns the real part as a Rational, otherwise a RangeError is raised.

 ``` ``` ```# File 'complex.c' 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)); }```

### #real ⇒ Object

Returns the real part.

 ``` ``` ```# File 'complex.c' static VALUE nucomp_real(VALUE self) { get_dat1(self); return dat->real; }```

### #real? ⇒ false

Returns false.

Returns:

• (false)
 ``` ``` ```# File 'complex.c' static VALUE nucomp_false(VALUE self) { return Qfalse; }```

### #rect ⇒ Array #rectangular ⇒ Array

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

 ``` ``` ```# File 'complex.c' static VALUE nucomp_rect(VALUE self) { get_dat1(self); return rb_assoc_new(dat->real, dat->imag); }```

### #rect ⇒ Array #rectangular ⇒ Array

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

 ``` ``` ```# File 'complex.c' static VALUE nucomp_rect(VALUE self) { get_dat1(self); return rb_assoc_new(dat->real, dat->imag); }```

### #to_f ⇒ Float

Returns the value as a float if possible.

Returns:

 ``` ``` ```# File 'complex.c' 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)); }```

### #to_i ⇒ Integer

Returns the value as an integer if possible.

Returns:

 ``` ``` ```# File 'complex.c' 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)); }```

### #to_r ⇒ Object

If the imaginary part is exactly 0, returns the real part as a Rational, otherwise a RangeError is raised.

 ``` ``` ```# File 'complex.c' 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)); }```

### #to_s ⇒ String

Returns the value as a string.

Returns:

 ``` ``` ```# File 'complex.c' static VALUE nucomp_to_s(VALUE self) { return f_format(self, f_to_s); }```

### #conj ⇒ Object #conjugate ⇒ Object

Returns the complex conjugate.

 ``` ``` ```# File 'complex.c' static VALUE nucomp_conj(VALUE self) { get_dat1(self); return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag)); }```