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

# toContentMathML

#####

method
Complex.toContentMathML() → string

A content MathML string representation

    Complex.toContentMathML = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			if (options.strict) {
    				return '<csymbol cd="setname1">C</csymbol>';
    			}
    			return '<complexes/>';
    		};

# toLaTeX

#####

method
Complex.toLaTeX() → string

A LaTeX string representation

    Complex.toLaTeX = function () {
    			return 'Complex Field $\\mathbb{C}$';
    		};

# toMathML

#####

method
Complex.toMathML() → string

A presentation MathML string representation

    Complex.toMathML = function () {
    			return '<mrow><mtext>Complex Field</mtext><mi mathvariant="double-struck">C</mi></mrow>';
    		};

# toString

#####

method
Complex.toString() → string

Custom toString function

    Complex.toString = function () {
    			return 'Complex Field ℂ';
    		};

# 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 (new MathLib.Complex(Math.PI / 2, -0)).minus(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, one = new MathLib.Complex(1, -0), 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(one, iz).divide(MathLib.minus(one, 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 () {
    			var one = new MathLib.Complex(1, -0);

    			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(one.plus(this).ln(), one.minus(this).ln()));
    		};

# coerceTo

#####

method
Complex.prototype.coerceTo() → Rational number Complex

Coerces the complex number to some other data type

    Complex.prototype.coerceTo = function (type) {
    			if (type === 'complex') {
    				return this.copy();
    			}

    			if (this.im === 0) {
    				return MathLib.coerceTo(this.re, type);
    			}

else {
// TODO: coercion error
}

    };

# 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
--- | --- | ---
n | Integer Rational number Complex | The number to be compared

Determines if the complex number is equal to another number.

    Complex.prototype.isEqual = function (n) {
    			if (n.type !== 'complex') {
    				if (MathLib.isZero(this.im)) {
    					return MathLib.isEqual.apply(null, MathLib.coerce(this.re, n));
    				}
    				else {
    					return false;
    				}
    			}
    			else {
    				return MathLib.isEqual(this.re, n.re) && MathLib.isEqual(this.im, n.im);
    			}
    		};

# 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 | Integer Rational number Complex | The number to be added

Add complex numbers

    Complex.prototype.plus = function (summand) {
    			if (summand.type !== 'complex') {
    				return new MathLib.Complex(MathLib.plus.apply(null, MathLib.coerce(this.re, summand)), this.im);
    			}
    			else {
    				return new MathLib.Complex(MathLib.plus(this.re, summand.re), MathLib.plus(this.im, summand.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.coerceTo('number');
    			}
    			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

Option name | Type | Description
--- | --- | ---
[options] | object | - Optional options to style the output

Returns the LaTeX representation of the complex number

    Complex.prototype.toLaTeX = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			var str = '', reFlag = !MathLib.isZero(this.re);

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

    			if (!MathLib.isZero(this.im)) {
    				str += MathLib.toLaTeX(this.im, {base: options.base, baseSubscript: options.baseSubscript, sign: reFlag || options.sign}) + 'i';
    			}

    			if (reFlag || str.length === 0) {
    				str = MathLib.toLaTeX(this.re, options) + str;
    			}

    			return str;
    		};

# toMathML

#####

method
Complex.prototype.toMathML() → string

Option name | Type | Description
--- | --- | ---
[options] | object | - Optional options to style the output

Returns the (presentation) MathML representation of the number

    Complex.prototype.toMathML = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			var str = '', reFlag = !MathLib.isZero(this.re);

    			if (!this.isFinite()) {
    				return (options.sign ? '<mo>+</mo>' : '') + '<mi>Complex' + this.re + '</mi>';
    			}

    			if (!MathLib.isZero(this.im)) {
    				if (reFlag || options.sign) {
    					str += '<mo>' + MathLib.toString(this.im, {sign: true}).slice(0, 1) + '</mo><mrow>' + MathLib.toMathML(MathLib.abs(this.im), {base: options.base, baseSubscript: options.baseSubscript, sign: false}) + '<mo>&#x2062;</mo><mi>i</mi></mrow>';
    				}
    				else {
    					str += '<mrow>' + MathLib.toMathML(this.im, {base: options.base, baseSubscript: options.baseSubscript}) + '<mo>&#x2062;</mo><mi>i</mi></mrow>';
    				}
    			}

    			if (reFlag || str.length === 0) {
    				str = MathLib.toMathML(this.re, options) + str;
    			}

    			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

Option name | Type | Description
--- | --- | ---
[options] | object | - Optional options to style the output

Custom toString function

    Complex.prototype.toString = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			var str = '', reFlag = !MathLib.isZero(this.re);

    			if (!this.isFinite()) {
    				return (options.sign ? '+' : '') + 'Complex' + this.re;
    			}

    			if (!MathLib.isZero(this.im)) {
    				str += MathLib.toString(this.im, {base: options.base, baseSubscript: options.baseSubscript, sign: reFlag || options.sign}) + 'i';
    			}

    			if (reFlag || str.length === 0) {
    				str = MathLib.toString(this.re, options) + str;
    			}

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