--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sympy-patches" group.
To post to this group, send email to sympy-patches@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sympy-patches?hl=en
-~----------~----~----~----~------~----~------~--~---

# HG changeset patch
# User Riccardo Gori <[EMAIL PROTECTED]>
# Date 1223660263 -7200
# Node ID dfdefff8125fae2a990d3480a120d860cba92edf
# Parent  7f66f97a31d76e7565512ca2ef8cb42d2005bceb
Subs speedup: _eval_subs should call _eval_subs instead of subs

Calling Basic.subs caused some overhead because it had to check len(*args) and
to sympify the args

Using our bench suite:

In [1]: from sympy.utilities import benchmarking

In [2]: benchmarking.main(['sympy/benchmarks'])

Before:
==============================
 *** BENCHMARKING RESULTS ***
==============================

bench_R1   |       301          ms  |  real(f(f(f(f(f(f(f(f(f(f(i/2)))))))))))
bench_R2   |       343          ms  |  Hermite polynomial hermite(15, y)
bench_R3   |            407     us  |  a = [bool(f==f) for _ in range(10)]
bench_R4   |              1.91  us  |  # we don't have Tuples
bench_R5   |        10.8        ms  |  blowup(L, 8); L=uniq(L)
bench_R6   |       225          ms  |  sum(trim((x+sin(i))/x+(x-sin(i))/x) for i in xrange(100))
bench_R7   |  38.7              s   |  [f.subs(x, random()) for _ in xrange(10**4)]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
bench_R8   |   5.64             s   |  right(x^2,0,5,10^4)
bench_R10  |        68.2        ms  |  v = [-pi,-pi+1/10..,pi]
bench_R11  |   1.52             s   |  a = [random() + random()*I for w in [0..1000]]
bench_S1   |  11.5              s   |  e=(x+y+z+1)**7;f=e*(e+1);f.expand()

After:
==============================
 *** BENCHMARKING RESULTS ***
==============================

bench_R1   |       302          ms  |  real(f(f(f(f(f(f(f(f(f(f(i/2)))))))))))
bench_R2   |       345          ms  |  Hermite polynomial hermite(15, y)
bench_R3   |            403     us  |  a = [bool(f==f) for _ in range(10)]
bench_R4   |              2.86  us  |  # we don't have Tuples
bench_R5   |        11          ms  |  blowup(L, 8); L=uniq(L)
bench_R6   |       222          ms  |  sum(trim((x+sin(i))/x+(x-sin(i))/x) for i in xrange(100))
bench_R7   |  30.1              s   |  [f.subs(x, random()) for _ in xrange(10**4)]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
bench_R8   |   4.9              s   |  right(x^2,0,5,10^4)
bench_R10  |        67.6        ms  |  v = [-pi,-pi+1/10..,pi]
bench_R11  |   1.54             s   |  a = [random() + random()*I for w in [0..1000]]
bench_S1   |  11.7              s   |  e=(x+y+z+1)**7;f=e*(e+1);f.expand()

diff --git a/sympy/concrete/sums_products.py b/sympy/concrete/sums_products.py
--- a/sympy/concrete/sums_products.py
+++ b/sympy/concrete/sums_products.py
@@ -98,7 +98,7 @@
 
         return self
 
-    def subs(self, x, y):
+    def _eval_subs(self, x, y):
         if x == self.b:
             return Sum2(self.f, (self.i, self.a, y))
         return self
diff --git a/sympy/core/add.py b/sympy/core/add.py
--- a/sympy/core/add.py
+++ b/sympy/core/add.py
@@ -293,7 +293,7 @@
     def _eval_subs(self, old, new):
         if self == old: return new
         if isinstance(old, FunctionClass):
-            return self.__class__(*[s.subs(old, new) for s in self.args ])
+            return self.__class__(*[s._eval_subs(old, new) for s in self.args ])
         coeff_self, factors_self = self.as_coeff_factors()
         coeff_old, factors_old = old.as_coeff_factors()
         if factors_self == factors_old: # (2+a).subs(3+a,y) -> 2-3+y
@@ -304,8 +304,8 @@
                 old_set = set(factors_old)
                 if old_set < self_set:
                     ret_set = self_set - old_set
-                    return Add(new, coeff_self, -coeff_old, *[s.subs(old, new) for s in ret_set])
-        return self.__class__(*[s.subs(old, new) for s in self.args])
+                    return Add(new, coeff_self, -coeff_old, *[s._eval_subs(old, new) for s in ret_set])
+        return self.__class__(*[s._eval_subs(old, new) for s in self.args])
 
     @cacheit
     def extract_leading_order(self, *symbols):
diff --git a/sympy/core/function.py b/sympy/core/function.py
--- a/sympy/core/function.py
+++ b/sympy/core/function.py
@@ -509,7 +509,7 @@
     def _eval_subs(self, old, new):
         if self==old:
             return new
-        return Derivative(self.args[0].subs(old, new), *self.args[1:], **{'evaluate': True})
+        return Derivative(self.args[0]._eval_subs(old, new), *self.args[1:], **{'evaluate': True})
 
     def matches(pattern, expr, repl_dict={}, evaluate=False):
         # this method needs a cleanup.
diff --git a/sympy/core/mul.py b/sympy/core/mul.py
--- a/sympy/core/mul.py
+++ b/sympy/core/mul.py
@@ -608,7 +608,7 @@
         if self == old:
             return new
         if isinstance(old, FunctionClass):
-            return self.__class__(*[s.subs(old, new) for s in self.args ])
+            return self.__class__(*[s._eval_subs(old, new) for s in self.args ])
         coeff_self,terms_self = self.as_coeff_terms()
         coeff_old,terms_old = old.as_coeff_terms()
         if terms_self == terms_old: # (2*a).subs(3*a,y) -> 2/3*y
@@ -616,7 +616,7 @@
         l1, l2 = len(terms_self), len(terms_old)
         if l2 == 0:
             # if old is just a number, go through the self.args one by one
-            return Mul(*[x.subs(old, new) for x in self.args])
+            return Mul(*[x._eval_subs(old, new) for x in self.args])
         elif l2 < l1:
             # old is some something more complex, like:
             # (a*b*c*d).subs(b*c,x) -> a*x*d
@@ -626,8 +626,8 @@
             old_set = set(terms_old)
             if old_set < self_set:
                 ret_set = self_set - old_set
-                return Mul(new, coeff_self/coeff_old, *[s.subs(old, new) for s in ret_set])
-        return self.__class__(*[s.subs(old, new) for s in self.args])
+                return Mul(new, coeff_self/coeff_old, *[s._eval_subs(old, new) for s in ret_set])
+        return self.__class__(*[s._eval_subs(old, new) for s in self.args])
 
     def _eval_nseries(self, x, x0, n):
         terms = [t.nseries(x, x0, n) for t in self.args]
diff --git a/sympy/core/power.py b/sympy/core/power.py
--- a/sympy/core/power.py
+++ b/sympy/core/power.py
@@ -200,7 +200,7 @@
             coeff1,terms1 = old.args[0].as_coeff_terms()
             coeff2,terms2 = (self.exp * C.log(self.base)).as_coeff_terms()
             if terms1==terms2: return new ** (coeff1/coeff2) # (x**(2*y)).subs(exp(3*y*log(x)),z) -> z**(2/3*y)
-        return self.base.subs(old, new) ** self.exp.subs(old, new)
+        return self.base._eval_subs(old, new) ** self.exp._eval_subs(old, new)
 
     def as_powers_dict(self):
         return { self.base : self.exp }
diff --git a/sympy/core/relational.py b/sympy/core/relational.py
--- a/sympy/core/relational.py
+++ b/sympy/core/relational.py
@@ -135,8 +135,8 @@
     def rhs(self):
         return self._args[1]
 
-    def subs(self, old, new):
-        return self.__class__(self.lhs.subs(old, new), self.rhs.subs(old, new))
+    def _eval_subs(self, old, new):
+        return self.__class__(self.lhs._eval_subs(old, new), self.rhs._eval_subs(old, new))
 
 class Equality(Relational):
 
diff --git a/sympy/functions/elementary/exponential.py b/sympy/functions/elementary/exponential.py
--- a/sympy/functions/elementary/exponential.py
+++ b/sympy/functions/elementary/exponential.py
@@ -145,12 +145,12 @@
                 old_al = []
                 coeff2,terms2 = oarg.as_coeff_terms()
                 for a in arg.args:
-                    a = a.subs(old, new)
+                    a = a._eval_subs(old, new)
                     coeff1,terms1 = a.as_coeff_terms()
                     if terms1==terms2:
                         new_l.append(new**(coeff1/coeff2))
                     else:
-                        old_al.append(a.subs(old, new))
+                        old_al.append(a._eval_subs(old, new))
                 if new_l:
                     new_l.append(self.func(C.Add(*old_al)))
                     r = C.Mul(*new_l)
@@ -466,12 +466,12 @@
 # MrvLog is used by limit.py
 class MrvLog(log):
 
-    def subs(self, old, new):
+    def _eval_subs(self, old, new):
         old = sympify(old)
         if old==self.func:
             arg = self.args[0]
             new = sympify(new)
-            return new(arg.subs(old, new))
+            return new(arg._eval_subs(old, new))
         return self
 
 
diff --git a/sympy/functions/elementary/piecewise.py b/sympy/functions/elementary/piecewise.py
--- a/sympy/functions/elementary/piecewise.py
+++ b/sympy/functions/elementary/piecewise.py
@@ -50,5 +50,5 @@
             return new
         new_pieces = []
         for start, end, f in self.args[1:]:
-            new_pieces.append( (start, end, f.subs(old,new)) )
+            new_pieces.append( (start, end, f._eval_subs(old,new)) )
         return Piecewise(self.args[0], *new_pieces)
diff --git a/sympy/polys/polynomial.py b/sympy/polys/polynomial.py
--- a/sympy/polys/polynomial.py
+++ b/sympy/polys/polynomial.py
@@ -2074,10 +2074,10 @@
                 else:
                     return self.evaluate((old, new))
         elif not new.has_any_symbols(*symbols):
-            coeffs = [ sympify(coeff).subs(old, new) for coeff in self.coeffs ]
+            coeffs = [ sympify(coeff)._eval_subs(old, new) for coeff in self.coeffs ]
             return self.__class__((coeffs, self.monoms), *symbols, **self.flags)
 
-        result = self.as_basic().subs(old, new)
+        result = self.as_basic()._eval_subs(old, new)
 
         try:
             return self.__class__(result, *symbols, **self.flags)
diff --git a/sympy/series/order.py b/sympy/series/order.py
--- a/sympy/series/order.py
+++ b/sympy/series/order.py
@@ -263,9 +263,9 @@
         if isinstance(old, C.Symbol) and old in self.symbols:
             i = list(self.symbols).index(old)
             if isinstance(new, C.Symbol):
-                return Order(self.expr.subs(old, new), *(self.symbols[:i]+(new,)+self.symbols[i+1:]))
-            return Order(self.expr.subs(old, new), *(self.symbols[:i]+self.symbols[i+1:]))
-        return Order(self.expr.subs(old, new), *self.symbols)
+                return Order(self.expr._eval_subs(old, new), *(self.symbols[:i]+(new,)+self.symbols[i+1:]))
+            return Order(self.expr._eval_subs(old, new), *(self.symbols[:i]+self.symbols[i+1:]))
+        return Order(self.expr._eval_subs(old, new), *self.symbols)
 
     def _sage_(self):
         #XXX: SAGE doesn't have Order yet. Let's return 0 instead.
diff --git a/sympy/simplify/cse_opts.py b/sympy/simplify/cse_opts.py
--- a/sympy/simplify/cse_opts.py
+++ b/sympy/simplify/cse_opts.py
@@ -34,7 +34,7 @@
         if self==old:
             return new
         else:
-            return self.__class__(*[s.subs(old, new) for s in self.args ])
+            return self.__class__(*[s._eval_subs(old, new) for s in self.args ])
 
 def sub_pre(e):
     """ Replace Add(x, Mul(NegativeOne(-1), y)) with Sub(x, y).

Reply via email to