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)
Defined Under Namespace
Classes: compatible
Constant Summary collapse
- I =
The imaginary unit.
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? ⇒ Boolean
: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? ⇒ Boolean
:nodoc:.
-
#exact? ⇒ Boolean
: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? ⇒ Boolean
:nodoc:.
-
#inspect ⇒ String
Returns the value as a string for inspection.
-
#magnitude ⇒ Object
Returns the absolute part of its polar form.
-
#marshal_dump ⇒ Object
private
: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
Returns the value as a rational if possible (the imaginary part should be exactly zero).
-
#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_c ⇒ self
Returns self.
-
#to_f ⇒ Float
Returns the value as a float if possible (the imaginary part should be exactly zero).
-
#to_i ⇒ Integer
Returns the value as an integer if possible (the imaginary part should be exactly zero).
-
#to_r ⇒ Object
Returns the value as a rational if possible (the imaginary part should be exactly zero).
-
#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_int, #truncate, #zero?
Methods included from Comparable
Class Method Details
.polar(abs[, arg]) ⇒ Object
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 |
# File 'complex.c', line 617
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;
}
return f_complex_polar(klass, abs, arg);
}
|
.rect(real[, imag]) ⇒ Object .rectangular(real[, imag]) ⇒ Object
Returns a complex object which denotes the given rectangular form.
Complex.rectangular(1, 2) #=> (1+2i)
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
# File 'complex.c', line 440
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]) ⇒ Object .rectangular(real[, imag]) ⇒ Object
Returns a complex object which denotes the given rectangular form.
Complex.rectangular(1, 2) #=> (1+2i)
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
# File 'complex.c', line 440
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);
}
|
Instance Method Details
#*(numeric) ⇒ Object
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 |
# File 'complex.c', line 755
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, '*');
}
|
#**(numeric) ⇒ Object
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 |
# File 'complex.c', line 884
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 */
}
if (k_complex_p(other)) {
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 (k_fixnum_p(other)) {
if (f_gt_p(other, ZERO)) {
VALUE x, z;
long n;
x = self;
z = x;
n = FIX2LONG(other) - 1;
while (n) {
long q, r;
while (1) {
get_dat1(x);
q = n / 2;
r = n % 2;
if (r)
break;
x = nucomp_s_new_internal(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 = q;
}
z = f_mul(z, x);
n--;
}
return z;
}
return f_expt(f_reciprocal(self), f_negate(other));
}
if (k_numeric_p(other) && f_real_p(other)) {
VALUE r, theta;
if (k_bignum_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);
}
|
#+(numeric) ⇒ Object
719 720 721 722 723 |
# File 'complex.c', line 719
static VALUE
nucomp_add(VALUE self, VALUE other)
{
return f_addsub(self, other, f_add, '+');
}
|
#-(numeric) ⇒ Object
737 738 739 740 741 |
# File 'complex.c', line 737
static VALUE
nucomp_sub(VALUE self, VALUE other)
{
return f_addsub(self, other, f_sub, '-');
}
|
#- ⇒ Object
Returns negation of the value.
-Complex(1, 2) #=> (-1-2i)
676 677 678 679 680 681 682 |
# File 'complex.c', line 676
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
847 848 849 850 851 |
# File 'complex.c', line 847
static VALUE
nucomp_div(VALUE self, VALUE other)
{
return f_divide(self, other, f_quo, id_quo);
}
|
#==(object) ⇒ Boolean
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 |
# File 'complex.c', line 975
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));
}
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_eqeq_p(other, self);
}
|
#abs ⇒ Object #magnitude ⇒ Object
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 |
# File 'complex.c', line 1016
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;
}
if (f_zero_p(dat->imag)) {
VALUE a = f_abs(dat->real);
if (!k_float_p(dat->real) && k_float_p(dat->imag))
a = f_to_f(a);
return a;
}
return m_hypot(dat->real, dat->imag);
}
|
#abs2 ⇒ Object
1045 1046 1047 1048 1049 1050 1051 |
# File 'complex.c', line 1045
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
1063 1064 1065 1066 1067 1068 |
# File 'complex.c', line 1063
static VALUE
nucomp_arg(VALUE self)
{
get_dat1(self);
return m_atan2_bang(dat->imag, dat->real);
}
|
#arg ⇒ Float #angle ⇒ Float #phase ⇒ Float
1063 1064 1065 1066 1067 1068 |
# File 'complex.c', line 1063
static VALUE
nucomp_arg(VALUE self)
{
get_dat1(self);
return m_atan2_bang(dat->imag, dat->real);
}
|
#coerce ⇒ Object
:nodoc:
993 994 995 996 997 998 999 1000 1001 1002 1003 1004 |
# File 'complex.c', line 993
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 (RB_TYPE_P(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? ⇒ Boolean
:nodoc:
1118 1119 1120 1121 1122 |
# File 'complex.c', line 1118
static VALUE
nucomp_true(VALUE self)
{
return Qtrue;
}
|
#conj ⇒ Object #conjugate ⇒ Object
1109 1110 1111 1112 1113 1114 |
# File 'complex.c', line 1109
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.
Complex(1, 2).conjugate #=> (1-2i)
1109 1110 1111 1112 1113 1114 |
# File 'complex.c', line 1109
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.
1162 1163 1164 1165 1166 1167 |
# File 'complex.c', line 1162
static VALUE
nucomp_denominator(VALUE self)
{
get_dat1(self);
return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag));
}
|
#eql? ⇒ Boolean
:nodoc:
1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 |
# File 'complex.c', line 1219
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));
}
return Qfalse;
}
|
#exact? ⇒ Boolean
:nodoc:
1139 1140 1141 1142 1143 1144 |
# File 'complex.c', line 1139
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.
Complex(11, 22).fdiv(3) #=> (3.6666666666666665+7.333333333333333i)
863 864 865 866 867 |
# File 'complex.c', line 863
static VALUE
nucomp_fdiv(VALUE self, VALUE other)
{
return f_divide(self, other, f_fdiv, id_fdiv);
}
|
#hash ⇒ Object
:nodoc:
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 |
# File 'complex.c', line 1203
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
661 662 663 664 665 666 |
# File 'complex.c', line 661
static VALUE
nucomp_imag(VALUE self)
{
get_dat1(self);
return dat->imag;
}
|
#imag ⇒ Object #imaginary ⇒ Object
661 662 663 664 665 666 |
# File 'complex.c', line 661
static VALUE
nucomp_imag(VALUE self)
{
get_dat1(self);
return dat->imag;
}
|
#inexact? ⇒ Boolean
:nodoc:
1147 1148 1149 1150 1151 |
# File 'complex.c', line 1147
static VALUE
nucomp_inexact_p(VALUE self)
{
return f_boolcast(!nucomp_exact_p(self));
}
|
#inspect ⇒ String
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 |
# File 'complex.c', line 1303
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
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 |
# File 'complex.c', line 1016
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;
}
if (f_zero_p(dat->imag)) {
VALUE a = f_abs(dat->real);
if (!k_float_p(dat->real) && k_float_p(dat->imag))
a = f_to_f(a);
return a;
}
return m_hypot(dat->real, dat->imag);
}
|
#marshal_dump ⇒ Object (private)
:nodoc:
1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 |
# File 'complex.c', line 1335
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;
}
|
#numerator ⇒ Numeric
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.
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 |
# File 'complex.c', line 1187
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
1063 1064 1065 1066 1067 1068 |
# File 'complex.c', line 1063
static VALUE
nucomp_arg(VALUE self)
{
get_dat1(self);
return m_atan2_bang(dat->imag, dat->real);
}
|
#polar ⇒ Array
1094 1095 1096 1097 1098 |
# File 'complex.c', line 1094
static VALUE
nucomp_polar(VALUE self)
{
return rb_assoc_new(f_abs(self), f_arg(self));
}
|
#quo ⇒ Object
#rationalize([eps]) ⇒ Object
1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 |
# File 'complex.c', line 1476
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));
}
return rb_funcall2(dat->real, rb_intern("rationalize"), argc, argv);
}
|
#real ⇒ Object
644 645 646 647 648 649 |
# File 'complex.c', line 644
static VALUE
nucomp_real(VALUE self)
{
get_dat1(self);
return dat->real;
}
|
#real? ⇒ false
Returns false.
1131 1132 1133 1134 1135 |
# File 'complex.c', line 1131
static VALUE
nucomp_false(VALUE self)
{
return Qfalse;
}
|
#rect ⇒ Array #rectangular ⇒ Array
Returns an array; [cmp.real, cmp.imag].
Complex(1, 2).rectangular #=> [1, 2]
1079 1080 1081 1082 1083 1084 |
# File 'complex.c', line 1079
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].
Complex(1, 2).rectangular #=> [1, 2]
1079 1080 1081 1082 1083 1084 |
# File 'complex.c', line 1079
static VALUE
nucomp_rect(VALUE self)
{
get_dat1(self);
return rb_assoc_new(dat->real, dat->imag);
}
|
#to_c ⇒ self
1500 1501 1502 1503 1504 |
# File 'complex.c', line 1500
static VALUE
nucomp_to_c(VALUE self)
{
return self;
}
|
#to_f ⇒ Float
1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 |
# File 'complex.c', line 1424
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 ⇒ Integer
1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 |
# File 'complex.c', line 1400
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 ⇒ Object
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 |
# File 'complex.c', line 1450
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 ⇒ String
1285 1286 1287 1288 1289 |
# File 'complex.c', line 1285
static VALUE
nucomp_to_s(VALUE self)
{
return f_format(self, f_to_s);
}
|