public function LUDecomposition() : array
{
if (!$this->isSquare()) {
throw new Exception\MatrixException('LU decomposition only works on square matrices');
}
$n = $this->n;
// Initialize L as diagonal ones matrix, and U as zero matrix
$L = (new DiagonalMatrix(array_fill(0, $n, 1)))->getMatrix();
$U = MatrixFactory::zero($n, $n)->getMatrix();
// Create permutation matrix P and pivoted PA
$P = $this->pivotize();
$PA = $P->multiply($this);
// Fill out L and U
for ($i = 0; $i < $n; $i++) {
// Calculate Uⱼᵢ
for ($j = 0; $j <= $i; $j++) {
$sum = 0;
for ($k = 0; $k < $j; $k++) {
$sum += $U[$k][$i] * $L[$j][$k];
}
$U[$j][$i] = $PA[$j][$i] - $sum;
}
// Calculate Lⱼᵢ
for ($j = $i; $j < $n; $j++) {
$sum = 0;
for ($k = 0; $k < $i; $k++) {
$sum += $U[$k][$i] * $L[$j][$k];
}
$L[$j][$i] = $U[$i][$i] == 0 ? \NAN : ($PA[$j][$i] - $sum) / $U[$i][$i];
}
}
// Assemble return array items: [L, U, P, A]
$this->L = MatrixFactory::create($L);
$this->U = MatrixFactory::create($U);
$this->P = $P;
return ['L' => $this->L, 'U' => $this->U, 'P' => $this->P, 'A' => MatrixFactory::create($this->A)];
}