Repository: sympy/sympy
File: sympy/concrete/summations.py (Python)

Code before:

    if denom.degree(i) - numer.degree(i) < 2:
        return None

    if (a, b) == (S.NegativeInfinity, S.Infinity):
        poles = get_poles(denom)
        if poles is None:
            return None
        int_roots, nonint_roots = poles

        if int_roots:
            return None

        residue_factor = get_residue_factor(numer, denom, alternating)
        residues = [residue(residue_factor, z, root) for root in nonint_roots]
        return -S.Pi * sum(residues)

    if not (a.is_finite and b is S.Infinity):

        if a is S.NegativeInfinity and b.is_finite:
            # Apply the decomposition formula:
            # (-oo, a) = (-oo, +oo) - (a+1, +oo)
            full_sum = eval_sum_residue(f, (i, S.NegativeInfinity, S.Infinity))
            tail_sum = eval_sum_residue(f, (i, b + 1, S.Infinity))
            if full_sum is not None and tail_sum is not None:
                return full_sum - tail_sum
            else:
                return None

        return None

    if not is_even_function(numer, denom):
        # Try shifting summation and check if the summand can be made
        # and even function from the origin.
        # Sum(f(n), (n, a, b)) => Sum(f(n + s), (n, a - s, b - s))
        shift = get_shift(denom)

        if not shift.is_Integer:
            return None
        if shift == 0:
            return None

        numer = numer.shift(shift)
        denom = denom.shift(shift)

        if not is_even_function(numer, denom):
            return None

        if alternating:
            f = S.NegativeOne**i * (S.NegativeOne**shift * numer.as_expr() / denom.as_expr())
        else:

Review comment (performance):
Would it not be more efficient to use the substitution `i -> -i` rather than calling `eval_sum_residue` twice?

Code after:
            return None

    if denom.degree(i) - numer.degree(i) < 2:
        return None

    # handle non-even function with limits (-oo, oo), (-oo, k) or (k, oo)

    both_inf = (a,b) == (S.NegativeInfinity, S.Infinity)

    if not is_even_function(numer, denom):
        # Try shifting summation and check if the summand can be made
        # even wrt the origin.
        # Sum(f(n), (n, a, b)) => Sum(f(n + s), (n, a - s, b - s))
        shift = get_shift(denom)

        if not shift:
            return None

        if shift.is_Integer:
            numer = numer.shift(shift)
            denom = denom.shift(shift)
            if not is_even_function(numer, denom):
                return None

            if alternating:
                f = S.NegativeOne**i * (S.NegativeOne**shift * numer.as_expr() / denom.as_expr())
            else:
                f = numer.as_expr() / denom.as_expr()
            return eval_sum_residue(f, (i, a-shift, b-shift))
        elif not both_inf:
            return None  # can't make a shift that keeps limits integer

    if both_inf:  # even or not
        poles = get_poles(denom)
        if poles is None:
            return None
        int_roots, nonint_roots = poles
        if int_roots:
            return None

        return -S.Pi * sum(residues(numer, denom, alternating, nonint_roots))

    # handle even function with semi-infinite limits

    if a is S.NegativeInfinity:
        # this is ok for an even function and will be necessary
        # so the extraneous roots can be handled properly below
        a, b = -b, -a

    assert a.is_Integer and b is S.Infinity  # even function with limits (k, oo)