<?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 ÷(&$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 ;
}
}
?>