Skip to content

Additions to symengine/sympy_compat.py #140

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

Merged
merged 4 commits into from
May 15, 2017
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
36 changes: 34 additions & 2 deletions symengine/sympy_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
from .compatibility import with_metaclass
from .lib.symengine_wrapper import (sympify, sympify as S,
SympifyError, sqrt, I, E, pi, Matrix, Derivative, exp,
Lambdify as lambdify, symarray, diff, eye, diag, ones, zeros,
expand, Subs, FunctionSymbol as AppliedUndef)
nextprime, mod_inverse, primitive_root, Lambdify as lambdify,
symarray, diff, eye, diag, ones, zeros, expand, Subs,
FunctionSymbol as AppliedUndef)
from types import ModuleType
import sys

def dps_to_prec(n):
"""Return the number of bits required to represent n decimals accurately."""
return max(1, int(round((int(n)+1)*3.3219280948873626)))

class BasicMeta(type):
def __instancecheck__(self, instance):
Expand Down Expand Up @@ -43,6 +47,34 @@ def __new__(cls, i):
return symengine.Integer(i)


class Float(Number):
_classes = (symengine.RealDouble, symengine.RealMPFR)

def __new__(cls, num, dps=None, precision=None):
if dps is not None and precision is not None:
raise ValueError('Both decimal and binary precision supplied. '
'Supply only one. ')
if dps is None and precision is None:
dps = 15
if precision is None:
precision = dps_to_prec(dps)

if symengine.have_mpfr:
if precision > 53:
if isinstance(num, symengine.RealMPFR) and precision == num.get_prec():
return num
return symengine.RealMPFR(str(num), precision)
if precision > 53:
raise ValueError('RealMPFR unavailable for high precision numerical values.')
elif isinstance(num, symengine.RealDouble):
return num
else:
return symengine.RealDouble(float(num))


RealNumber = Float


class Add(Basic):
_classes = (symengine.Add,)

Expand Down
37 changes: 36 additions & 1 deletion symengine/tests/test_sympy_compat.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from symengine.sympy_compat import (Integer, Rational, S, Basic, Add, Mul,
Pow, symbols, Symbol, log, sin, sech, csch, zeros, atan2, Number)
Pow, symbols, Symbol, log, sin, sech, csch, zeros, atan2, Number, Float,
symengine)
from symengine.utilities import raises


def test_Integer():
Expand All @@ -24,6 +26,39 @@ def test_Rational():
assert not isinstance(x, Number)


def test_Float():
A = Float("1.23", precision = 53)
B = Float("1.23")
C = Float(A)
assert A == B == C
assert isinstance(A, Float)
assert isinstance(B, Float)
assert isinstance(C, Float)
assert isinstance(A, symengine.RealDouble)
assert isinstance(B, symengine.RealDouble)
assert isinstance(C, symengine.RealDouble)
raises(ValueError, lambda: Float("1.23", dps = 3, precision = 10))
raises(ValueError, lambda: Float(A, dps = 3, precision = 16))
if symengine.have_mpfr:
A = Float("1.23", dps = 16)
B = Float("1.23", precision = 56)
assert A == B
assert isinstance(A, Float)
assert isinstance(B, Float)
assert isinstance(A, symengine.RealMPFR)
assert isinstance(B, symengine.RealMPFR)
A = Float(C, dps = 16)
assert A == B
assert isinstance(A, Float)
assert isinstance(A, symengine.RealMPFR)
A = Float(A, precision = 53)
assert A == C
assert isinstance(A, Float)
assert isinstance(A, symengine.RealDouble)
if not symengine.have_mpfr:
raises(ValueError, lambda: Float("1.23", precision = 58))


def test_Add():
x, y = symbols("x y")
i = Add(x, x)
Expand Down