class_docstr: Represents unevaluated summation.
  
  Explanation
  ===========
  
  ``Sum`` represents a finite or infinite series, with the first argument
  being the general form of terms in the series, and the second argument
  being ``(dummy_variable, start, end)``, with ``dummy_variable`` taking
  all integer values from ``start`` through ``end``. In accordance with
  long-standing mathematical convention, the end term is included in the
  summation.
  
  Finite sums
  ===========
  
  For finite sums (and sums with symbolic limits assumed to be finite) we
  follow the summation convention described by Karr [1], especially
  definition 3 of section 1.4. The sum:
  
  .. math::
  
      \sum_{m \leq i < n} f(i)
  
  has *the obvious meaning* for `m < n`, namely:
  
  .. math::
  
      \sum_{m \leq i < n} f(i) = f(m) + f(m+1) + \ldots + f(n-2) + f(n-1)
  
  with the upper limit value `f(n)` excluded. The sum over an empty set is
  zero if and only if `m = n`:
  
  .. math::
  
      \sum_{m \leq i < n} f(i) = 0  \quad \mathrm{for} \quad  m = n
  
  Finally, for all other sums over empty sets we assume the following
  definition:
  
  .. math::
  
      \sum_{m \leq i < n} f(i) = - \sum_{n \leq i < m} f(i)  \quad \mathrm{for} \quad  m > n
  
  It is important to note that Karr defines all sums with the upper
  limit being exclusive. This is in contrast to the usual mathematical notation,
  but does not affect the summation convention. Indeed we have:
  
  .. math::
  
      \sum_{m \leq i < n} f(i) = \sum_{i = m}^{n - 1} f(i)
  
  where the difference in notation is intentional to emphasize the meaning,
  with limits typeset on the top being inclusive.
  
  Examples
  ========
  
  >>> from sympy.abc import i, k, m, n, x
  >>> from sympy import Sum, factorial, oo, IndexedBase, Function
  >>> Sum(k, (k, 1, m))
  Sum(k, (k, 1, m))
  >>> Sum(k, (k, 1, m)).doit()
  m**2/2 + m/2
  >>> Sum(k**2, (k, 1, m))
  Sum(k**2, (k, 1, m))
  >>> Sum(k**2, (k, 1, m)).doit()
  m**3/3 + m**2/2 + m/6
  >>> Sum(x**k, (k, 0, oo))
  Sum(x**k, (k, 0, oo))
  >>> Sum(x**k, (k, 0, oo)).doit()
  Piecewise((1/(1 - x), Abs(x) < 1), (Sum(x**k, (k, 0, oo)), True))
  >>> Sum(x**k/factorial(k), (k, 0, oo)).doit()
  exp(x)
  
  Here are examples to do summation with symbolic indices.  You
  can use either Function of IndexedBase classes:
  
  >>> f = Function('f')
  >>> Sum(f(n), (n, 0, 3)).doit()
  f(0) + f(1) + f(2) + f(3)
  >>> Sum(f(n), (n, 0, oo)).doit()
  Sum(f(n), (n, 0, oo))
  >>> f = IndexedBase('f')
  >>> Sum(f[n]**2, (n, 0, 3)).doit()
  f[0]**2 + f[1]**2 + f[2]**2 + f[3]**2
  
  An example showing that the symbolic result of a summation is still
  valid for seemingly nonsensical values of the limits. Then the Karr
  convention allows us to give a perfectly valid interpretation to
  those sums by interchanging the limits according to the above rules:
  
  >>> S = Sum(i, (i, 1, n)).doit()
  >>> S
  n**2/2 + n/2
  >>> S.subs(n, -4)
  6
  >>> Sum(i, (i, 1, -4)).doit()
  6
  >>> Sum(-i, (i, -3, 0)).doit()
  6
  
  An explicit example of the Karr summation convention:
  
  >>> S1 = Sum(i**2, (i, m, m+n-1)).doit()
  >>> S1
  m**2*n + m*n**2 - m*n + n**3/3 - n**2/2 + n/6
  >>> S2 = Sum(i**2, (i, m+n, m-1)).doit()
  >>> S2
  -m**2*n - m*n**2 + m*n - n**3/3 + n**2/2 - n/6
  >>> S1 + S2
  0
  >>> S3 = Sum(i, (i, m, m-1)).doit()
  >>> S3
  0
  
  See Also
  ========
  
  summation
  Product, sympy.concrete.products.product
  
  References
  ==========
  
  .. [1] Michael Karr, "Summation in Finite Terms", Journal of the ACM,
         Volume 28 Issue 2, April 1981, Pages 305-350
         https://dl.acm.org/doi/10.1145/322248.322255
  .. [2] https://en.wikipedia.org/wiki/Summation#Capital-sigma_notation
  .. [3] https://en.wikipedia.org/wiki/Empty_sum
class_docstr_tok: ["Represents","unevaluated","summation",".","Explanation","===========","``","Sum","``","represents","a","finite","or","infinite","series",",","with","the","first","argument","being","the","general","form","of","terms","in","the","series",",","and","the","second","argument","being","``","(","dummy_variable",",","start",",","end",")","``",",","with","``","dummy_variable","``","taking","all","integer","values","from","``","start","``","through","``","end","``",".","In","accordance","with","long-standing","mathematical","convention",",","the","end","term","is","included","in","the","summation",".","Finite","sums","===========","For","finite","sums","(","and","sums","with","symbolic","limits","assumed","to","be","finite",")","we","follow","the","summation","convention","described","by","Karr","[","1","]",",","especially","definition","3","of","section","1.4",".","The","sum",":","..","math",":",":","\\sum_","{","m","\\leq","i","<","n","}","f","(","i",")","has","*","the","obvious","meaning","*","for","`","m","<","n","`",",","namely",":","..","math",":",":","\\sum_","{","m","\\leq","i","<","n","}","f","(","i",")","=","f","(","m",")","+","f","(","m+1",")","+","\\ldots","+","f","(","n-2",")","+","f","(","n-1",")","with","the","upper","limit","value","`","f","(","n",")","`","excluded",".","The","sum","over","an","empty","set","is","zero","if","and","only","if","`","m","=","n","`",":","..","math",":",":","\\sum_","{","m","\\leq","i","<","n","}","f","(","i",")","=","0","\\quad","\\mathrm","{","for","}","\\quad","m","=","n","Finally",",","for","all","other","sums","over","empty","sets","we","assume","the","following","definition",":","..","math",":",":","\\sum_","{","m","\\leq","i","<","n","}","f","(","i",")","=","-","\\sum_","{","n","\\leq","i","<","m","}","f","(","i",")","\\quad","\\mathrm","{","for","}","\\quad","m",">","n","It","is","important","to","note","that","Karr","defines","all","sums","with","the","upper","limit","being","exclusive",".","This","is","in","contrast","to","the","usual","mathematical","notation",",","but","does","not","affect","the","summation","convention",".","Indeed","we","have",":","..","math",":",":","\\sum_","{","m","\\leq","i","<","n","}","f","(","i",")","=","\\sum_","{","i","=","m","}","^","{","n","-","1","}","f","(","i",")","where","the","difference","in","notation","is","intentional","to","emphasize","the","meaning",",","with","limits","typeset","on","the","top","being","inclusive",".","Examples","========",">",">",">","from","sympy.abc","import","i",",","k",",","m",",","n",",","x",">",">",">","from","sympy","import","Sum",",","factorial",",","oo",",","IndexedBase",",","Function",">",">",">","Sum","(","k",",","(","k",",","1",",","m",")",")","Sum","(","k",",","(","k",",","1",",","m",")",")",">",">",">","Sum","(","k",",","(","k",",","1",",","m",")",")",".doit","(",")","m","*","*","2\/2","+","m\/2",">",">",">","Sum","(","k","*","*","2",",","(","k",",","1",",","m",")",")","Sum","(","k","*","*","2",",","(","k",",","1",",","m",")",")",">",">",">","Sum","(","k","*","*","2",",","(","k",",","1",",","m",")",")",".doit","(",")","m","*","*","3\/3","+","m","*","*","2\/2","+","m\/6",">",">",">","Sum","(","x","*","*","k",",","(","k",",","0",",","oo",")",")","Sum","(","x","*","*","k",",","(","k",",","0",",","oo",")",")",">",">",">","Sum","(","x","*","*","k",",","(","k",",","0",",","oo",")",")",".doit","(",")","Piecewise","(","(","1\/","(","1","-","x",")",",","Abs","(","x",")","<","1",")",",","(","Sum","(","x","*","*","k",",","(","k",",","0",",","oo",")",")",",","True",")",")",">",">",">","Sum","(","x","*","*","k\/factorial","(","k",")",",","(","k",",","0",",","oo",")",")",".doit","(",")","exp","(","x",")","Here","are","examples","to","do","summation","with","symbolic","indices",".","You","can","use","either","Function","of","IndexedBase","classes",":",">",">",">","f","=","Function","(","'","f","'",")",">",">",">","Sum","(","f","(","n",")",",","(","n",",","0",",","3",")",")",".doit","(",")","f","(","0",")","+","f","(","1",")","+","f","(","2",")","+","f","(","3",")",">",">",">","Sum","(","f","(","n",")",",","(","n",",","0",",","oo",")",")",".doit","(",")","Sum","(","f","(","n",")",",","(","n",",","0",",","oo",")",")",">",">",">","f","=","IndexedBase","(","'","f","'",")",">",">",">","Sum","(","f","[","n","]","*","*","2",",","(","n",",","0",",","3",")",")",".doit","(",")","f","[","0","]","*","*","2","+","f","[","1","]","*","*","2","+","f","[","2","]","*","*","2","+","f","[","3","]","*","*","2","An","example","showing","that","the","symbolic","result","of","a","summation","is","still","valid","for","seemingly","nonsensical","values","of","the","limits",".","Then","the","Karr","convention","allows","us","to","give","a","perfectly","valid","interpretation","to","those","sums","by","interchanging","the","limits","according","to","the","above","rules",":",">",">",">","S","=","Sum","(","i",",","(","i",",","1",",","n",")",")",".doit","(",")",">",">",">","S","n","*","*","2\/2","+","n\/2",">",">",">","S.subs","(","n",",","-4",")","6",">",">",">","Sum","(","i",",","(","i",",","1",",","-4",")",")",".doit","(",")","6",">",">",">","Sum","(","-i",",","(","i",",","-3",",","0",")",")",".doit","(",")","6","An","explicit","example","of","the","Karr","summation","convention",":",">",">",">","S1","=","Sum","(","i","*","*","2",",","(","i",",","m",",","m+n-1",")",")",".doit","(",")",">",">",">","S1","m","*","*","2","*","n","+","m","*","n","*","*","2","-","m","*","n","+","n","*","*","3\/3","-","n","*","*","2\/2","+","n\/6",">",">",">","S2","=","Sum","(","i","*","*","2",",","(","i",",","m+n",",","m-1",")",")",".doit","(",")",">",">",">","S2","-m","*","*","2","*","n","-","m","*","n","*","*","2","+","m","*","n","-","n","*","*","3\/3","+","n","*","*","2\/2","-","n\/6",">",">",">","S1","+","S2","0",">",">",">","S3","=","Sum","(","i",",","(","i",",","m",",","m-1",")",")",".doit","(",")",">",">",">","S3","0","See","Also","========","summation","Product",",","sympy.concrete.products.product","References","==========","..","[","1","]","Michael","Karr",",","``","Summation","in","Finite","Terms","''",",","Journal","of","the","ACM",",","Volume","28","Issue","2",",","April","1981",",","Pages","305-350","https",":","\/\/dl.acm.org\/doi\/10.1145\/322248.322255","..","[","2","]","https",":","\/\/en.wikipedia.org\/wiki\/Summation","#","Capital-sigma_notation","..","[","3","]","https",":","\/\/en.wikipedia.org\/wiki\/Empty_sum"]
docstr: Checks for the convergence of a Sum.
  
  Explanation
  ===========
  
  We divide the study of convergence of infinite sums and products in
  two parts.
  
  First Part:
  One part is the question whether all the terms are well defined, i.e.,
  they are finite in a sum and also non-zero in a product. Zero
  is the analogy of (minus) infinity in products as
  :math:`e^{-\infty} = 0`.
  
  Second Part:
  The second part is the question of convergence after infinities,
  and zeros in products, have been omitted assuming that their number
  is finite. This means that we only consider the tail of the sum or
  product, starting from some point after which all terms are well
  defined.
  
  For example, in a sum of the form:
  
  .. math::
  
      \sum_{1 \leq i < \infty} \frac{1}{n^2 + an + b}
  
  where a and b are numbers. The routine will return true, even if there
  are infinities in the term sequence (at most two). An analogous
  product would be:
  
  .. math::
  
      \prod_{1 \leq i < \infty} e^{\frac{1}{n^2 + an + b}}
  
  This is how convergence is interpreted. It is concerned with what
  happens at the limit. Finding the bad terms is another independent
  matter.
  
  Note: It is responsibility of user to see that the sum or product
  is well defined.
  
  There are various tests employed to check the convergence like
  divergence test, root test, integral test, alternating series test,
  comparison tests, Dirichlet tests. It returns true if Sum is convergent
  and false if divergent and NotImplementedError if it cannot be checked.
  
  References
  ==========
  
  .. [1] https://en.wikipedia.org/wiki/Convergence_tests
  
  Examples
  ========
  
  >>> from sympy import factorial, S, Sum, Symbol, oo
  >>> n = Symbol('n', integer=True)
  >>> Sum(n/(n - 1), (n, 4, 7)).is_convergent()
  True
  >>> Sum(n/(2*n + 1), (n, 1, oo)).is_convergent()
  False
  >>> Sum(factorial(n)/5**n, (n, 1, oo)).is_convergent()
  False
  >>> Sum(1/n**(S(6)/5), (n, 1, oo)).is_convergent()
  True
  
  See Also
  ========
  
  Sum.is_absolutely_convergent
  sympy.concrete.products.Product.is_convergent
docstr_tok: ["Checks","for","the","convergence","of","a","Sum",".","Explanation","===========","We","divide","the","study","of","convergence","of","infinite","sums","and","products","in","two","parts",".","First","Part",":","One","part","is","the","question","whether","all","the","terms","are","well","defined",",","i.e.",",","they","are","finite","in","a","sum","and","also","non-zero","in","a","product",".","Zero","is","the","analogy","of","(","minus",")","infinity","in","products","as",":","math",":","`","e^","{","-\\infty","}","=","0","`",".","Second","Part",":","The","second","part","is","the","question","of","convergence","after","infinities",",","and","zeros","in","products",",","have","been","omitted","assuming","that","their","number","is","finite",".","This","means","that","we","only","consider","the","tail","of","the","sum","or","product",",","starting","from","some","point","after","which","all","terms","are","well","defined",".","For","example",",","in","a","sum","of","the","form",":","..","math",":",":","\\sum_","{","1","\\leq","i","<","\\infty","}","\\frac","{","1","}","{","n^2","+","an","+","b","}","where","a","and","b","are","numbers",".","The","routine","will","return","true",",","even","if","there","are","infinities","in","the","term","sequence","(","at","most","two",")",".","An","analogous","product","would","be",":","..","math",":",":","\\prod_","{","1","\\leq","i","<","\\infty","}","e^","{","\\frac","{","1","}","{","n^2","+","an","+","b","}","}","This","is","how","convergence","is","interpreted",".","It","is","concerned","with","what","happens","at","the","limit",".","Finding","the","bad","terms","is","another","independent","matter",".","Note",":","It","is","responsibility","of","user","to","see","that","the","sum","or","product","is","well","defined",".","There","are","various","tests","employed","to","check","the","convergence","like","divergence","test",",","root","test",",","integral","test",",","alternating","series","test",",","comparison","tests",",","Dirichlet","tests",".","It","returns","true","if","Sum","is","convergent","and","false","if","divergent","and","NotImplementedError","if","it","can","not","be","checked",".","References","==========","..","[","1","]","https",":","\/\/en.wikipedia.org\/wiki\/Convergence_tests","Examples","========",">",">",">","from","sympy","import","factorial",",","S",",","Sum",",","Symbol",",","oo",">",">",">","n","=","Symbol","(","'n","'",",","integer=True",")",">",">",">","Sum","(","n\/","(","n","-","1",")",",","(","n",",","4",",","7",")",")",".is_convergent","(",")","True",">",">",">","Sum","(","n\/","(","2","*","n","+","1",")",",","(","n",",","1",",","oo",")",")",".is_convergent","(",")","False",">",">",">","Sum","(","factorial","(","n",")","\/5","*","*","n",",","(","n",",","1",",","oo",")",")",".is_convergent","(",")","False",">",">",">","Sum","(","1\/n","*","*","(","S","(","6",")","\/5",")",",","(","n",",","1",",","oo",")",")",".is_convergent","(",")","True","See","Also","========","Sum.is_absolutely_convergent","sympy.concrete.products.Product.is_convergent"]
code: def is_convergent(self):
      r"""
      Checks for the convergence of a Sum.
  
      Explanation
      ===========
  
      We divide the study of convergence of infinite sums and products in
      two parts.
  
      First Part:
      One part is the question whether all the terms are well defined, i.e.,
      they are finite in a sum and also non-zero in a product. Zero
      is the analogy of (minus) infinity in products as
      :math:`e^{-\infty} = 0`.
  
      Second Part:
      The second part is the question of convergence after infinities,
      and zeros in products, have been omitted assuming that their number
      is finite. This means that we only consider the tail of the sum or
      product, starting from some point after which all terms are well
      defined.
  
      For example, in a sum of the form:
  
      .. math::
  
          \sum_{1 \leq i < \infty} \frac{1}{n^2 + an + b}
  
      where a and b are numbers. The routine will return true, even if there
      are infinities in the term sequence (at most two). An analogous
      product would be:
  
      .. math::
  
          \prod_{1 \leq i < \infty} e^{\frac{1}{n^2 + an + b}}
  
      This is how convergence is interpreted. It is concerned with what
      happens at the limit. Finding the bad terms is another independent
      matter.
  
      Note: It is responsibility of user to see that the sum or product
      is well defined.
  
      There are various tests employed to check the convergence like
      divergence test, root test, integral test, alternating series test,
      comparison tests, Dirichlet tests. It returns true if Sum is convergent
      and false if divergent and NotImplementedError if it cannot be checked.
  
      References
      ==========
  
      .. [1] https://en.wikipedia.org/wiki/Convergence_tests
  
      Examples
      ========
  
      >>> from sympy import factorial, S, Sum, Symbol, oo
      >>> n = Symbol('n', integer=True)
      >>> Sum(n/(n - 1), (n, 4, 7)).is_convergent()
      True
      >>> Sum(n/(2*n + 1), (n, 1, oo)).is_convergent()
      False
      >>> Sum(factorial(n)/5**n, (n, 1, oo)).is_convergent()
      False
      >>> Sum(1/n**(S(6)/5), (n, 1, oo)).is_convergent()
      True
  
      See Also
      ========
  
      Sum.is_absolutely_convergent
      sympy.concrete.products.Product.is_convergent
      """
      p, q, r = symbols("p q r", cls=Wild)
  
      sym = self.limits[0][0]
      lower_limit = self.limits[0][1]
      upper_limit = self.limits[0][2]
      sequence_term = self.function.simplify()
  
      if len(sequence_term.free_symbols) > 1:
          raise NotImplementedError(
              "convergence checking for more than one symbol "
              "containing series is not handled"
          )
  
      if lower_limit.is_finite and upper_limit.is_finite:
          return S.true
  
      # transform sym -> -sym and swap the upper_limit = S.Infinity
      # and lower_limit = - upper_limit
      if lower_limit is S.NegativeInfinity:
          if upper_limit is S.Infinity:
              return (
                  Sum(
                      sequence_term, (sym, 0, S.Infinity)
                  ).is_convergent()
                  and Sum(
                      sequence_term, (sym, S.NegativeInfinity, 0)
                  ).is_convergent()
              )
          from sympy.simplify.simplify import simplify
  
          sequence_term = simplify(sequence_term.xreplace({sym: -sym}))
          lower_limit = -upper_limit
          upper_limit = S.Infinity
  
      sym_ = Dummy(sym.name, integer=True, positive=True)
      sequence_term = sequence_term.xreplace({sym: sym_})
      sym = sym_
  
      interval = Interval(lower_limit, upper_limit)
  
      # Piecewise function handle
      if sequence_term.is_Piecewise:
          for func, cond in sequence_term.args:
              # see if it represents something going to oo
              if cond == True or cond.as_set().sup is S.Infinity:
                  s = Sum(func, (sym, lower_limit, upper_limit))
                  return s.is_convergent()
          return S.true
  
      ###  -------- Divergence test ----------- ###
      try:
          lim_val = limit_seq(sequence_term, sym)
          if lim_val is not None and lim_val.is_zero is False:
              return S.false
      except NotImplementedError:
          pass
  
      try:
          lim_val_abs = limit_seq(abs(sequence_term), sym)
          if lim_val_abs is not None and lim_val_abs.is_zero is False:
              return S.false
      except NotImplementedError:
          pass
  
      order = O(sequence_term, (sym, S.Infinity))
  
      ### --------- p-series test (1/n**p) ---------- ###
      p_series_test = order.expr.match(sym**p)
      if p_series_test is not None:
          if p_series_test[p] < -1:
              return S.true
          if p_series_test[p] >= -1:
              return S.false
  
      ### ------------- comparison test ------------- ###
      # 1/(n**p*log(n)**q*log(log(n))**r) comparison
      n_log_test = order.expr.match(
          1 / (sym**p * log(1 / sym) ** q * log(-log(1 / sym)) ** r)
      ) or order.expr.match(
          1
          / (sym**p * (-log(1 / sym)) ** q * log(-log(1 / sym)) ** r)
      )
      if n_log_test is not None:
          if (
              n_log_test[p] > 1
              or (n_log_test[p] == 1 and n_log_test[q] > 1)
              or (
                  n_log_test[p] == n_log_test[q] == 1
                  and n_log_test[r] > 1
              )
          ):
              return S.true
          return S.false
  
      ### ------------- Limit comparison test -----------###
      # (1/n) comparison
      try:
          lim_comp = limit_seq(sym * sequence_term, sym)
          if (
              lim_comp is not None
              and lim_comp.is_number
              and lim_comp > 0
          ):
              return S.false
      except NotImplementedError:
          pass
  
      ### ----------- ratio test ---------------- ###
      next_sequence_term = sequence_term.xreplace({sym: sym + 1})
      from sympy.simplify.combsimp import combsimp
      from sympy.simplify.powsimp import powsimp
  
      ratio = combsimp(powsimp(next_sequence_term / sequence_term))
      try:
          lim_ratio = limit_seq(ratio, sym)
          if lim_ratio is not None and lim_ratio.is_number:
              if abs(lim_ratio) > 1:
                  return S.false
              if abs(lim_ratio) < 1:
                  return S.true
      except NotImplementedError:
          lim_ratio = None
  
      ### ---------- Raabe's test -------------- ###
      if lim_ratio == 1:  # ratio test inconclusive
          test_val = sym * (
              sequence_term / sequence_term.subs(sym, sym + 1) - 1
          )
          test_val = test_val.gammasimp()
          try:
              lim_val = limit_seq(test_val, sym)
              if lim_val is not None and lim_val.is_number:
                  if lim_val > 1:
                      return S.true
                  if lim_val < 1:
                      return S.false
          except NotImplementedError:
              pass
  
      ### ----------- root test ---------------- ###
      # lim = Limit(abs(sequence_term)**(1/sym), sym, S.Infinity)
      try:
          lim_evaluated = limit_seq(
              abs(sequence_term) ** (1 / sym), sym
          )
          if lim_evaluated is not None and lim_evaluated.is_number:
              if lim_evaluated < 1:
                  return S.true
              if lim_evaluated > 1:
                  return S.false
      except NotImplementedError:
          pass
  
      ### ------------- alternating series test ----------- ###
      dict_val = sequence_term.match(S.NegativeOne ** (sym + p) * q)
      if not dict_val[p].has(sym) and is_decreasing(
          dict_val[q], interval
      ):
          return S.true
  
      ### ------------- integral test -------------- ###
      check_interval = None
      from sympy.solvers.solveset import solveset
  
      maxima = solveset(sequence_term.diff(sym), sym, interval)
      if not maxima:
          check_interval = interval
      elif isinstance(maxima, FiniteSet) and maxima.sup.is_number:
          check_interval = Interval(maxima.sup, interval.sup)
      if check_interval is not None and (
          is_decreasing(sequence_term, check_interval)
          or is_decreasing(-sequence_term, check_interval)
      ):
          integral_val = Integral(
              sequence_term, (sym, lower_limit, upper_limit)
          )
          try:
              integral_val_evaluated = integral_val.doit()
              if integral_val_evaluated.is_number:
                  return S(integral_val_evaluated.is_finite)
          except NotImplementedError:
              pass
  
      ### ----- Dirichlet and bounded times convergent tests ----- ###
      # TODO
      #
      # Dirichlet_test
      # https://en.wikipedia.org/wiki/Dirichlet%27s_test
      #
      # Bounded times convergent test
      # It is based on comparison theorems for series.
      # In particular, if the general term of a series can
      # be written as a product of two terms a_n and b_n
      # and if a_n is bounded and if Sum(b_n) is absolutely
      # convergent, then the original series Sum(a_n * b_n)
      # is absolutely convergent and so convergent.
      #
      # The following code can grows like 2**n where n is the
      # number of args in order.expr
      # Possibly combined with the potentially slow checks
      # inside the loop, could make this test extremely slow
      # for larger summation expressions.
  
      if order.expr.is_Mul:
          args = order.expr.args
          argset = set(args)
  
          ### -------------- Dirichlet tests -------------- ###
          m = Dummy("m", integer=True)
  
          def _dirichlet_test(g_n):
              try:
                  ing_val = limit_seq(
                      Sum(g_n, (sym, interval.inf, m)).doit(), m
                  )
                  if ing_val is not None and ing_val.is_finite:
                      return S.true
              except NotImplementedError:
                  pass
  
          ### -------- bounded times convergent test ---------###
          def _bounded_convergent_test(g1_n, g2_n):
              try:
                  lim_val = limit_seq(g1_n, sym)
                  if lim_val is not None and (
                      lim_val.is_finite
                      or (
                          isinstance(lim_val, AccumulationBounds)
                          and (lim_val.max - lim_val.min).is_finite
                      )
                  ):
                      if Sum(
                          g2_n, (sym, lower_limit, upper_limit)
                      ).is_absolutely_convergent():
                          return S.true
              except NotImplementedError:
                  pass
  
          for n in range(1, len(argset)):
              for a_tuple in itertools.combinations(args, n):
                  b_set = argset - set(a_tuple)
                  a_n = Mul(*a_tuple)
                  b_n = Mul(*b_set)
  
                  if is_decreasing(a_n, interval):
                      dirich = _dirichlet_test(b_n)
                      if dirich is not None:
                          return dirich
  
                  bc_test = _bounded_convergent_test(a_n, b_n)
                  if bc_test is not None:
                      return bc_test
  
      _sym = self.limits[0][0]
      sequence_term = sequence_term.xreplace({sym: _sym})
      raise NotImplementedError(
          "The algorithm to find the Sum convergence of %s "
          "is not yet implemented" % (sequence_term)
      )
  
imports: from typing import Tuple
  from sympy.calculus.singularities import is_decreasing
  from sympy.calculus.accumulationbounds import AccumulationBounds
  from .expr_with_intlimits import ExprWithIntLimits
  from .expr_with_limits import AddWithLimits
  from .gosper import gosper_sum
  from sympy.core.expr import Expr
  from sympy.core.add import Add
  from sympy.core.containers import Tuple
  from sympy.core.function import Derivative, expand
  from sympy.core.mul import Mul
  from sympy.core.numbers import Float, _illegal
  from sympy.core.relational import Eq
  from sympy.core.singleton import S
  from sympy.core.sorting import ordered
  from sympy.core.symbol import Dummy, Wild, Symbol, symbols
  from sympy.functions.combinatorial.factorials import factorial
  from sympy.functions.combinatorial.numbers import bernoulli, harmonic
  from sympy.functions.elementary.exponential import exp, log
  from sympy.functions.elementary.piecewise import Piecewise
  from sympy.functions.elementary.trigonometric import cot, csc
  from sympy.functions.special.hyper import hyper
  from sympy.functions.special.tensor_functions import KroneckerDelta
  from sympy.functions.special.zeta_functions import zeta
  from sympy.integrals.integrals import Integral
  from sympy.logic.boolalg import And
  from sympy.polys.partfrac import apart
  from sympy.polys.polyerrors import PolynomialError, PolificationFailed
  from sympy.polys.polytools import parallel_poly_from_expr, Poly, factor
  from sympy.polys.rationaltools import together
  from sympy.series.limitseq import limit_seq
  from sympy.series.order import O
  from sympy.series.residues import residue
  from sympy.sets.sets import FiniteSet, Interval
  from sympy.utilities.iterables import sift
  import itertools
label_desc: Use image node_id 12 for calling the Sum obj's underlying member method code with example usage: obj.is_convergent() and returns: S, S, S, S, unknown, S, S, S, S, S, S, s, S, S, S, S, S, S, S, S, bc_test, S, dirich