public ReducedRowEchelonForm(double[,] value, bool inPlace = false)
{
if (value == null)
throw new ArgumentNullException("value");
rref = inPlace ? value : (double[,])value.Clone();
int lead = 0;
rows = rref.GetLength(0);
cols = rref.GetLength(1);
pivot = new int[rows];
for (int i = 0; i < pivot.Length; i++)
pivot[i] = i;
for (int r = 0; r < rows; r++)
{
if (cols <= lead)
break;
int i = r;
while (rref[i, lead] == 0)
{
i++;
if (i >= rows)
{
i = r;
if (lead < cols - 1)
lead++;
else break;
}
}
if (i != r)
{
// Swap rows i and r
for (int j = 0; j < cols; j++)
{
var temp = rref[r, j];
rref[r, j] = rref[i, j];
rref[i, j] = temp;
}
// Update indices
{
var temp = pivot[r];
pivot[r] = pivot[i];
pivot[i] = temp;
}
}
// Set to reduced row echelon form
var div = rref[r, lead];
if (div != 0)
{
for (int j = 0; j < cols; j++)
rref[r, j] /= div;
}
for (int j = 0; j < rows; j++)
{
if (j != r)
{
var sub = rref[j, lead];
for (int k = 0; k < cols; k++)
rref[j, k] -= (sub * rref[r, k]);
}
}
lead++;
}
}