class Complex - Documentation for Ruby 4.0
Description: class Complex: i>. en.
Keywords: ruby,class,Complex

🔍

No recent searches

# 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:

- A complex literal.

- Method `Complex.rect`.

- Method `Kernel#Complex`, either with numeric arguments or with certain string arguments.

- Method `String#to_c`, for certain strings.

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:

- Separately, with methods `Complex#real` and `Complex#imaginary`.

- Together, with method `Complex#rect`.

The corresponding (computed) polar values may be retrieved:

- Separately, with methods `Complex#abs` and `Complex#arg`.

- Together, with method `Complex#polar`.

## 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:

- Method `Complex.polar`.

- Method `Kernel#Complex`, with certain string arguments.

- Method `String#to_c`, for certain strings.

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:

- Separately, with methods `Complex#abs` and `Complex#arg`.

- Together, with method `Complex#polar`.

The corresponding (computed) rectangular values may be retrieved:

- Separately, with methods `Complex#real` and `Complex#imag`.

- Together, with method `Complex#rect`.

## 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

json_create (object)
Source

    # File ext/json/lib/json/add/complex.rb, line 9
    def self.json_create(object)
      Complex(object['r'], object['i'])
    end

See `as_json`.

polar(abs, arg = 0) → complex
Source

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

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)

rect(real, imag = 0) → complex
Source

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

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.

rect(real, imag = 0) → complex
Source

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

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.

### Public Instance Methods

self * other → numeric
Source

    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, '*');
    }

Returns the numeric product of `self` and `other`:

    Complex.rect(9, 8)  * 4                   # => (36+32i)
    Complex.rect(20, 9) * 9.8                 # => (196.0+88.2i)
    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)  * Rational(2, 3)      # => ((6/1)+(16/3)*i)

self ** exponent → complex
Source

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

Returns `self` raised to the power `exponent`:

    Complex.rect(0, 1) ** 2            # => (-1+0i)
    Complex.rect(-8) ** Rational(1, 3) # => (1.0000000000000002+1.7320508075688772i)

self + other → numeric
Source

    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, '+');
    }

Returns the sum of `self` and `other`:

    Complex(1, 2) + 0  # => (1+2i)
    Complex(1, 2) + 1  # => (2+2i)
    Complex(1, 2) + -1 # => (0+2i)

    Complex(1, 2) + 1.0  # => (2.0+2i)

    Complex(1, 2) + Complex(2, 1)     # => (3+3i)
    Complex(1, 2) + Complex(2.0, 1.0) # => (3.0+3.0i)

    Complex(1, 2) + Rational(1, 1) # => ((2/1)+2i)
    Complex(1, 2) + Rational(1, 2) # => ((3/2)+2i)

For a computation involving Floats, the result may be inexact (see `Float#+`):

    Complex(1, 2) + 3.14 # => (4.140000000000001+2i)

self - other → complex
Source

    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, '-');
    }

Returns the difference of `self` and `other`:

    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)

-self → complex
Source

    VALUE
    rb_complex_uminus(VALUE self)
    {
        get_dat1(self);
        return f_complex_new2(CLASS_OF(self),
                              f_negate(dat->real), f_negate(dat->imag));
    }

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

    -Complex.rect(1, 2)   # => (-1-2i)
    -Complex.rect(-1, -2) # => (1+2i)

self / other → complex
Source

    VALUE
    rb_complex_div(VALUE self, VALUE other)
    {
        return f_divide(self, other, f_quo, id_quo);
    }

Returns the quotient of `self` and `other`:

    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)

self <=> other → -1, 0, 1, or nil
Source

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

Compares `self` and `other`.

Returns:

- `self.real <=> other.real` if both of the following are true:

  - `self.imag == 0`.

  - `other.imag == 0` (always true if `other` 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.

Class Complex includes module `Comparable`, each of whose methods uses `Complex#<=>` for comparison.

complex == object → true or false
Source

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

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

    Complex.rect(2, 3)  == Complex.rect(2.0, 3.0) # => true

abs → float
Source

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

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.

Also aliased as: magnitude
abs2 → float
Source

    static VALUE
    nucomp_abs2(VALUE self)
    {
        get_dat1(self);
        return f_add(f_mul(dat->real, dat->real),
                     f_mul(dat->imag, dat->imag));
    }

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

angle
Alias for: arg
arg → float
Source

    VALUE
    rb_complex_arg(VALUE self)
    {
        get_dat1(self);
        return rb_math_atan2(dat->imag, dat->real);
    }

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

Also aliased as: angle, phase
as_json (*)
Source

    # File ext/json/lib/json/add/complex.rb, line 29
    def as_json(*)
      {
        JSON.create_id => self.class.name,
        'r'            => real,
        'i'            => imag,
      }
    end

Methods `Complex#as_json` and `Complex.json_create` may be used to serialize and deserialize a Complex object; see `Marshal`.

Method `Complex#as_json` serializes `self`, returning a 2-element hash representing `self`:

    require 'json/add/complex'
    x = Complex(2).as_json      # => {"json_class"=>"Complex", "r"=>2, "i"=>0}
    y = Complex(2.0, 4).as_json # => {"json_class"=>"Complex", "r"=>2.0, "i"=>4}

Method `JSON.create` deserializes such a hash, returning a Complex object:

    Complex.json_create(x) # => (2+0i)
    Complex.json_create(y) # => (2.0+4i)

conj → complex

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

    Complex.rect(1, 2).conj # => (1-2i)

Alias for: conjugate
conjugate
Source

    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
Source

    static VALUE
    nucomp_denominator(VALUE self)
    {
        get_dat1(self);
        return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag));
    }

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

fdiv(numeric) → new_complex
Source

    static VALUE
    nucomp_fdiv(VALUE self, VALUE other)
    {
        return f_divide(self, other, f_fdiv, id_fdiv);
    }

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

    Complex.rect(11, 22).fdiv(3) # => (3.6666666666666665+7.333333333333333i)

finite? → true or false
Source

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

        return RBOOL(f_finite_p(dat->real) && f_finite_p(dat->imag));
    }

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

hash → integer
Source

    static VALUE
    nucomp_hash(VALUE self)
    {
        return ST2FIX(rb_complex_hash(self));
    }

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

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
Source

    VALUE
    rb_complex_imag(VALUE self)
    {
        get_dat1(self);
        return dat->imag;
    }

Also aliased as: imag
infinite? → 1 or nil
Source

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

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

inspect → string
Source

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

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

magnitude
Alias for: abs
numerator → new_complex
Source

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

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

phase
Alias for: arg
polar → array
Source

    static VALUE
    nucomp_polar(VALUE self)
    {
        return rb_assoc_new(f_abs(self), f_arg(self));
    }

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]

self / other → complex
Source

    VALUE
    rb_complex_div(VALUE self, VALUE other)
    {
        return f_divide(self, other, f_quo, id_quo);
    }

Returns the quotient of `self` and `other`:

    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)

rationalize(epsilon = nil) → rational
Source

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

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

real → numeric
Source

    VALUE
    rb_complex_real(VALUE self)
    {
        get_dat1(self);
        return dat->real;
    }

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.

real? → false
Source

    static VALUE
    nucomp_real_p_m(VALUE self)
    {
        return Qfalse;
    }

Returns `false`; for compatibility with `Numeric#real?`.

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
Source

    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
Source

    static VALUE
    nucomp_to_c(VALUE self)
    {
        return self;
    }

Returns `self`.

to_f → float
Source

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

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

to_i → integer
Source

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

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

to_json (*args)
Source

    # File ext/json/lib/json/add/complex.rb, line 48
    def to_json(*args)
      as_json.to_json(*args)
    end

Returns a `JSON` string representing `self`:

    require 'json/add/complex'
    puts Complex(2).to_json
    puts Complex(2.0, 4).to_json

Output:

    {"json_class":"Complex","r":2,"i":0}
    {"json_class":"Complex","r":2.0,"i":4}

to_r → rational
Source

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

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

to_s → string
Source

    static VALUE
    nucomp_to_s(VALUE self)
    {
        return f_format(self, rb_usascii_str_new2(""), rb_String);
    }

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"