Add: optimize collect of poly terms (2*x*y + 3*x*z) + general speedup
The main speedup is achieved bu carefully not recreating Mul the dumb way, e.g.
s = Mul(*o.args[1:])
but leveraging our knowledge of arguments nature and using ._new_rawargs() and
Mul.as_two_terms() /which is now too converted to us ._new_rawargs()/ in
performance critical points, e.g.
if o.is_Mul:
...
# o=3*x*y -- this will call ._new_rawargs(*o.args[1:]) behind the scene
# o= x*y -- this will just return y
s = o.as_two_terms()[1]
Also, general cleanup/speedup is done:
- we don't do seq.pop(0) anymore (this is slow), instead we just iterate over seq
- we don't do terms.has_key(s) -- this is slower than "s in terms"
Timings (cache: off)
--------------------
d = [2*x*y, 3*x*y]
q = [2*x*y, 3*x*z]
p = [x, 3, y]
Add(*d) Add(*q) (x+y+z+1)**40 Add(*p) fem_test.py
.expand()
old: 922 µs 1200 µs 27.8 s 173 µs 5.72 s
new: 325 µs 354 µs 13.7 s 160 µs 5.35 s
speedup: 2.83x 3.39x 2.03x 8% 7%
Signed-off-by: Kirill Smelkov <kirr@landau.phys.spbu.ru>
Signed-off-by: Ondrej Certik <ondrej@certik.cz>
Signed-off-by: Riccardo Gori <goriccardo@gmail.com>