Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert Basic to float #265

Merged
merged 2 commits into from
Jan 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions symengine/lib/symengine.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ cdef extern from "<symengine/basic.h>" namespace "SymEngine":
RCP[const Subs] rcp_static_cast_Subs "SymEngine::rcp_static_cast<const SymEngine::Subs>"(rcp_const_basic &b) nogil
RCP[const RealDouble] rcp_static_cast_RealDouble "SymEngine::rcp_static_cast<const SymEngine::RealDouble>"(rcp_const_basic &b) nogil
RCP[const ComplexDouble] rcp_static_cast_ComplexDouble "SymEngine::rcp_static_cast<const SymEngine::ComplexDouble>"(rcp_const_basic &b) nogil
RCP[const ComplexBase] rcp_static_cast_ComplexBase "SymEngine::rcp_static_cast<const SymEngine::ComplexBase>"(rcp_const_basic &b) nogil
RCP[const RealMPFR] rcp_static_cast_RealMPFR "SymEngine::rcp_static_cast<const SymEngine::RealMPFR>"(rcp_const_basic &b) nogil
RCP[const ComplexMPC] rcp_static_cast_ComplexMPC "SymEngine::rcp_static_cast<const SymEngine::ComplexMPC>"(rcp_const_basic &b) nogil
RCP[const Log] rcp_static_cast_Log "SymEngine::rcp_static_cast<const SymEngine::Log>"(rcp_const_basic &b) nogil
Expand Down Expand Up @@ -363,7 +364,9 @@ cdef extern from "<symengine/integer.h>" namespace "SymEngine":
Integer(int i) nogil
Integer(integer_class i) nogil
int compare(const Basic &o) nogil
integer_class as_mpz() nogil
integer_class as_integer_class() nogil
cdef long mp_get_si(integer_class &i) nogil
cdef double mp_get_d(integer_class &i) nogil
cdef RCP[const Integer] integer(int i) nogil
cdef RCP[const Integer] integer(integer_class i) nogil
int i_nth_root(const Ptr[RCP[Integer]] &r, const Integer &a, unsigned long int n) nogil
Expand All @@ -372,16 +375,19 @@ cdef extern from "<symengine/integer.h>" namespace "SymEngine":

cdef extern from "<symengine/rational.h>" namespace "SymEngine":
cdef cppclass Rational(Number):
rational_class as_mpq() nogil
rational_class as_rational_class() nogil
cdef double mp_get_d(rational_class &i) nogil
cdef RCP[const Number] from_mpq "SymEngine::Rational::from_mpq"(rational_class r) nogil
cdef void get_num_den(const Rational &rat, const Ptr[RCP[Integer]] &num,
const Ptr[RCP[Integer]] &den) nogil
cdef RCP[const Number] rational(long n, long d) nogil

cdef extern from "<symengine/complex.h>" namespace "SymEngine":
cdef cppclass Complex(Number):
cdef cppclass ComplexBase(Number):
RCP[const Number] real_part() nogil
RCP[const Number] imaginary_part() nogil
cdef cppclass Complex(ComplexBase):
pass

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

cdef extern from "<symengine/complex_double.h>" namespace "SymEngine":
cdef cppclass ComplexDouble(Number):
cdef cppclass ComplexDouble(ComplexBase):
ComplexDouble(double complex x) nogil
RCP[const Number] real_part() nogil
RCP[const Number] imaginary_part() nogil
double complex as_complex_double() nogil
RCP[const ComplexDouble] complex_double(double complex d) nogil

Expand Down Expand Up @@ -751,12 +755,10 @@ IF HAVE_SYMENGINE_MPC:
mpc_ptr get_mpc_t() nogil
mpc_class(string s, mpfr_prec_t prec, unsigned base) nogil

cdef cppclass ComplexMPC(Number):
cdef cppclass ComplexMPC(ComplexBase):
ComplexMPC(mpc_class) nogil
mpc_class as_mpc() nogil
mpfr_prec_t get_prec() nogil
RCP[const Number] real_part() nogil
RCP[const Number] imaginary_part() nogil

RCP[const ComplexMPC] complex_mpc(mpc_class t) nogil
ELSE:
Expand Down
95 changes: 59 additions & 36 deletions symengine/lib/symengine_wrapper.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,25 @@ cdef class Basic(object):
s.append(c2py(<rcp_const_basic>(Y[i]))._sympy_())
return s

def __float__(self):
f = self.n(real=True)
if not isinstance(f, RealDouble):
raise TypeError("Can't convert expression to float")
return float(f)

def __int__(self):
return int(float(self))

def __long__(self):
return long(float(self))

def __complex__(self):
f = self.n(real=False)
if not isinstance(f, (ComplexDouble, RealDouble)):
raise TypeError("Can't convert expression to float")
return complex(f)


def series(ex, x=None, x0=0, n=6, as_deg_coef_pair=False):
# TODO: check for x0 an infinity, see sympy/core/expr.py
# TODO: nonzero x0
Expand Down Expand Up @@ -1546,6 +1565,14 @@ cdef class Number(Expr):
def is_complex(Basic self):
return deref(symengine.rcp_static_cast_Number(self.thisptr)).is_complex()

@property
def real(self):
return self

@property
def imag(self):
return S.Zero


class Rational(Number):

Expand Down Expand Up @@ -1602,6 +1629,7 @@ class Rational(Number):
def func(self):
return self.__class__


class Integer(Rational):

def __new__(cls, i):
Expand Down Expand Up @@ -1687,14 +1715,8 @@ class Integer(Rational):
import sage.all as sage
return sage.Integer(str(self))

def __int__(self):
return int(str(self))

def __long__(self):
return long(str(self))

def __float__(self):
return float(str(self))
def __int__(Basic self):
return symengine.mp_get_si(deref(symengine.rcp_static_cast_Integer(self.thisptr)).as_integer_class())

@property
def p(self):
Expand Down Expand Up @@ -1779,27 +1801,40 @@ class RealDouble(Float):

def _sage_(Basic self):
import sage.all as sage
cdef double i = deref(symengine.rcp_static_cast_RealDouble(self.thisptr)).as_double()
return sage.RealDoubleField()(i)
return sage.RealDoubleField()(float(self))

def __float__(self):
return float(str(self))
def __float__(Basic self):
return deref(symengine.rcp_static_cast_RealDouble(self.thisptr)).as_double()

def __complex__(self):
return complex(float(self))


cdef class ComplexDouble(Number):
cdef class ComplexBase(Number):

def real_part(Basic self):
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_ComplexBase(self.thisptr)).real_part())

def imaginary_part(Basic self):
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_ComplexBase(self.thisptr)).imaginary_part())

@property
def real(self):
return self.real_part()

@property
def imag(self):
return self.imaginary_part()


cdef class ComplexDouble(ComplexBase):

def __cinit__(self, i = None):
if i is None:
return
cdef double complex i_ = i
self.thisptr = symengine.make_rcp_ComplexDouble(i_)

def real_part(Basic self):
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_ComplexDouble(self.thisptr)).real_part())

def imaginary_part(Basic self):
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_ComplexDouble(self.thisptr)).imaginary_part())

def _sympy_(self):
import sympy
return self.real_part()._sympy_() + sympy.I * self.imaginary_part()._sympy_()
Expand All @@ -1808,6 +1843,9 @@ cdef class ComplexDouble(Number):
import sage.all as sage
return self.real_part()._sage_() + sage.I * self.imaginary_part()._sage_()

def __complex__(Basic self):
return deref(symengine.rcp_static_cast_ComplexDouble(self.thisptr)).as_complex_double()


class RealMPFR(Float):

Expand Down Expand Up @@ -1836,14 +1874,11 @@ class RealMPFR(Float):
except ImportError:
import sage.all as sage
return sage.RealField(int(self.get_prec()))(str(self))

def __float__(self):
return float(str(self))
ELSE:
pass


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

def real_part(self):
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_ComplexMPC(self.thisptr)).real_part())

def imaginary_part(self):
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_ComplexMPC(self.thisptr)).imaginary_part())

def _sympy_(self):
import sympy
return self.real_part()._sympy_() + sympy.I * self.imaginary_part()._sympy_()
Expand All @@ -1873,13 +1902,7 @@ cdef class ComplexMPC(Number):
pass


cdef class Complex(Number):

def real_part(self):
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_Complex(self.thisptr)).real_part())

def imaginary_part(self):
return c2py(<rcp_const_basic>deref(symengine.rcp_static_cast_Complex(self.thisptr)).imaginary_part())
cdef class Complex(ComplexBase):

def _sympy_(self):
import sympy
Expand Down
31 changes: 30 additions & 1 deletion symengine/tests/test_number.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
from symengine.utilities import raises

from symengine import Integer, I
from symengine import Integer, I, S
from symengine.lib.symengine_wrapper import (perfect_power, is_square, integer_nthroot)


def test_integer():
i = Integer(5)
assert str(i) == "5"
assert int(i) == 5
assert float(i) == 5.0
assert complex(i) == 5.0 + 0j
assert i.real == i
assert i.imag == S.Zero


def test_integer_long():
Expand All @@ -18,6 +23,30 @@ def test_integer_string():
assert Integer("133") == 133


def test_rational():
i = Integer(5)/10
assert str(i) == "1/2"
assert int(i) == 0
assert float(i) == 0.5
assert complex(i) == 0.5 + 0j
assert i.real == i
assert i.imag == S.Zero


def test_complex():
i = Integer(5)/10 + I
assert str(i) == "1/2 + I"
assert complex(i) == 0.5 + 1j
assert i.real == Integer(1)/2
assert i.imag == 1

i = 0.5 + I
assert str(i) == "0.5 + 1.0*I"
assert complex(i) == 0.5 + 1j
assert i.real == 0.5
assert i.imag == 1.0


def test_smallfloat_valid():
i = Integer(7.5)
assert str(i) == "7"
Expand Down