def ref2rref(M, epsilon=1e-08):
    """ convert a matrix M that is already in row-echelon form to reduced
        row-echelon form and read off the rank of M. The operation is performed
        in place, i.e. M is overwritten with the result.
    """
    lead = 0
    nRows, nCols = M.shape
    rank = nRows
    for i in range(nRows):
        while lead < nCols and abs(M[i, lead]) < epsilon:
            lead += 1
        if lead >= nCols:
            rank = i
            break
        M[(i), :] /= M[i, lead]
        for j in range(i):
            M[(j), :] -= M[j, lead] * M[(i), :]
        lead += 1
    return rank
