/**
  * 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 testComputeReturnsCorrectResult()
 {
     $testArray = [[1, 2, 3], [3, 2, 1], [2, 1, 3]];
     $expectedArray = [[RationalTypeFactory::create(3), RationalTypeFactory::create(4), RationalTypeFactory::create(5)], [RationalTypeFactory::create(5), RationalTypeFactory::create(4), RationalTypeFactory::create(3)], [RationalTypeFactory::create(4), RationalTypeFactory::create(3), RationalTypeFactory::create(5)]];
     $object = new RationalMatrix($testArray);
     $computation = new \Chippyash\Math\Matrix\Computation\Add\Scalar();
     $this->assertEquals($expectedArray, $object->compute($computation, 2)->toArray());
 }
 /**
  * Construct a complete Matrix with all entries set to a complex number
  * Takes a source matrix or array (which can be incomplete and converts each
  * entry to complex number type, setting a default value if entry does not exist.
  *
  * If a Matrix is supplied as $source, the data is cloned into the ComplexMatrix
  * converting to complex number values, with no further checks, although you
  * may get exceptions thrown if conversion is not possible.
  *
  * If you don't supply a default value, then 0+0i will be used
  *
  * @param Matrix|array $source Array to initialise the matrix with
  * @param ComplexType $normalizeDefault Value to set missing vertices
  *
  */
 public function __construct($source, ComplexType $normalizeDefault = null)
 {
     if (is_null($normalizeDefault)) {
         $ri = RationalTypeFactory::create(0, 1);
         $normalizeDefault = ComplexTypeFactory::create($ri, clone $ri);
     }
     parent::__construct($source, $normalizeDefault);
 }
function createMatrix($size)
{
    $c = 0;
    $fn = function ($r, $c) use(&$c) {
        return RationalTypeFactory::create($c++, 1);
    };
    $iSize = TypeFactory::createInt($size);
    return MatrixFactory::createFromFunction($fn, $iSize, $iSize, new StringType('rational'));
}
 /**
  * Create a new scalar based on type of original matrix
  *
  * @param \Chippyash\Math\Matrix\NumericMatrix $originalMatrix
  * @param scalar $scalar
  * @return Chippyash\Type\Interfaces\NumericTypeInterface
  *
  */
 protected function createCorrectScalarType(NumericMatrix $originalMatrix, $scalar)
 {
     if ($scalar instanceof NumericTypeInterface) {
         if ($originalMatrix instanceof RationalMatrix) {
             return $scalar->asRational();
         }
         if ($originalMatrix instanceof ComplexMatrix) {
             return $scalar->asComplex();
         }
         return $scalar;
     }
     if ($originalMatrix instanceof ComplexMatrix) {
         if (is_numeric($scalar)) {
             return ComplexTypeFactory::create($scalar, 0);
         }
         if (is_string($scalar)) {
             try {
                 return RationalTypeFactory::create($scalar)->asComplex();
             } catch (\Exception $e) {
                 //do nothing
             }
         }
         if (is_bool($scalar)) {
             return ComplexTypeFactory::create($scalar ? 1 : 0, 0);
         }
         return ComplexTypeFactory::create($scalar);
     }
     if ($originalMatrix instanceof RationalMatrix) {
         if (is_bool($scalar)) {
             $scalar = $scalar ? 1 : 0;
         }
         return RationalTypeFactory::create($scalar);
     }
     //handling for NumericMatrix
     if (is_int($scalar)) {
         return TypeFactory::createInt($scalar);
     } elseif (is_float($scalar)) {
         return TypeFactory::createRational($scalar);
     } elseif (is_bool($scalar)) {
         return TypeFactory::createInt($scalar ? 1 : 0);
     } elseif (is_string($scalar)) {
         try {
             return TypeFactory::createRational($scalar);
         } catch (\InvalidArgumentException $e) {
             try {
                 return ComplexTypeFactory::create($scalar);
             } catch (\InvalidArgumentException $e) {
                 //do nothing
             }
         }
     }
     throw new ComputationException('Scalar parameter is not a supported type for numeric matrices: ' . getType($scalar));
 }
Exemple #6
0
 /**
  * @dataProvider luData
  *
  */
 public function testDecomposeReturnsCorrectResult($source, $LUD, $LD, $UD, $pivotVectorD, $permutationMatrixD, $det)
 {
     $mA = new RationalMatrix($source);
     $LU = new RationalMatrix($LUD);
     $L = new RationalMatrix($LD);
     $U = new RationalMatrix($UD);
     $pivotVector = new RationalMatrix($pivotVectorD);
     $permutationMatrix = new RationalMatrix($permutationMatrixD);
     $decomp = $this->object->decompose($mA);
     //        var_dump($decomp->Det);return;
     $this->assertEquals($LU, $this->object->LU, 'LU matrix incorrect');
     $this->assertEquals($L, $this->object->L, 'L matrix incorrect');
     $this->assertEquals($U, $this->object->U, 'U matrix incorrect');
     $this->assertEquals($pivotVector, $this->object->PivotVector, 'PivotVector matrix incorrect');
     $this->assertEquals($permutationMatrix, $this->object->PermutationMatrix, 'Permutation matrix incorrect');
     $det = is_null($det) ? null : RTF::create($det);
     $this->assertEquals($det, $this->object->Det, 'Determinant incorrect');
 }
 /**
  * Construct a square NumericMatrix whose entries on the diagonal ==  1, 1/1 or 1+0i
  * All other entries == 0, 0/1 or 0+0i
  *
  * @param IntType $size Number of required rows and columns
  * @param IntType $identityType Type of identity entries: default == IDM_TYPE_INT
  *
  * @throws \InvalidArgumentException
  */
 public function __construct(IntType $size, IntType $identityType = null)
 {
     if (is_null($identityType)) {
         $idt = self::IDM_TYPE_INT;
     } else {
         $idt = $identityType();
     }
     if (!in_array($idt, $this->availableTypes)) {
         throw new \InvalidArgumentException('Identity type invalid');
     }
     if ($size() < 1) {
         throw new \InvalidArgumentException('size must be >= 1');
     }
     $f = function ($row, $col) use($idt) {
         if ($idt == self::IDM_TYPE_RATIONAL) {
             return RationalTypeFactory::create($row == $col ? 1 : 0, 1);
         } elseif ($idt == self::IDM_TYPE_COMPLEX) {
             return ComplexTypeFactory::create(RationalTypeFactory::create($row == $col ? 1 : 0, 1), RationalTypeFactory::create(0, 1));
         } else {
             return TypeFactory::createInt($row == $col ? 1 : 0);
         }
     };
     parent::__construct($f, $size, $size);
 }
 public function testCreateRationalMatrixWithRationalTypeEntriesReturnsRationalMatrix()
 {
     $data = [[RF::create(1, -3), RF::create(-4, 6), RF::create(12, 3)]];
     $this->assertInstanceOf('Chippyash\\Math\\Matrix\\RationalMatrix', MatrixFactory::createRational($data));
 }
 public function nonComplexNumbers()
 {
     return [[RationalTypeFactory::create(2, 5)]];
 }
 /**
  * Return the modulus, also known as absolute value or magnitude of this number
  * = sqrt(r^2 + i^2);
  *
  * @return \Chippyash\Type\Number\Rational\GMPRationalType
  */
 public function modulus()
 {
     if ($this->isReal()) {
         //sqrt(r^2 + 0^2) = sqrt(r^2) = abs(r)
         /** @noinspection PhpUndefinedMethodInspection */
         return $this->value['real']->abs();
     }
     //get r^2 and i^2
     $sqrR = array('n' => gmp_pow($this->value['real']->numerator()->gmp(), 2), 'd' => gmp_pow($this->value['real']->denominator()->gmp(), 2));
     $sqrI = array('n' => gmp_pow($this->value['imaginary']->numerator()->gmp(), 2), 'd' => gmp_pow($this->value['imaginary']->denominator()->gmp(), 2));
     //r^2 + i^2
     $den = $this->lcm($sqrR['d'], $sqrI['d']);
     $numRaw = gmp_strval(gmp_add(gmp_div_q(gmp_mul($sqrR['n'], $den), $sqrR['d']), gmp_div_q(gmp_mul($sqrI['n'], $den), $sqrI['d'])));
     $num = TypeFactory::createInt($numRaw);
     //sqrt(num/den) = sqrt(num)/sqrt(den)
     //now this a fudge - we ought to be able to get a proper square root using
     //factors etc but what we do instead is to do an approximation by converting
     //to intermediate rationals using as much precision as we can i.e.
     // rNum = GMPRationaType(sqrt(num))
     // rDen = GMPRationalType(sqrt(den))
     // mod = rN/1 * 1/rD
     $rNum = RationalTypeFactory::fromFloat(sqrt($num()));
     $rDen = RationalTypeFactory::fromFloat(sqrt(gmp_strval($den)));
     $modN = gmp_mul($rNum->numerator()->gmp(), $rDen->denominator()->gmp());
     $modD = gmp_mul($rNum->denominator()->gmp(), $rDen->numerator()->gmp());
     return RationalTypeFactory::create((int) gmp_strval($modN), (int) gmp_strval($modD));
 }
Exemple #11
0
 public function computeMatrices()
 {
     //set required type as data is generated before tests
     RequiredType::getInstance()->set(RequiredType::TYPE_NATIVE);
     return [[[[1, 2, 3], [3, 2, 1], [2, 1, 3]], [[TypeFactory::createInt(2), TypeFactory::createInt(4), TypeFactory::createInt(6)], [TypeFactory::createInt(6), TypeFactory::createInt(4), TypeFactory::createInt(2)], [TypeFactory::createInt(4), TypeFactory::createInt(2), TypeFactory::createInt(6)]], 2], [[[1, 2, 3]], [[RationalTypeFactory::create(2.5), RationalTypeFactory::create(5.0), RationalTypeFactory::create(7.5)]], 2.5], [[[1.5, 2.5, 3.5]], [[RationalTypeFactory::create(3.0), RationalTypeFactory::create(5.0), RationalTypeFactory::create(7.0)]], 2], [[[1.12, 2.12, 3.12]], [[RationalTypeFactory::create(1.12), RationalTypeFactory::create(2.12), RationalTypeFactory::create(3.12)]], 1.0], [[[1, 2, 3]], [[TypeFactory::createInt(1), TypeFactory::createInt(2), TypeFactory::createInt(3)]], true], [[[1, 2, 3]], [[TypeFactory::createInt(0), TypeFactory::createInt(0), TypeFactory::createInt(0)]], false], [[[true, false]], [[TypeFactory::createInt(1), TypeFactory::createInt(0)]], true], [[[true, false]], [[TypeFactory::createInt(0), TypeFactory::createInt(0)]], false]];
 }
 /**
  * @expectedException Chippyash\Type\Exceptions\InvalidTypeException
  * @expectedExceptionMessage Invalid Type: integer:object for Rational type construction
  */
 public function testCreateFromUnsupportedTypeForDenominatorThrowsException()
 {
     RationalTypeFactory::create(2, new \stdClass());
 }
 public function correctResults()
 {
     //set required type as data created before tests are run
     RequiredType::getInstance()->set(RequiredType::TYPE_NATIVE);
     return [[1, 2, new IntType(3)], [new IntType(1), 2, new IntType(3)], [1, new IntType(2), new IntType(3)], [new IntType(1), new IntType(2), new IntType(3)], [2.0, 3.0, new FloatType(5.0)], [new FloatType(2.0), 3.0, new FloatType(5.0)], [2.0, new FloatType(3.0), new FloatType(5.0)], [new FloatType(2.0), new FloatType(3.0), new FloatType(5.0)], [new IntType(2), 3.0, new FloatType(5.0)], [new WholeIntType(2), 3, new WholeIntType(5)], [2, new WholeIntType(3), new WholeIntType(5)], [new NaturalIntType(2), 3, new NaturalIntType(5)], [2, new NaturalIntType(3), new NaturalIntType(5)], [RationalTypeFactory::create(4), RationalTypeFactory::create(4), RationalTypeFactory::create(8)]];
 }
Exemple #14
0
 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 testCanComputeRootsUsingPow()
 {
     $this->assertEquals(3, $this->object->pow(new IntType(27), RationalTypeFactory::create(1, 3))->get());
     $this->assertEquals('3/4', (string) $this->object->pow(RationalTypeFactory::create(27, 64), RationalTypeFactory::create(1, 3)));
     $this->assertEquals('32479891/17872077+17872077/32479891i', (string) $this->object->pow(ComplexTypeFactory::fromString('3+2i'), RationalTypeFactory::create(1, 2)));
 }
 /**
  * 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);
 }
 public function testSqrtRationalTypeReturnsRationalType()
 {
     $res = $this->object->sqrt(RationalTypeFactory::create(7));
     $this->assertInstanceOf('\\Chippyash\\Type\\Number\\Rational\\RationalType', $res);
     $this->assertEquals('46256493/17483311', (string) $res);
 }
 /**
  * Complex sqrt
  *
  * @param ComplexType $a operand
  *
  * @return ComplexType
  */
 public function complexSqrt(ComplexType $a)
 {
     return $this->complexPow($a, RationalTypeFactory::create(1, 2));
 }
 public function nonComplexNumbers()
 {
     return [[2], [-2.4], [new FloatType(2)], [new FloatType(2.6)], [RationalTypeFactory::create(1, 5)], [new WholeIntType(3)], [new NaturalIntType(6)]];
 }
 /**
  * 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");
 }
Exemple #21
0
 /**
  * Return the modulus, also known as absolute value or magnitude of this number
  * = sqrt(r^2 + i^2);
  *
  * @return \Chippyash\Type\Number\Rational\RationalType
  */
 public function modulus()
 {
     if ($this->isReal()) {
         //sqrt(r^2 + 0^2) = sqrt(r^2) = abs(r)
         /** @noinspection PhpUndefinedMethodInspection */
         return $this->value['real']->abs();
     }
     //r^2 & i^2
     $sqrR = array('n' => pow($this->value['real']->numerator()->get(), 2), 'd' => pow($this->value['real']->denominator()->get(), 2));
     $sqrI = array('n' => pow($this->value['imaginary']->numerator()->get(), 2), 'd' => pow($this->value['imaginary']->denominator()->get(), 2));
     //r^2 + i^2
     $den = $this->lcm($sqrR['d'], $sqrI['d']);
     $num = $sqrR['n'] * $den / $sqrR['d'] + $sqrI['n'] * $den / $sqrI['d'];
     //sqrt(num/den) = sqrt(num)/sqrt(den)
     //now this a fudge - we ought to be able to get a proper square root using
     //factors etc but what we do instead is to do an approximation by converting
     //to intermediate rationals i.e.
     // rNum = RationaType(sqrt(num))
     // rDen = RationalType(sqrt(den))
     // mod = rN/1 * 1/rD
     $rNum = RationalTypeFactory::fromFloat(sqrt($num));
     $rDen = RationalTypeFactory::fromFloat(sqrt($den));
     $modN = $rNum->numerator()->get() * $rDen->denominator()->get();
     $modD = $rNum->denominator()->get() * $rDen->numerator()->get();
     return RationalTypeFactory::create($modN, $modD);
 }
 public function testReciprocalOfRationalTypeReturnsRationalType()
 {
     $this->assertInstanceOf('Chippyash\\Type\\Number\\Rational\\RationalType', $this->object->reciprocal(RationalTypeFactory::create(2, 1)));
 }
 /**
  * Perform Guass Jordan Elimination on the two supplied matrices
  *
  * @param NumericMatrix $mA First matrix to act on - required
  * @param NumericMatrix $extra Second matrix to act upon - required
  *
  * @return \Chippyash\Math\Matrix\DecompositionAbstractDecomposition Fluent Interface
  *
  * @throws \Chippyash\Math\Matrix\Exceptions\SingularMatrixException
  */
 public function decompose(NumericMatrix $mA, $extra = null)
 {
     $this->assertParameterIsMatrix($extra, 'Parameter extra is not a matrix')->assertMatrixIsNumeric($extra, 'Parameter extra is not a numeric matrix')->assertMatrixIsSquare($mA, 'Parameter mA is not a square matrix')->assertMatrixRowsAreEqual($mA, $extra, 'mA->rows != extra->rows');
     $rows = $mA->rows();
     $dA = $mA->toArray();
     $dB = $extra->toArray();
     $zero = function () {
         return RationalTypeFactory::create(0, 1);
     };
     $one = function () {
         return RationalTypeFactory::create(1, 1);
     };
     $calc = new Calculator();
     $comp = new Comparator();
     $ipiv = array_fill(0, $rows, $zero());
     $indxr = array_fill(0, $rows, 0);
     $indxc = array_fill(0, $rows, 0);
     // find the pivot element by searching the entire matrix for its largest value, but excluding columns already reduced.
     $irow = $icol = 0;
     for ($i = 0; $i < $rows; $i++) {
         $big = $zero();
         for ($j = 0; $j < $rows; $j++) {
             if ($comp->neq($ipiv[$j], $one())) {
                 for ($k = 0; $k < $rows; $k++) {
                     if ($comp->eq($ipiv[$k], $zero())) {
                         $absVal = $dA[$j][$k]->abs();
                         if ($comp->gt($absVal, $big)) {
                             unset($big);
                             $big = clone $absVal;
                             $irow = $j;
                             $icol = $k;
                         }
                     } elseif ($comp->gt($ipiv[$k], $one())) {
                         throw new SingularMatrixException('GaussJordanElimination');
                     }
                 }
             }
         }
         //Now interchange row to move the pivot element to a diagonal
         $ipiv[$icol] = $calc->add($ipiv[$icol], $one());
         if ($irow != $icol) {
             $this->swapRows($dA, $irow, $icol);
             $this->swapRows($dB, $irow, $icol);
         }
         // Remember permutations to later
         $indxr[$i] = $irow;
         $indxc[$i] = $icol;
         if ($comp->eq($dA[$icol][$icol], $zero())) {
             throw new SingularMatrixException('GaussJordanElimination');
         }
         // Now divide the found row to make the pivot element 1
         // To maintain arithmetic integrity we use the reciprocal to multiply by
         $pivinv = $calc->reciprocal($dA[$icol][$icol]);
         $this->multRow($dA, $icol, $pivinv, $calc);
         $this->multRow($dB, $icol, $pivinv, $calc);
         // And reduce all other rows but the pivoted row with the value of the pivot row
         for ($ll = 0; $ll < $rows; $ll++) {
             if ($ll != $icol) {
                 $multiplier = clone $dA[$ll][$icol];
                 $multiplier->negate();
                 $this->addMultipleOfOtherRowToRow($dA, $multiplier, $icol, $ll, $calc);
                 $this->addMultipleOfOtherRowToRow($dB, $multiplier, $icol, $ll, $calc);
             }
         }
     }
     $this->set('left', $this->createCorrectMatrixType($mA, $dA));
     $this->set('right', $this->createCorrectMatrixType($extra, $dB));
     return clone $this;
 }
Exemple #24
0
 /**
  * Create a Rational number
  * @see RationalTypeFactory::create
  *
  * @param int|string|float $numerator
  * @param int $denominator
  *
  * @return \Chippyash\Type\Number\Rational\RationalType
  */
 public static function createRational($numerator, $denominator = 1)
 {
     return RationalTypeFactory::create($numerator, $denominator);
 }