2 from sympy
.core
import Basic
, S
, C
, Add
, Mul
, Symbol
, Equality
, Interval
, sympify
3 from sympy
.core
.methods
import NoRelMeths
, ArithMeths
5 class Sum(Basic
, NoRelMeths
, ArithMeths
):
6 """Represents unevaluated summation."""
8 precedence
= Basic
.Apply_precedence
10 def __new__(cls
, f
, *symbols
, **assumptions
):
13 if isinstance(f
, C
.Number
):
20 limits
= f
.atoms(Symbol
)
28 if isinstance(V
, Symbol
):
31 elif isinstance(V
, Equality
):
32 if isinstance(V
.lhs
, Symbol
):
33 if isinstance(V
.rhs
, Interval
):
34 limits
.append((V
.lhs
, V
.rhs
.start
, V
.rhs
.end
))
36 limits
.append((V
.lhs
, V
.rhs
))
39 elif isinstance(V
, (tuple, list)):
41 if isinstance(V
[0], Symbol
):
44 elif len(V
) in (2, 3):
45 if isinstance(V
[0], Symbol
):
46 limits
.append(tuple(map(sympify
, V
)))
49 raise ValueError("Invalid summation variable or limits")
51 obj
= Basic
.__new
__(cls
, **assumptions
)
52 obj
._args
= (f
, tuple(limits
))
64 def tostr(self
, level
=0):
65 L
= ', '.join([ str(L
) for L
in self
.limits
])
66 return 'Sum(%s, %s)' % (self
.function
.tostr(), L
)
68 def doit(self
, **hints
):
69 #if not hints.get('sums', True):
72 for i
, a
, b
in self
.limits
:
73 f
= eval_sum(f
, (i
, a
, b
))
78 def _eval_summation(self
, f
, x
):
81 def sum(*args
, **kwargs
):
82 summation
= Sum(*args
, **kwargs
)
84 if isinstance(summation
, Sum
):
85 return summation
.doit()
92 return cls(expr
.args
[0]), cls(*expr
.args
[1:])
94 def eval_sum(f
, (i
, a
, b
)):
97 definite
= isinstance(a
, C
.Integer
) and isinstance(b
, C
.Integer
)
98 # Doing it directly may be faster if there are very few terms.
99 if definite
and (b
-a
< 100):
100 return eval_sum_direct(f
, (i
, a
, b
))
101 # Try to do it symbolically. Even when the number of terms is known,
102 # this can save time when b-a is big.
103 value
= eval_sum_symbolic(f
.expand(), (i
, a
, b
))
104 if value
is not None:
108 return eval_sum_direct(f
, (i
, a
, b
))
110 def eval_sum_symbolic(f
, (i
, a
, b
)):
114 if isinstance(f
, C
.Mul
):
116 if not L
.has(i
): return L
*eval_sum_symbolic(R
, (i
, a
, b
))
117 if not R
.has(i
): return R
*eval_sum_symbolic(L
, (i
, a
, b
))
118 if isinstance(f
, C
.Add
):
120 lsum
= eval_sum_symbolic(L
, (i
, a
, b
))
121 rsum
= eval_sum_symbolic(R
, (i
, a
, b
))
122 if None not in (lsum
, rsum
):
124 # Polynomial terms with Faulhaber's formula
130 if c
.is_integer
and c
>= 0:
131 s
= (B(c
+1, b
+1) - B(c
+1, a
))/(c
+1)
134 if isinstance(f
, C
.Pow
):
136 if not r
.has(i
) and k
== i
:
137 # TODO: Pow should be able to simplify x**oo depending
138 # on whether |x| < 1 or |x| > 1 for non-rational x
139 if (b
is S
.Infinity
) and abs(r
.evalf()) < 1:
142 return (r
**a
- r
**(b
+1)) / (1-r
)
145 def eval_sum_direct(expr
, (i
, a
, b
)):
148 for j
in xrange(a
, b
+1):
151 for j
in xrange(a
, b
+1):