Skip to content

Commit 5179f17

Browse files
authored
Merge pull request #265 from isuruf/convert
Convert Basic to float
2 parents df48df0 + 43e93c6 commit 5179f17

File tree

3 files changed

+100
-46
lines changed

3 files changed

+100
-46
lines changed

symengine/lib/symengine.pxd

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ cdef extern from "<symengine/basic.h>" namespace "SymEngine":
214214
RCP[const Subs] rcp_static_cast_Subs "SymEngine::rcp_static_cast<const SymEngine::Subs>"(rcp_const_basic &b) nogil
215215
RCP[const RealDouble] rcp_static_cast_RealDouble "SymEngine::rcp_static_cast<const SymEngine::RealDouble>"(rcp_const_basic &b) nogil
216216
RCP[const ComplexDouble] rcp_static_cast_ComplexDouble "SymEngine::rcp_static_cast<const SymEngine::ComplexDouble>"(rcp_const_basic &b) nogil
217+
RCP[const ComplexBase] rcp_static_cast_ComplexBase "SymEngine::rcp_static_cast<const SymEngine::ComplexBase>"(rcp_const_basic &b) nogil
217218
RCP[const RealMPFR] rcp_static_cast_RealMPFR "SymEngine::rcp_static_cast<const SymEngine::RealMPFR>"(rcp_const_basic &b) nogil
218219
RCP[const ComplexMPC] rcp_static_cast_ComplexMPC "SymEngine::rcp_static_cast<const SymEngine::ComplexMPC>"(rcp_const_basic &b) nogil
219220
RCP[const Log] rcp_static_cast_Log "SymEngine::rcp_static_cast<const SymEngine::Log>"(rcp_const_basic &b) nogil
@@ -363,7 +364,9 @@ cdef extern from "<symengine/integer.h>" namespace "SymEngine":
363364
Integer(int i) nogil
364365
Integer(integer_class i) nogil
365366
int compare(const Basic &o) nogil
366-
integer_class as_mpz() nogil
367+
integer_class as_integer_class() nogil
368+
cdef long mp_get_si(integer_class &i) nogil
369+
cdef double mp_get_d(integer_class &i) nogil
367370
cdef RCP[const Integer] integer(int i) nogil
368371
cdef RCP[const Integer] integer(integer_class i) nogil
369372
int i_nth_root(const Ptr[RCP[Integer]] &r, const Integer &a, unsigned long int n) nogil
@@ -372,16 +375,19 @@ cdef extern from "<symengine/integer.h>" namespace "SymEngine":
372375

373376
cdef extern from "<symengine/rational.h>" namespace "SymEngine":
374377
cdef cppclass Rational(Number):
375-
rational_class as_mpq() nogil
378+
rational_class as_rational_class() nogil
379+
cdef double mp_get_d(rational_class &i) nogil
376380
cdef RCP[const Number] from_mpq "SymEngine::Rational::from_mpq"(rational_class r) nogil
377381
cdef void get_num_den(const Rational &rat, const Ptr[RCP[Integer]] &num,
378382
const Ptr[RCP[Integer]] &den) nogil
379383
cdef RCP[const Number] rational(long n, long d) nogil
380384

381385
cdef extern from "<symengine/complex.h>" namespace "SymEngine":
382-
cdef cppclass Complex(Number):
386+
cdef cppclass ComplexBase(Number):
383387
RCP[const Number] real_part() nogil
384388
RCP[const Number] imaginary_part() nogil
389+
cdef cppclass Complex(ComplexBase):
390+
pass
385391

386392
cdef extern from "<symengine/real_double.h>" namespace "SymEngine":
387393
cdef cppclass RealDouble(Number):
@@ -390,10 +396,8 @@ cdef extern from "<symengine/real_double.h>" namespace "SymEngine":
390396
RCP[const RealDouble] real_double(double d) nogil
391397

392398
cdef extern from "<symengine/complex_double.h>" namespace "SymEngine":
393-
cdef cppclass ComplexDouble(Number):
399+
cdef cppclass ComplexDouble(ComplexBase):
394400
ComplexDouble(double complex x) nogil
395-
RCP[const Number] real_part() nogil
396-
RCP[const Number] imaginary_part() nogil
397401
double complex as_complex_double() nogil
398402
RCP[const ComplexDouble] complex_double(double complex d) nogil
399403

@@ -751,12 +755,10 @@ IF HAVE_SYMENGINE_MPC:
751755
mpc_ptr get_mpc_t() nogil
752756
mpc_class(string s, mpfr_prec_t prec, unsigned base) nogil
753757

754-
cdef cppclass ComplexMPC(Number):
758+
cdef cppclass ComplexMPC(ComplexBase):
755759
ComplexMPC(mpc_class) nogil
756760
mpc_class as_mpc() nogil
757761
mpfr_prec_t get_prec() nogil
758-
RCP[const Number] real_part() nogil
759-
RCP[const Number] imaginary_part() nogil
760762

761763
RCP[const ComplexMPC] complex_mpc(mpc_class t) nogil
762764
ELSE:

symengine/lib/symengine_wrapper.pyx

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,25 @@ cdef class Basic(object):
10661066
s.append(c2py(<rcp_const_basic>(Y[i]))._sympy_())
10671067
return s
10681068

1069+
def __float__(self):
1070+
f = self.n(real=True)
1071+
if not isinstance(f, RealDouble):
1072+
raise TypeError("Can't convert expression to float")
1073+
return float(f)
1074+
1075+
def __int__(self):
1076+
return int(float(self))
1077+
1078+
def __long__(self):
1079+
return long(float(self))
1080+
1081+
def __complex__(self):
1082+
f = self.n(real=False)
1083+
if not isinstance(f, (ComplexDouble, RealDouble)):
1084+
raise TypeError("Can't convert expression to float")
1085+
return complex(f)
1086+
1087+
10691088
def series(ex, x=None, x0=0, n=6, as_deg_coef_pair=False):
10701089
# TODO: check for x0 an infinity, see sympy/core/expr.py
10711090
# TODO: nonzero x0
@@ -1546,6 +1565,14 @@ cdef class Number(Expr):
15461565
def is_complex(Basic self):
15471566
return deref(symengine.rcp_static_cast_Number(self.thisptr)).is_complex()
15481567

1568+
@property
1569+
def real(self):
1570+
return self
1571+
1572+
@property
1573+
def imag(self):
1574+
return S.Zero
1575+
15491576

15501577
class Rational(Number):
15511578

@@ -1602,6 +1629,7 @@ class Rational(Number):
16021629
def func(self):
16031630
return self.__class__
16041631

1632+
16051633
class Integer(Rational):
16061634

16071635
def __new__(cls, i):
@@ -1687,14 +1715,8 @@ class Integer(Rational):
16871715
import sage.all as sage
16881716
return sage.Integer(str(self))
16891717

1690-
def __int__(self):
1691-
return int(str(self))
1692-
1693-
def __long__(self):
1694-
return long(str(self))
1695-
1696-
def __float__(self):
1697-
return float(str(self))
1718+
def __int__(Basic self):
1719+
return symengine.mp_get_si(deref(symengine.rcp_static_cast_Integer(self.thisptr)).as_integer_class())
16981720

16991721
@property
17001722
def p(self):
@@ -1779,27 +1801,40 @@ class RealDouble(Float):
17791801

17801802
def _sage_(Basic self):
17811803
import sage.all as sage
1782-
cdef double i = deref(symengine.rcp_static_cast_RealDouble(self.thisptr)).as_double()
1783-
return sage.RealDoubleField()(i)
1804+
return sage.RealDoubleField()(float(self))
17841805

1785-
def __float__(self):
1786-
return float(str(self))
1806+
def __float__(Basic self):
1807+
return deref(symengine.rcp_static_cast_RealDouble(self.thisptr)).as_double()
1808+
1809+
def __complex__(self):
1810+
return complex(float(self))
17871811

17881812

1789-
cdef class ComplexDouble(Number):
1813+
cdef class ComplexBase(Number):
1814+
1815+
def real_part(Basic self):
1816+
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_ComplexBase(self.thisptr)).real_part())
1817+
1818+
def imaginary_part(Basic self):
1819+
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_ComplexBase(self.thisptr)).imaginary_part())
1820+
1821+
@property
1822+
def real(self):
1823+
return self.real_part()
1824+
1825+
@property
1826+
def imag(self):
1827+
return self.imaginary_part()
1828+
1829+
1830+
cdef class ComplexDouble(ComplexBase):
17901831

17911832
def __cinit__(self, i = None):
17921833
if i is None:
17931834
return
17941835
cdef double complex i_ = i
17951836
self.thisptr = symengine.make_rcp_ComplexDouble(i_)
17961837

1797-
def real_part(Basic self):
1798-
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_ComplexDouble(self.thisptr)).real_part())
1799-
1800-
def imaginary_part(Basic self):
1801-
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_ComplexDouble(self.thisptr)).imaginary_part())
1802-
18031838
def _sympy_(self):
18041839
import sympy
18051840
return self.real_part()._sympy_() + sympy.I * self.imaginary_part()._sympy_()
@@ -1808,6 +1843,9 @@ cdef class ComplexDouble(Number):
18081843
import sage.all as sage
18091844
return self.real_part()._sage_() + sage.I * self.imaginary_part()._sage_()
18101845

1846+
def __complex__(Basic self):
1847+
return deref(symengine.rcp_static_cast_ComplexDouble(self.thisptr)).as_complex_double()
1848+
18111849

18121850
class RealMPFR(Float):
18131851

@@ -1836,14 +1874,11 @@ class RealMPFR(Float):
18361874
except ImportError:
18371875
import sage.all as sage
18381876
return sage.RealField(int(self.get_prec()))(str(self))
1839-
1840-
def __float__(self):
1841-
return float(str(self))
18421877
ELSE:
18431878
pass
18441879

18451880

1846-
cdef class ComplexMPC(Number):
1881+
cdef class ComplexMPC(ComplexBase):
18471882
IF HAVE_SYMENGINE_MPC:
18481883
def __cinit__(self, i = None, j = 0, long prec = 53, unsigned base = 10):
18491884
if i is None:
@@ -1852,12 +1887,6 @@ cdef class ComplexMPC(Number):
18521887
cdef symengine.mpc_class m = symengine.mpc_class(i_, prec, base)
18531888
self.thisptr = <rcp_const_basic>symengine.complex_mpc(symengine.std_move_mpc(m))
18541889

1855-
def real_part(self):
1856-
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_ComplexMPC(self.thisptr)).real_part())
1857-
1858-
def imaginary_part(self):
1859-
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_ComplexMPC(self.thisptr)).imaginary_part())
1860-
18611890
def _sympy_(self):
18621891
import sympy
18631892
return self.real_part()._sympy_() + sympy.I * self.imaginary_part()._sympy_()
@@ -1873,13 +1902,7 @@ cdef class ComplexMPC(Number):
18731902
pass
18741903

18751904

1876-
cdef class Complex(Number):
1877-
1878-
def real_part(self):
1879-
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_Complex(self.thisptr)).real_part())
1880-
1881-
def imaginary_part(self):
1882-
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_Complex(self.thisptr)).imaginary_part())
1905+
cdef class Complex(ComplexBase):
18831906

18841907
def _sympy_(self):
18851908
import sympy

symengine/tests/test_number.py

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

3-
from symengine import Integer, I
3+
from symengine import Integer, I, S
44
from symengine.lib.symengine_wrapper import (perfect_power, is_square, integer_nthroot)
55

66

77
def test_integer():
88
i = Integer(5)
99
assert str(i) == "5"
10+
assert int(i) == 5
11+
assert float(i) == 5.0
12+
assert complex(i) == 5.0 + 0j
13+
assert i.real == i
14+
assert i.imag == S.Zero
1015

1116

1217
def test_integer_long():
@@ -18,6 +23,30 @@ def test_integer_string():
1823
assert Integer("133") == 133
1924

2025

26+
def test_rational():
27+
i = Integer(5)/10
28+
assert str(i) == "1/2"
29+
assert int(i) == 0
30+
assert float(i) == 0.5
31+
assert complex(i) == 0.5 + 0j
32+
assert i.real == i
33+
assert i.imag == S.Zero
34+
35+
36+
def test_complex():
37+
i = Integer(5)/10 + I
38+
assert str(i) == "1/2 + I"
39+
assert complex(i) == 0.5 + 1j
40+
assert i.real == Integer(1)/2
41+
assert i.imag == 1
42+
43+
i = 0.5 + I
44+
assert str(i) == "0.5 + 1.0*I"
45+
assert complex(i) == 0.5 + 1j
46+
assert i.real == 0.5
47+
assert i.imag == 1.0
48+
49+
2150
def test_smallfloat_valid():
2251
i = Integer(7.5)
2352
assert str(i) == "7"

0 commit comments

Comments
 (0)