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, 2012
  8:  * @licence GPL V3 or later : http://www.gnu.org/licenses/gpl.html
  9:  */
 10: namespace chippyash\Type\Number\Complex;
 11: 
 12: use chippyash\Type\AbstractMultiValueType;
 13: use chippyash\Type\TypeFactory;
 14: use chippyash\Type\Interfaces\ComplexTypeInterface;
 15: use chippyash\Type\Interfaces\NumericTypeInterface;
 16: use chippyash\Type\Number\Rational\RationalType;
 17: use chippyash\Type\Exceptions\NotRealComplexException;
 18: 
 19: /**
 20:  * Abstract complex number type
 21:  */
 22: abstract class AbstractComplexType extends AbstractMultiValueType implements ComplexTypeInterface, NumericTypeInterface
 23: {
 24:     /**
 25:      * Map of values for this type
 26:      * @var array
 27:      */
 28:     protected $valueMap = array(
 29:         0 => array(
 30:             'name' => 'real',
 31:             'class' => 'chippyash\Type\Interfaces\NumericTypeInterface'
 32:         ),
 33:         1 => array(
 34:             'name' => 'imaginary',
 35:             'class' => 'chippyash\Type\Interfaces\NumericTypeInterface'
 36:         )
 37:     );
 38: 
 39:     /**
 40:      * Return the modulus, also known as absolute value or magnitude of this number
 41:      * = sqrt(r^2 + i^2);
 42:      *
 43:      * @return \chippyash\Type\Number\Rational\RationalType
 44:      */
 45:     abstract public function modulus();
 46:     
 47:     /**
 48:      * Return the angle (sometimes known as the argument) of the number
 49:      * when expressed in polar notation
 50:      * 
 51:      * The return value is a rational expressing theta as radians
 52:      * 
 53:      * @return \chippyash\Type\Number\Rational\RationalType
 54:      */
 55:     abstract public function theta();
 56:     
 57:     /**
 58:      * Return the number as a Complex number i.e. n+0i
 59:      * 
 60:      * @return \chippyash\Type\Number\Complex\ComplexType
 61:      */
 62:     abstract public function asComplex();
 63: 
 64:     /**
 65:      * Return number as Rational number.
 66:      * NB, numerator and denominator will be caste as IntTypes
 67:      *
 68:      * @return \chippyash\Type\Number\Rational\RationalType
 69:      *
 70:      * @throws NotRealComplexException
 71:      */
 72:     abstract public function asRational();
 73: 
 74:     /**
 75:      * Return complex number expressed as a string in polar form
 76:      * i.e. r(cosθ + i⋅sinθ)
 77:      *
 78:      * @return string
 79:      */
 80:     public function polarString()
 81:     {
 82:         if ($this->isZero()) {
 83:             return '0';
 84:         }
 85: 
 86:         $rho = $this->checkIntType($this->radius()->asFloatType()->get());
 87:         $theta = $this->checkIntType($this->theta()->asFloatType()->get());
 88:         if (is_int($theta)) {
 89:             $tpattern = 'cos %1$d + i⋅sin %1$d';
 90:         } else {
 91:             $tpattern = 'cos %1$f + i⋅sin %1$f';
 92:         }
 93:         if ($rho == 1) {
 94:             return sprintf($tpattern, $theta);
 95:         }
 96:         if (is_int($rho)) {
 97:             $rpattern = '%2$d';
 98:         } else {
 99:             $rpattern = '%2$f';
100:         }
101:         $pattern = "{$rpattern}({$tpattern})";
102:         return sprintf($pattern, $theta, $rho);
103:     }
104: 
105:     /**
106:      * Return number as an IntType number.
107:      * If number isReal() will return floor(r())
108:      *
109:      * @return \chippyash\Type\Number\IntType
110:      * @throws NotRealComplexException
111:      */
112:     public function asIntType()
113:     {
114:         if ($this->isReal()) {
115:             /** @noinspection PhpUndefinedMethodInspection */
116:             return TypeFactory::create('int', floor($this->value['real']->get()));
117:         } else {
118:             throw new NotRealComplexException();
119:         }
120:     }
121: 
122:     /**
123:      * Return number as a FloatType number.
124:      *
125:      * @return \chippyash\Type\Number\FloatType
126:      * @throws NotRealComplexException
127:      */
128:     public function asFloatType()
129:     {
130:         if ($this->isReal()) {
131:             return TypeFactory::create('float', $this->value['real']->get());
132:         } else {
133:             throw new NotRealComplexException();
134:         }
135:     }
136: 
137:     /**
138:      * If this complex number isReal() then return float equivalent
139:      * else throw an excepton
140:      *
141:      * @return float
142:      *
143:      * @throws NotRealComplexException
144:      */
145:     public function toFloat()
146:     {
147:         if ($this->isReal()) {
148:             return $this->value['real']->get();
149:         } else {
150:             throw new NotRealComplexException();
151:         }
152:     }
153:     
154:     /**
155:      * Return the absolute value of the number
156:      * 
157:      * @abstract
158:      *
159:      * @return \chippyash\Type\Number\Rational\AbstractRationalType
160:      */
161:     public function abs()
162:     {
163:         return $this->modulus();
164:     }
165:     
166: 
167:     /**
168:      * Negates the number
169:      *
170:      * @return \chippyash\Type\Number\Complex\ComplexType Fluent Interface
171:      */
172:     public function negate()
173:     {
174:         $this->value['real']->negate();
175:         $this->value['imaginary']->negate();
176: 
177:         return $this;
178:     }
179: 
180:     /**
181:      * Get the real part
182:      * @return RationalType
183:      */
184:     public function r()
185:     {
186:         return $this->value['real'];
187:     }
188: 
189:     /**
190:      * Get the imaginary part
191:      *
192:      * @return RationalType
193:      */
194:     public function i()
195:     {
196:         return $this->value['imaginary'];
197:     }
198:     
199:     /**
200:      * Is this number equal to zero?
201:      * @return boolean
202:      */
203:     public function isZero()
204:     {
205:         return ($this->value['real']->get() == 0 && $this->value['imaginary']->get() == 0);
206:     }
207: 
208:     /**
209:      * Is this number a real number?  i.e. is it in form n+0i
210:      *
211:      * @return boolean
212:      */
213:     public function isReal()
214:     {
215:         return ($this->value['imaginary']->numerator()->get() == 0);
216:     }
217:     
218:     /**
219:      * Is this number Gaussian, i.e r & i are both equivelent to integers
220:      *
221:      * @return boolean
222:      * @link http://en.wikipedia.org/wiki/Gaussian_integer
223:      */
224:     public function isGaussian()
225:     {
226:         return ($this->value['real']->denominator()->get() == 1  && 
227:                 $this->value['imaginary']->denominator()->get() == 1);
228:     }
229:     
230:     /**
231:      * Return conjugate of this number
232:      * @return \chippyash\Type\Number\Complex\ComplexType
233:      */
234:     public function conjugate()
235:     {
236:         $imaginary = clone $this->value['imaginary'];
237:         return new static(clone $this->value['real'], $imaginary->negate());
238:     }
239:     
240:     /**
241:      * Return the radius (sometimes known as Rho) of the number
242:      * when expressed in polar notation
243:      * 
244:      * @return \chippyash\Type\Number\Rational\RationalType
245:      */
246:     public function radius()
247:     {
248:         return $this->modulus();
249:     }
250: 
251:     /**
252:      * Returns complex number expressed in polar form
253:      * 
254:      * `radius` == this->modulus()
255:      * `theta` is angle expressed in radians
256:      * 
257:      * @return array[radius => RationalType, theta => RationalType] 
258:      */
259:     public function asPolar()
260:     {
261:         return array('radius'=>$this->modulus(), 'theta'=>$this->theta());
262:     }
263:     
264:     /**
265:      * Returns the polar quadrant for the complex number
266:      * Returns 1, 2, 3 or 4 dependent on the quadrant
267:      * 
268:      * @return int
269:      */
270:     public function polarQuadrant()
271:     {
272:         $signR = ($this->value['real']->numerator()->get() > 0 ? '+' : '-');
273:         $signI = ($this->value['imaginary']->numerator()->get() > 0 ? '+' : '-');
274:         $ret = 0;
275:         switch ("{$signR}{$signI}") {
276:             case '++':
277:                 $ret = 1;
278:                 break;
279:             case '-+':
280:                 $ret = 2;
281:                 break;
282:             case '--':
283:                 $ret = 3;
284:                 break;
285:             case '+-':
286:                 $ret = 4;
287:                 break;
288:         }
289: 
290:         return $ret;
291:     }
292: 
293:     /**
294:      * String representation of complex number
295:      * If isReal() then string representation of the real part
296:      * else r(+/-)ii
297:      *
298:      * @return string
299:      */
300:     public function __toString()
301:     {
302:         if ($this->isZero()) {
303:             return '0';
304:         }
305:         
306:         $real = (string) $this->value['real'];
307: 
308:         if ($this->isReal()) {
309:             return $real;
310:         }
311: 
312:         $imaginary = (string) $this->value['imaginary'];
313:         if ($imaginary[0] != '-') {
314:             $imaginary = '+' . $imaginary;
315:         }
316:         return "{$real}{$imaginary}i";
317:     }
318:     
319:     /**
320:      * Magic clone method
321:      * Ensure value gets cloned when object is cloned
322:      *
323:      * @return void
324:      */
325:     public function __clone()
326:     {
327:         $this->value['real'] = clone $this->value['real'];
328:         $this->value['imaginary'] = clone $this->value['imaginary'];
329:     }
330: 
331:     /**
332:      * Proxy to get()
333:      *
334:      * @return string
335:      */
336:     public function __invoke()
337:     {
338:         return $this->get();
339:     }
340:     
341:     /**
342:      * Return multi value as native PHP type
343:      * 
344:      * @return float|int|string
345:      */
346:     protected function getAsNativeType()
347:     {
348:         if ($this->isZero()) {
349:             return 0;
350:         }
351:         if ($this->isReal()) {
352:             return $this->value['real']->get();
353:         }
354:         //return as string
355:         return (string) $this;
356:     }
357: 
358:     /**
359:      * @param $value
360:      * @return int|float
361:      */
362:     protected function checkIntType($value)
363:     {
364:         $test = intval($value);
365:         if (($value - $test) == 0) {
366:             return $test;
367:         }
368: 
369:         return $value;
370:     }
371: }
372: 
Chippyash Strong Types API documentation generated by ApiGen 2.8.0