/** * Convert if possible a supplied argument to a rational * * @param int|float|string|NumericTypeInterface $value * * @return \Chippyash\Math\Matrix\RationalNumber * * @throws \Chippyash\Matrix\Exceptions\MatrixException * @throws \Exception */ protected function convertNumberToRational($value) { if ($value instanceof NumericTypeInterface) { return $value->asRational(); } switch (gettype($value)) { case 'integer': return RationalTypeFactory::create($value, 1); case 'double': return RationalTypeFactory::fromFloat($value); case 'string': try { return RationalTypeFactory::fromString($value); } catch (\Exception $e) { try { return ComplexTypeFactory::fromString($value)->asRational(); } catch (\Exception $ex) { throw new MatrixException('The string representation of the number is invalid for a rational'); } } case 'NULL': return RationalTypeFactory::create(0, 1); case 'boolean': return RationalTypeFactory::create($value ? 1 : 0, 1); default: throw new MatrixException('Rational expects int, float, string, Rational or NumericTypeInterface '); } }
public function testIntPowReturnsRationalOrIntOrComplexTypes() { $base = new IntType(5); $exp = new IntType(3); $this->assertInstanceOf('\\Chippyash\\Type\\Number\\IntType', $this->object->intPow($base, $exp)); $this->assertEquals(125, $this->object->intPow($base, $exp)->get()); $exp2 = new FloatType(3.5); $this->assertInstanceOf('\\Chippyash\\Type\\Number\\Rational\\RationalType', $this->object->intPow($base, $exp2)); $this->assertEquals('332922571/1191100', (string) $this->object->intPow($base, $exp2)); $exp3 = RationalTypeFactory::fromFloat(3.5); $this->assertInstanceOf('\\Chippyash\\Type\\Number\\Rational\\RationalType', $this->object->intPow($base, $exp3)); $this->assertEquals('332922571/1191100', (string) $this->object->intPow($base, $exp3)); $base2 = new IntType(4); $exp4 = ComplexTypeFactory::fromString('5+3i'); $pow = $this->object->intPow($base2, $exp4); $this->assertInstanceOf('\\Chippyash\\Type\\Number\\Complex\\ComplexType', $pow); $this->assertEquals('-778299179/1445876', (string) $pow->r()); $this->assertEquals('-861158767/988584', (string) $pow->i()); $exp5 = ComplexTypeFactory::fromString('0+3i'); $pow = $this->object->intPow($base2, $exp5); $this->assertInstanceOf('\\Chippyash\\Type\\Number\\Complex\\ComplexType', $pow); $this->assertEquals('-1722722/3277175', (string) $pow->r()); $this->assertEquals('-20905959/24575389', (string) $pow->i()); $exp6 = ComplexTypeFactory::fromString('5+0i'); $pow = $this->object->intPow($base2, $exp6); $this->assertInstanceOf('\\Chippyash\\Type\\Number\\Rational\\RationalType', $pow); $this->assertEquals(1024, $pow->get()); }
public function testPowWithRationalBaseReturnsRationalType() { $r = RationalTypeFactory::fromFloat(2.5); $p = $this->object->pow($r, new IntType(3)); $this->assertInstanceOf('Chippyash\\Type\\Number\\Rational\\RationalType', $p); $this->assertEquals('125/8', (string) $p); $p1 = $this->object->pow($r, new FloatType(3.2)); $this->assertInstanceOf('Chippyash\\Type\\Number\\Rational\\RationalType', $p1); $this->assertEquals('9893770810229553/527173799766761', (string) $p1); }
private function toStrongType(array $values, $expectedType) { $ns = '\\Chippyash\\Type\\Number\\'; $class = $ns . $expectedType; $ret = []; foreach ($values as $r => $row) { foreach ($row as $c => $item) { if ($expectedType == 'Rational\\RationalType') { $ret[$r][$c] = RationalTypeFactory::fromFloat($item); } else { $ret[$r][$c] = new $class($item); } } } return $ret; }
/** * Construct a complete Matrix with all entries set to Chippyash/Type * Takes a source matrix or array (which can be incomplete and converts each * entry to Chippyash/Type), setting a default value if entry does not exist. * * If a NumericMatrix is supplied as $source, the data is cloned into the Matrix * with no further checks. * * @param NumericMatrix|array $source Array to initialise the matrix with * @param mixed $normalizeDefault Value to set missing vertices * @throws \Chippyash\Math\Matrix\Exceptions\MathMatrixException */ public function __construct($source, $normalizeDefault = 0) { if ($source instanceof self) { $this->store($source->toArray()); return; } if (is_array($source)) { if (is_int($normalizeDefault)) { $default = TypeFactory::createInt($normalizeDefault); } elseif (is_float($normalizeDefault)) { $default = RationalTypeFactory::fromFloat($normalizeDefault); } elseif (!$normalizeDefault instanceof NumericTypeInterface) { throw new MathMatrixException('NumericMatrix expects numeric default value'); } else { $default = $normalizeDefault; } parent::__construct($source, false, true, $default); } else { throw new MathMatrixException('NumericMatrix expects NumericMatrix or array as source data'); } }
/** * Create and return a rational number matrix * $data elements are either: * - a RationalType * - string representations of rational number * - a PHP float * - a 2 item array representing numerator & denominator e.g. [2,-4] = '-2/4' * * @param array $data * * @return \Chippyash\Math\Matrix\RationalMatrix * * @throws \Chippyash\Math\Matrix\Exceptions\MathMatrixException */ public static function createRational(array $data) { foreach ($data as &$row) { foreach ($row as &$item) { if (!$item instanceof RationalType) { if (is_array($item) && count($item) == 2) { $item = RationalTypeFactory::create($item[0], $item[1]); } elseif (is_string($item)) { try { $item = RationalTypeFactory::fromString($item); } catch (\InvalidArgumentException $e) { throw new MathMatrixException('Invalid item type for Rational Matrix'); } } elseif (is_float($item)) { $item = RationalTypeFactory::fromFloat($item); } else { throw new MathMatrixException('Invalid item type for Rational Matrix'); } } } } return new RationalMatrix($data); }
/** * Convert to RationalType * * @param mixed $original * * @return \Chippyash\Type\Number\Rational\RationalType|\Chippyash\Type\Number\Rational\GMPRationalType * * @throws InvalidTypeException */ protected static function convertType($original) { if ($original instanceof AbstractRationalType) { return RationalTypeFactory::create($original->numerator()->get(), $original->denominator()->get()); } if (is_numeric($original)) { if (is_int($original)) { return RationalTypeFactory::create($original, 1); } //default - convert to float return RationalTypeFactory::fromFloat(floatval($original)); } if ($original instanceof FloatType) { return RationalTypeFactory::fromFloat($original()); } if ($original instanceof IntType) { return RationalTypeFactory::create($original, 1); } if (is_string($original)) { try { return RationalTypeFactory::fromString($original); } catch (\InvalidArgumentException $e) { throw new InvalidTypeException("{$original} for Complex type construction"); } } $type = gettype($original); throw new InvalidTypeException("{$type} for Complex type construction"); }
/** * @runInSeparateProcess */ public function testSetDefaultFromFloatToleranceIsStatic() { RationalTypeFactory::setDefaultFromFloatTolerance(1.0E-5); $this->assertEquals('113/355', (string) RationalTypeFactory::fromFloat(M_1_PI)); RationalTypeFactory::setDefaultFromFloatTolerance(1.0E-15); $this->assertEquals('25510582/80143857', (string) RationalTypeFactory::fromFloat(M_1_PI)); }
/** * Return the angle (sometimes known as the argument) of the number * when expressed in polar notation * * The return value is a rational expressing theta as radians * * @return \Chippyash\Type\Number\Rational\RationalType */ public function theta() { return RationalTypeFactory::fromFloat(atan2($this->value['imaginary']->asFloatType()->get(), $this->value['real']->asFloatType()->get())); }
/** * Create complex power from natural base and complex exponent * * @param int|float $base base * @param ComplexType $exp exponent * * @return NI|ComplexType */ private function complexExponent($base, ComplexType $exp) { if ($exp->isReal()) { return $this->rationalPow(RationalTypeFactory::fromFloat($base), $exp->r()); } //do the imaginary part //n^bi = cos(b.lg(n)) + i.sin(b.lg(n)) $b = $exp->i()->get(); $n = log($base); $r = cos($b * $n); $i = sin($b * $n); //no real part if ($exp->r()->get() == 0) { return new ComplexType(RationalTypeFactory::fromFloat($r), RationalTypeFactory::fromFloat($i)); } //real and imaginary part //n^a+bi = n^a(cos(b.lg(n)) + i.sin(b.lg(n))) $na = pow($base, $exp->r()->get()); $rr = $na * $r; $ii = $na * $i; return new ComplexType(RationalTypeFactory::fromFloat($rr), RationalTypeFactory::fromFloat($ii)); }
public function mixedMatrices() { return [[[[1, 2, 3]], TypeFactory::createInt(6)], [[[1], [2], [3]], TypeFactory::createInt(6)], [[[1, 2, 3], [1, 2, 3]], TypeFactory::createInt(12)], [[[1.1, 2, 3], [1, 2.2, 3]], RationalTypeFactory::fromFloat(12.3)], [[[0.5, 0.5]], RationalTypeFactory::create(1)]]; }
public function testMagicInvokeReturnsFloatForRealFloatComplexNumber() { $c = new ComplexType(RationalTypeFactory::fromFloat(2.5), $this->createRationalType(0)); $this->assertInternalType('float', $c()); $this->assertEquals(2.5, $c()); }
protected function toRational(array $dA) { foreach ($dA as &$row) { foreach ($row as &$entry) { if ($entry instanceof NumericTypeInterface) { $entry = $entry->asRational(); } elseif (is_numeric($entry)) { $entry = RationalTypeFactory::fromFloat(floatval($entry)); } else { $entry = $entry; } } } return new Matrix($dA); }
/** * Return number as Rational number. * NB, numerator and denominator will be caste as IntTypes * * @return \Chippyash\Type\Number\Rational\RationalType */ public function asRational() { return RationalTypeFactory::fromFloat($this->value); }
/** * Compare int and float types * * @param NI $a * @param NI $b * @return int */ protected function intFloatCompare(NI $a, NI $b) { return $this->rationalCompare(RationalTypeFactory::fromFloat($a->asFloatType()), RationalTypeFactory::fromFloat($b->asFloatType())); }