/** * @inheritDoc */ public function derive(NumericMatrix $mA, $extra = null) { if ($mA->is('empty')) { return TypeFactory::createInt(0); } if ($mA->is('singleitem')) { return $mA->get(1, 1); } $calc = new Calculator(); return array_reduce($mA->toArray(), function ($c1, $row) use($calc) { return array_reduce($row, function ($carry, $item) use($calc) { return $calc->add($item, $carry); }, $c1); }, TypeFactory::createInt(0)); }
/** * Carry out the actual multiplication using standard matrix multiplication * method. * * @param \Chippyash\Math\Matrix\NumericMatrix $mA * @param \Chippyash\Math\Matrix\NumericMatrix $mB * @return array * @throws ComputationException */ protected function doComputation(NumericMatrix $mA, NumericMatrix $mB) { $size = max([$mA->columns(), $mA->rows(), $mB->columns(), $mB->rows()]); $product = (new ZMatrix())->create([$size, $size])->toArray(); $dA = $mA->toArray(); $dB = $mB->toArray(); $zero = $this->createCorrectScalarType($mA, 0); $calc = new Calculator(); for ($i = 0; $i < $size; $i++) { for ($k = 0; $k < $size; $k++) { for ($j = 0; $j < $size; $j++) { $a = isset($dA[$i][$k]) ? $dA[$i][$k] : $zero; $b = isset($dB[$k][$j]) ? $dB[$k][$j] : $zero; $product[$i][$j] = $calc->add($product[$i][$j], $calc->mul($a, $b)); } } } return $product; }
/** * 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'); } }
/** * LU Decomposition constructor. * * @param \Chippyash\Math\Matrix\NumericMatrix $mA */ protected function LUDecomposition(NumericMatrix $mA) { // Use a "left-looking", dot-product, Crout/Doolittle algorithm. $LU = $mA->toArray(); $m = $this->rows = $mA->rows(); $n = $this->cols = $mA->columns(); for ($i = 0; $i < $m; $i++) { $this->piv[$i] = $i; } $this->pivsign = 1; $LUrowi = []; $LUcolj = []; $calc = new Calculator(); $comp = new Comparator(); $zeroInt = $this->createCorrectScalarType($mA, 0); // Outer loop. for ($j = 0; $j < $n; $j++) { // Make a copy of the j-th column to localize references. for ($i = 0; $i < $m; $i++) { $LUcolj[$i] =& $LU[$i][$j]; } // Apply previous transformations. for ($i = 0; $i < $m; $i++) { $LUrowi = $LU[$i]; // Most of the time is spent in the following dot product. $kmax = min($i, $j); $s = clone $zeroInt; for ($k = 0; $k < $kmax; $k++) { $s = $calc->add($s, $calc->mul($LUrowi[$k], $LUcolj[$k])); } $LUcolj[$i] = $calc->sub($LUcolj[$i], $s); $LUrowi[$j] = $LUcolj[$i]; } // Find pivot and exchange if necessary. $p = $j; for ($i = $j + 1; $i < $m; $i++) { if ($comp->gt($LUcolj[$i]->abs(), $LUcolj[$p]->abs())) { $p = $i; } } if ($p != $j) { for ($k = 0; $k < $n; $k++) { //swap $t = $LU[$p][$k]; $LU[$p][$k] = $LU[$j][$k]; $LU[$j][$k] = $t; } $k = $this->piv[$p]; $this->piv[$p] = $this->piv[$j]; $this->piv[$j] = $k; $this->pivsign = $this->pivsign * -1; } // Compute multipliers. if ($j < $m && $comp->neq($LU[$j][$j], $zeroInt)) { for ($i = $j + 1; $i < $m; $i++) { $LU[$i][$j] = $calc->div($LU[$i][$j], $LU[$j][$j]); } } } $this->set('LU', $this->createCorrectMatrixType($mA, $LU)); }