public JaggedReducedRowEchelonForm(double[][] value, bool inPlace = false)
{
if (value == null)
throw new ArgumentNullException("value");
rref = inPlace ? value : value.MemberwiseClone();
int lead = 0;
rows = rref.Length;
cols = rref[0].Length;
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++;
}
}