code: def _dm_rref_choose_method_ZZ(M, *, denominator=False):
      """Choose the fastest method for computing RREF over ZZ."""
      # In the extreme of very sparse matrices and low bit counts it is faster to
      # use Gauss-Jordan elimination over QQ rather than fraction-free
      # Gauss-Jordan over ZZ. In the opposite extreme of dense matrices and high
      # bit counts it is faster to use fraction-free Gauss-Jordan over ZZ. These
      # two extreme cases need to be handled differently because they lead to
      # different asymptotic complexities. In between these two extremes we need
      # a threshold for deciding which method to use. This threshold is
      # determined empirically by timing the two methods with random matrices.
  
      # The disadvantage of using empirical timings is that future optimisations
      # might change the relative speeds so this can easily become out of date.
      # The main thing is to get the asymptotic complexity right for the extreme
      # cases though so the precise value of the threshold is hopefully not too
      # important.
  
      # Empirically determined parameter.
      PARAM = 10000
  
      # First compute the density. This is the average number of non-zero entries
      # per row but only counting rows that have at least one non-zero entry
      # since RREF can ignore fully zero rows.
      density, nrows_nz, ncols = _dm_row_density(M)
  
      # For small matrices use QQ if more than half the entries are zero.
      if nrows_nz < 10:
          if density < ncols / 2:
              return "GJ"
          else:
              return "FF"
  
      # These are just shortcuts for the formula below.
      if density < 5:
          return "GJ"
      elif density > 5 + PARAM / nrows_nz:
          return "FF"  # pragma: no cover
  
      # Maximum bitsize of any entry.
      elements = _dm_elements(M)
      bits = max([e.bit_length() for e in elements], default=1)
  
      # Wideness parameter. This is 1 for square or tall matrices but >1 for wide
      # matrices.
      wideness = max(1, 2 / 3 * ncols / nrows_nz)
  
      max_density = (5 + PARAM / (nrows_nz * bits**2)) * wideness
  
      if density < max_density:
          return "GJ"
      else:
          return "FF"
  
file_path: sympy/sympy/polys/matrices/rref.py
imports: from sympy.polys.domains import ZZ
  from sympy.polys.matrices.sdm import SDM, sdm_irref, sdm_rref_den
  from sympy.polys.matrices.ddm import DDM
  from sympy.polys.matrices.dense import ddm_irref, ddm_irref_den
label_desc: Use image node_id 12 for calling a global function with example usage: _dm_rref_choose_method_ZZ(M) and returns: str, str, str, str, str, str