Home Manual Reference Source Test Repository

src/Complex.js

import ZeroDivisionError from './ZeroDivisionError' ;

import COMPLEX_DEFAULT_DISPLAY from './COMPLEX_DEFAULT_DISPLAY' ;

export default class Complex {

	constructor ( representation , real , img ) {
		this.representation = representation ;
		this.real = real ;
		this.img = img ;
	}

	move ( other ) {
		other.representation = this.representation ;
		other.real = this.real ;
		other.img = this.img ;
		return other ;
	}

	copy ( ) {
		return new Complex( this.representation , this.real , this.img ) ;
	}

	toString ( representation = COMPLEX_DEFAULT_DISPLAY ) {
		// TODO use proper representation conversion
		return this.representation.kernel.stringify( this.real , this.img ) ;
	}

	add ( other ) {

		const [ real , img ] = this.representation.kernel.add( this.real , this.img , other.real , other.img ) ;

		return new Complex( this.representation , real , img ) ;

	}

	iadd ( other ) {
		// TODO optimize but be careful with side effects
		return this.add(other).move(this);
	}

	sub ( other ) {

		const [ real , img ] = this.representation.kernel.sub( this.real , this.img , other.real , other.img ) ;

		return new Complex( this.representation , real , img ) ;

	}

	isub ( other ) {
		// TODO optimize but be careful with side effects
		return this.sub(other).move(this);
	}

	mul ( other ) {

		const [ real , img ] = this.representation.kernel.mul( this.real , this.img , other.real , other.img ) ;

		return new Complex( this.representation , real , img ) ;

	}

	imul ( other ) {
		// TODO optimize but be careful with side effects
		return this.mul(other).move(this);
	}

	/**
	 * Computes <code>this</code> raised to the <code>other</code>th power.
	 *
	 * @param {Complex} other The power to raise <code>this</code> to.
	 * @return {Complex} <code>this ^ other</code>
	 */
	pow ( other ) {
		// TODO optimize for special cases
		const [ real , img ] = this.representation.kernel.pow( this.real , this.img , other.real , other.img ) ;
		return new Complex( this.representation , real , img ) ;
	}

	ipow ( other ) {
		// TODO optimize but be careful with side effects
		return this.pow(x).move(this);
	}

	square ( ) {
		// TODO optimize
		return this.mul(this);
	}

	isquare ( ) {
		// TODO optimize but be careful with side effects
		return this.square().move(this);
	}

	div ( other ) {
		return this.__truediv__( other ) ;
	}

	idiv ( other ) {
		// TODO optimize but be careful with side effects
		return this.div(other).move(this);
	}

	mod ( other ) {
		throw new TypeError( "can't mod complex numbers." ) ;
	}

	imod ( other ) {
		throw new TypeError( "can't mod complex numbers." ) ;
	}

	divmod ( other ) {
		throw new TypeError( "can't take floor or mod of complex number." ) ;
	}

	__truediv__ ( other ) {
		const [ real , img ] = this.representation.kernel.div( this.real , this.img , other.real , other.img ) ;
		return new Complex( this.representation , real , img ) ;
	}

	__floordiv__ ( other ) {
		throw new TypeError( "can't take floor of complex number." ) ;
	}

	opposite ( ) {
		return new Complex( this.representation , this.representation.model.neg( this.real ) , this.representation.model.neg( this.img ) ) ;
	}

	conjugate ( ) {
		return new Complex( this.representation , this.real , this.representation.model.neg( this.img ) ) ;
	}

	negate ( ) {
		// TODO optimize but be careful with side effects
		// TODO what would be the name for in-place conjugate -_- ?
		return this.opposite().move(this);
	}

	signum ( ) {
		return this.iszero() ? this : this.divide_knowing_model_contains( this.abs() ) ;
	}

	iszero ( ) {
		return this.representation.model.eq( this.representation.model.$0() , this.real ) &&
		this.representation.model.eq( this.representation.model.$0() , this.img ) ;
	}

	isone ( ) {
		return this.representation.model.eq( this.representation.model.$1() , this.real ) &&
		this.representation.model.eq( this.representation.model.$0() , this.img ) ;
	}

	nonzero ( ) {
		return !this.iszero();
	}

	divides ( other ) {
		return other.mod( this ).iszero( ) ;
	}

	divide_knowing_divisible_by ( other ) {
		return this.div( other ) ;
	}

	divide_knowing_model_contains ( other ) {
		const real = this.representation.model.div( this.real , other ) ;
		const img = this.representation.model.div( this.img , other ) ;
		return new Complex( this.representation , real , img ) ;
	}

	abs ( ) {
		return this.representation.kernel.abs( this.real , this.img ) ;
	}

	cmp ( other ) {
		// TODO could also be
		// throw TypeError: no ordering relation is defined for complex numbers
		return this.representation.model.increasing( this.abs() , other.abs() ) ;
	}

	eq ( other ) {
		return this.representation.model.eq(this.real, other.real) && this.representation.model.eq(this.img, other.img) ;
	}

	ne ( other ) {
		return !this.eq(other) ;
	}

	ge ( other ) {
		return this.cmp( other ) >= 0 ;
	}

	gt ( other ) {
		return this.cmp( other ) > 0 ;
	}

	le ( other ) {
		return this.cmp( other ) <= 0 ;
	}

	lt ( other ) {
		return this.cmp( other ) < 0 ;
	}

}