ref()); } /** * Reduce a matrix from REF to reduced row echelon form (row canonical form) - RREF * Factory method to create ReducedRowEchelonForm from a RowEchelonForm Matrix. * * @param RowEchelonForm $A * * @return ReducedRowEchelonForm * * @throws Exception\BadDataException * @throws Exception\BadParameterException * @throws Exception\IncorrectTypeException * @throws Exception\MatrixException */ public static function reduceFromRowEchelonForm(RowEchelonForm $A): ReducedRowEchelonForm { $m = $A->m; $n = $A->n; $R = $A; $ε = $A->getError(); // Starting conditions $row = 0; $col = 0; $rref = false; while (!$rref) { // No non-zero pivot, go to next column of the same row if (Support::isZero($R[$row][$col], $ε)) { $col++; if ($row >= $m || $col >= $n) { $rref = true; } continue; } // Scale pivot to 1 if ($R[$row][$col] != 1) { $divisor = $R[$row][$col]; $R = $R->rowDivide($row, $divisor); } // Eliminate elements above pivot for ($j = $row - 1; $j >= 0; $j--) { $factor = $R[$j][$col]; if (Support::isNotZero($factor, $ε)) { $R = $R->rowAdd($row, $j, -$factor); } } // Move on to next row and column $row++; $col++; // If no more rows or columns, rref achieved if ($row >= $m || $col >= $n) { $rref = true; } } $R = $R->getMatrix(); // Floating point adjustment for zero values for ($i = 0; $i < $m; $i++) { for ($j = 0; $j < $n; $j++) { if (Support::isZero($R[$i][$j], $ε)) { $R[$i][$j] = 0; } } } $rref = new ReducedRowEchelonForm($R); $rref->setError($ε); return $rref; } }