code: def qp(ctx, a, q=None, n=None, **kwargs):
      r"""
      Evaluates the q-Pochhammer symbol (or q-rising factorial)
  
      .. math ::
  
          (a; q)_n = \prod_{k=0}^{n-1} (1-a q^k)
  
      where `n = \infty` is permitted if `|q| < 1`. Called with two arguments,
      ``qp(a,q)`` computes `(a;q)_{\infty}`; with a single argument, ``qp(q)``
      computes `(q;q)_{\infty}`. The special case
  
      .. math ::
  
          \phi(q) = (q; q)_{\infty} = \prod_{k=1}^{\infty} (1-q^k) =
              \sum_{k=-\infty}^{\infty} (-1)^k q^{(3k^2-k)/2}
  
      is also known as the Euler function, or (up to a factor `q^{-1/24}`)
      the Dedekind eta function.
  
      **Examples**
  
      If `n` is a positive integer, the function amounts to a finite product::
  
          >>> from mpmath import *
          >>> mp.dps = 25; mp.pretty = True
          >>> qp(2,3,5)
          -725305.0
          >>> fprod(1-2*3**k for k in range(5))
          -725305.0
          >>> qp(2,3,0)
          1.0
  
      Complex arguments are allowed::
  
          >>> qp(2-1j, 0.75j)
          (0.4628842231660149089976379 + 4.481821753552703090628793j)
  
      The regular Pochhammer symbol `(a)_n` is obtained in the
      following limit as `q \to 1`::
  
          >>> a, n = 4, 7
          >>> limit(lambda q: qp(q**a,q,n) / (1-q)**n, 1)
          604800.0
          >>> rf(a,n)
          604800.0
  
      The Taylor series of the reciprocal Euler function gives
      the partition function `P(n)`, i.e. the number of ways of writing
      `n` as a sum of positive integers::
  
          >>> taylor(lambda q: 1/qp(q), 0, 10)
          [1.0, 1.0, 2.0, 3.0, 5.0, 7.0, 11.0, 15.0, 22.0, 30.0, 42.0]
  
      Special values include::
  
          >>> qp(0)
          1.0
          >>> findroot(diffun(qp), -0.4)   # location of maximum
          -0.4112484791779547734440257
          >>> qp(_)
          1.228348867038575112586878
  
      The q-Pochhammer symbol is related to the Jacobi theta functions.
      For example, the following identity holds::
  
          >>> q = mpf(0.5)    # arbitrary
          >>> qp(q)
          0.2887880950866024212788997
          >>> root(3,-2)*root(q,-24)*jtheta(2,pi/6,root(q,6))
          0.2887880950866024212788997
  
      """
      a = ctx.convert(a)
      if n is None:
          n = ctx.inf
      else:
          n = ctx.convert(n)
      if n < 0:
          raise ValueError("n cannot be negative")
      if q is None:
          q = a
      else:
          q = ctx.convert(q)
      if n == 0:
          return ctx.one + 0 * (a + q)
      infinite = n == ctx.inf
      same = a == q
      if infinite:
          if abs(q) >= 1:
              if same and (q == -1 or q == 1):
                  return ctx.zero * q
              raise ValueError("q-function only defined for |q| < 1")
          elif q == 0:
              return ctx.one - a
      maxterms = kwargs.get("maxterms", 50 * ctx.prec)
      if infinite and same:
          # Euler's pentagonal theorem
          def terms():
              t = 1
              yield t
              k = 1
              x1 = q
              x2 = q**2
              while 1:
                  yield (-1) ** k * x1
                  yield (-1) ** k * x2
                  x1 *= q ** (3 * k + 1)
                  x2 *= q ** (3 * k + 2)
                  k += 1
                  if k > maxterms:
                      raise ctx.NoConvergence
  
          return ctx.sum_accurately(terms)
  
      # return ctx.nprod(lambda k: 1-a*q**k, [0,n-1])
      def factors():
          k = 0
          r = ctx.one
          while 1:
              yield 1 - a * r
              r *= q
              k += 1
              if k >= n:
                  return
              if k > maxterms:
                  raise ctx.NoConvergence
  
      return ctx.mul_accurately(factors)
  
imports: from .functions import defun, defun_wrapped
label_desc: Use image node_id 1 for calling a global function with example usage: qp(ctx, a, q, n) and returns: ctx, unknown, ctx, unknown, unknown