All Downloads are FREE. Search and download functionalities are using the official Maven repository.

expr.Complex.scala Maven / Gradle / Ivy

package galileo.complex

import galileo.constants.ConstantPi
import galileo.environment.Environment
import galileo.expr._
import galileo.trigonometry.{SinF1,CosF1,AtanF1}

case class Complex(real:Expr, imag:Expr) extends Expr {
	def +(that:Number) = Complex( Sum( this.real, that ), this.imag )
	def +(that:Complex) = Complex( Sum( this.real, that.real ), Sum( this.imag, that.imag ) )
	//override def +(that:Expr) = Complex( Sum(this.real, that), this.imag )
	def *(that:Number) = Complex( Product( this.real, that ), Product( this.imag, that ) )
	def *(that:Complex) = Complex( 
		Sum( Sum( this.real, that.real ), Product( Number(-1), Product( this.imag, that.imag ) ) ),
		Sum( Product( this.real, that.imag ), Product( this.imag, that.real ) )
	)

	// don't call visit here... Visit should only be called in visit functions
	def ^(that:Number) = (real, imag ) match {
		case ( Number( 0 ), i:Expr ) if (that.value%4 == 0 ) => Power( i, that ) // of for pos and neg multiples of 4
		case ( Number( 0 ), i:Expr ) if (that.value%2 == 0 ) => Product( Number( -1 ), Power( i, that ) ) // of for pos and neg multples of 2
		case ( Number( 0 ), i:Expr ) if ((that.value+1)%4==0) => Complex( Number( 0 ), Product( Number( -1 ), Power( i, that ) ) )
		case ( Number( 0 ), i:Expr ) if ((that.value-1)%4==0) => Complex( Number( 0 ), Power( i, that ) )
		case ( r:Number, i:Number ) => Complex( 
			Product( modulus, CosF1( Product( that, this.phase ) ) ),
			Product( modulus, SinF1( Product( that, this.phase ) ) )
		)
		case _ => Power( this, that ) // this will cause a cycle if called 
	}
	
	val modulus = RootN( Sum( 
		Power( real, Number( 2 ) ),
		Power( imag, Number( 2 ) )
	), Number( 2 ) )

	val phase = (real, imag) match {
		case ( Number( 0 ), Number( 0 ) ) => Number( 0 )
		case ( Number( 0 ), im ) if ( im > 0 )  => Fraction( ConstantPi(), Number( 2 ) )
		case ( Number( 0 ), im ) if ( im < 0  ) => Product( Number( -1 ), Fraction( ConstantPi(), Number( 2 ) ) )
		case (_,_ ) => AtanF1( Fraction( imag, real ) )
	}

	// a * e^(i*theta) = a * cos( theta ) + a * i * sin( theta )
	// a * e^(n*i*theta ) = a * cos( n * theta ) + a * i * sin ( n * theta )
	// if that decomp does not exist...
	// expr + i * expr..., then what?
	/*def ^(that:Number) = {
		Complex( )
	}
	*/

	override def toString() = (real, imag ) match {
		case ( a, Number( 0 ) ) => a.toString()
		case ( Number( 0 ), Number( 1 ) ) => "j"
		case ( Number( 0 ), Number( -1 ) ) => "-j"
		case ( Number( 0 ), a ) => "j * " + a.factorToString()
		case ( a, Number(  1 ) ) => a.toString() + "+j"
		case ( a, Number( -1 ) ) => a.toString() + "-j"
		case ( _,_ ) => real.toString() + "+j*" + imag.factorToString() 
	}
	def info(env:Option[Environment]=None) = "Complex(" + real.info(env) + "," + imag.info( env ) + ")"
		// the way to print a complex expression if it is used as a factor
		// e.g. ( 6 + j ) in ( 6 + j ) * a
	override def factorToString():String = (real,imag) match {
			case ( Number( 0 ), a ) => this.toString()
			case ( a, Number( 0 ) ) => this.toString()
			case (_,_) => "(" + this.toString() + ")" 
	} 

	override def visit( env:Option[Environment]=None):Expr = ( real.visit( env ), imag.visit( env ) ) match {
		case ( r:Expr, Number( 0.0 ) ) => r
		case ( r, i ) => Complex( r, i )
	}

	def variables:List[Variable] = real.variables ++ imag.variables
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy