def gaussJordan(M, epsilon=1e-08):
    """ transform the given matrix to reduced row-echelon form using Gauss-
        Jordan elimination 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:
            j = i + 1
            while j < nRows and abs(M[j, lead]) < epsilon:
                j += 1
            if j < nRows:
                temp = M[(i), :].copy()
                M[(i), :] = M[(j), :]
                M[(j), :] = temp
                break
            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), :]
        for j in range(i + 1, nRows):
            M[(j), :] -= M[j, lead] * M[(i), :]
        lead += 1
    return rank
