class Complex

A Complex object houses a pair of values, given when the object is created as either rectangular coordinates or polar coordinates.

Rectangular Coordinates

The rectangular coordinates of a complex number are called the real and imaginary parts; see Complex number definition.

You can create a Complex object from rectangular coordinates with:

Note that each of the stored parts may be a an instance one of the classes Complex, Float, Integer, or Rational; they may be retrieved:

The corresponding (computed) polar values may be retrieved:

Polar Coordinates

The polar coordinates of a complex number are called the absolute and argument parts; see Complex polar plane.

In this class, the argument part in expressed radians (not degrees).

You can create a Complex object from polar coordinates with:

Note that each of the stored parts may be a an instance one of the classes Complex, Float, Integer, or Rational; they may be retrieved:

The corresponding (computed) rectangular values may be retrieved:

What’s Here

First, what’s elsewhere:

  • Class Complex inherits (directly or indirectly) from classes Numeric and Object.

  • Includes (indirectly) module Comparable.

Here, class Complex has methods for:

Creating Complex Objects

  • ::polar: Returns a new Complex object based on given polar coordinates.

  • ::rect (and its alias ::rectangular): Returns a new Complex object based on given rectangular coordinates.

Querying

  • abs (and its alias magnitude): Returns the absolute value for self.

  • arg (and its aliases angle and phase): Returns the argument (angle) for self in radians.

  • denominator: Returns the denominator of self.

  • finite?: Returns whether both self.real and self.image are finite.

  • hash: Returns the integer hash value for self.

  • imag (and its alias imaginary): Returns the imaginary value for self.

  • infinite?: Returns whether self.real or self.image is infinite.

  • numerator: Returns the numerator of self.

  • polar: Returns the array [self.abs, self.arg].

  • inspect: Returns a string representation of self.

  • real: Returns the real value for self.

  • real?: Returns false; for compatibility with Numeric#real?.

  • rect (and its alias rectangular): Returns the array [self.real, self.imag].

Comparing

  • #<=>: Returns whether self is less than, equal to, or greater than the given argument.

  • ==: Returns whether self is equal to the given argument.

Converting

  • rationalize: Returns a Rational object whose value is exactly or approximately equivalent to that of self.real.

  • to_c: Returns self.

  • to_d: Returns the value as a BigDecimal object.

  • to_f: Returns the value of self.real as a Float, if possible.

  • to_i: Returns the value of self.real as an Integer, if possible.

  • to_r: Returns the value of self.real as a Rational, if possible.

  • to_s: Returns a string representation of self.

Performing Complex Arithmetic

  • *: Returns the product of self and the given numeric.

  • **: Returns self raised to power of the given numeric.

  • +: Returns the sum of self and the given numeric.

  • -: Returns the difference of self and the given numeric.

  • -@: Returns the negation of self.

  • #/: Returns the quotient of self and the given numeric.

  • abs2: Returns square of the absolute value (magnitude) for self.

  • conj (and its alias conjugate): Returns the conjugate of self.

  • fdiv: Returns Complex.rect(self.real/numeric, self.imag/numeric).

Working with JSON

  • ::json_create: Returns a new Complex object, deserialized from the given serialized hash.

  • as_json: Returns a serialized hash constructed from self.

  • to_json: Returns a JSON string representing self.

These methods are provided by the JSON gem. To make these methods available:

require 'json/add/complex'

Constants

I

Equivalent to Complex.rect(0, 1):

Complex::I # => (0+1i)

Public Class Methods

polar(abs, arg = 0) → complex click to toggle source

Returns a new Complex object formed from the arguments, each of which must be an instance of Numeric, or an instance of one of its subclasses: Complex, Float, Integer, Rational. Argument arg is given in radians; see Polar Coordinates:

Complex.polar(3)        # => (3+0i)
Complex.polar(3, 2.0)   # => (-1.2484405096414273+2.727892280477045i)
Complex.polar(-3, -2.0) # => (1.2484405096414273+2.727892280477045i)
static VALUE
nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
{
    VALUE abs, arg;

    argc = rb_scan_args(argc, argv, "11", &abs, &arg);
    abs = nucomp_real_check(abs);
    if (argc == 2) {
        arg = nucomp_real_check(arg);
    }
    else {
        arg = ZERO;
    }
    return f_complex_polar_real(klass, abs, arg);
}
rect(real, imag = 0) → complex click to toggle source

Returns a new Complex object formed from the arguments, each of which must be an instance of Numeric, or an instance of one of its subclasses: Complex, Float, Integer, Rational; see Rectangular Coordinates:

Complex.rect(3)             # => (3+0i)
Complex.rect(3, Math::PI)   # => (3+3.141592653589793i)
Complex.rect(-3, -Math::PI) # => (-3-3.141592653589793i)

Complex.rectangular is an alias for Complex.rect.

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:
        real = nucomp_real_check(real);
        imag = ZERO;
        break;
      default:
        real = nucomp_real_check(real);
        imag = nucomp_real_check(imag);
        break;
    }

    return nucomp_s_new_internal(klass, real, imag);
}
rect(real, imag = 0) → complex click to toggle source

Returns a new Complex object formed from the arguments, each of which must be an instance of Numeric, or an instance of one of its subclasses: Complex, Float, Integer, Rational; see Rectangular Coordinates:

Complex.rect(3)             # => (3+0i)
Complex.rect(3, Math::PI)   # => (3+3.141592653589793i)
Complex.rect(-3, -Math::PI) # => (-3-3.141592653589793i)

Complex.rectangular is an alias for Complex.rect.

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:
        real = nucomp_real_check(real);
        imag = ZERO;
        break;
      default:
        real = nucomp_real_check(real);
        imag = nucomp_real_check(imag);
        break;
    }

    return nucomp_s_new_internal(klass, real, imag);
}

Public Instance Methods

complex * numeric → new_complex click to toggle source

Returns the product of self and numeric:

Complex.rect(2, 3)  * Complex.rect(2, 3)  # => (-5+12i)
Complex.rect(900)   * Complex.rect(1)     # => (900+0i)
Complex.rect(-2, 9) * Complex.rect(-9, 2) # => (0-85i)
Complex.rect(9, 8)  * 4                   # => (36+32i)
Complex.rect(20, 9) * 9.8                 # => (196.0+88.2i)
VALUE
rb_complex_mul(VALUE self, VALUE other)
{
    if (RB_TYPE_P(other, T_COMPLEX)) {
        VALUE real, imag;
        get_dat2(self, other);

        comp_mul(adat->real, adat->imag, bdat->real, bdat->imag, &real, &imag);

        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, '*');
}
complex ** numeric → new_complex click to toggle source

Returns self raised to power numeric:

Complex.rect(0, 1) ** 2            # => (-1+0i)
Complex.rect(-8) ** Rational(1, 3) # => (1.0000000000000002+1.7320508075688772i)
VALUE
rb_complex_pow(VALUE self, VALUE other)
{
    if (k_numeric_p(other) && k_exact_zero_p(other))
        return f_complex_new_bang1(CLASS_OF(self), ONE);

    if (RB_TYPE_P(other, T_RATIONAL) && RRATIONAL(other)->den == LONG2FIX(1))
        other = RRATIONAL(other)->num; /* c14n */

    if (RB_TYPE_P(other, T_COMPLEX)) {
        get_dat1(other);

        if (k_exact_zero_p(dat->imag))
            other = dat->real; /* c14n */
    }

    if (other == ONE) {
        get_dat1(self);
        return nucomp_s_new_internal(CLASS_OF(self), dat->real, dat->imag);
    }

    VALUE result = complex_pow_for_special_angle(self, other);
    if (!UNDEF_P(result)) return result;

    if (RB_TYPE_P(other, T_COMPLEX)) {
        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 (FIXNUM_P(other)) {
        long n = FIX2LONG(other);
        if (n == 0) {
            return nucomp_s_new_internal(CLASS_OF(self), ONE, ZERO);
        }
        if (n < 0) {
            self = f_reciprocal(self);
            other = rb_int_uminus(other);
            n = -n;
        }
        {
            get_dat1(self);
            VALUE xr = dat->real, xi = dat->imag, zr = xr, zi = xi;

            if (f_zero_p(xi)) {
                zr = rb_num_pow(zr, other);
            }
            else if (f_zero_p(xr)) {
                zi = rb_num_pow(zi, other);
                if (n & 2) zi = f_negate(zi);
                if (!(n & 1)) {
                    VALUE tmp = zr;
                    zr = zi;
                    zi = tmp;
                }
            }
            else {
                while (--n) {
                    long q, r;

                    for (; q = n / 2, r = n % 2, r == 0; n = q) {
                        VALUE tmp = f_sub(f_mul(xr, xr), f_mul(xi, xi));
                        xi = f_mul(f_mul(TWO, xr), xi);
                        xr = tmp;
                    }
                    comp_mul(zr, zi, xr, xi, &zr, &zi);
                }
            }
            return nucomp_s_new_internal(CLASS_OF(self), zr, zi);
        }
    }
    if (k_numeric_p(other) && f_real_p(other)) {
        VALUE r, theta;

        if (RB_BIGNUM_TYPE_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);
}
complex + numeric → new_complex click to toggle source

Returns the sum of self and numeric:

Complex.rect(2, 3)  + Complex.rect(2, 3)  # => (4+6i)
Complex.rect(900)   + Complex.rect(1)     # => (901+0i)
Complex.rect(-2, 9) + Complex.rect(-9, 2) # => (-11+11i)
Complex.rect(9, 8)  + 4                   # => (13+8i)
Complex.rect(20, 9) + 9.8                 # => (29.8+9i)
VALUE
rb_complex_plus(VALUE self, VALUE other)
{
    if (RB_TYPE_P(other, T_COMPLEX)) {
        VALUE real, imag;

        get_dat2(self, other);

        real = f_add(adat->real, bdat->real);
        imag = f_add(adat->imag, bdat->imag);

        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_add(dat->real, other), dat->imag);
    }
    return rb_num_coerce_bin(self, other, '+');
}
complex - numeric → new_complex click to toggle source

Returns the difference of self and numeric:

Complex.rect(2, 3)  - Complex.rect(2, 3)  # => (0+0i)
Complex.rect(900)   - Complex.rect(1)     # => (899+0i)
Complex.rect(-2, 9) - Complex.rect(-9, 2) # => (7+7i)
Complex.rect(9, 8)  - 4                   # => (5+8i)
Complex.rect(20, 9) - 9.8                 # => (10.2+9i)
VALUE
rb_complex_minus(VALUE self, VALUE other)
{
    if (RB_TYPE_P(other, T_COMPLEX)) {
        VALUE real, imag;

        get_dat2(self, other);

        real = f_sub(adat->real, bdat->real);
        imag = f_sub(adat->imag, bdat->imag);

        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_sub(dat->real, other), dat->imag);
    }
    return rb_num_coerce_bin(self, other, '-');
}
-complex → new_complex click to toggle source

Returns the negation of self, which is the negation of each of its parts:

-Complex.rect(1, 2)   # => (-1-2i)
-Complex.rect(-1, -2) # => (1+2i)
VALUE
rb_complex_uminus(VALUE self)
{
    get_dat1(self);
    return f_complex_new2(CLASS_OF(self),
                          f_negate(dat->real), f_negate(dat->imag));
}
complex / numeric → new_complex click to toggle source

Returns the quotient of self and numeric:

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

Returns:

  • self.real <=> object.real if both of the following are true:

    • self.imag == 0.

    • object.imag == 0. # Always true if object is numeric but not complex.

  • nil otherwise.

Examples:

Complex.rect(2) <=> 3                  # => -1
Complex.rect(2) <=> 2                  # => 0
Complex.rect(2) <=> 1                  # => 1
Complex.rect(2, 1) <=> 1               # => nil # self.imag not zero.
Complex.rect(1) <=> Complex.rect(1, 1) # => nil # object.imag not zero.
Complex.rect(1) <=> 'Foo'              # => nil # object.imag not defined.
static VALUE
nucomp_cmp(VALUE self, VALUE other)
{
    if (!k_numeric_p(other)) {
        return rb_num_coerce_cmp(self, other, idCmp);
    }
    if (!nucomp_real_p(self)) {
        return Qnil;
    }
    if (RB_TYPE_P(other, T_COMPLEX)) {
        if (nucomp_real_p(other)) {
            get_dat2(self, other);
            return rb_funcall(adat->real, idCmp, 1, bdat->real);
        }
    }
    else {
        get_dat1(self);
        if (f_real_p(other)) {
            return rb_funcall(dat->real, idCmp, 1, other);
        }
        else {
            return rb_num_coerce_cmp(dat->real, other, idCmp);
        }
    }
    return Qnil;
}
complex == object → true or false click to toggle source

Returns true if self.real == object.real and self.imag == object.imag:

Complex.rect(2, 3)  == Complex.rect(2.0, 3.0) # => true
static VALUE
nucomp_eqeq_p(VALUE self, VALUE other)
{
    if (RB_TYPE_P(other, T_COMPLEX)) {
        get_dat2(self, other);

        return RBOOL(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 RBOOL(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
    }
    return RBOOL(f_eqeq_p(other, self));
}
abs → float click to toggle source

Returns the absolute value (magnitude) for self; see polar coordinates:

Complex.polar(-1, 0).abs # => 1.0

If self was created with rectangular coordinates, the returned value is computed, and may be inexact:

Complex.rectangular(1, 1).abs # => 1.4142135623730951 # The square root of 2.
VALUE
rb_complex_abs(VALUE self)
{
    get_dat1(self);

    if (f_zero_p(dat->real)) {
        VALUE a = f_abs(dat->imag);
        if (RB_FLOAT_TYPE_P(dat->real) && !RB_FLOAT_TYPE_P(dat->imag))
            a = f_to_f(a);
        return a;
    }
    if (f_zero_p(dat->imag)) {
        VALUE a = f_abs(dat->real);
        if (!RB_FLOAT_TYPE_P(dat->real) && RB_FLOAT_TYPE_P(dat->imag))
            a = f_to_f(a);
        return a;
    }
    return rb_math_hypot(dat->real, dat->imag);
}
Also aliased as: magnitude
abs2 → float click to toggle source

Returns square of the absolute value (magnitude) for self; see polar coordinates:

Complex.polar(2, 2).abs2 # => 4.0

If self was created with rectangular coordinates, the returned value is computed, and may be inexact:

Complex.rectangular(1.0/3, 1.0/3).abs2 # => 0.2222222222222222
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()

Returns the argument (angle) for self in radians; see polar coordinates:

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

If self was created with rectangular coordinates, the returned value is computed, and may be inexact:

Complex.polar(1, 1.0/3).arg # => 0.33333333333333326
Alias for: arg
arg → float click to toggle source

Returns the argument (angle) for self in radians; see polar coordinates:

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

If self was created with rectangular coordinates, the returned value is computed, and may be inexact:

Complex.polar(1, 1.0/3).arg # => 0.33333333333333326
VALUE
rb_complex_arg(VALUE self)
{
    get_dat1(self);
    return rb_math_atan2(dat->imag, dat->real);
}
Also aliased as: angle, phase
conj → complex

Returns the conjugate of self, Complex.rect(self.imag, self.real):

Complex.rect(1, 2).conj # => (1-2i)
Alias for: conjugate
conjugate -> complex click to toggle source

Returns the conjugate of self, Complex.rect(self.imag, self.real):

Complex.rect(1, 2).conj # => (1-2i)
VALUE
rb_complex_conjugate(VALUE self)
{
    get_dat1(self);
    return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}
Also aliased as: conj
denominator → integer click to toggle source

Returns the denominator of self, which is the least common multiple of self.real.denominator and self.imag.denominator:

Complex.rect(Rational(1, 2), Rational(2, 3)).denominator # => 6

Note that n.denominator of a non-rational numeric is 1.

Related: Complex#numerator.

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

Returns Complex.rect(self.real/numeric, self.imag/numeric):

Complex.rect(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);
}
finite? → true or false click to toggle source

Returns true if both self.real.finite? and self.imag.finite? are true, false otherwise:

Complex.rect(1, 1).finite?               # => true
Complex.rect(Float::INFINITY, 0).finite? # => false

Related: Numeric#finite?, Float#finite?.

static VALUE
rb_complex_finite_p(VALUE self)
{
    get_dat1(self);

    return RBOOL(f_finite_p(dat->real) && f_finite_p(dat->imag));
}
hash → integer click to toggle source

Returns the integer hash value for self.

Two Complex objects created from the same values will have the same hash value (and will compare using eql?):

Complex.rect(1, 2).hash == Complex.rect(1, 2).hash # => true
static VALUE
nucomp_hash(VALUE self)
{
    return ST2FIX(rb_complex_hash(self));
}
imag → numeric

Returns the imaginary value for self:

Complex.rect(7).imag     # => 0
Complex.rect(9, -4).imag # => -4

If self was created with polar coordinates, the returned value is computed, and may be inexact:

Complex.polar(1, Math::PI/4).imag # => 0.7071067811865476 # Square root of 2.
Alias for: imaginary
imaginary -> numeric click to toggle source

Returns the imaginary value for self:

Complex.rect(7).imag     # => 0
Complex.rect(9, -4).imag # => -4

If self was created with polar coordinates, the returned value is computed, and may be inexact:

Complex.polar(1, Math::PI/4).imag # => 0.7071067811865476 # Square root of 2.
VALUE
rb_complex_imag(VALUE self)
{
    get_dat1(self);
    return dat->imag;
}
Also aliased as: imag
infinite? → 1 or nil click to toggle source

Returns 1 if either self.real.infinite? or self.imag.infinite? is true, nil otherwise:

Complex.rect(Float::INFINITY, 0).infinite? # => 1
Complex.rect(1, 1).infinite?               # => nil

Related: Numeric#infinite?, Float#infinite?.

static VALUE
rb_complex_infinite_p(VALUE self)
{
    get_dat1(self);

    if (!f_infinite_p(dat->real) && !f_infinite_p(dat->imag)) {
        return Qnil;
    }
    return ONE;
}
inspect → string click to toggle source

Returns a string representation of self:

Complex.rect(2).inspect                      # => "(2+0i)"
Complex.rect(-8, 6).inspect                  # => "(-8+6i)"
Complex.rect(0, Rational(1, 2)).inspect      # => "(0+(1/2)*i)"
Complex.rect(0, Float::INFINITY).inspect     # => "(0+Infinity*i)"
Complex.rect(Float::NAN, Float::NAN).inspect # => "(NaN+NaN*i)"
static VALUE
nucomp_inspect(VALUE self)
{
    VALUE s;

    s = rb_usascii_str_new2("(");
    f_format(self, s, rb_inspect);
    rb_str_cat2(s, ")");

    return s;
}
magnitude()

Returns the absolute value (magnitude) for self; see polar coordinates:

Complex.polar(-1, 0).abs # => 1.0

If self was created with rectangular coordinates, the returned value is computed, and may be inexact:

Complex.rectangular(1, 1).abs # => 1.4142135623730951 # The square root of 2.
Alias for: abs
numerator → new_complex click to toggle source

Returns the Complex object created from the numerators of the real and imaginary parts of self, after converting each part to the lowest common denominator of the two:

c = Complex.rect(Rational(2, 3), Rational(3, 4)) # => ((2/3)+(3/4)*i)
c.numerator                                      # => (8+9i)

In this example, the lowest common denominator of the two parts is 12; the two converted parts may be thought of as Rational(8, 12) and Rational(9, 12), whose numerators, respectively, are 8 and 9; so the returned value of c.numerator is Complex.rect(8, 9).

Related: Complex#denominator.

static VALUE
nucomp_numerator(VALUE self)
{
    VALUE cd;

    get_dat1(self);

    cd = nucomp_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()

Returns the argument (angle) for self in radians; see polar coordinates:

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

If self was created with rectangular coordinates, the returned value is computed, and may be inexact:

Complex.polar(1, 1.0/3).arg # => 0.33333333333333326
Alias for: arg
polar → array click to toggle source

Returns the array [self.abs, self.arg]:

Complex.polar(1, 2).polar # => [1.0, 2.0]

See Polar Coordinates.

If self was created with rectangular coordinates, the returned value is computed, and may be inexact:

Complex.rect(1, 1).polar # => [1.4142135623730951, 0.7853981633974483]
static VALUE
nucomp_polar(VALUE self)
{
    return rb_assoc_new(f_abs(self), f_arg(self));
}
complex / numeric → new_complex click to toggle source

Returns the quotient of self and numeric:

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

Returns a Rational object whose value is exactly or approximately equivalent to that of self.real.

With no argument epsilon given, returns a Rational object whose value is exactly equal to that of self.real.rationalize:

Complex.rect(1, 0).rationalize              # => (1/1)
Complex.rect(1, Rational(0, 1)).rationalize # => (1/1)
Complex.rect(3.14159, 0).rationalize        # => (314159/100000)

With argument epsilon given, returns a Rational object whose value is exactly or approximately equal to that of self.real to the given precision:

Complex.rect(3.14159, 0).rationalize(0.1)          # => (16/5)
Complex.rect(3.14159, 0).rationalize(0.01)         # => (22/7)
Complex.rect(3.14159, 0).rationalize(0.001)        # => (201/64)
Complex.rect(3.14159, 0).rationalize(0.0001)       # => (333/106)
Complex.rect(3.14159, 0).rationalize(0.00001)      # => (355/113)
Complex.rect(3.14159, 0).rationalize(0.000001)     # => (7433/2366)
Complex.rect(3.14159, 0).rationalize(0.0000001)    # => (9208/2931)
Complex.rect(3.14159, 0).rationalize(0.00000001)   # => (47460/15107)
Complex.rect(3.14159, 0).rationalize(0.000000001)  # => (76149/24239)
Complex.rect(3.14159, 0).rationalize(0.0000000001) # => (314159/100000)
Complex.rect(3.14159, 0).rationalize(0.0)          # => (3537115888337719/1125899906842624)

Related: Complex#to_r.

static VALUE
nucomp_rationalize(int argc, VALUE *argv, VALUE self)
{
    get_dat1(self);

    rb_check_arity(argc, 0, 1);

    if (!k_exact_zero_p(dat->imag)) {
       rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
                self);
    }
    return rb_funcallv(dat->real, id_rationalize, argc, argv);
}
real → numeric click to toggle source

Returns the real value for self:

Complex.rect(7).real     # => 7
Complex.rect(9, -4).real # => 9

If self was created with polar coordinates, the returned value is computed, and may be inexact:

Complex.polar(1, Math::PI/4).real # => 0.7071067811865476 # Square root of 2.
VALUE
rb_complex_real(VALUE self)
{
    get_dat1(self);
    return dat->real;
}
real? → false click to toggle source

Returns false; for compatibility with Numeric#real?.

static VALUE
nucomp_real_p_m(VALUE self)
{
    return Qfalse;
}
rect → array

Returns a new Complex object formed from the arguments, each of which must be an instance of Numeric, or an instance of one of its subclasses: Complex, Float, Integer, Rational; see Rectangular Coordinates:

Complex.rect(3)             # => (3+0i)
Complex.rect(3, Math::PI)   # => (3+3.141592653589793i)
Complex.rect(-3, -Math::PI) # => (-3-3.141592653589793i)

Complex.rectangular is an alias for Complex.rect.

Alias for: rectangular
rectangular -> array click to toggle source

Returns the array [self.real, self.imag]:

Complex.rect(1, 2).rect # => [1, 2]

See Rectangular Coordinates.

If self was created with polar coordinates, the returned value is computed, and may be inexact:

Complex.polar(1.0, 1.0).rect # => [0.5403023058681398, 0.8414709848078965]

Complex#rectangular is an alias for Complex#rect.

static VALUE
nucomp_rect(VALUE self)
{
    get_dat1(self);
    return rb_assoc_new(dat->real, dat->imag);
}
Also aliased as: rect, rect
to_c → self click to toggle source

Returns self.

static VALUE
nucomp_to_c(VALUE self)
{
    return self;
}
to_f → float click to toggle source

Returns the value of self.real as a Float, if possible:

Complex.rect(1, 0).to_f              # => 1.0
Complex.rect(1, Rational(0, 1)).to_f # => 1.0

Raises RangeError if self.imag is not exactly zero (either Integer(0) or Rational(0, n)).

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);
}
to_i → integer click to toggle source

Returns the value of self.real as an Integer, if possible:

Complex.rect(1, 0).to_i              # => 1
Complex.rect(1, Rational(0, 1)).to_i # => 1

Raises RangeError if self.imag is not exactly zero (either Integer(0) or Rational(0, n)).

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_r → rational click to toggle source

Returns the value of self.real as a Rational, if possible:

Complex.rect(1, 0).to_r              # => (1/1)
Complex.rect(1, Rational(0, 1)).to_r # => (1/1)
Complex.rect(1, 0.0).to_r            # => (1/1)

Raises RangeError if self.imag is not exactly zero (either Integer(0) or Rational(0, n)) and self.imag.to_r is not exactly zero.

Related: Complex#rationalize.

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

    if (RB_FLOAT_TYPE_P(dat->imag) && FLOAT_ZERO_P(dat->imag)) {
        /* Do nothing here */
    }
    else if (!k_exact_zero_p(dat->imag)) {
        VALUE imag = rb_check_convert_type_with_id(dat->imag, T_RATIONAL, "Rational", idTo_r);
        if (NIL_P(imag) || !k_exact_zero_p(imag)) {
            rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
                     self);
        }
    }
    return f_to_r(dat->real);
}
to_s → string click to toggle source

Returns a string representation of self:

Complex.rect(2).to_s                      # => "2+0i"
Complex.rect(-8, 6).to_s                  # => "-8+6i"
Complex.rect(0, Rational(1, 2)).to_s      # => "0+1/2i"
Complex.rect(0, Float::INFINITY).to_s     # => "0+Infinity*i"
Complex.rect(Float::NAN, Float::NAN).to_s # => "NaN+NaN*i"
static VALUE
nucomp_to_s(VALUE self)
{
    return f_format(self, rb_usascii_str_new2(""), rb_String);
}