node package manager
Stop writing boring code. Discover, share, and reuse within your team. Create a free org »

complex-js

Complex-js is a lightweight module that enables complex mathematics in JavaScript. It comes with every elementary function and all mathematical operators. It also includes many utility functions and common non-analytical functions such as the complex conjugate, the argument function, the absolute value function and many others.

Lastly, but most importantly, this module contains a compiler to parse human-readable expressions into native JavaScript functions. The compiler, accessible from Complex.compile, accepts an arbitrary amount of parameters to pass to the function, specified by their human-readable names. Example usage can be found below in the section Parsing Human-Readable Expressions.

Although originally written for use in the browser, it can also now be used within Node.js.

Overview

## Download

To install via npm, run:

npm install --save complex-js

To include this module in the Node.js environment, add the line:

var Complex = require('complex-js');

In the browser, use a script tag:

<script type="text/javascript" src="complex.min.js"></script>

Complex.js can be included as an AMD module as well, and is available via bower:

bower install --save complex-js

## Functions vs. Operators

Functions are denoted as Complex.staticMethod. For example, to evaluate the tangent of the imaginary unit, do the following:

console.log(Complex.tan(Complex(0, 1)));

All functions are static, meaning that they are called directly by the Complex namespace. Operators are non-static methods, which means they must be called by an instance of Complex. For example, to raise 1+5i to the power of 3 e^(pi i), do the following:

console.log(Complex(1, 5).pow(Complex.Polar(3, Math.PI)));

Notice how pow is a method of a Complex instance, and not of the namespace Complex. That's because it is an operator rather than a function. Non-static methods are denoted as Complex#nonStaticMethod. Now you can use symbolic operators as well. These include addition (+), subtraction (-), multiplication (*), division (/), modulii (%), powers (^), and equalities (=). Below is a couple examples.

// 1+5i 
var onePlusFiveI = Complex(1, 0)['+'](Complex(0, 5));
// e^(pi i)*3 
var negThree = Complex.exp(Complex(0, Math.PI))['*'](Complex(3, 0));

## Coordinate Notation

Complex.js supports both cartesian and polar notation. In order to declare a Complex number with cartesian coordinates, you can call the Cartesian constructor with the following arguments:

var onePlusFiveI = Complex.Cartesian(1, 5);

Declaring it with the new keyword is optional, since the constructor detects and corrects instantiation automatically. Polar notation is supported through the Polar constructor as such:

var negOne = Complex.Polar(1, Math.PI);

Similarly, both notations are supported in the Complex#toString method. Simply call toString() for cartesian (the default), or toString(true) for polar notation.

These strings can be used to reconstruct the Complex instances, but that will be covered in the next section.

## Parsing Human-Readable Expressions

Complex.js also includes a compiler for human-readable expressions, which is very useful for constructing functions callable from JavaScript. Since it supports virtually any common notations and fully supports order of operations, it's very easy to use. It even detects implied multiplication and non-parenthetical grouping by default. A simple use-case example is below.

HTML:

<!DOCTYPE html>
  <head>
    <script type="text/javascript" src="complex.min.js"></script> 
  </head>
  <body>
    <div>
      <span>Evaluate:</span>
      <input type="text" id="calc" value="(5+i)^(3e-5+10*sin(5i))"/>
    </div>
    <div>
      <span>Cartesian:</span>
      <span id="ans-cart"></span>
    </div>
    <div>
      <span>Exponential:</span>
      <span id="ans-expo"></span>
    </div>
    <script type="text/javascript">
      ...
    </script> 
  </body>
</html>

JavaScript:

var input = document.getElementById('calc'),
  cart = document.getElementById('ans-cart'),
  expo = document.getElementById('ans-expo');
 
input.addEventListener('change', function () {
  try {
        //will throw an error if input is invalid 
    var calc = Complex.compile(input.value),
      //evaluate the compiled function for the answer 
      ans = calc();
 
    //use the toString method 
    cart.innerHTML = ans.toString();
    expo.innerHTML = ans.toString(true);
  } catch(error) {
    //if the parser throws an error, clear outputs and alert error 
    cart.innerHTML = '';
    expo.innerHTML = '';
    alert(error.message);
  }
});

Note that the compiler creates a function rather than evaluating the expression that is compiled immediately. The function returned is high-performace, since it caches all constant expressions in the string so that they don't need to be re-evaluated with each call.

The following is an example where the compiler provides parameters for the compiled function:

// Node.js 
var Complex = require('complex-js'),
  paramA = Complex(5, 1),
  paramB = Complex(3e-5, 0),
  paramC = Complex.Polar(5, Math.PI / 2),
  // human-readable variable names in expression 
  complexFunc = 'a^(b+10*sin(c))',
  // array of parameters for function is order-dependent 
  jsFunc = Complex.compile(complexFunc, ['b', 'a', 'c']),
  // how to pass parameters to compiled function 
  output = jsFunc(paramB, paramA, paramC);
 
// output cartesian form as string 
console.log(output.toString());

The Complex.compile method can also reconstruct a Complex number from a string created by Complex.toString. See below for a demonstration:

var fivePlusIStr = Complex(5, 1).toString(), //store as cartesian 
    fivePlusI = Complex.compile(fivePlusIStr)();
 
console.log(Complex(5, 1).equals(fivePlusI));

## Documentation

Constructors

Non-Static Methods

Static Methods

Misc. Methods

Constants

For convenience, but also used in many of the trigonometric methods.

  • Complex.ZERO - zero
  • Complex.ONE - one
  • Complex.NEG_ONE - negative one
  • Complex.I - i
  • Complex.NEG_I - negative i
  • Complex.TWO - two
  • Complex.TWO_I - two i
  • Complex.PI - irrational constant "π"
  • Complex.E - irrational constant "e"

## Constructors

### Complex([real = 0[, imag = 0[, abs = Math.sqrt(real * real + imag * imag)[, arg = Math.atan2(real, imag)]]]])

The main constructor for instances of the Complex class. Optionally call with new, but not required.

Arguments

  • real - An optional Number specifying the real value of the Complex number.
  • imag - An optional Number specifying the imaginary value of the Complex number.
  • abs - An optional Number specifying the absolute value of the Complex number. Not recommended unless accurately calculated.
  • arg - An optional Number specifying the argument of the Complex number. Not recommended unless accurately calculated.

### Complex.Cartesian([real = 0[, imag = 0]])

The cartesian constructor for instances of the Complex class. Optionally call with new, but not required.

Arguments

  • real - An optional Number specifying the real value of the Complex number.
  • imag - An optional Number specifying the imaginary value of the Complex number.

### Complex.Polar([abs = 0[, arg = 0]])

The polar constructor for instances of the Complex class. Optionally call with new, but not required.

Arguments

  • abs - An optional Number specifying the absolute value of the Complex number.
  • arg - An optional Number specifying the argument of the Complex number.

Note In order to access the components from an instance, examine the following demo code, which applies to all three constructors:

var complex = Complex(Math.random()*2-1,Math.random()*2-1);
console.log(
  complex.real, // real part 
  complex.imag, // imaginary part 
  complex.abs,  // absolute value 
  complex.arg   // argument 
);

## Non-Static Methods

### Complex#toString([polar = false])

The toString method for the Complex class. Outputs to cartesian or polar form.

Arguments

  • polar - An optional Boolean specifying the output form. If truthy, it outputs as polar, otherwise it outputs as cartesian.

Examples

var c1 = Complex(-3,0),
  c2 = Complex(0,-1),
  c3 = Complex(3,4),
  c4 = Complex(-2,-5);
 
console.log(c1.toString(true));
// "3 e^(3.141592653589793 i)" 
 
console.log(c2.toString());
// "-i" 
 
console.log(c3.toString(true));
// "5 e^(0.9272952180016123 i)" 
 
console.log(c4.toString());
// "-2-5 i" 

### Complex#equals(complex[, maxUlps = 4]), Complex#equ(complex[, maxUlps = 4])

Compares two complex numbers and determines whether they are approximately equal, taking into consideration truncation error.

Arguments

  • complex - An instance of the Complex class to which to compare.
  • maxUlps - An optional integer representing the difference of units in the last place allotted for successful equality.

### Complex#plus(complex), Complex#add(complex), Complex#['+'](complex)

Adds two Complex numbers.

Arguments

  • complex - An instance of the Complex class to add.

### Complex#subtract(complex), Complex#minus(complex), Complex#sub(complex), Complex#['-'](complex)

Subtracts a Complex number from another.

Arguments

  • complex - An instance of the Complex class to subtract.

### Complex#multiply(complex), Complex#times(complex), Complex#mul(complex), Complex#['*'](complex)

Multiplies two Complex numbers.

Arguments

  • complex - An instance of the Complex class to multiply.

### Complex#divide(complex), Complex#div(complex), Complex#['/'](complex)

Divides a Complex number by another.

Arguments

  • complex - An instance of the Complex class by which to divide.

### Complex#modulo(complex), Complex#mod(complex), Complex#['%'](complex)

Applies a Complex Modulus to a Complex number by cartesian coordinates.

Arguments

  • complex - An instance of the Complex class for the modulus.

### Complex#power(complex), Complex#pow(complex), Complex#['^'](complex), Complex#['**'](complex)

Raises a Complex number to a Complex power.

Arguments

  • complex - An instance of the Complex class by which to raise.

## Static Methods (and non-static counterparts)

### Complex.negate(complex), Complex#negate()

Returns the negative of complex.

Arguments

  • complex - An instance of the Complex class to negate.

### Complex.conjugate(complex), Complex#conjugate()

Returns the conjugate of complex.

Arguments

  • complex - An instance of the Complex class to conjugate.

### Complex.normalize(complex), Complex#normalize()

Returns the unit complex number with the same argument as complex. If the magnitude of complex is 0, then an instance of Complex is returned with a magnitude of NaN.

Arguments

  • complex - An instance of the Complex class to normalize.

### Complex.sign(complex), Complex#sign()

Calculates the signs of the cartesian components of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.floor(complex), Complex#floor()

Rounds down the cartesian components of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.ceil(complex), Complex#ceil()

Rounds up the cartesian components of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.round(complex), Complex#round()

Rounds the cartesian components of complex to the nearest integers.

Arguments

  • complex - An instance of the Complex class.

### Complex.truncate(complex), Complex#truncate()

Returns the integer parts of the cartesian components in complex. This floors positive components and ceilings negative components.

Arguments

  • complex - An instance of the Complex class.

### Complex.fraction(complex), Complex#fraction()

Returns the fractional parts of the cartesian components in complex. This retains the sign of each component.

Arguments

  • complex - An instance of the Complex class.

### Complex.square(complex), Complex#square()

Returns the square of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.cube(complex), Complex#cube()

Returns the cube of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.sqrt(complex), Complex#sqrt()

Returns the square root of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.cbrt(complex), Complex#cbrt()

Returns the cube root of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.exp(complex), Complex#exp()

Returns the exponent function of complex, i.e. e^complex

Arguments

  • complex - An instance of the Complex class.

### Complex.log(complex), Complex#log()

Returns the natural logarithm of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.cos(complex), Complex#cos()

Returns the cosine of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.sin(complex), Complex#sin()

Returns the sine of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.tan(complex), Complex#tan()

Returns the tangent of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.sec(complex), Complex#sec()

Returns the secant of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.csc(complex), Complex#csc()

Returns the cosecant of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.cot(complex), Complex#cot()

Returns the cotangent of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.acos(complex), Complex#acos()

Returns the acosine of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.asin(complex), Complex#asin()

Returns the asine of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.atan(complex), Complex#atan()

Returns the atangent of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.asec(complex), Complex#asec()

Returns the asecant of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.acsc(complex), Complex#acsc()

Returns the acosecant of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.acot(complex), Complex#acot()

Returns the acotangent of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.cosh(complex), Complex#cosh()

Returns the hyperbolic cosine of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.sinh(complex), Complex#sinh()

Returns the hyperbolic sine of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.tanh(complex), Complex#tanh()

Returns the hyperbolic tangent of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.sech(complex), Complex#sech()

Returns the hyperbolic secant of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.csch(complex), Complex#csch()

Returns the hyperbolic cosecant of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.coth(complex), Complex#coth()

Returns the hyperbolic cotangent of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.acosh(complex), Complex#acosh()

Returns the hyperbolic acosine of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.asinh(complex), Complex#asinh()

Returns the hyperbolic asine of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.atanh(complex), Complex#atanh()

Returns the hyperbolic atangent of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.asech(complex), Complex#asech()

Returns the hyperbolic asecant of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.acsch(complex), Complex#acsch()

Returns the hyperbolic acosecant of complex.

Arguments

  • complex - An instance of the Complex class.

### Complex.acoth(complex), Complex#acoth()

Returns the hyperbolic acotangent of complex.

Arguments

  • complex - An instance of the Complex class.

## Misc. Static Methods

### Complex.min(complex_1[, complex_2...])

Returns the first complex instance with the smallest absolute value.

Arguments

  • complex_n - An instance of the Complex class.

### Complex.max(complex_1[, complex_2...])

Returns the first complex instance with the largest absolute value.

Arguments

  • complex_n - An instance of the Complex class.

### Complex.isNaN(complex), Complex#isNaN()

Returns a Boolean; if any component of complex evaluates to NaN, this returns true, otherwise false.

Arguments

  • complex - An instance of the Complex class.

### Complex.isFinite(complex), Complex#isFinite()

Returns a Boolean; if the absolute value of complex is finite, this returns true, otherwise false.

Arguments

  • complex - An instance of the Complex class.

### Complex.isReal(complex), Complex#isReal()

Returns a Boolean; if imaginary component of complex is close to 0, this returns true, otherwise false.

Arguments

  • complex - An instance of the Complex class.

### Complex.isImag(complex), Complex#isImag()

Returns a Boolean; if real component of complex is close to 0, this returns true, otherwise false.

Arguments

  • complex - An instance of the Complex class.

### Complex.compile(string[, params = []])

Returns a JavaScript function bound with pre-compiled constants parsed from the human-readable math expression string. Optionally, an Array of human-readable parameters may be supplied to parse from the expression.

Arguments

  • string - A human-readable String of a math expression to be compiled.
  • params - An optional Array[String] of human-readable parameters to parse.

License

Copyright (c) 2017 Patrick Roberts

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.