From 418baf6f410bd1e897996d8e4c9960b0df0a7ef1 Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Sat, 9 Aug 2008 18:08:51 +0400 Subject: [PATCH] Add: current code expects coeff to always live in .args[0] For example Add.as_coeff_terms do this # -2 + 2 * a -> -1, 2-2*a if self.args[0].is_Number and self.args[0].is_negative: return -S.One,(-self,) return S.One,(self,) (note how it checks arg[0] for .is_Number) But when we introduced sort-args-by-hash in 2e496abeb32b we broke this invariant. Let's restore it -- it is really needed by current SymPy code. For example #974 was caused by this problem (test included), and on i386 once observed the following: In [1]: n = Symbol('n', integer=True) In [2]: e = n-2 In [3]: e.args Out[3]: (n, -2) Which was the cause of this: In [4]: (n-2).as_coeff_terms() Out[4]: (1, (-2 + n,)) <-- should be (-1, (2 - n,)) As .as_coeff_terms() catches this on i386 -- test for it was also written. All tests pass -- tested on i386 and amd64. Signed-off-by: Kirill Smelkov Signed-off-by: Ondrej Certik --- sympy/core/add.py | 16 +++++++++++----- sympy/core/tests/test_arit.py | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/sympy/core/add.py b/sympy/core/add.py index bb6e1c4..b03e266 100644 --- a/sympy/core/add.py +++ b/sympy/core/add.py @@ -104,13 +104,15 @@ class Add(AssocOp): newseq.append(Mul(c,s)) noncommutative = noncommutative or not s.is_commutative - # deal with nan, oo, -oo, etc... + # nan if coeff is S.NaN: - newseq = [coeff] + # we know for sure the result will be nan + return [S.NaN], [], None + + # oo, -oo elif (coeff is S.Infinity) or (coeff is S.NegativeInfinity): - newseq = [coeff] + [f for f in newseq if not f.is_real] - elif coeff is not S.Zero: - newseq.insert(0, coeff) + newseq = [f for f in newseq if not f.is_real] + # process O(x) if order_factors: @@ -130,6 +132,10 @@ class Add(AssocOp): # fixing. newseq.sort(key=hash) + # current code expects coeff to be always in slot-0 + if coeff is not S.Zero: + newseq.insert(0, coeff) + # we are done if noncommutative: return [], newseq, None diff --git a/sympy/core/tests/test_arit.py b/sympy/core/tests/test_arit.py index 5c2f8d6..0a6f85b 100644 --- a/sympy/core/tests/test_arit.py +++ b/sympy/core/tests/test_arit.py @@ -1021,3 +1021,27 @@ def test_suppressed_evaluation(): assert c != 9 assert c.func is Pow assert c.args == (3,2) + + +def test_Add_as_coeff_terms(): + assert (x+1).as_coeff_terms() == ( 1, (x+1,) ) + assert (x+2).as_coeff_terms() == ( 1, (x+2,) ) + assert (x+3).as_coeff_terms() == ( 1, (x+3,) ) + + assert (x-1).as_coeff_terms() == (-1, (1-x,) ) + assert (x-2).as_coeff_terms() == (-1, (2-x,) ) + assert (x-3).as_coeff_terms() == (-1, (3-x,) ) + + n = Symbol('n', integer=True) + assert (n+1).as_coeff_terms() == ( 1, (n+1,) ) + assert (n+2).as_coeff_terms() == ( 1, (n+2,) ) + assert (n+3).as_coeff_terms() == ( 1, (n+3,) ) + + assert (n-1).as_coeff_terms() == (-1, (1-n,) ) + assert (n-2).as_coeff_terms() == (-1, (2-n,) ) + assert (n-3).as_coeff_terms() == (-1, (3-n,) ) + + +def test_issue974(): + assert -1/(-1-x) == 1/(1+x) + -- 2.11.4.GIT