diff --git a/symengine/lib/symengine.pxd b/symengine/lib/symengine.pxd index 65b3456a..e6b963d3 100644 --- a/symengine/lib/symengine.pxd +++ b/symengine/lib/symengine.pxd @@ -769,6 +769,7 @@ cdef extern from "" namespace "SymEngine": unsigned next_prime() nogil cdef extern from "" namespace "SymEngine": + bool has_basic(const Basic &b, const Basic &x) nogil except + bool has_symbol(const Basic &b, const Basic &x) nogil except + rcp_const_basic coeff(const Basic &b, const Basic &x, const Basic &n) nogil except + set_basic free_symbols(const Basic &b) nogil except + diff --git a/symengine/lib/symengine_wrapper.in.pyx b/symengine/lib/symengine_wrapper.in.pyx index 413eb184..d5c68b23 100644 --- a/symengine/lib/symengine_wrapper.in.pyx +++ b/symengine/lib/symengine_wrapper.in.pyx @@ -1187,8 +1187,11 @@ cdef class Basic(object): cdef Basic _n = sympify(n) return c2py(symengine.coeff(deref(self.thisptr), deref(_x.thisptr), deref(_n.thisptr))) - def has(self, *symbols): - return any([has_symbol(self, symbol) for symbol in symbols]) + def has(self, *args): + for arg in args: + if has_basic(self, arg): + return True + return False def args_as_sage(Basic self): cdef symengine.vec_basic Y = deref(self.thisptr).get_args() @@ -4945,6 +4948,11 @@ def powermod_list(a, b, m): s.append(c2py((v[i]))) return s +def has_basic(obj, looking_for=None): + cdef Basic b = _sympify(obj) + cdef Basic s = _sympify(looking_for) + return symengine.has_basic(deref(b.thisptr), deref(s.thisptr)) + def has_symbol(obj, symbol=None): cdef Basic b = _sympify(obj) cdef Basic s = _sympify(symbol) diff --git a/symengine/tests/test_expr.py b/symengine/tests/test_expr.py index 8cbf4ab7..70607351 100644 --- a/symengine/tests/test_expr.py +++ b/symengine/tests/test_expr.py @@ -1,4 +1,4 @@ -from symengine import Symbol, Integer, oo +from symengine import Symbol, Integer, oo, sin from symengine.test_utilities import raises @@ -26,3 +26,18 @@ def test_as_powers_dict(): assert (x*(1/Integer(2))**y).as_powers_dict() == {x: Integer(1), Integer(2): -y} assert (2**y).as_powers_dict() == {2: y} assert (2**-y).as_powers_dict() == {2: -y} + + +def test_Basic__has(): + x = Symbol('x') + y = Symbol('y') + xpowy = x**y + e = sin(xpowy) + assert e.has(x) + assert e.has(y) + assert e.has(xpowy) + raises(Exception, lambda: e.has(x+1)) # subtree matching of associative operators not yet supported + assert (x + oo).has(oo) + assert (x - oo).has(-oo) + assert not (x + oo).has(-oo) + #assert not (x - oo).has(oo) <-- not sure we want to test explicitly for "x + NegativeInfinity" diff --git a/symengine/tests/test_functions.py b/symengine/tests/test_functions.py index 207add98..7c4573df 100644 --- a/symengine/tests/test_functions.py +++ b/symengine/tests/test_functions.py @@ -86,6 +86,7 @@ def test_derivative(): fxy = Function("f")(x, y) assert (1+fxy).has(fxy) + assert (1+fxy).has(1) g = Derivative(Function("f")(x, y), x, 2, y, 1) assert g == fxy.diff(x, x, y) assert g == fxy.diff(y, 1, x, 2) diff --git a/symengine_version.txt b/symengine_version.txt index e49372be..57395265 100644 --- a/symengine_version.txt +++ b/symengine_version.txt @@ -1 +1 @@ -c9510fb4b5c30b84adb993573a51f2a9a38a4cfe +8a3bc848cd8246a4c15eee9bddc15de0d1157812