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

breeze.math.Complex.scala Maven / Gradle / Ivy

The newest version!
package breeze.math
/*
 Copyright 2012 David Hall

 Licensed under the Apache License, Version 2.0 (the "License")
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/
import breeze.linalg.operators._
import breeze.storage.DefaultArrayValue

/**
 * Immutable complex numbex number representation backed by doubles
 * for the real and imaginary parts.
 *
 * Integration with `scala.math.Numeric` and `scala.math.Fractional` is
 * provided.
 *
 * @author dramage, lancelet
 */
case class Complex(real : Double, imag : Double) {
  override def toString = real + " + " + imag + "i"

  def +(that : Complex) =
    Complex(this.real + that.real, this.imag + that.imag)

  def +(that : Int) =
    Complex(this.real + that, this.imag)

  def +(that : Long) =
    Complex(this.real + that, this.imag)

  def +(that : Float) =
    Complex(this.real + that, this.imag)

  def +(that : Double) =
    Complex(this.real + that, this.imag)

  def -(that : Complex) =
    Complex(this.real - that.real, this.imag - that.imag)

  def -(that : Int) =
    Complex(this.real - that, this.imag)

  def -(that : Long) =
    Complex(this.real - that, this.imag)

  def -(that : Float) =
    Complex(this.real - that, this.imag)

  def -(that : Double) =
    Complex(this.real - that, this.imag)

  def *(that : Complex) =
    Complex(this.real * that.real - this.imag * that.imag,
            this.real * that.imag + this.imag * that.real)

  def *(that : Int) =
    Complex(this.real * that, this.imag * that)

  def *(that : Long) =
    Complex(this.real * that, this.imag * that)

  def *(that : Float) =
    Complex(this.real * that, this.imag * that)

  def *(that : Double) =
    Complex(this.real * that, this.imag * that)

  def /(that : Complex) = {
    val denom = that.real * that.real + that.imag * that.imag
    Complex((this.real * that.real + this.imag * that.imag) / denom,
            (this.imag * that.real - this.real * that.imag) / denom)
  }

  def /(that : Int) =
    Complex(this.real / that, this.imag / that)

  def /(that : Long) =
    Complex(this.real / that, this.imag / that)

  def /(that : Float) =
    Complex(this.real / that, this.imag / that)

  def /(that : Double) =
    Complex(this.real / that, this.imag / that)

  def unary_- =
    Complex(-real, -imag)

  def abs =
    math.sqrt(real*real + imag*imag)

  def conjugate =
    Complex(real, -imag)

  override def equals(that : Any) = that match {
    case that : Complex => this.real == that.real && this.imag == that.imag
    case real : Double => this.real == real && this.imag == 0
    case real : Int => this.real == real && this.imag == 0
    case real : Short => this.real == real && this.imag == 0
    case real : Long => this.real == real && this.imag == 0
    case real : Float => this.real == real && this.imag == 0
    case _ => false
  }
}

object Complex { outer =>

  /** Constant Complex(0,0). */
  val zero = new Complex(0,0)

  /** Constant Complex(1,0). */
  val one = new Complex(1,0)

  /** Constant Complex(NaN, NaN). */
  val nan = new Complex(Double.NaN, Double.NaN)

  /** Constant Complex(0,1). */
  val i = new Complex(0,1)

  //
  // scalar
  //

  implicit object scalar extends Field[Complex] {
    def zero = outer.zero

    def one = outer.one

    def nan = outer.nan

    def ==(a : Complex, b : Complex) = a == b

    def !=(a : Complex, b : Complex) = a != b

    def >(a : Complex, b : Complex) =
      (a.real > b.real || (a.real == b.real && a.imag > b.imag))

    def >=(a : Complex, b : Complex) =
      (a.real >= b.real || (a.real == b.real && a.imag >= b.imag))

    def <(a : Complex, b : Complex) =
      (a.real < b.real || (a.real == b.real && a.imag < b.imag))

    def <=(a : Complex, b : Complex) =
      (a.real <= b.real || (a.real == b.real && a.imag <= b.imag))

    def +(a : Complex, b : Complex) = a + b

    def -(a : Complex, b : Complex) = a - b

    def *(a : Complex, b : Complex) = a * b

    def /(a : Complex, b : Complex) = a / b

    def norm(a : Complex) = a.abs

    def toDouble(a : Complex) =
      throw new UnsupportedOperationException("Cannot automatically convert complex numbers to doubles")

    def isNaN(a : Complex) =
      a.real.isNaN || a.imag.isNaN

    val manifest = implicitly[ClassManifest[Complex]]

    val defaultArrayValue = DefaultArrayValue(Complex(0, 0))

  }

  //
  // neg
  //

  implicit object Neg extends UnaryOp[Complex,OpNeg,Complex]
    { def apply(v : Complex) = -v}

  //
  // add
  //

  implicit object AddCC extends BinaryOp[Complex,Complex,OpAdd,Complex]
  { def apply(a : Complex, b : Complex) = a + b}

  implicit object AddIC extends BinaryOp[Int,Complex,OpAdd,Complex]
  { def apply(a : Int, b : Complex) = a + b}

  implicit object AddLC extends BinaryOp[Long,Complex,OpAdd,Complex]
  { def apply(a : Long, b : Complex) = a + b}

  implicit object AddFC extends BinaryOp[Float,Complex,OpAdd,Complex]
  { def apply(a : Float, b : Complex) = a + b}

  implicit object AddDC extends BinaryOp[Double,Complex,OpAdd,Complex]
  { def apply(a : Double, b : Complex) = a + b}

  implicit object AddCI extends BinaryOp[Complex,Int,OpAdd,Complex]
  { def apply(a : Complex, b : Int) = a + b}

  implicit object AddCL extends BinaryOp[Complex,Long,OpAdd,Complex]
  { def apply(a : Complex, b : Long) = a + b}

  implicit object AddCF extends BinaryOp[Complex,Float,OpAdd,Complex]
  { def apply(a : Complex, b : Float) = a + b}

  implicit object AddCD extends BinaryOp[Complex,Double,OpAdd,Complex]
  { def apply(a : Complex, b : Double) = a + b}

  //
  // sub
  //

  implicit object SubCC extends BinaryOp[Complex,Complex,OpSub,Complex]
  { def apply(a : Complex, b : Complex) = a - b}

  implicit object SubIC extends BinaryOp[Int,Complex,OpSub,Complex]
  { def apply(a : Int, b : Complex) = a - b}

  implicit object SubLC extends BinaryOp[Long,Complex,OpSub,Complex]
  { def apply(a : Long, b : Complex) = a - b}

  implicit object SubFC extends BinaryOp[Float,Complex,OpSub,Complex]
  { def apply(a : Float, b : Complex) = a - b}

  implicit object SubDC extends BinaryOp[Double,Complex,OpSub,Complex]
  { def apply(a : Double, b : Complex) = a - b}

  implicit object SubCI extends BinaryOp[Complex,Int,OpSub,Complex]
  { def apply(a : Complex, b : Int) = a - b}

  implicit object SubCL extends BinaryOp[Complex,Long,OpSub,Complex]
  { def apply(a : Complex, b : Long) = a - b}

  implicit object SubCF extends BinaryOp[Complex,Float,OpSub,Complex]
  { def apply(a : Complex, b : Float) = a - b}

  implicit object SubCD extends BinaryOp[Complex,Double,OpSub,Complex]
  { def apply(a : Complex, b : Double) = a - b}

  //
  // mul
  //

  implicit object MulCC extends BinaryOp[Complex,Complex,OpMulMatrix,Complex]
  { def apply(a : Complex, b : Complex) = a * b}

  implicit object MulIC extends BinaryOp[Int,Complex,OpMulMatrix,Complex]
  { def apply(a : Int, b : Complex) = a * b}

  implicit object MulLC extends BinaryOp[Long,Complex,OpMulMatrix,Complex]
  { def apply(a : Long, b : Complex) = a * b}

  implicit object MulFC extends BinaryOp[Float,Complex,OpMulMatrix,Complex]
  { def apply(a : Float, b : Complex) = a * b}

  implicit object MulDC extends BinaryOp[Double,Complex,OpMulMatrix,Complex]
  { def apply(a : Double, b : Complex) = a * b}

  implicit object MulCI extends BinaryOp[Complex,Int,OpMulMatrix,Complex]
  { def apply(a : Complex, b : Int) = a * b}

  implicit object MulCL extends BinaryOp[Complex,Long,OpMulMatrix,Complex]
  { def apply(a : Complex, b : Long) = a * b}

  implicit object MulCF extends BinaryOp[Complex,Float,OpMulMatrix,Complex]
  { def apply(a : Complex, b : Float) = a * b}

  implicit object MulCD extends BinaryOp[Complex,Double,OpMulMatrix,Complex]
  { def apply(a : Complex, b : Double) = a * b}

  //
  // div
  //

  implicit object DivCC extends BinaryOp[Complex,Complex,OpDiv,Complex]
  { def apply(a : Complex, b : Complex) = a / b}

  implicit object DivIC extends BinaryOp[Int,Complex,OpDiv,Complex]
  { def apply(a : Int, b : Complex) = a / b}

  implicit object DivLC extends BinaryOp[Long,Complex,OpDiv,Complex]
  { def apply(a : Long, b : Complex) = a / b}

  implicit object DivFC extends BinaryOp[Float,Complex,OpDiv,Complex]
  { def apply(a : Float, b : Complex) = a / b}

  implicit object DivDC extends BinaryOp[Double,Complex,OpDiv,Complex]
  { def apply(a : Double, b : Complex) = a / b}

  implicit object DivCI extends BinaryOp[Complex,Int,OpDiv,Complex]
  { def apply(a : Complex, b : Int) = a / b}

  implicit object DivCL extends BinaryOp[Complex,Long,OpDiv,Complex]
  { def apply(a : Complex, b : Long) = a / b}

  implicit object DivCF extends BinaryOp[Complex,Float,OpDiv,Complex]
  { def apply(a: Complex, b : Float) = a / b}

  implicit object DivCD extends BinaryOp[Complex,Double,OpDiv,Complex]
  { def apply(a : Complex, b : Double) = a / b}

  //
  // scala.math.Numeric and scala.math.Fractional
  //
  // TODO: Implement scala.math.Integral trait, if this is ever required
  //       for some reason.

  /** `Complex` as `scala.math.Numeric` trait.
    * Conversions to `Int`, `Long`, `Float` and `Double` are only performed
    * if the imaginary component of the complex number is exactly 0. */
  trait ComplexIsConflicted extends Numeric[Complex] {
    def plus(x: Complex, y: Complex): Complex = x + y
    def minus(x: Complex, y: Complex): Complex = x - y
    def times(x: Complex, y: Complex): Complex = x * y
    def negate(x: Complex): Complex = -x
    def fromInt(x: Int): Complex = Complex(x, 0)
    def toInt(x: Complex): Int = strictlyReal(x).toInt
    def toLong(x: Complex): Long = strictlyReal(x).toLong
    def toFloat(x: Complex): Float = strictlyReal(x).toFloat
    def toDouble(x: Complex): Double = strictlyReal(x)

    /** Checks that a `Complex` number is strictly real, and returns the real
      * component. */
    private def strictlyReal(x: Complex): Double = {
      require(x.imag == 0.0)  // only proceed if x.imag is *exactly* zero
      x.real
    }
  }
  /** `Complex` as `scala.math.Fractional` trait. */
  trait ComplexIsFractional extends ComplexIsConflicted
		            with Fractional[Complex]
  {
    def div(x: Complex, y: Complex): Complex = x / y
  }
  /** Ordering for complex numbers: orders lexicographically first
    * on the real, then on the imaginary part of the number. */
  trait ComplexOrdering extends Ordering[Complex] {
    override def compare(a : Complex, b : Complex) = {
      if (a.real < b.real) -1
      else if (a.real > b.real) 1
      else if (a.imag < b.imag) -1
      else if (a.imag > b.imag) 1
      else 0
    }
  }
  /** Implicit object providing `scala.math.Fractional` capabilities.
    * Although complex numbers have no natural ordering, some kind of
    * `Ordering` is required because `Numeric` extends `Ordering`.  Hence,
    * an ordering based upon the real then imaginary components is used. */
  implicit object ComplexIsFractional extends ComplexIsFractional
                                      with ComplexOrdering

}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy