Skip to content

Commit 630a2b0

Browse files
authored
Merge pull request #521 from bjodah/has_basic
Make Basic.has behave more like SymPy, use new visitor
2 parents 4508987 + a9389cd commit 630a2b0

File tree

5 files changed

+29
-4
lines changed

5 files changed

+29
-4
lines changed

symengine/lib/symengine.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,7 @@ cdef extern from "<symengine/prime_sieve.h>" namespace "SymEngine":
769769
unsigned next_prime() nogil
770770

771771
cdef extern from "<symengine/visitor.h>" namespace "SymEngine":
772+
bool has_basic(const Basic &b, const Basic &x) nogil except +
772773
bool has_symbol(const Basic &b, const Basic &x) nogil except +
773774
rcp_const_basic coeff(const Basic &b, const Basic &x, const Basic &n) nogil except +
774775
set_basic free_symbols(const Basic &b) nogil except +

symengine/lib/symengine_wrapper.in.pyx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,8 +1187,11 @@ cdef class Basic(object):
11871187
cdef Basic _n = sympify(n)
11881188
return c2py(symengine.coeff(deref(self.thisptr), deref(_x.thisptr), deref(_n.thisptr)))
11891189

1190-
def has(self, *symbols):
1191-
return any([has_symbol(self, symbol) for symbol in symbols])
1190+
def has(self, *args):
1191+
for arg in args:
1192+
if has_basic(self, arg):
1193+
return True
1194+
return False
11921195

11931196
def args_as_sage(Basic self):
11941197
cdef symengine.vec_basic Y = deref(self.thisptr).get_args()
@@ -4945,6 +4948,11 @@ def powermod_list(a, b, m):
49454948
s.append(c2py(<rcp_const_basic>(v[i])))
49464949
return s
49474950

4951+
def has_basic(obj, looking_for=None):
4952+
cdef Basic b = _sympify(obj)
4953+
cdef Basic s = _sympify(looking_for)
4954+
return symengine.has_basic(deref(b.thisptr), deref(s.thisptr))
4955+
49484956
def has_symbol(obj, symbol=None):
49494957
cdef Basic b = _sympify(obj)
49504958
cdef Basic s = _sympify(symbol)

symengine/tests/test_expr.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from symengine import Symbol, Integer, oo
1+
from symengine import Symbol, Integer, oo, sin
22
from symengine.test_utilities import raises
33

44

@@ -26,3 +26,18 @@ def test_as_powers_dict():
2626
assert (x*(1/Integer(2))**y).as_powers_dict() == {x: Integer(1), Integer(2): -y}
2727
assert (2**y).as_powers_dict() == {2: y}
2828
assert (2**-y).as_powers_dict() == {2: -y}
29+
30+
31+
def test_Basic__has():
32+
x = Symbol('x')
33+
y = Symbol('y')
34+
xpowy = x**y
35+
e = sin(xpowy)
36+
assert e.has(x)
37+
assert e.has(y)
38+
assert e.has(xpowy)
39+
raises(Exception, lambda: e.has(x+1)) # subtree matching of associative operators not yet supported
40+
assert (x + oo).has(oo)
41+
assert (x - oo).has(-oo)
42+
assert not (x + oo).has(-oo)
43+
#assert not (x - oo).has(oo) <-- not sure we want to test explicitly for "x + NegativeInfinity"

symengine/tests/test_functions.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def test_derivative():
8686

8787
fxy = Function("f")(x, y)
8888
assert (1+fxy).has(fxy)
89+
assert (1+fxy).has(1)
8990
g = Derivative(Function("f")(x, y), x, 2, y, 1)
9091
assert g == fxy.diff(x, x, y)
9192
assert g == fxy.diff(y, 1, x, 2)

symengine_version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
c9510fb4b5c30b84adb993573a51f2a9a38a4cfe
1+
8a3bc848cd8246a4c15eee9bddc15de0d1157812

0 commit comments

Comments
 (0)