Add: optimize collect of poly terms (2*x*y + 3*x*z) + general speedup
commit4fa9eb3e28a4b87be7c92b35cf7f77260c48329a
authorKirill Smelkov <kirr@landau.phys.spbu.ru>
Sun, 10 Aug 2008 07:50:39 +0000 (10 11:50 +0400)
committerKirill Smelkov <kirr@landau.phys.spbu.ru>
Sun, 10 Aug 2008 07:50:39 +0000 (10 11:50 +0400)
treec59959d3848a3048c2e3810f6f92a10929aa3c0f
parentfd09ab843cde789d295b9b001a27a3a4cbffc576
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>
sympy/core/add.py
sympy/core/mul.py