code: def to_rational(ctx, s, limit=True):
      p, q = to_rational(s._mpf_)
  
      # Needed for GROUND_TYPES=flint if gmpy2 is installed because mpmath's
      # to_rational() function returns a gmpy2.mpz instance and if MPQ is
      # flint.fmpq then MPQ(p, q) will fail.
      p = int(p)
  
      if not limit or q <= ctx.max_denom:
          return p, q
  
      p0, q0, p1, q1 = 0, 1, 1, 0
      n, d = p, q
  
      while True:
          a = n // d
          q2 = q0 + a * q1
          if q2 > ctx.max_denom:
              break
          p0, q0, p1, q1 = p1, q1, p0 + a * p1, q2
          n, d = d, n - a * d
  
      k = (ctx.max_denom - q0) // q1
  
      number = MPQ(p, q)
      bound1 = MPQ(p0 + k * p1, q0 + k * q1)
      bound2 = MPQ(p1, q1)
  
      if not bound2 or not bound1:
          return p, q
      elif abs(bound2 - number) <= abs(bound1 - number):
          return bound2.numerator, bound2.denominator
      else:
          return bound1.numerator, bound1.denominator
  
imports: from sympy.external.gmpy import MPQ
  from sympy.polys.domains.domainelement import DomainElement
  from sympy.utilities import public
  from mpmath.ctx_mp_python import PythonMPContext, _mpf, _mpc, _constant
  from mpmath.libmp import MPZ_ONE, fzero, fone, finf, fninf, fnan, round_nearest, mpf_mul, repr_dps, int_types, from_int, from_float, from_str, to_rational
label_desc: Use image node_id 8 for calling the MPContext obj's underlying member method code with example usage: obj.to_rational(ctx, s, limit) and returns: p,  q, p,  q, bound2,  bound2, bound1,  bound1