Location: PHPKode > scripts > dm.Complex > dm-complex/class.Complex.php
<?php

//
// Edit History:
//
//  $Author: munroe $
//  $Date: 2006/01/22 19:43:32 $
//
//  Dick Munroe (hide@address.com) 20-Jan-2006
//      Initial version created.
//
//  Dick Munroe (hide@address.com) 22-Jan-2006
//      Add polar coordinate class.
//      Add Square root, exp, and log base e functions.
//      Add log base 10 and exp base 10 functions.
//

/**
 * @author Dick Munroe <hide@address.com>
 * @copyright copyright @ 2006 by Dick Munroe, Cottage Software Works, Inc.
 * @license http://www.csworks.com/publications/ModifiedNetBSD.html
 * @version 1.1.0
 * @package Complex
 * @example ./example.php
 */

/*
 * Provide complex number manipulation.  The numeric operation methods
 * provide two interfaces, one object oriented, one procedural.  The
 * procedural interfaces all return references to NEW objects which must
 * be freed by the calling procedures to prevent memory leaks.
 */
        
class Complex
{
    var $_real ;
    var $_imaginary ;
    
    /*
     * Construct an imaginary number.
     * 
     * @access public
     * @param mixed $theReal The real component of the imaginary number or an imaginary number
     *                       expressed in either imaginary or polar form.
     * @param float $theImaginary The imaginary component of the imaginary number (default = 0)
     * @return void
     */

    function Complex($theReal, $theImaginary = 0)
    {
        if (is_object($theReal))
        {
            $xxx = get_class($theReal) ;
            
            if ($xxx == "complex")
            {
                $this->_real = $theReal->real() ;
                $this->_imaginary = $theReal->imaginary() ;
            }
            else if ($xxx == "polar")
            {
                $this->_real = $theReal->radius() * cos($theReal->theta()) ;
                $this->_imaginary = $theReal->radius() * sin($theReal->theta()) ;
            }
            else
            {
                die("Invalid class: $xxx") ;
            }
        }
        else
        {
            $this->_real = $theReal ;
            $this->_imaginary = $theImaginary ;
        }
    }
    
    /*
     * Access the real component of an imaginary number.
     * 
     * @access public
     * @return reference to float
     */

    function &real()
    {
        return $this->_real ;
    }
    
    /*
     * Access the imaginary component of an imaginary number.
     * 
     * @access public
     * @return reference to float
     */

    function &imaginary()
    {
        return $this->_imaginary ;
    }
    
    /*
     * Check two imaginary numbers for equality.
     *
     * @access public
     * @param object An imaginary number.
     * @return boolean True if the two complex numbers are equal, false otherwise.
     */
    
    function isEqual(&$theComprand)
    {
        return ($this->_real == $theComprand->real()) && ($this->_imaginary == $theComprand->imaginary()) ;
    }
    
    /*
     * Check imaginary number for 0.
     *
     * @access public
     * @return boolean True if the number is zero, false otherwise.
     */
    
    function isZero()
    {
        return ($this->_real == 0) && ($this->_imaginary == 0) ;
    }
    
    /*
     * Add two imaginary numbers.
     * 
     * @access public
     * @param object The Addend
     * @return reference to imaginary number
     */

    function &add(&$theAddend, $n2 = NULL)
    {
        if ($n2 !== NULL)
        {
            $n1 = new Complex($theAddend) ;
            return $n1->add($n2) ;
        }
        else
        {
            $this->_real += $theAddend->real() ;
            $this->_imaginary += $theAddend->imaginary() ;
            return $this ;
        }
    }
    
    /*
     * Subtract two imaginary numbers.
     * 
     * @access public
     * @param object The Subtrahend
     * @return reference to imaginary number
     */

    function &subtract(&$theSubtrahend, $n2 = NULL)
    {
        if ($n2 !== NULL)
        {
            $n1 = new Complex($theSubtrahend) ;
            return $n1->subtract($n2) ;
        }
        else
        {
            $this->_real -= $theSubtrahend->real() ;
            $this->_imaginary -= $theSubtrahend->imaginary() ;
            return $this ;
        }
    }
    
    /*
     * Multiply two imaginary numbers.
     * 
     * @access public
     * @param object The Multiplacand
     * @return reference to imaginary number
     */

    function &multiply(&$theMultiplacand, $n2 = NULL)
    {
        if ($n2 !== NULL)
        {
            $n1 = new Complex($theMultiplacand) ;
            return $n1->multiply($n2) ;
        }
        else
        {
            $xxx = ($this->_real * $theMultiplacand->real()) -
                   ($this->_imaginary * $theMultiplacand->imaginary()) ;
            $yyy = ($this->_real * $theMultiplacand->imaginary()) +
                   ($this->_imaginary * $theMultiplacand->real()) ;
            $this->_real = $xxx ;
            $this->_imaginary = $yyy ;
            return $this ;
        }
    }
    
    /*
     * Divide two imaginary numbers.
     * 
     * @access public
     * @param object The Divisor
     * @return reference to imaginary number
     */

    function &divide(&$theDivisor, $n2 = NULL)
    {
        if ($n2 !== NULL)
        {
            $n1 = new Complex($theDivisor) ;
            return $n1->divide($n2) ;
        }
        else
        {
            $xxx = pow($theDivisor->real(), 2) + pow($theDivisor->imaginary(), 2) ;
        
            $yyy =
                (($this->_real * $theDivisor->real()) + ($this->_imaginary * $theDivisor->imaginary())) / $xxx ;
                    
            $zzz =
                (($this->_imaginary * $theDivisor->real()) - ($this->_real * $theDivisor->imaginary())) / $xxx ;
        
            $this->_real = $yyy ;
            $this->_imaginary = $zzz ;
            return $this;
        }
    }

    /*
     * Take the Naperian power of an imaginary number.
     *
     * @access public
     * @param the number to take the naperian power of.
     * @return reference to imaginary number
     */

    function &exp($n2 = NULL)
    {
        if ($n2 !== NULL)
        {
            $n1 = new Complex($n2) ;
            return $n1->exp() ;
        }
        else
        {
            $x = exp($this->_real) * cos($this->_imaginary) ;
            $y = exp($this->_real) * sin($this->_imaginary) ;
            
            $this->_real = $x ;
            $this->_imaginary = $y ;

            return $this ;
        }
    }
    
    /*
     * Take the base 10 power of an imaginary number.
     *
     * @access public
     * @param the number to take the base 10 power of.
     * @return reference to imaginary number
     */

    function &exp10($n2 = NULL)
    {
        if ($n2 !== NULL)
        {
            $n1 = new Complex($n2) ;
            return $n1->exp10() ;
        }
        else
        {
            $x = pow(10, $this->_real) * cos($this->_imaginary) ;
            $y = pow(10, $this->_real) * sin($this->_imaginary) ;
            
            $this->_real = $x ;
            $this->_imaginary = $y ;

            return $this ;
        }
    }
    
    /*
     * Take the Naperian logarithm of an imaginary number.
     *
     * Note that this method only returns the first logarithm of a complex
     * number.  For any given complex number there are multiple logarithms
     * due to the fact that the complex component of the log is the arctan
     * which has the same value if a multiple of 2 PI is added.
     * 
     * @access public
     * @param the number to take the naperian log of.
     * @return reference to imaginary number
     */

    function &log($n2 = NULL)
    {
        if ($n2 !== NULL)
        {
            $n1 = new Complex($n2) ;
            return $n1->log() ;
        }
        else
        {
            $x = log(sqrt(pow($this->_real, 2) +  pow($this->_imaginary, 2))) ;
            $y = atan2($this->_imaginary, $this->_real) ;
            
            $this->_real = $x ;
            $this->_imaginary = $y ;

            return $this ;
        }
    }
    
    /*
     * Take the base 10 logarithm of an imaginary number.
     *
     * Note that this method only returns the first logarithm of a complex
     * number.  For any given complex number there are multiple logarithms
     * due to the fact that the complex component of the log is the arctan
     * which has the same value if a multiple of 2 PI is added.
     * 
     * @access public
     * @param the number to take the naperian log of.
     * @return reference to imaginary number
     */

    function &log10($n2 = NULL)
    {
        if ($n2 !== NULL)
        {
            $n1 = new Complex($n2) ;
            return $n1->log10() ;
        }
        else
        {
            $x = log10(sqrt(pow($this->_real, 2) +  pow($this->_imaginary, 2))) ;
            $y = atan2($this->_imaginary, $this->_real) ;
            
            $this->_real = $x ;
            $this->_imaginary = $y ;

            return $this ;
        }
    }
    
    /*
     * Take the square root of an imaginary number.
     * 
     * @access public
     * @param the number to take the square root of.
     * @return reference to imaginary number
     */

    function &sqrt($n2 = NULL)
    {
        if ($n2 !== NULL)
        {
            $n1 = new Complex($n2) ;
            return $n1->sqrt() ;
        }
        else
        {
            $r = sqrt(pow($this->_real, 2) +  pow($this->_imaginary, 2)) ;
            
            $y = sqrt(($r - $this->_real)/2) ;
            $x = $this->_imaginary / (2 * $y) ;
            
            $this->_real = $x ;
            $this->_imaginary = $y ;
            
            return $this ;
        }
    }
}

/*
 * Provide a polar coordinate form for imaginary numbers.
 */

class Polar
{
    var $_radius ;
    var $_theta ;
    
    function Polar($theRadius, $theTheta = 0)
    {
        if (is_object($theRadius))
        {
            $xxx = get_class($theRadius) ;
            
            if ($xxx == "polar")
            {
                $this->_radius = $theRadius->radius() ;
                $this->_theta = $theRadius->theta() ;
            }
            else if ($xxx = "complex")
            {
                $this->_radius = sqrt(pow($theRadius->real(), 2) + pow($theRadius->imaginary(), 2)) ;
                $this->_theta = atan2($theRadius->imaginary(), $theRadius->real()) ;
            }
            else
            {
                die("Invalid class argument: $xxx") ;
            }
        }
        else
        {
            $this->_radius = $theRadius ;
            $this->_theta = atan(tan($theTheta)) ;
        }
    }
    
    /*
     * Accessor functions.
     */
    
    function &radius()
    {
        return $this->_radius ;
    }
    
    function &theta()
    {
        return $this->_theta ;
    }
}
?>
Return current item: dm.Complex