class Complex - RDoc Documentation (original) (raw)

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, Complex::rect, Complex::polar or to_c method.

2+1i
Complex(1)
Complex(2, 3)
Complex.polar(2, 3)
3.to_c

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

Complex(0.3)
Complex('0.3-0.5i')
Complex('2/3+3/4i')
Complex('1@2')

0.3.to_c
'0.3-0.5i'.to_c
'2/3+3/4i'.to_c
'1@2'.to_c

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

Complex(1, 1) / 2
Complex(1, 1) / 2.0

Constants

I

The imaginary unit.

Public Class Methods

json_create(object) click to toggle source

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

def self.json_create(object) Complex(object['r'], object['i']) end

polar(abs[, arg]) → complex click to toggle source

Returns a complex object which denotes the given polar form.

Complex.polar(3, 0)
Complex.polar(3, Math::PI/2)
Complex.polar(3, Math::PI)
Complex.polar(3, -Math::PI/2)

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);
    return nucomp_s_new_internal(klass, abs, ZERO);
  default:
    nucomp_real_check(abs);
    nucomp_real_check(arg);
    break;
}
if (RB_TYPE_P(abs, T_COMPLEX)) {
    get_dat1(abs);
    abs = dat->real;
}
if (RB_TYPE_P(arg, T_COMPLEX)) {
    get_dat1(arg);
    arg = dat->real;
}
return f_complex_polar(klass, abs, arg);

}

rect(real[, imag]) → complex click to toggle source

rectangular(real[, imag]) → complex

Returns a complex object which denotes the given rectangular form.

Complex.rectangular(1, 2)

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

}

rect(real[, imag]) → complex click to toggle source

rectangular(real[, imag]) → complex

Returns a complex object which denotes the given rectangular form.

Complex.rectangular(1, 2)

static VALUE nucomp_s_new(int argc, VALUE *argv, VALUE klass) { VALUE real, imag;

switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
  case 1:
    nucomp_real_check(real);
    imag = ZERO;
    break;
  default:
    nucomp_real_check(real);
    nucomp_real_check(imag);
    break;
}

return nucomp_s_canonicalize_internal(klass, real, imag);

}

Public Instance Methods

cmp * numeric → complex click to toggle source

Performs multiplication.

Complex(2, 3) * Complex(2, 3)
Complex(900) * Complex(1)
Complex(-2, 9) * Complex(-9, 2)
Complex(9, 8) * 4
Complex(20, 9) * 9.8

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

}

cmp ** numeric → complex click to toggle source

Performs exponentiation.

Complex('i') ** 2
Complex(-8) ** Rational(1, 3)

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 (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_TYPE_P(other, T_BIGNUM))
        rb_warn("in a**b, b may be too big");

    r = f_abs(self);
    theta = f_arg(self);

    return f_complex_polar(CLASS_OF(self), f_expt(r, other),
                           f_mul(theta, other));
}
return rb_num_coerce_bin(self, other, id_expt);

}

cmp + numeric → complex click to toggle source

Performs addition.

Complex(2, 3) + Complex(2, 3)
Complex(900) + Complex(1)
Complex(-2, 9) + Complex(-9, 2)
Complex(9, 8) + 4
Complex(20, 9) + 9.8

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

}

cmp - numeric → complex click to toggle source

Performs subtraction.

Complex(2, 3) - Complex(2, 3)
Complex(900) - Complex(1)
Complex(-2, 9) - Complex(-9, 2)
Complex(9, 8) - 4
Complex(20, 9) - 9.8

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

}

-cmp → complex click to toggle source

Returns negation of the value.

-Complex(1, 2)

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

cmp / numeric → complex click to toggle source

quo(numeric) → complex

Performs division.

Complex(2, 3) / Complex(2, 3)
Complex(900) / Complex(1)
Complex(-2, 9) / Complex(-9, 2)
Complex(9, 8) / 4
Complex(20, 9) / 9.8

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

cmp <=> object → 0, 1, -1, or nil click to toggle source

If cmp's imaginary part is zero, and object is also a real number (or a Complex number where the imaginary part is zero), compare the real part of cmp to object. Otherwise, return nil.

Complex(2, 3) <=> Complex(2, 3)
Complex(2, 3) <=> 1
Complex(2) <=> 1
Complex(2) <=> 2
Complex(2) <=> 3

static VALUE nucomp_cmp(VALUE self, VALUE other) { if (nucomp_real_p(self) && k_numeric_p(other)) { if (RB_TYPE_P(other, T_COMPLEX) && nucomp_real_p(other)) { get_dat2(self, other); return rb_funcall(adat->real, idCmp, 1, bdat->real); } else if (f_real_p(other)) { get_dat1(self); return rb_funcall(dat->real, idCmp, 1, other); } } return Qnil; }

cmp == object → true or false click to toggle source

Returns true if cmp equals object numerically.

Complex(2, 3) == Complex(2, 3)
Complex(5) == 5
Complex(0) == 0.0
Complex('1/3') == 0.33
Complex('1/2') == '1/2'

static VALUE nucomp_eqeq_p(VALUE self, VALUE other) { if (RB_TYPE_P(other, T_COMPLEX)) { get_dat2(self, other);

    return f_boolcast(f_eqeq_p(adat->real, bdat->real) &&
                      f_eqeq_p(adat->imag, bdat->imag));
}
if (k_numeric_p(other) && f_real_p(other)) {
    get_dat1(self);

    return f_boolcast(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
}
return f_boolcast(f_eqeq_p(other, self));

}

abs → real click to toggle source

Returns the absolute part of its polar form.

Complex(-1).abs
Complex(3.0, -4.0).abs

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

}

abs2 → real click to toggle source

Returns square of the absolute value.

Complex(-1).abs2
Complex(3.0, -4.0).abs2

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

angle → float

Returns the angle part of its polar form.

Complex.polar(3, Math::PI/2).arg

Alias for: arg

arg → float click to toggle source

Returns the angle part of its polar form.

Complex.polar(3, Math::PI/2).arg

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

as_json(*) click to toggle source

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

def as_json(*) { JSON.create_id => self.class.name, 'r' => real, 'i' => imag, } end

conj → complex

Returns the complex conjugate.

Complex(1, 2).conjugate

Returns the complex conjugate.

Complex(1, 2).conjugate

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 (lcm of both denominator - real and imag).

See numerator.

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

fdiv(numeric) → complex click to toggle source

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

Complex(11, 22).fdiv(3)

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 cmp's real and imaginary parts are both finite numbers, otherwise returns false.

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

if (f_finite_p(dat->real) && f_finite_p(dat->imag)) {
    return Qtrue;
}
return Qfalse;

}

hash() click to toggle source

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

imag → real

Returns the imaginary part.

Complex(7).imaginary
Complex(9, -4).imaginary

Returns the imaginary part.

Complex(7).imaginary
Complex(9, -4).imaginary

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

Also aliased as: imag

infinite? → nil or 1 click to toggle source

Returns 1 if cmp's real or imaginary part is an infinite number, otherwise returns nil.

For example:

(1+1i).infinite?
(Float::INFINITY + 1i).infinite?

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

if (NIL_P(f_infinite_p(dat->real)) && NIL_P(f_infinite_p(dat->imag))) {
    return Qnil;
}
return ONE;

}

inspect → string click to toggle source

Returns the value as a string for inspection.

Complex(2).inspect
Complex('-8/6').inspect
Complex('1/2i').inspect
Complex(0, Float::INFINITY).inspect
Complex(Float::NAN, Float::NAN).inspect

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;

}

magnitude → real

Returns the absolute part of its polar form.

Complex(-1).abs
Complex(3.0, -4.0).abs

Alias for: abs

numerator → numeric click to toggle source

Returns the numerator.

1   2       3+4i  <-  numerator
- + -i  ->  ----
2   3        6    <-  denominator

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

See denominator.

static VALUE nucomp_numerator(VALUE self) { VALUE cd;

get_dat1(self);

cd = 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 → float

Returns the angle part of its polar form.

Complex.polar(3, Math::PI/2).arg

Alias for: arg

polar → array click to toggle source

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

Complex(1, 2).polar

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

cmp / numeric → complex click to toggle source

quo(numeric) → complex

Performs division.

Complex(2, 3) / Complex(2, 3)
Complex(900) / Complex(1)
Complex(-2, 9) / Complex(-9, 2)
Complex(9, 8) / 4
Complex(20, 9) / 9.8

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

rationalize([eps]) → rational click to toggle source

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

Complex(1.0/3, 0).rationalize
Complex(1, 0.0).rationalize
Complex(1, 2).rationalize

See 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 → real click to toggle source

Returns the real part.

Complex(7).real
Complex(9, -4).real

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

Complex(1).real? → false click to toggle source

Complex(1, 2).real? → false

Returns false, even if the complex number has no imaginary part.

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

rect → array

Returns a complex object which denotes the given rectangular form.

Complex.rectangular(1, 2)

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

Complex(1, 2).rectangular

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.

Complex(2).to_c
Complex(-8, 6).to_c

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

to_d → bigdecimal click to toggle source

to_d(precision) → bigdecimal

Returns the value as a BigDecimal.

The precision parameter is required for a rational complex number. This parameter is used to determine the number of significant digits for the result.

require 'bigdecimal' require 'bigdecimal/util'

Complex(0.1234567, 0).to_d(4)
Complex(Rational(22, 7), 0).to_d(3)

See also BigDecimal::new.

def to_d(*args) BigDecimal(self) unless self.imag.zero?

if args.length == 0 case self.real when Rational BigDecimal(self.real) end end self.real.to_d(*args) end

to_f → float click to toggle source

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

Complex(1, 0).to_f
Complex(1, 0.0).to_f
Complex(1, 2).to_f

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 as an integer if possible (the imaginary part should be exactly zero).

Complex(1, 0).to_i
Complex(1, 0.0).to_i
Complex(1, 2).to_i

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(*args) click to toggle source

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

def to_json(*args) as_json.to_json(*args) end

to_r → rational click to toggle source

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

Complex(1, 0).to_r
Complex(1, 0.0).to_r
Complex(1, 2).to_r

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

}

to_s → string click to toggle source

Returns the value as a string.

Complex(2).to_s
Complex('-8/6').to_s
Complex('1/2i').to_s
Complex(0, Float::INFINITY).to_s
Complex(Float::NAN, Float::NAN).to_s

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