function _rref (mat, rows, cols) {
    const M = clone(mat)
    let lead = 0
    for (let r = 0; r < rows; r++) {
      if (cols <= lead) {
        return M
      }
      let i = r
      while (_isZero(M[i][lead])) {
        i++
        if (rows === i) {
          i = r
          lead++
          if (cols === lead) {
            return M
          }
        }
      }

      [M[i], M[r]] = [M[r], M[i]]

      let val = M[r][lead]
      for (let j = 0; j < cols; j++) {
        M[r][j] = dotDivide(M[r][j], val)
      }

      for (let i = 0; i < rows; i++) {
        if (i === r) continue
        val = M[i][lead]
        for (let j = 0; j < cols; j++) {
          M[i][j] = add(M[i][j], multiply(-1, multiply(val, M[r][j])))
        }
      }
      lead++
    }
    return M
  }
Calculate the reduced row echelon form of a matrix

Modified from https://rosettacode.org/wiki/Reduced_row_echelon_form

@param {Array[]} mat     A matrix
@param {number} rows     Number of rows
@param {number} cols     Number of columns
@return {Array[]}        Reduced row echelon form
@private