Overview

Namespaces

  • chippyash
    • Type
      • Exceptions
      • Interfaces
      • Number
        • Complex
        • Rational
      • String

Classes

  • AbstractComplexType
  • ComplexType
  • ComplexTypeFactory
  • GMPComplexType
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Hard type support
  4:  * For when you absolutely want to know what you are getting
  5:  *
  6:  * @author Ashley Kitson <akitson@zf4.biz>
  7:  * @copyright Ashley Kitson, UK, 2014
  8:  * @licence GPL V3 or later : http://www.gnu.org/licenses/gpl.html
  9:  */
 10: 
 11: namespace chippyash\Type\Number\Complex;
 12: 
 13: use chippyash\Type\Number\Rational\RationalType;
 14: use chippyash\Type\Number\Rational\RationalTypeFactory;
 15: use chippyash\Type\Exceptions\NotRealComplexException;
 16: 
 17: /**
 18:  * A complex number - algabraic form
 19:  *
 20:  * A complex number is a number that can be expressed in the form a + bi,
 21:  * where a and b are real numbers and i is the imaginary unit,
 22:  * which satisfies the equation i² = −1
 23:  *
 24:  * Complex numbers use real numbers expressed as a RationalType.  This allows
 25:  * for greater arithmetic stability
 26:  *
 27:  * @link http://en.wikipedia.org/wiki/Complex_number
 28:  */
 29: class ComplexType extends AbstractComplexType
 30: {
 31:     /**
 32:      * Map of values for this type
 33:      * @var array
 34:      */
 35:     protected $valueMap = array(
 36:         0 => array(
 37:             'name' => 'real',
 38:             'class' => 'chippyash\Type\Number\Rational\RationalType'
 39:         ),
 40:         1 => array(
 41:             'name' => 'imaginary',
 42:             'class' => 'chippyash\Type\Number\Rational\RationalType'
 43:         )
 44:     );
 45: 
 46:     /**
 47:      * Constructor
 48:      *
 49:      * @param RationalType $real
 50:      * @param RationalType $imaginary
 51:      */
 52:     public function __construct(RationalType $real, RationalType $imaginary)
 53:     {
 54:         $this->setFromTypes(array($real, $imaginary));
 55:     }
 56: 
 57:     /**
 58:      * Return the number as a Complex number i.e. n+0i
 59:      * 
 60:      * @return \chippyash\Type\Number\Complex\ComplexType
 61:      */
 62:     public function asComplex()
 63:     {
 64:         return clone $this;
 65:     }
 66: 
 67:     /**
 68:      * Return number as Rational number.
 69:      * NB, numerator and denominator will be caste as IntTypes
 70:      *
 71:      * @return \chippyash\Type\Number\Rational\RationalType
 72:      *
 73:      * @throws NotRealComplexException
 74:      */
 75:     public function asRational()
 76:     {
 77:         if ($this->isReal()) {
 78:             return clone $this->value['real'];
 79:         } else {
 80:             throw new NotRealComplexException();
 81:         }
 82:     }
 83:     
 84:     /**
 85:      * Return the modulus, also known as absolute value or magnitude of this number
 86:      * = sqrt(r^2 + i^2);
 87:      *
 88:      * @return \chippyash\Type\Number\Rational\RationalType
 89:      */
 90:     public function modulus()
 91:     {
 92:         if ($this->isReal()) {
 93:             //sqrt(r^2 + 0^2) = sqrt(r^2) = abs(r)
 94:             /** @noinspection PhpUndefinedMethodInspection */
 95:             return $this->value['real']->abs();
 96:         }
 97:         //r^2 & i^2
 98:         $sqrR = array(
 99:             'n'=>pow($this->value['real']->numerator()->get(), 2),
100:             'd'=>pow($this->value['real']->denominator()->get(), 2)
101:         );
102:         $sqrI = array(
103:             'n'=>pow($this->value['imaginary']->numerator()->get(), 2),
104:             'd'=>pow($this->value['imaginary']->denominator()->get(), 2)
105:         );
106:         //r^2 + i^2
107:         $den = $this->lcm($sqrR['d'], $sqrI['d']);
108:         $num = ($sqrR['n'] * $den / $sqrR['d']) +
109:                ($sqrI['n'] * $den / $sqrI['d']);
110: 
111:         //sqrt(num/den) = sqrt(num)/sqrt(den)
112:         //now this a fudge - we ought to be able to get a proper square root using
113:         //factors etc but what we do instead is to do an approximation by converting
114:         //to intermediate rationals i.e.
115:         // rNum = RationaType(sqrt(num))
116:         // rDen = RationalType(sqrt(den))
117:         // mod = rN/1 * 1/rD
118:         $rNum = RationalTypeFactory::fromFloat(sqrt($num));
119:         $rDen = RationalTypeFactory::fromFloat(sqrt($den));
120:         $modN = $rNum->numerator()->get() * $rDen->denominator()->get();
121:         $modD = $rNum->denominator()->get() * $rDen->numerator()->get();
122: 
123:         return RationalTypeFactory::create($modN, $modD);
124:     }
125: 
126:     /**
127:      * Return the angle (sometimes known as the argument) of the number
128:      * when expressed in polar notation
129:      * 
130:      * The return value is a rational expressing theta as radians
131:      * 
132:      * @return \chippyash\Type\Number\Rational\RationalType
133:      */
134:     public function theta()
135:     {
136:         return RationalTypeFactory::fromFloat(
137:             atan2(
138:                 $this->value['imaginary']->asFloatType()->get(),
139:                 $this->value['real']->asFloatType()->get()
140:             )
141:         );
142:     }
143: 
144:     /**
145:      * Return Greatest Common Denominator of two numbers
146:      *
147:      * @param int $a
148:      * @param int $b
149:      *
150:      * @return int
151:      */
152:     private function gcd($a, $b)
153:     {
154:         return $b ? $this->gcd($b, $a % $b) : $a;
155:     }
156: 
157:     /**
158:      * Return Least Common Multiple of two numbers
159:      * @param int $a
160:      * @param int $b
161:      * @return int
162:      */
163:     private function lcm($a, $b)
164:     {
165:         return \abs(($a * $b) / $this->gcd($a, $b));
166:     }
167: }
168: 
Chippyash Strong Types API documentation generated by ApiGen 2.8.0