In Files

  • complex.c

Complex

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, ::rect, ::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('1@2')       #=> (-0.4161468365471424+0.9092974268256817i)

0.3.to_c             #=> (0.3+0i)
'0.3-0.5i'.to_c      #=> (0.3-0.5i)
'2/3+3/4i'.to_c      #=> ((2/3)+(3/4)*i)
'1@2'.to_c           #=> (-0.4161468365471424+0.9092974268256817i)

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

Complex(1, 1) / 2    #=> ((1/2)+(1/2)*i)
Complex(1, 1) / 2.0  #=> (0.5+0.5i)

Constants

I

Public Class Methods

polar(p1, p2) click to toggle source
 
               static VALUE
nucomp_s_polar(VALUE klass, VALUE abs, VALUE arg)
{
    return f_complex_polar(klass, abs, arg);
}
            
rect(p1, p2 = v2) click to toggle 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:
        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);
}
            
rectangular(p1, p2 = v2) click to toggle 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:
        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

*(p1) click to toggle source
 
               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);
    }
    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, '*');
}
            
**(p1) click to toggle source
 
               static VALUE
nucomp_expt(VALUE self, VALUE other)
{
    if (k_exact_p(other) && f_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); /* good? */

    if (k_complex_p(other)) {
        VALUE a, r, theta, ore, oim, nr, ntheta;

        get_dat1(other);

        a = f_polar(self);
        r = RARRAY_PTR(a)[0];
        theta = RARRAY_PTR(a)[1];

        ore = dat->real;
        oim = dat->imag;
        nr = m_exp_bang(f_sub(f_mul(ore, m_log_bang(r)),
                              f_mul(oim, theta)));
        ntheta = f_add(f_mul(theta, ore), f_mul(oim, m_log_bang(r)));
        return f_complex_polar(CLASS_OF(self), nr, ntheta);
    }
    if (k_integer_p(other)) {
        if (f_gt_p(other, ZERO)) {
            VALUE x, z, n;

            x = self;
            z = x;
            n = f_sub(other, ONE);

            while (f_nonzero_p(n)) {
                VALUE a;

                while (a = f_divmod(n, TWO),
                       f_zero_p(RARRAY_PTR(a)[1])) {
                    get_dat1(x);

                    x = f_complex_new2(CLASS_OF(self),
                                       f_sub(f_mul(dat->real, dat->real),
                                             f_mul(dat->imag, dat->imag)),
                                       f_mul(f_mul(TWO, dat->real), dat->imag));
                    n = RARRAY_PTR(a)[0];
                }
                z = f_mul(z, x);
                n = f_sub(n, ONE);
            }
            return z;
        }
        return f_expt(f_div(f_to_r(ONE), self), f_negate(other));
    }
    if (k_numeric_p(other) && f_real_p(other)) {
        VALUE a, r, theta;

        a = f_polar(self);
        r = RARRAY_PTR(a)[0];
        theta = RARRAY_PTR(a)[1];
        return f_complex_polar(CLASS_OF(self), f_expt(r, other),
                              f_mul(theta, other));
    }
    return rb_num_coerce_bin(self, other, id_expt);
}
            
+(p1) click to toggle source
 
               static VALUE
nucomp_add(VALUE self, VALUE other)
{
    if (k_complex_p(other)) {
        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, '+');
}
            
-(p1) click to toggle source
 
               static VALUE
nucomp_sub(VALUE self, VALUE other)
{
    if (k_complex_p(other)) {
        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, '-');
}
            
-@() click to toggle source
 
               static VALUE
nucomp_negate(VALUE self)
{
  get_dat1(self);
  return f_complex_new2(CLASS_OF(self),
                        f_negate(dat->real), f_negate(dat->imag));
}
            
/(p1) click to toggle source
 
               static VALUE
nucomp_div(VALUE self, VALUE other)
{
    if (k_complex_p(other)) {
        get_dat2(self, other);

        if (TYPE(adat->real)  == T_FLOAT ||
            TYPE(adat->imag) == T_FLOAT ||
            TYPE(bdat->real)  == T_FLOAT ||
            TYPE(bdat->imag) == T_FLOAT) {
            VALUE magn = m_hypot(bdat->real, bdat->imag);
            VALUE tmp = f_complex_new_bang2(CLASS_OF(self),
                                            f_div(bdat->real, magn),
                                            f_div(bdat->imag, magn));
            return f_div(f_mul(self, f_conj(tmp)), magn);
        }
        return f_div(f_mul(self, f_conj(other)), f_abs2(other));
    }
    if (k_numeric_p(other) && f_real_p(other)) {
        get_dat1(self);

        return f_complex_new2(CLASS_OF(self),
                              f_div(dat->real, other),
                              f_div(dat->imag, other));
    }
    return rb_num_coerce_bin(self, other, '/');
}
            
==(p1) click to toggle source
 
               static VALUE
nucomp_equal_p(VALUE self, VALUE other)
{
    if (k_complex_p(other)) {
        get_dat2(self, other);

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

        return f_boolcast(f_equal_p(dat->real, other) && f_zero_p(dat->imag));
    }
    return f_equal_p(other, self);
}
            
abs() click to toggle source
 
               static VALUE
nucomp_abs(VALUE self)
{
    get_dat1(self);
    return m_hypot(dat->real, dat->imag);
}
            
abs2() click to toggle 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));
}
            
angle() click to toggle source
 
               static VALUE
nucomp_arg(VALUE self)
{
    get_dat1(self);
    return m_atan2_bang(dat->imag, dat->real);
}
            
arg() click to toggle source
 
               static VALUE
nucomp_arg(VALUE self)
{
    get_dat1(self);
    return m_atan2_bang(dat->imag, dat->real);
}
            
coerce(p1) click to toggle source
 
               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?() click to toggle source
 
               static VALUE
nucomp_true(VALUE self)
{
    return Qtrue;
}
            
conj() click to toggle source
 
               static VALUE
nucomp_conj(VALUE self)
{
    get_dat1(self);
    return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}
            
conjugate() click to toggle source
 
               static VALUE
nucomp_conj(VALUE self)
{
    get_dat1(self);
    return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}
            
denominator() click to toggle source
 
               static VALUE
nucomp_denominator(VALUE self)
{
    get_dat1(self);
    return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag));
}
            
eql?(p1) click to toggle source
 
               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_equal_p(self, other));

    }
    return Qfalse;
}
            
exact?() click to toggle source
 
               static VALUE
nucomp_exact_p(VALUE self)
{
    get_dat1(self);
    return f_boolcast(f_exact_p(dat->real) && f_exact_p(dat->imag));
}
            
fdiv(p1) click to toggle source
 
               static VALUE
nucomp_fdiv(VALUE self, VALUE other)
{
    get_dat1(self);

    return f_div(f_complex_new2(CLASS_OF(self),
                                f_to_f(dat->real),
                                f_to_f(dat->imag)), other);
}
            
hash() click to toggle source
 
               static VALUE
nucomp_hash(VALUE self)
{
    get_dat1(self);
    return f_xor(f_hash(dat->real), f_hash(dat->imag));
}
            
imag() click to toggle source
 
               static VALUE
nucomp_imag(VALUE self)
{
    get_dat1(self);
    return dat->imag;
}
            
imaginary() click to toggle source
 
               static VALUE
nucomp_imag(VALUE self)
{
    get_dat1(self);
    return dat->imag;
}
            
inexact?() click to toggle source
 
               static VALUE
nucomp_inexact_p(VALUE self)
{
    return f_boolcast(!nucomp_exact_p(self));
}
            
inspect() click to toggle source
 
               static VALUE
nucomp_inspect(VALUE self)
{
    VALUE s;

    s = rb_usascii_str_new2("(");
    rb_str_concat(s, nucomp_format(self, f_inspect));
    rb_str_cat2(s, ")");

    return s;
}
            
magnitude() click to toggle source
 
               static VALUE
nucomp_abs(VALUE self)
{
    get_dat1(self);
    return m_hypot(dat->real, dat->imag);
}
            
marshal_dump() click to toggle source
 
               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(p1) click to toggle source
 
               static VALUE
nucomp_marshal_load(VALUE self, VALUE a)
{
    get_dat1(self);
    dat->real = RARRAY_PTR(a)[0];
    dat->imag = RARRAY_PTR(a)[1];
    rb_copy_generic_ivar(self, a);
    return self;
}
            
numerator() click to toggle source
 
               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))));
}
            
phase() click to toggle source
 
               static VALUE
nucomp_arg(VALUE self)
{
    get_dat1(self);
    return m_atan2_bang(dat->imag, dat->real);
}
            
polar() click to toggle source
 
               static VALUE
nucomp_polar(VALUE self)
{
    return rb_assoc_new(f_abs(self), f_arg(self));
}
            
quo(p1) click to toggle source
 
               static VALUE
nucomp_div(VALUE self, VALUE other)
{
    if (k_complex_p(other)) {
        get_dat2(self, other);

        if (TYPE(adat->real)  == T_FLOAT ||
            TYPE(adat->imag) == T_FLOAT ||
            TYPE(bdat->real)  == T_FLOAT ||
            TYPE(bdat->imag) == T_FLOAT) {
            VALUE magn = m_hypot(bdat->real, bdat->imag);
            VALUE tmp = f_complex_new_bang2(CLASS_OF(self),
                                            f_div(bdat->real, magn),
                                            f_div(bdat->imag, magn));
            return f_div(f_mul(self, f_conj(tmp)), magn);
        }
        return f_div(f_mul(self, f_conj(other)), f_abs2(other));
    }
    if (k_numeric_p(other) && f_real_p(other)) {
        get_dat1(self);

        return f_complex_new2(CLASS_OF(self),
                              f_div(dat->real, other),
                              f_div(dat->imag, other));
    }
    return rb_num_coerce_bin(self, other, '/');
}
            
real() click to toggle source
 
               static VALUE
nucomp_real(VALUE self)
{
    get_dat1(self);
    return dat->real;
}
            
real?() click to toggle source
 
               static VALUE
nucomp_false(VALUE self)
{
    return Qfalse;
}
            
rect() click to toggle source
 
               static VALUE
nucomp_rect(VALUE self)
{
    get_dat1(self);
    return rb_assoc_new(dat->real, dat->imag);
}
            
rectangular() click to toggle source
 
               static VALUE
nucomp_rect(VALUE self)
{
    get_dat1(self);
    return rb_assoc_new(dat->real, dat->imag);
}
            
to_f() click to toggle source
 
               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));
    }
    return f_to_f(dat->real);
}
            
to_i() click to toggle source
 
               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));
    }
    return f_to_i(dat->real);
}
            
to_r() click to toggle source
 
               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));
    }
    return f_to_r(dat->real);
}
            
to_s() click to toggle source
 
               static VALUE
nucomp_to_s(VALUE self)
{
    return nucomp_format(self, f_to_s);
}
            
~() click to toggle source
 
               static VALUE
nucomp_conj(VALUE self)
{
    get_dat1(self);
    return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.

blog comments powered by Disqus