Class: Complex
Overview
A complex number can be represented as a paired real number with imaginary unit; a+bi. Where a is real part, b is imaginary part and i is imaginary unit. Real a equals complex a+0i mathematically.
In ruby, you can create complex object with Complex, Complex::rect, Complex::polar or to_c method.
Complex(1) #=> (1+0i)
Complex(2, 3) #=> (2+3i)
Complex.polar(2, 3) #=> (-1.9799849932008908+0.2822400161197344i)
3.to_c #=> (3+0i)
You can also create complex object from floating-point numbers or strings.
Complex(0.3) #=> (0.3+0i)
Complex('0.3-0.5i') #=> (0.3-0.5i)
Complex('2/3+3/4i') #=> ((2/3)+(3/4)*i)
Complex('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)
Constant Summary collapse
- I =
f_complex_new_bang2(rb_cComplex, ZERO, ONE)
Class Method Summary collapse
-
.polar(abs[, arg]) ⇒ Object
Returns a complex object which denotes the given polar form.
-
.rect ⇒ Object
Returns a complex object which denotes the given rectangular form.
-
.rectangular ⇒ Object
Returns a complex object which denotes the given rectangular form.
Instance Method Summary collapse
-
#*(numeric) ⇒ Object
Performs multiplication.
-
#**(numeric) ⇒ Object
Performs exponentiation.
-
#+(numeric) ⇒ Object
Performs addition.
-
#-(numeric) ⇒ Object
Performs subtraction.
-
#- ⇒ Object
Returns negation of the value.
-
#/ ⇒ Object
Performs division.
-
#==(object) ⇒ Boolean
Returns true if cmp equals object numerically.
-
#abs ⇒ Object
Returns the absolute part of its polar form.
-
#abs2 ⇒ Object
Returns square of the absolute value.
-
#angle ⇒ Object
Returns the angle part of its polar form.
-
#arg ⇒ Object
Returns the angle part of its polar form.
-
#coerce ⇒ Object
:nodoc:.
-
#complex? ⇒ Object
:nodoc:.
-
#conj ⇒ Object
Returns the complex conjugate.
-
#conjugate ⇒ Object
Returns the complex conjugate.
-
#denominator ⇒ Integer
Returns the denominator (lcm of both denominator - real and imag).
-
#eql? ⇒ Object
:nodoc:.
-
#exact? ⇒ Object
:nodoc:.
-
#fdiv(numeric) ⇒ Object
Performs division as each part is a float, never returns a float.
-
#hash ⇒ Object
:nodoc:.
-
#imag ⇒ Object
Returns the imaginary part.
-
#imaginary ⇒ Object
Returns the imaginary part.
-
#inexact? ⇒ Object
:nodoc:.
-
#inspect ⇒ String
Returns the value as a string for inspection.
-
#magnitude ⇒ Object
Returns the absolute part of its polar form.
-
#marshal_dump ⇒ Object
:nodoc:.
-
#marshal_load ⇒ Object
:nodoc:.
-
#numerator ⇒ Numeric
Returns the numerator.
-
#phase ⇒ Object
Returns the angle part of its polar form.
-
#polar ⇒ Array
Returns an array; [cmp.abs, cmp.arg].
- #quo ⇒ Object
-
#rationalize([eps]) ⇒ Object
If the imaginary part is exactly 0, returns the real part as a Rational, otherwise a RangeError is raised.
-
#real ⇒ Object
Returns the real part.
-
#real? ⇒ false
Returns false.
-
#rect ⇒ Object
Returns an array; [cmp.real, cmp.imag].
-
#rectangular ⇒ Object
Returns an array; [cmp.real, cmp.imag].
-
#to_f ⇒ Float
Returns the value as a float if possible.
-
#to_i ⇒ Integer
Returns the value as an integer if possible.
-
#to_r ⇒ Object
If the imaginary part is exactly 0, returns the real part as a Rational, otherwise a RangeError is raised.
-
#to_s ⇒ String
Returns the value as a string.
-
#~ ⇒ Object
Returns the complex conjugate.
Methods inherited from Numeric
#%, #+@, #<=>, #ceil, #div, #divmod, #floor, #i, #initialize_copy, #integer?, #modulo, #nonzero?, #remainder, #round, #singleton_method_added, #step, #to_c, #to_int, #truncate, #zero?
Methods included from Comparable
Class Method Details
.polar(abs[, arg]) ⇒ Object
Returns a complex object which denotes the given polar form.
Complex.polar(3, 0) #=> (3.0+0.0i)
Complex.polar(3, Math::PI/2) #=> (1.836909530733566e-16+3.0i)
Complex.polar(3, Math::PI) #=> (-3.0+3.673819061467132e-16i)
Complex.polar(3, -Math::PI/2) #=> (1.836909530733566e-16-3.0i)
|
# File 'complex.c'
static VALUE
nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
{
VALUE abs, arg;
switch (rb_scan_args(argc, argv, "11", &abs, &arg)) {
case 1:
nucomp_real_check(abs);
arg = ZERO;
break;
default:
nucomp_real_check(abs);
nucomp_real_check(arg);
break;
}
|
.rect(real[, imag]) ⇒ Object .rectangular(real[, imag]) ⇒ Object
Returns a complex object which denotes the given rectangular form.
|
# File 'complex.c'
static VALUE
nucomp_s_new(int argc, VALUE *argv, VALUE klass)
{
VALUE real, imag;
switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
case 1:
nucomp_real_check(real);
imag = ZERO;
break;
default:
nucomp_real_check(real);
nucomp_real_check(imag);
break;
}
|
.rect(real[, imag]) ⇒ Object .rectangular(real[, imag]) ⇒ Object
Returns a complex object which denotes the given rectangular form.
|
# File 'complex.c'
static VALUE
nucomp_s_new(int argc, VALUE *argv, VALUE klass)
{
VALUE real, imag;
switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
case 1:
nucomp_real_check(real);
imag = ZERO;
break;
default:
nucomp_real_check(real);
nucomp_real_check(imag);
break;
}
|
Instance Method Details
#*(numeric) ⇒ Object
Performs multiplication.
|
# File 'complex.c'
static VALUE
nucomp_mul(VALUE self, VALUE other)
{
if (k_complex_p(other)) {
VALUE real, imag;
get_dat2(self, other);
real = f_sub(f_mul(adat->real, bdat->real),
f_mul(adat->imag, bdat->imag));
imag = f_add(f_mul(adat->real, bdat->imag),
f_mul(adat->imag, bdat->real));
return f_complex_new2(CLASS_OF(self), real, imag);
}
|
#**(numeric) ⇒ Object
Performs exponentiation.
For example:
Complex('i') ** 2 #=> (-1+0i)
Complex(-8) ** Rational(1,3) #=> (1.0000000000000002+1.7320508075688772i)
|
# File 'complex.c'
static VALUE
nucomp_expt(VALUE self, VALUE other)
{
if (k_numeric_p(other) && k_exact_zero_p(other))
return f_complex_new_bang1(CLASS_OF(self), ONE);
if (k_rational_p(other) && f_one_p(f_denominator(other)))
other = f_numerator(other); /* c14n */
if (k_complex_p(other)) {
get_dat1(other);
if (k_exact_zero_p(dat->imag))
other = dat->real; /* c14n */
}
|
#+(numeric) ⇒ Object
Performs addition.
|
# File 'complex.c'
static VALUE
nucomp_add(VALUE self, VALUE other)
{
return f_addsub(self, other, f_add, '+');
}
|
#-(numeric) ⇒ Object
Performs subtraction.
|
# File 'complex.c'
static VALUE
nucomp_sub(VALUE self, VALUE other)
{
return f_addsub(self, other, f_sub, '-');
}
|
#- ⇒ Object
Returns negation of the value.
|
# File 'complex.c'
static VALUE
nucomp_negate(VALUE self)
{
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
f_negate(dat->real), f_negate(dat->imag));
}
|
#/(numeric) ⇒ Object #quo(numeric) ⇒ Object
Performs division.
For example:
Complex(10.0) / 3 #=> (3.3333333333333335+(0/1)*i)
Complex(10) / 3 #=> ((10/3)+(0/1)*i) # not (3+0i)
|
# File 'complex.c'
static VALUE
nucomp_div(VALUE self, VALUE other)
{
return f_divide(self, other, f_quo, id_quo);
}
|
#==(object) ⇒ Boolean
Returns true if cmp equals object numerically.
|
# File 'complex.c'
static VALUE
nucomp_eqeq_p(VALUE self, VALUE other)
{
if (k_complex_p(other)) {
get_dat2(self, other);
return f_boolcast(f_eqeq_p(adat->real, bdat->real) &&
f_eqeq_p(adat->imag, bdat->imag));
}
|
#abs ⇒ Object #magnitude ⇒ Object
Returns the absolute part of its polar form.
|
# File 'complex.c'
static VALUE
nucomp_abs(VALUE self)
{
get_dat1(self);
if (f_zero_p(dat->real)) {
VALUE a = f_abs(dat->imag);
if (k_float_p(dat->real) && !k_float_p(dat->imag))
a = f_to_f(a);
return a;
}
|
#abs2 ⇒ Object
Returns square of the absolute value.
|
# File 'complex.c'
static VALUE
nucomp_abs2(VALUE self)
{
get_dat1(self);
return f_add(f_mul(dat->real, dat->real),
f_mul(dat->imag, dat->imag));
}
|
#arg ⇒ Float #angle ⇒ Float #phase ⇒ Float
Returns the angle part of its polar form.
Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
|
# File 'complex.c'
static VALUE
nucomp_arg(VALUE self)
{
get_dat1(self);
return m_atan2_bang(dat->imag, dat->real);
}
|
#arg ⇒ Float #angle ⇒ Float #phase ⇒ Float
Returns the angle part of its polar form.
Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
|
# File 'complex.c'
static VALUE
nucomp_arg(VALUE self)
{
get_dat1(self);
return m_atan2_bang(dat->imag, dat->real);
}
|
#coerce ⇒ Object
:nodoc:
|
# File 'complex.c'
static VALUE
nucomp_coerce(VALUE self, VALUE other)
{
if (k_numeric_p(other) && f_real_p(other))
return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self), other), self);
if (TYPE(other) == T_COMPLEX)
return rb_assoc_new(other, self);
rb_raise(rb_eTypeError, "%s can't be coerced into %s",
rb_obj_classname(other), rb_obj_classname(self));
return Qnil;
}
|
#complex? ⇒ Object
:nodoc:
|
# File 'complex.c'
static VALUE
nucomp_true(VALUE self)
{
return Qtrue;
}
|
#conj ⇒ Object #conjugate ⇒ Object
Returns the complex conjugate.
|
# File 'complex.c'
static VALUE
nucomp_conj(VALUE self)
{
get_dat1(self);
return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}
|
#conj ⇒ Object #conjugate ⇒ Object
Returns the complex conjugate.
|
# File 'complex.c'
static VALUE
nucomp_conj(VALUE self)
{
get_dat1(self);
return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}
|
#denominator ⇒ Integer
Returns the denominator (lcm of both denominator - real and imag).
See numerator.
|
# File 'complex.c'
static VALUE
nucomp_denominator(VALUE self)
{
get_dat1(self);
return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag));
}
|
#eql? ⇒ Object
:nodoc:
|
# File 'complex.c'
static VALUE
nucomp_eql_p(VALUE self, VALUE other)
{
if (k_complex_p(other)) {
get_dat2(self, other);
return f_boolcast((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) &&
(CLASS_OF(adat->imag) == CLASS_OF(bdat->imag)) &&
f_eqeq_p(self, other));
}
|
#exact? ⇒ Object
:nodoc:
|
# File 'complex.c'
static VALUE
nucomp_exact_p(VALUE self)
{
get_dat1(self);
return f_boolcast(k_exact_p(dat->real) && k_exact_p(dat->imag));
}
|
#fdiv(numeric) ⇒ Object
Performs division as each part is a float, never returns a float.
For example:
Complex(11,22).fdiv(3) #=> (3.6666666666666665+7.333333333333333i)
|
# File 'complex.c'
static VALUE
nucomp_fdiv(VALUE self, VALUE other)
{
return f_divide(self, other, f_fdiv, id_fdiv);
}
|
#hash ⇒ Object
:nodoc:
|
# File 'complex.c'
static VALUE
nucomp_hash(VALUE self)
{
st_index_t v, h[2];
VALUE n;
get_dat1(self);
n = rb_hash(dat->real);
h[0] = NUM2LONG(n);
n = rb_hash(dat->imag);
h[1] = NUM2LONG(n);
v = rb_memhash(h, sizeof(h));
return LONG2FIX(v);
}
|
#imag ⇒ Object #imaginary ⇒ Object
Returns the imaginary part.
|
# File 'complex.c'
static VALUE
nucomp_imag(VALUE self)
{
get_dat1(self);
return dat->imag;
}
|
#imag ⇒ Object #imaginary ⇒ Object
Returns the imaginary part.
|
# File 'complex.c'
static VALUE
nucomp_imag(VALUE self)
{
get_dat1(self);
return dat->imag;
}
|
#inexact? ⇒ Object
:nodoc:
|
# File 'complex.c'
static VALUE
nucomp_inexact_p(VALUE self)
{
return f_boolcast(!nucomp_exact_p(self));
}
|
#inspect ⇒ String
Returns the value as a string for inspection.
|
# File 'complex.c'
static VALUE
nucomp_inspect(VALUE self)
{
VALUE s;
s = rb_usascii_str_new2("(");
rb_str_concat(s, f_format(self, f_inspect));
rb_str_cat2(s, ")");
return s;
}
|
#abs ⇒ Object #magnitude ⇒ Object
Returns the absolute part of its polar form.
|
# File 'complex.c'
static VALUE
nucomp_abs(VALUE self)
{
get_dat1(self);
if (f_zero_p(dat->real)) {
VALUE a = f_abs(dat->imag);
if (k_float_p(dat->real) && !k_float_p(dat->imag))
a = f_to_f(a);
return a;
}
|
#marshal_dump ⇒ Object
:nodoc:
|
# File 'complex.c'
static VALUE
nucomp_marshal_dump(VALUE self)
{
VALUE a;
get_dat1(self);
a = rb_assoc_new(dat->real, dat->imag);
rb_copy_generic_ivar(a, self);
return a;
}
|
#marshal_load ⇒ Object
:nodoc:
|
# File 'complex.c'
static VALUE
nucomp_marshal_load(VALUE self, VALUE a)
{
get_dat1(self);
Check_Type(a, T_ARRAY);
if (RARRAY_LEN(a) != 2)
rb_raise(rb_eArgError, "marshaled complex must have an array whose length is 2 but %ld", RARRAY_LEN(a));
dat->real = RARRAY_PTR(a)[0];
dat->imag = RARRAY_PTR(a)[1];
rb_copy_generic_ivar(self, a);
return self;
}
|
#numerator ⇒ Numeric
Returns the numerator.
For example:
1 2 3+4i <- numerator
- + -i -> ----
2 3 6 <- denominator
c = Complex('1/2+2/3i') #=> ((1/2)+(2/3)*i)
n = c.numerator #=> (3+4i)
d = c.denominator #=> 6
n / d #=> ((1/2)+(2/3)*i)
Complex(Rational(n.real, d), Rational(n.imag, d))
#=> ((1/2)+(2/3)*i)
See denominator.
|
# File 'complex.c'
static VALUE
nucomp_numerator(VALUE self)
{
VALUE cd;
get_dat1(self);
cd = f_denominator(self);
return f_complex_new2(CLASS_OF(self),
f_mul(f_numerator(dat->real),
f_div(cd, f_denominator(dat->real))),
f_mul(f_numerator(dat->imag),
f_div(cd, f_denominator(dat->imag))));
}
|
#arg ⇒ Float #angle ⇒ Float #phase ⇒ Float
Returns the angle part of its polar form.
Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
|
# File 'complex.c'
static VALUE
nucomp_arg(VALUE self)
{
get_dat1(self);
return m_atan2_bang(dat->imag, dat->real);
}
|
#polar ⇒ Array
Returns an array; [cmp.abs, cmp.arg].
|
# File 'complex.c'
static VALUE
nucomp_polar(VALUE self)
{
return rb_assoc_new(f_abs(self), f_arg(self));
}
|
#quo ⇒ Object
#rationalize([eps]) ⇒ Object
If the imaginary part is exactly 0, returns the real part as a Rational, otherwise a RangeError is raised.
|
# File 'complex.c'
static VALUE
nucomp_rationalize(int argc, VALUE *argv, VALUE self)
{
get_dat1(self);
rb_scan_args(argc, argv, "01", NULL);
if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
VALUE s = f_to_s(self);
rb_raise(rb_eRangeError, "can't convert %s into Rational",
StringValuePtr(s));
}
|
#real ⇒ Object
Returns the real part.
|
# File 'complex.c'
static VALUE
nucomp_real(VALUE self)
{
get_dat1(self);
return dat->real;
}
|
#real? ⇒ false
Returns false.
|
# File 'complex.c'
static VALUE
nucomp_false(VALUE self)
{
return Qfalse;
}
|
#rect ⇒ Array #rectangular ⇒ Array
Returns an array; [cmp.real, cmp.imag].
|
# File 'complex.c'
static VALUE
nucomp_rect(VALUE self)
{
get_dat1(self);
return rb_assoc_new(dat->real, dat->imag);
}
|
#rect ⇒ Array #rectangular ⇒ Array
Returns an array; [cmp.real, cmp.imag].
|
# File 'complex.c'
static VALUE
nucomp_rect(VALUE self)
{
get_dat1(self);
return rb_assoc_new(dat->real, dat->imag);
}
|
#to_f ⇒ Float
Returns the value as a float if possible.
|
# File 'complex.c'
static VALUE
nucomp_to_f(VALUE self)
{
get_dat1(self);
if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
VALUE s = f_to_s(self);
rb_raise(rb_eRangeError, "can't convert %s into Float",
StringValuePtr(s));
}
|
#to_i ⇒ Integer
Returns the value as an integer if possible.
|
# File 'complex.c'
static VALUE
nucomp_to_i(VALUE self)
{
get_dat1(self);
if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
VALUE s = f_to_s(self);
rb_raise(rb_eRangeError, "can't convert %s into Integer",
StringValuePtr(s));
}
|
#to_r ⇒ Object
If the imaginary part is exactly 0, returns the real part as a Rational, otherwise a RangeError is raised.
|
# File 'complex.c'
static VALUE
nucomp_to_r(VALUE self)
{
get_dat1(self);
if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
VALUE s = f_to_s(self);
rb_raise(rb_eRangeError, "can't convert %s into Rational",
StringValuePtr(s));
}
|
#to_s ⇒ String
Returns the value as a string.
|
# File 'complex.c'
static VALUE
nucomp_to_s(VALUE self)
{
return f_format(self, f_to_s);
}
|