Skip to content

Commit 169ba50

Browse files
authored
Merge pull request #179 from ShikharJ/Misc
Miscellaneous Additions
2 parents 445559e + add40b1 commit 169ba50

File tree

4 files changed

+134
-14
lines changed

4 files changed

+134
-14
lines changed

symengine/lib/symengine.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ cdef extern from "<symengine/basic.h>" namespace "SymEngine":
311311
bool is_a_Or "SymEngine::is_a<SymEngine::Or>"(const Basic &b) nogil
312312
bool is_a_Xor "SymEngine::is_a<SymEngine::Xor>"(const Basic &b) nogil
313313
RCP[const Basic] expand(RCP[const Basic] &o) nogil except +
314+
void as_numer_denom(RCP[const Basic] &x, const Ptr[RCP[Basic]] &numer, const Ptr[RCP[Basic]] &denom) nogil
314315

315316
cdef extern from "<symengine/subs.h>" namespace "SymEngine":
316317
RCP[const Basic] msubs (RCP[const Basic] &x, const map_basic_basic &x) nogil

symengine/lib/symengine_wrapper.pyx

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,16 @@ def sympify(a):
460460
"""
461461
if isinstance(a, str):
462462
return c2py(symengine.parse(a.encode("utf-8")))
463+
elif isinstance(a, tuple):
464+
v = []
465+
for e in a:
466+
v.append(sympify(e))
467+
return tuple(v)
468+
elif isinstance(a, list):
469+
v = []
470+
for e in a:
471+
v.append(sympify(e))
472+
return v
463473
return _sympify(a, True)
464474

465475

@@ -494,16 +504,6 @@ def _sympify(a, raise_error=True):
494504
return RealDouble(a)
495505
elif isinstance(a, complex):
496506
return ComplexDouble(a)
497-
elif isinstance(a, tuple):
498-
v = []
499-
for e in a:
500-
v.append(_sympify(e, True))
501-
return tuple(v)
502-
elif isinstance(a, list):
503-
v = []
504-
for e in a:
505-
v.append(_sympify(e, True))
506-
return v
507507
elif hasattr(a, '_symengine_'):
508508
return _sympify(a._symengine_(), raise_error)
509509
elif hasattr(a, '_sympy_'):
@@ -773,12 +773,17 @@ cdef class Basic(object):
773773
cdef _DictBasic D = get_dict(*args)
774774
return c2py(symengine.ssubs(self.thisptr, D.c))
775775

776-
xreplace = subs
776+
replace = xreplace = subs
777777

778778
def msubs(Basic self not None, *args):
779779
cdef _DictBasic D = get_dict(*args)
780780
return c2py(symengine.msubs(self.thisptr, D.c))
781781

782+
def as_numer_denom(Basic self not None):
783+
cdef RCP[const symengine.Basic] _num, _den
784+
symengine.as_numer_denom(self.thisptr, symengine.outArg(_num), symengine.outArg(_den))
785+
return c2py(<RCP[const symengine.Basic]>_num), c2py(<RCP[const symengine.Basic]>_den)
786+
782787
def n(self, prec = 53, real = False):
783788
if real:
784789
return eval_real(self, prec)
@@ -885,6 +890,9 @@ cdef class Basic(object):
885890
def is_Matrix(self):
886891
return False
887892

893+
def copy(self):
894+
return self
895+
888896
def _symbolic_(self, ring):
889897
return ring(self._sage_())
890898

@@ -1406,6 +1414,10 @@ class Integer(Rational):
14061414
def is_integer(self):
14071415
return True
14081416

1417+
@property
1418+
def doit(self, **hints):
1419+
return self
1420+
14091421
def __hash__(Basic self):
14101422
return deref(self.thisptr).hash()
14111423

@@ -1740,7 +1752,20 @@ class NaN(Number):
17401752
import sage.all as sage
17411753
return sage.NaN
17421754

1743-
class Add(Basic):
1755+
1756+
class AssocOp(Basic):
1757+
1758+
@classmethod
1759+
def make_args(cls, expr):
1760+
if isinstance(expr, cls):
1761+
return expr.args
1762+
else:
1763+
return (sympify(expr),)
1764+
1765+
1766+
class Add(AssocOp):
1767+
1768+
identity = 0
17441769

17451770
def __new__(cls, *args, **kwargs):
17461771
cdef symengine.vec_basic v_
@@ -1750,6 +1775,15 @@ class Add(Basic):
17501775
v_.push_back(e.thisptr)
17511776
return c2py(symengine.add(v_))
17521777

1778+
@classmethod
1779+
def _from_args(self, args):
1780+
if len(args) == 0:
1781+
return self.identity
1782+
elif len(args) == 1:
1783+
return args[0]
1784+
1785+
return Add(*args)
1786+
17531787
@property
17541788
def is_Add(self):
17551789
return True
@@ -1783,7 +1817,9 @@ class Add(Basic):
17831817
inc(iter)
17841818
return d
17851819

1786-
class Mul(Basic):
1820+
class Mul(AssocOp):
1821+
1822+
identity = 1
17871823

17881824
def __new__(cls, *args, **kwargs):
17891825
cdef symengine.vec_basic v_
@@ -1793,6 +1829,15 @@ class Mul(Basic):
17931829
v_.push_back(e.thisptr)
17941830
return c2py(symengine.mul(v_))
17951831

1832+
@classmethod
1833+
def _from_args(self, args):
1834+
if len(args) == 0:
1835+
return self.identity
1836+
elif len(args) == 1:
1837+
return args[0]
1838+
1839+
return Mul(*args)
1840+
17961841
@property
17971842
def is_Mul(self):
17981843
return True
@@ -1828,6 +1873,19 @@ class Pow(Basic):
18281873
def __new__(cls, a, b):
18291874
return _sympify(a) ** b
18301875

1876+
@property
1877+
def base(Basic self):
1878+
cdef RCP[const symengine.Pow] X = symengine.rcp_static_cast_Pow(self.thisptr)
1879+
return c2py(deref(X).get_base())
1880+
1881+
@property
1882+
def exp(Basic self):
1883+
cdef RCP[const symengine.Pow] X = symengine.rcp_static_cast_Pow(self.thisptr)
1884+
return c2py(deref(X).get_exp())
1885+
1886+
def as_base_exp(self):
1887+
return self.base, self.exp
1888+
18311889
@property
18321890
def is_Pow(self):
18331891
return True

symengine/tests/test_arit.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from symengine.utilities import raises
22

3-
from symengine import Symbol, Integer, Add, Pow
3+
from symengine import Symbol, Integer, Add, Mul, Pow, Rational, sqrt
44

55

66
def test_arit1():
@@ -149,3 +149,62 @@ def test_free_symbols():
149149
z = Symbol("z")
150150
assert (x**2).free_symbols == set([x])
151151
assert (x**y + z).free_symbols == set([x, y, z])
152+
153+
154+
def test_as_numer_denom():
155+
x, y = Rational(17, 26).as_numer_denom()
156+
assert x == Integer(17)
157+
assert y == Integer(26)
158+
159+
x, y = Integer(-5).as_numer_denom()
160+
assert x == Integer(-5)
161+
assert y == Integer(1)
162+
163+
164+
def test_from_args():
165+
x = Symbol("x")
166+
y = Symbol("y")
167+
168+
assert Add._from_args([]) == 0
169+
assert Add._from_args([x]) == x
170+
assert Add._from_args([x, y]) == x + y
171+
172+
assert Mul._from_args([]) == 1
173+
assert Mul._from_args([x]) == x
174+
assert Mul._from_args([x, y]) == x * y
175+
176+
177+
def test_make_args():
178+
x = Symbol("x")
179+
y = Symbol("y")
180+
z = Symbol("z")
181+
182+
assert Add.make_args(x) == (x,)
183+
assert Mul.make_args(x) == (x,)
184+
185+
assert Add.make_args(x*y*z) == (x*y*z,)
186+
assert Mul.make_args(x*y*z) == (x*y*z).args
187+
188+
assert Add.make_args(x + y + z) == (x + y + z).args
189+
assert Mul.make_args(x + y + z) == (x + y + z,)
190+
191+
assert Add.make_args((x + y)**z) == ((x + y)**z,)
192+
assert Mul.make_args((x + y)**z) == ((x + y)**z,)
193+
194+
195+
def test_Pow_base_exp():
196+
x = Symbol("x")
197+
y = Symbol("y")
198+
e = Pow(x + y, 2)
199+
assert isinstance(e, Pow)
200+
assert e.exp == 2
201+
assert e.base == x + y
202+
203+
assert sqrt(x - 1).as_base_exp() == (x - 1, Rational(1, 2))
204+
205+
206+
def test_copy():
207+
b = Symbol("b")
208+
a = b.copy()
209+
assert a is b
210+
assert type(a) == type(b)

symengine/tests/test_sympify.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ def test_sympify1():
99
assert sympify(2) != Integer(1)
1010
assert sympify(-5) == Integer(-5)
1111
assert sympify(Integer(3)) == Integer(3)
12+
assert sympify(('0', '0')) == (0, 0)
13+
assert sympify(['0', '0']) == [0, 0]
1214
assert sympify("3+5") == Integer(8)
1315
assert true == sympify(True)
1416
assert false == sympify(False)

0 commit comments

Comments
 (0)