# Complex

#####

declaration
Complex

MathLib.Complex is the MathLib implementation of complex numbers.

There are two ways of defining complex numbers:

- Two numbers representing the real and the complex part.
- MathLib.Complex.polar(abs, arg)

#### Simple example:

    // Create the complex number 1 + 2i
    var c = new MathLib.Complex(1, 2);

    var Complex = (function () {
    function Complex(re, im) {
        if (typeof im === "undefined") { im = 0; }
        this.type = 'complex';
        if (MathLib.isNaN(re) || MathLib.isNaN(im)) {
            this.re = NaN;
            this.im = NaN;
        } else if (!MathLib.isFinite(re) || !MathLib.isFinite(im)) {
            this.re = Infinity;
            this.im = Infinity;
        } else {
            this.re = re;
            this.im = im;
        }
    }

# abs

#####

method
Complex.prototype.abs() → number

Returns the absolute value of the number.

    Complex.prototype.abs = function () {
        return MathLib.hypot(this.re, this.im);
    };

# arccos

#####

method
Complex.prototype.arccos() → Complex

Returns the inverse cosine of the number.

    Complex.prototype.arccos = function () {
        return MathLib.minus(Math.PI / 2, this.arcsin());
    };

# arccot

#####

method
Complex.prototype.arccot() → Complex

Returns the inverse cotangent of the number.

    Complex.prototype.arccot = function () {
        if (this.isZero()) {
            return new MathLib.Complex(MathLib.sign(1 / this.re) * Math.PI / 2, -this.im);
        }
        return this.inverse().arctan();
    };

# arccsc

#####

method
Complex.prototype.arccsc() → Complex

Returns the inverse cosecant of the number

    Complex.prototype.arccsc = function () {
        // arccsc(0) = ComplexInfinity not ComplexNaN
        if (this.isZero()) {
            return new MathLib.Complex(Infinity);
        }

        return this.inverse().arcsin();
    };

# arcsec

#####

method
Complex.prototype.arcsec() → Complex

Returns the inverse secant of the number

    Complex.prototype.arcsec = function () {
        // arcsec(0) = ComplexInfinity not ComplexNaN
        if (this.isZero()) {
            return new MathLib.Complex(Infinity);
        }

        return this.inverse().arccos();
    };

# arcsin

#####

method
Complex.prototype.arcsin() → Complex

Returns the inverse sine of the number

    Complex.prototype.arcsin = function () {
        var a = this.re, b = this.im, aa = a * a, bb = b * b, sqrt = Math.sqrt(Math.pow(aa + bb - 1, 2) + 4 * bb), sgn = function (x) {
            if (x > 0) {
                return 1;
            }
            if (x < 0) {
                return -1;
            }
            if (1 / x === Infinity) {
                return 1;
            }
            if (1 / x === -Infinity) {
                return -1;
            }
        };

        if (a === Infinity) {
            return new MathLib.Complex(Infinity);
        }

        return new MathLib.Complex(sgn(a) / 2 * MathLib.arccos(sqrt - (aa + bb)), sgn(b) / 2 * MathLib.arcosh(sqrt + (aa + bb)));
    };

# arctan

#####

method
Complex.prototype.arctan() → Complex

Returns the inverse tangent of the number

    Complex.prototype.arctan = function () {
        var res, iz = new MathLib.Complex(-this.im, this.re);

        if (this.isZero()) {
            return new MathLib.Complex(this.re, this.im);
        }

        res = MathLib.times(new MathLib.Complex(0, -0.5), MathLib.plus(1, iz).divide(MathLib.minus(1, iz)).ln());

        // Correct some values on the axis imaginary axis.
        // TODO: Are this all the wrong values?
        if (MathLib.isNegZero(this.re) && res.re !== Infinity && (this.im < 0 || this.im > 1)) {
            res.re = -res.re;
        }

        return res;
    };

# arg

#####

method
Complex.prototype.arg() → number

Returns the argument (= the angle) of the complex number

    Complex.prototype.arg = function () {
        if (this.re === Infinity) {
            return NaN;
        }
        return Math.atan2(this.im, this.re);
    };

# artanh

#####

method
Complex.prototype.artanh() → Complex

Returns the inverse hyperbolic tangent of the number

    Complex.prototype.artanh = function () {
        if (this.isZero()) {
            return new MathLib.Complex(this.re, this.im);
        }

        if (this.re === Infinity) {
            return new MathLib.Complex(NaN);
        }

        return MathLib.times(0.5, MathLib.minus(MathLib.ln(MathLib.plus(1, this)), MathLib.ln(MathLib.minus(1, this))));
    };

# compare

#####

method
Complex.prototype.compare() → number

Compares two complex numbers

    Complex.prototype.compare = function (x) {
        var a = MathLib.sign(this.abs() - x.abs());

        if (MathLib.isNaN(this.re)) {
            if (MathLib.isNaN(x.re)) {
                return 0;
            }
            return -1;
        }

        if (this.re === Infinity) {
            if (x.re === Infinity) {
                return 0;
            }
            return 1;
        }

        return a ? a : MathLib.sign(this.arg() - x.arg());
    };

# conjugate

#####

method
Complex.prototype.conjugate() → Complex

Calculates the conjugate of a complex number

    Complex.prototype.conjugate = function () {
        return new MathLib.Complex(this.re, MathLib.negative(this.im));
    };

# copy

#####

method
Complex.prototype.copy() → Complex

Copies the complex number

    Complex.prototype.copy = function () {
        return new MathLib.Complex(MathLib.copy(this.re), MathLib.copy(this.im));
    };

# cos

#####

method
Complex.prototype.cos() → Complex

Calculates the cosine of a complex number

    Complex.prototype.cos = function () {
        return new MathLib.Complex(MathLib.cos(this.re) * MathLib.cosh(this.im), -MathLib.sin(this.re) * MathLib.sinh(this.im));
    };

# cosh

#####

method
Complex.prototype.cosh() → Complex

Calculates the hyperbolic cosine of a complex number

    Complex.prototype.cosh = function () {
        return new MathLib.Complex(MathLib.cos(this.im) * MathLib.cosh(this.re), MathLib.sin(this.im) * MathLib.sinh(this.re));
    };

# cot

#####

method
Complex.prototype.cot() → Complex

Calculates the cotangent of a complex number

    Complex.prototype.cot = function () {
        var aa = 2 * this.re, bb = 2 * this.im, d = MathLib.cos(aa) - MathLib.cosh(bb);

        if (this.isZero()) {
            return new MathLib.Complex(Infinity);
        }

        return new MathLib.Complex(-MathLib.sin(aa) / d, MathLib.sinh(bb) / d);
    };

# coth

#####

method
Complex.prototype.coth() → Complex

Calculates the hyperbolic cotangent of a complex number

    Complex.prototype.coth = function () {
        var aa = 2 * this.re, bb = 2 * this.im, d = MathLib.cosh(aa) - MathLib.cos(bb);

        if (this.isZero()) {
            return new MathLib.Complex(Infinity);
        }

        return new MathLib.Complex(MathLib.sinh(aa) / d, -MathLib.sin(bb) / d);
    };

# csc

#####

method
Complex.prototype.csc() → Complex

Calculates the cosecant of a complex number

    Complex.prototype.csc = function () {
        var a = this.re, b = this.im, d = MathLib.cos(2 * a) - MathLib.cosh(2 * b);

        if (this.isZero()) {
            return new MathLib.Complex(Infinity);
        }

        return new MathLib.Complex(-2 * MathLib.sin(a) * MathLib.cosh(b) / d, 2 * MathLib.cos(a) * MathLib.sinh(b) / d);
    };

# csch

#####

method
Complex.prototype.csch() → Complex

Calculates the hyperbolic cosecant of a complex number

    Complex.prototype.csch = function () {
        var a = this.re, b = this.im, d = MathLib.cosh(2 * a) - MathLib.cos(2 * b);

        if (this.isZero()) {
            return new MathLib.Complex(Infinity);
        }

        return new MathLib.Complex(2 * MathLib.sinh(a) * MathLib.cos(b) / d, -2 * MathLib.cosh(a) * MathLib.sin(b) / d);
    };

# divide

#####

method
Complex.prototype.divide() → Complex

Option name | Type | Description
--- | --- | ---
divisor | number Complex | The divisor

Divides a complex number by an other

    Complex.prototype.divide = function (divisor) {
        return this.times(MathLib.inverse(divisor));
    };

# exp

#####

method
Complex.prototype.exp() → Complex

Evaluates the exponential function with a complex argument

    Complex.prototype.exp = function () {
        return new MathLib.Complex(MathLib.exp(this.re) * MathLib.cos(this.im), MathLib.exp(this.re) * MathLib.sin(this.im));
    };

# inverse

#####

method
Complex.prototype.inverse() → Complex

Calculates the inverse of a complex number

    Complex.prototype.inverse = function () {
        var d = MathLib.plus(MathLib.pow(this.re, 2), MathLib.pow(this.im, 2));

        if (this.isZero()) {
            return new MathLib.Complex(Infinity);
        }

        if (this.re === Infinity) {
            return new MathLib.Complex(0);
        }

        return new MathLib.Complex(MathLib.divide(this.re, d), MathLib.divide(MathLib.negative(this.im), d));
    };

# isEqual

#####

method
Complex.prototype.isEqual() → boolean

Option name | Type | Description
--- | --- | ---
number | Complex number Rational | The number to be compared

Determines if the complex number is equal to another number.

    Complex.prototype.isEqual = function (number) {
        if (typeof number === 'number') {
            return MathLib.isEqual(this.re, number) && MathLib.isZero(this.im);
        }
        if (number.type === 'complex') {
            return MathLib.isEqual(this.re, number.re) && MathLib.isEqual(this.im, number.im);
        }
        return false;
    };

# isFinite

#####

method
Complex.prototype.isFinite() → boolean

Determines if the complex number is finite.

    Complex.prototype.isFinite = function () {
        return MathLib.isFinite(this.re);
    };

# isZero

#####

method
Complex.prototype.isZero() → boolean

Determines if the complex number is equal to 0.

    Complex.prototype.isZero = function () {
        return MathLib.isZero(this.re) && MathLib.isZero(this.im);
    };

# ln

#####

method
Complex.prototype.ln() → Complex

Evaluates the natural logarithm with complex arguments

    Complex.prototype.ln = function () {
        if (this.re === Infinity) {
            return new MathLib.Complex(Infinity);
        }
        return new MathLib.Complex(MathLib.ln(this.abs()), this.arg());
    };

# minus

#####

method
Complex.prototype.minus() → Complex

Option name | Type | Description
--- | --- | ---
subtrahend | number Complex | The subtrahend

Calculates the difference of two complex numbers

    Complex.prototype.minus = function (subtrahend) {
        return this.plus(MathLib.negative(subtrahend));
    };

# negative

#####

method
Complex.prototype.negative() → Complex

Calculates the negative of the complex number

    Complex.prototype.negative = function () {
        return new MathLib.Complex(MathLib.negative(this.re), MathLib.negative(this.im));
    };

# plus

#####

method
Complex.prototype.plus() → Complex

Option name | Type | Description
--- | --- | ---
summand | number Complex Rational | The number to be added

Add complex numbers

    Complex.prototype.plus = function (summand) {
        if (summand.type === 'complex') {
            return new MathLib.Complex(MathLib.plus(this.re, summand.re), MathLib.plus(this.im, summand.im));
        } else if (summand.type === 'rational') {
            summand = summand.toNumber();
        }
        if (typeof summand === 'number') {
            return new MathLib.Complex(MathLib.plus(this.re, summand), this.im);
        }
    };

# pow

#####

method
Complex.prototype.pow() → Complex

Option name | Type | Description
--- | --- | ---
c | numeric | The power to which the complex number should be raised

Calculates the complex number raised to some power

    Complex.prototype.pow = function (c) {
        var re, im, abs, arg;

        if (MathLib.type(c) === 'complex') {
            re = c.re;
            im = c.im;
            abs = this.abs();
            arg = this.arg();

            // Fixes inf^(2+5i) = inf and 0^(2+5i) = 0
            if ((this.isZero() || this.re === Infinity) && !(c.isZero() || c.re === Infinity || MathLib.isNaN(c.re))) {
                return new MathLib.Complex(this.re, this.im);
            }

            return MathLib.Complex.polar(MathLib.times(MathLib.pow(abs, re), MathLib.exp(MathLib.negative(MathLib.times(im, arg)))), MathLib.plus(MathLib.times(re, arg), MathLib.times(im, MathLib.ln(abs))));
        } else {
            // The naive pow method has some rounding errrors. For example
            // (2+5i)^3 = -142.00000000000006-64.99999999999999i
            // instead of -142-65i which are errors of magnitude around 1e-14.
            // This error increases quickly for increasing exponents.
            // (2+5i)^21 has an error of 5.8 in the real part
            // return MathLib.Complex.polar(MathLib.pow(abs, c), MathLib.times(arg, c));
            // The following algorithm uses a different approach for integer exponents,
            // where it yields exact results.
            // Non integer exponents are evaluated using the naive approach.
            // TODO: Improve the algorithm.
            var i, int = MathLib.floor(Math.abs(c)), res = new MathLib.Complex(1), power = this, bin = int.toString(2);

            // If the exponent is not an integer we use the naive approach
            if (c % 1) {
                abs = this.abs();
                arg = this.arg();
                return MathLib.Complex.polar(MathLib.pow(abs, c), MathLib.times(arg, c));
            }

            // The imaginary part of (2+5i)^-0 should be -0 not +0.
            if (MathLib.isZero(c)) {
                return new MathLib.Complex(1, c);
            }

            for (i = bin.length - 1; i >= 0; i--) {
                if (bin[i] === '1') {
                    res = MathLib.times(res, power);
                }
                power = MathLib.times(power, power);
            }

            if (c < 0) {
                res = res.inverse();
            }

            return res;
        }
    };

# sec

#####

method
Complex.prototype.sec() → Complex

Calculates the secant of a complex number

    Complex.prototype.sec = function () {
        var a = this.re, b = this.im, d = MathLib.cos(2 * a) + MathLib.cosh(2 * b);

        return new MathLib.Complex(2 * MathLib.cos(a) * MathLib.cosh(b) / d, 2 * MathLib.sin(a) * MathLib.sinh(b) / d);
    };

# sech

#####

method
Complex.prototype.sech() → Complex

Calculates the hyperbolic secant of a complex number

    Complex.prototype.sech = function () {
        var a = this.re, b = this.im, d = MathLib.cosh(2 * a) + MathLib.cos(2 * b);

        return new MathLib.Complex(2 * MathLib.cosh(a) * MathLib.cos(b) / d, -2 * MathLib.sinh(a) * MathLib.sin(b) / d);
    };

# sign

#####

method
Complex.prototype.sign() → Complex

Calculates the signum of a complex number

    Complex.prototype.sign = function () {
        if (this.isZero() || MathLib.isNaN(this.re)) {
            return this;
        } else if (this.re === Infinity) {
            return new MathLib.Complex(NaN);
        }
        return MathLib.Complex.polar(1, this.arg());
    };

# sin

#####

method
Complex.prototype.sin() → Complex

Calculates the sine of a complex number

    Complex.prototype.sin = function () {
        return new MathLib.Complex(MathLib.sin(this.re) * MathLib.cosh(this.im), MathLib.cos(this.re) * MathLib.sinh(this.im));
    };

# sinh

#####

method
Complex.prototype.sinh() → Complex

Calculates the hyperbolic sine of a complex number

    Complex.prototype.sinh = function () {
        return new MathLib.Complex(MathLib.cos(this.im) * MathLib.sinh(this.re), MathLib.sin(this.im) * MathLib.cosh(this.re));
    };

# sqrt

#####

method
Complex.prototype.sqrt() → Complex

Takes the square root of a complex number

    Complex.prototype.sqrt = function () {
        return MathLib.Complex.polar(Math.sqrt(this.abs()), this.arg() / 2);
    };

# tan

#####

method
Complex.prototype.tan() → Complex

Calculates the tangent of a complex number

    Complex.prototype.tan = function () {
        var aa = 2 * this.re, bb = 2 * this.im, d = MathLib.cos(aa) + MathLib.cosh(bb);

        return new MathLib.Complex(MathLib.sin(aa) / d, MathLib.sinh(bb) / d);
    };

# tanh

#####

method
Complex.prototype.tanh() → Complex

Calculates the hyperbolic tangent of a complex number

    Complex.prototype.tanh = function () {
        var aa = 2 * this.re, bb = 2 * this.im, d = MathLib.cosh(aa) + MathLib.cos(bb);

        return new MathLib.Complex(MathLib.sinh(aa) / d, MathLib.sin(bb) / d);
    };

# times

#####

method
Complex.prototype.times() → Complex

Option name | Type | Description
--- | --- | ---
factor | Complex number Rational | The number to be multiplied

Multiplies complex numbers

    Complex.prototype.times = function (factor) {
        if (factor.type === 'complex') {
            if (this.re === Infinity) {
                if (factor.isZero() || MathLib.isNaN(factor.re)) {
                    return new MathLib.Complex(NaN);
                } else {
                    return new MathLib.Complex(Infinity);
                }
            }

            if (factor.re === Infinity) {
                if (this.isZero() || MathLib.isNaN(this.re)) {
                    return new MathLib.Complex(NaN);
                } else {
                    return new MathLib.Complex(Infinity);
                }
            }

            return new MathLib.Complex(MathLib.minus(MathLib.times(this.re, factor.re), MathLib.times(this.im, factor.im)), MathLib.plus(MathLib.times(this.re, factor.im), MathLib.times(this.im, factor.re)));
        } else if (factor.type === 'rational') {
            factor = factor.toNumber();
        }
        if (typeof factor === 'number') {
            return new MathLib.Complex(MathLib.times(this.re, factor), MathLib.times(this.im, factor));
        }
    };

# toContentMathML

#####

method
Complex.prototype.toContentMathML() → string

Returns the content MathML representation of the number

    Complex.prototype.toContentMathML = function () {
        if (!this.isFinite()) {
            return '<csymbol cd="nums1">' + (this.re === Infinity ? 'infinity' : 'NaN') + '</csymbol>';
        }

        return '<apply><plus />' + MathLib.toContentMathML(this.re) + '<apply><times />' + MathLib.toContentMathML(this.im) + '<imaginaryi /></apply></apply>';
    };

# toLaTeX

#####

method
Complex.prototype.toLaTeX() → string

Returns the LaTeX representation of the complex number

    Complex.prototype.toLaTeX = function () {
        var str = '', reFlag = false;

        if (!this.isFinite()) {
            return '\\text{Complex' + this.re + '}';
        }

        if (!MathLib.isZero(this.re)) {
            str = MathLib.toLaTeX(this.re);
            reFlag = true;
        }
        if (!MathLib.isZero(this.im)) {
            str += MathLib.toLaTeX(this.im, reFlag) + 'i';
        }
        if (str.length === 0) {
            str = '0';
        }
        return str;
    };

# toMathML

#####

method
Complex.prototype.toMathML() → string

Returns the (presentation) MathML representation of the number

    Complex.prototype.toMathML = function () {
        var str = '', reFlag = false;

        if (!this.isFinite()) {
            return '<mi>Complex' + this.re + '</mi>';
        }

        if (!MathLib.isZero(this.re)) {
            str = MathLib.toMathML(this.re);
            reFlag = true;
        }
        if (!MathLib.isZero(this.im)) {
            str += MathLib.toMathML(this.im, reFlag) + '<mo>&#x2062;</mo><mi>i</mi>';
        }
        if (str.length === 0) {
            str = '<mn>0</mn>';
        }
        return str;
    };

# toPoint

#####

method
Complex.prototype.toPoint() → Point

Interprets the complex number as point in the two dimensional plane

    Complex.prototype.toPoint = function () {
        if (this.re == Infinity || MathLib.isNaN(this.re)) {
            return new MathLib.Point([0, 0, 0]);
        }

        return new MathLib.Point([this.re, this.im, 1]);
    };

# toString

#####

method
Complex.prototype.toString() → string

Custom toString function

    Complex.prototype.toString = function () {
        var str = '';

        if (!this.isFinite()) {
            return 'Complex' + this.re;
        }

        if (!MathLib.isZero(this.re)) {
            str = MathLib.toString(this.re);
        }
        if (!MathLib.isZero(this.im)) {
            str += (this.im > 0 ? (str.length ? '+' : '') : '-') + MathLib.toString(Math.abs(this.im)) + 'i';
        }
        if (str.length === 0) {
            str = '0';
        }
        return str;
    };
    Complex.polar = function (abs, arg) {
        if (abs === Infinity) {
            return new MathLib.Complex(Infinity);
        }
        return new MathLib.Complex(abs * Math.cos(arg), abs * Math.sin(arg));
    };
    return Complex;
        })();
        MathLib.Complex = Complex;
    })(MathLib || (MathLib = {}));