Class: Complex

Inherits:
Numeric show all
Defined in:
complex.c

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.

Complex object can be created as literal, and also by using Kernel#Complex, Complex::rect, Complex::polar or to_c method.

2+1i                 #=> (2+1i)
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('[email protected]')       #=> (-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)
'[email protected]'.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

Instance Method Summary collapse

Methods inherited from Numeric

#%, #[email protected], #ceil, #clone, #div, #divmod, #dup, #floor, #i, #integer?, #modulo, #negative?, #nonzero?, #positive?, #remainder, #round, #singleton_method_added, #step, #to_int, #truncate, #zero?

Methods included from Comparable

#<, #<=, #>, #>=, #between?, #clamp

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)

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
# File 'complex.c', line 708

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);
	if (canonicalization) return abs;
	return nucomp_s_new_internal(klass, abs, ZERO);
      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)

499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
# File 'complex.c', line 499

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)

499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
# File 'complex.c', line 499

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

Performs multiplication.

Complex(2, 3)  * Complex(2, 3)   #=> (-5+12i)
Complex(900)   * Complex(1)      #=> (900+0i)
Complex(-2, 9) * Complex(-9, 2)  #=> (0-85i)
Complex(9, 8)  * 4               #=> (36+32i)
Complex(20, 9) * 9.8             #=> (196.0+88.2i)

881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
# File 'complex.c', line 881

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

#**(numeric) ⇒ Object

Performs exponentiation.

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

994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
# File 'complex.c', line 994

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

#+(numeric) ⇒ Object

Performs addition.

Complex(2, 3)  + Complex(2, 3)   #=> (4+6i)
Complex(900)   + Complex(1)      #=> (901+0i)
Complex(-2, 9) + Complex(-9, 2)  #=> (-11+11i)
Complex(9, 8)  + 4               #=> (13+8i)
Complex(20, 9) + 9.8             #=> (29.8+9i)

787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
# File 'complex.c', line 787

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

#-(numeric) ⇒ Object

Performs subtraction.

Complex(2, 3)  - Complex(2, 3)   #=> (0+0i)
Complex(900)   - Complex(1)      #=> (899+0i)
Complex(-2, 9) - Complex(-9, 2)  #=> (7+7i)
Complex(9, 8)  - 4               #=> (5+8i)
Complex(20, 9) - 9.8             #=> (10.2+9i)

821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
# File 'complex.c', line 821

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

#-Object

Returns negation of the value.

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

767
768
769
770
771
772
773
# File 'complex.c', line 767

VALUE
rb_complex_uminus(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.

Complex(2, 3)  / Complex(2, 3)   #=> ((1/1)+(0/1)*i)
Complex(900)   / Complex(1)      #=> ((900/1)+(0/1)*i)
Complex(-2, 9) / Complex(-9, 2)  #=> ((36/85)-(77/85)*i)
Complex(9, 8)  / 4               #=> ((9/4)+(2/1)*i)
Complex(20, 9) / 9.8             #=> (2.0408163265306123+0.9183673469387754i)

957
958
959
960
961
# File 'complex.c', line 957

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

#<=>(object) ⇒ 0, ...

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)   #=> nil
Complex(2, 3)  <=> 1               #=> nil
Complex(2)     <=> 1               #=> 1
Complex(2)     <=> 2               #=> 0
Complex(2)     <=> 3               #=> -1

1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
# File 'complex.c', line 1130

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

#==(object) ⇒ Boolean

Returns true if cmp equals object numerically.

Complex(2, 3)  == Complex(2, 3)   #=> true
Complex(5)     == 5               #=> true
Complex(0)     == 0.0             #=> true
Complex('1/3') == 0.33            #=> false
Complex('1/2') == '1/2'           #=> false

1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
# File 'complex.c', line 1092

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

#absObject #magnitudeObject

Returns the absolute part of its polar form.

Complex(-1).abs         #=> 1
Complex(3.0, -4.0).abs  #=> 5.0

1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
# File 'complex.c', line 1170

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

#abs2Object

Returns square of the absolute value.

Complex(-1).abs2         #=> 1
Complex(3.0, -4.0).abs2  #=> 25.0

1199
1200
1201
1202
1203
1204
1205
# File 'complex.c', line 1199

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

#argFloat #angleFloat #phaseFloat

Returns the angle part of its polar form.

Complex.polar(3, Math::PI/2).arg  #=> 1.5707963267948966

1217
1218
1219
1220
1221
1222
# File 'complex.c', line 1217

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

#argFloat #angleFloat #phaseFloat

Returns the angle part of its polar form.

Complex.polar(3, Math::PI/2).arg  #=> 1.5707963267948966

1217
1218
1219
1220
1221
1222
# File 'complex.c', line 1217

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

#coerce(other) ⇒ Object

:nodoc:


1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
# File 'complex.c', line 1147

static VALUE
nucomp_coerce(VALUE self, VALUE other)
{
    if (RB_TYPE_P(other, T_COMPLEX))
	return rb_assoc_new(other, self);
    if (k_numeric_p(other) && f_real_p(other))
        return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self), other), self);

    rb_raise(rb_eTypeError, "%"PRIsVALUE" can't be coerced into %"PRIsVALUE,
	     rb_obj_class(other), rb_obj_class(self));
    return Qnil;
}

#conjObject #conjugateObject

Returns the complex conjugate.

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

1263
1264
1265
1266
1267
1268
# File 'complex.c', line 1263

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

#conjObject #conjugateObject

Returns the complex conjugate.

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

1263
1264
1265
1266
1267
1268
# File 'complex.c', line 1263

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

#denominatorInteger

Returns the denominator (lcm of both denominator - real and imag).

See numerator.


1291
1292
1293
1294
1295
1296
# File 'complex.c', line 1291

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

#eql?(other) ⇒ Boolean

:nodoc:


1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
# File 'complex.c', line 1348

static VALUE
nucomp_eql_p(VALUE self, VALUE other)
{
    if (RB_TYPE_P(other, T_COMPLEX)) {
	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;
}

#fdiv(numeric) ⇒ Object

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

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

973
974
975
976
977
# File 'complex.c', line 973

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

#finite?Boolean

Returns true if cmp's real and imaginary parts are both finite numbers, otherwise returns false.


1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
# File 'complex.c', line 1450

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

#hashObject

:nodoc:


1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
# File 'complex.c', line 1332

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 ST2FIX(v);
}

#imagObject #imaginaryObject

Returns the imaginary part.

Complex(7).imaginary      #=> 0
Complex(9, -4).imaginary  #=> -4

752
753
754
755
756
757
# File 'complex.c', line 752

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

#imagObject #imaginaryObject

Returns the imaginary part.

Complex(7).imaginary      #=> 0
Complex(9, -4).imaginary  #=> -4

752
753
754
755
756
757
# File 'complex.c', line 752

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

#infinite?nil, 1

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

For example:

   (1+1i).infinite?                   #=> nil
   (Float::INFINITY + 1i).infinite?   #=> 1

1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
# File 'complex.c', line 1473

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

#inspectString

Returns the value as a string for inspection.

Complex(2).inspect                       #=> "(2+0i)"
Complex('-8/6').inspect                  #=> "((-4/3)+0i)"
Complex('1/2i').inspect                  #=> "(0+(1/2)*i)"
Complex(0, Float::INFINITY).inspect      #=> "(0+Infinity*i)"
Complex(Float::NAN, Float::NAN).inspect  #=> "(NaN+NaN*i)"

1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
# File 'complex.c', line 1429

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

#absObject #magnitudeObject

Returns the absolute part of its polar form.

Complex(-1).abs         #=> 1
Complex(3.0, -4.0).abs  #=> 5.0

1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
# File 'complex.c', line 1170

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

#marshal_dumpObject (private)

:nodoc:


1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
# File 'complex.c', line 1505

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

#numeratorNumeric

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.


1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
# File 'complex.c', line 1316

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

#argFloat #angleFloat #phaseFloat

Returns the angle part of its polar form.

Complex.polar(3, Math::PI/2).arg  #=> 1.5707963267948966

1217
1218
1219
1220
1221
1222
# File 'complex.c', line 1217

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

#polarArray

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

Complex(1, 2).polar  #=> [2.23606797749979, 1.1071487177940904]

1248
1249
1250
1251
1252
# File 'complex.c', line 1248

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

#quoObject

#rationalize([eps]) ⇒ Object

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

Complex(1.0/3, 0).rationalize  #=> (1/3)
Complex(1, 0.0).rationalize    # RangeError
Complex(1, 2).rationalize      # RangeError

See to_r.


1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
# File 'complex.c', line 1660

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

#realObject

Returns the real part.

Complex(7).real      #=> 7
Complex(9, -4).real  #=> 9

735
736
737
738
739
740
# File 'complex.c', line 735

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

#Complex(1) ⇒ false #Complex(1, 2) ⇒ false

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


1277
1278
1279
1280
1281
# File 'complex.c', line 1277

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

#rectArray #rectangularArray

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

Complex(1, 2).rectangular  #=> [1, 2]

1233
1234
1235
1236
1237
1238
# File 'complex.c', line 1233

static VALUE
nucomp_rect(VALUE self)
{
    get_dat1(self);
    return rb_assoc_new(dat->real, dat->imag);
}

#rectArray #rectangularArray

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

Complex(1, 2).rectangular  #=> [1, 2]

1233
1234
1235
1236
1237
1238
# File 'complex.c', line 1233

static VALUE
nucomp_rect(VALUE self)
{
    get_dat1(self);
    return rb_assoc_new(dat->real, dat->imag);
}

#to_cself

Returns self.

Complex(2).to_c      #=> (2+0i)
Complex(-8, 6).to_c  #=> (-8+6i)

1683
1684
1685
1686
1687
# File 'complex.c', line 1683

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

#to_fFloat

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

Complex(1, 0).to_f    #=> 1.0
Complex(1, 0.0).to_f  # RangeError
Complex(1, 2).to_f    # RangeError

1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
# File 'complex.c', line 1610

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_iInteger

Returns the value as an integer if possible (the imaginary part should be exactly zero).

Complex(1, 0).to_i    #=> 1
Complex(1, 0.0).to_i  # RangeError
Complex(1, 2).to_i    # RangeError

1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
# File 'complex.c', line 1587

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_rObject

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

Complex(1, 0).to_r    #=> (1/1)
Complex(1, 0.0).to_r  # RangeError
Complex(1, 2).to_r    # RangeError

See rationalize.


1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
# File 'complex.c', line 1635

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_sString

Returns the value as a string.

Complex(2).to_s                       #=> "2+0i"
Complex('-8/6').to_s                  #=> "-4/3+0i"
Complex('1/2i').to_s                  #=> "0+1/2i"
Complex(0, Float::INFINITY).to_s      #=> "0+Infinity*i"
Complex(Float::NAN, Float::NAN).to_s  #=> "NaN+NaN*i"

1411
1412
1413
1414
1415
# File 'complex.c', line 1411

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