Feat: to_be_token decorator and force token to be Integer when it's
possible
This commit is contained in:
parent
419e5955eb
commit
219d923ff5
@ -15,10 +15,12 @@ from ...core.MO.fraction import MOFraction
|
||||
from ...core.MO.monomial import MOstrPower, MOMonomial
|
||||
from ...core.MO.polynomial import MOpolynomial
|
||||
from decimal import Decimal as _Decimal
|
||||
from functools import wraps
|
||||
from .token import Token
|
||||
|
||||
__all__ = ["factory"]
|
||||
|
||||
|
||||
def tokenify(mo, name="", ancestor=None):
|
||||
""" Transform a MO or a python builtin to the appropriate token
|
||||
|
||||
@ -51,11 +53,33 @@ def tokenify(mo, name="", ancestor=None):
|
||||
"""
|
||||
if isinstance(mo, MO):
|
||||
return _tokenify(mo, name, ancestor)
|
||||
elif isinstance(mo, Token):
|
||||
return _tokenify(mo._mo, name, ancestor)
|
||||
|
||||
if isinstance(mo, Token):
|
||||
if name == "":
|
||||
_name = mo.name
|
||||
else:
|
||||
_name = name
|
||||
if ancestor is None:
|
||||
_ancestor = mo._ancestor
|
||||
else:
|
||||
_ancestor = ancestor
|
||||
return _tokenify(mo._mo, _name, _ancestor)
|
||||
|
||||
return _tokenify(moify(mo), name, ancestor)
|
||||
|
||||
|
||||
def to_be_token(func):
|
||||
""" Decorator to ensure that the return value is a Token """
|
||||
@wraps(func)
|
||||
def wrapped(*args, **kwds):
|
||||
ans = func(*args, **kwds)
|
||||
try:
|
||||
return [tokenify(t) for t in ans]
|
||||
except TypeError:
|
||||
return tokenify(ans)
|
||||
return wrapped
|
||||
|
||||
|
||||
def _tokenify(mo, name="", ancestor=None):
|
||||
""" Transform a MO (from core) to the appropriate token (from API)
|
||||
|
||||
@ -91,25 +115,28 @@ def _tokenify(mo, name="", ancestor=None):
|
||||
if isinstance(mo, MOnumber):
|
||||
if isinstance(mo.value, int):
|
||||
from .number import Integer
|
||||
|
||||
return Integer.from_mo(mo, name, ancestor)
|
||||
elif isinstance(mo.value, _Decimal):
|
||||
from .number import Decimal
|
||||
|
||||
return Decimal.from_mo(mo, name, ancestor)
|
||||
|
||||
raise TypeError(f"Can't build from MOnumber ({mo}) neither int nor decimal")
|
||||
|
||||
elif isinstance(mo, MOFraction):
|
||||
if isinstance(mo, MOFraction):
|
||||
if isinstance(mo._denominator, MOnumber) and isinstance(
|
||||
mo._numerator, MOnumber
|
||||
):
|
||||
from .number import Fraction
|
||||
|
||||
return Fraction.from_mo(mo, name, ancestor)
|
||||
|
||||
raise TypeError(
|
||||
f"Can't build from MOFraction ({mo}) numerator and denominator are not MOnumber"
|
||||
)
|
||||
|
||||
elif isinstance(mo, (MOstr, MOstrPower, MOMonomial, MOpolynomial)):
|
||||
if isinstance(mo, (MOstr, MOstrPower, MOMonomial, MOpolynomial)):
|
||||
if not isinstance(mo._variable, (MOstr, str)):
|
||||
raise TypeError(
|
||||
f"Can't build Polynom over something else than a letter (got {mo._variable})"
|
||||
@ -120,6 +147,7 @@ def _tokenify(mo, name="", ancestor=None):
|
||||
or (isinstance(mo, MOpolynomial) and mo.power.value == 1)
|
||||
):
|
||||
from .polynomial import Linear
|
||||
|
||||
return Linear.from_mo(mo, name, ancestor)
|
||||
elif (
|
||||
(isinstance(mo, MOstrPower) and mo.power.value == 2)
|
||||
@ -127,14 +155,14 @@ def _tokenify(mo, name="", ancestor=None):
|
||||
or (isinstance(mo, MOpolynomial) and mo.power.value == 2)
|
||||
):
|
||||
from .polynomial import Quadratic
|
||||
|
||||
return Quadratic.from_mo(mo, name, ancestor)
|
||||
else:
|
||||
from .polynomial import Polynomial
|
||||
|
||||
return Polynomial.from_mo(mo, name, ancestor)
|
||||
|
||||
else:
|
||||
raise TypeError(f"{type(mo)} is unknown MathObject")
|
||||
|
||||
raise TypeError(f"{type(mo)} is unknown MathObject")
|
||||
|
||||
|
||||
def factory(exp, name="", ancestor=None):
|
||||
|
@ -12,6 +12,7 @@ Tokens representing polynomials functions
|
||||
"""
|
||||
from ..expression import Expression
|
||||
from .token import Token
|
||||
from . import to_be_token
|
||||
from ...core.MO import MO
|
||||
from ...core.MO.atoms import moify
|
||||
|
||||
@ -60,6 +61,7 @@ class Polynomial(Token):
|
||||
""" Use Polynomial like if they were a dictionnary to set coefficients """
|
||||
raise NotImplementedError("Can't set coefficient of a polynomial")
|
||||
|
||||
@to_be_token
|
||||
def __getitem__(self, key):
|
||||
""" Use Polynomial like if they were a dictionnary to get coefficients
|
||||
|
||||
@ -67,11 +69,11 @@ class Polynomial(Token):
|
||||
>>> from ...core.MO.polynomial import MOpolynomial
|
||||
>>> P = Polynomial(MOpolynomial('x', [1, 2, 3]))
|
||||
>>> P[0]
|
||||
<MOnumber 1>
|
||||
<Integer 1>
|
||||
>>> P[1]
|
||||
<MOnumber 2>
|
||||
<Integer 2>
|
||||
>>> P[2]
|
||||
<MOnumber 3>
|
||||
<Integer 3>
|
||||
>>> P[3]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
@ -128,9 +130,9 @@ class Linear(Polynomial):
|
||||
>>> P
|
||||
<Linear 2x + 1>
|
||||
>>> P.a
|
||||
<MOnumber 2>
|
||||
<Integer 2>
|
||||
>>> P.b
|
||||
<MOnumber 1>
|
||||
<Integer 1>
|
||||
>>> P.differentiate()
|
||||
<Integer 2>
|
||||
>>> P.roots
|
||||
@ -158,14 +160,17 @@ class Linear(Polynomial):
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@to_be_token
|
||||
def a(self):
|
||||
return self[1]
|
||||
|
||||
@property
|
||||
@to_be_token
|
||||
def b(self):
|
||||
return self[0]
|
||||
|
||||
@property
|
||||
@to_be_token
|
||||
def roots(self):
|
||||
""" Get the root of the polynomial
|
||||
|
||||
@ -194,11 +199,11 @@ class Quadratic(Polynomial):
|
||||
>>> P
|
||||
<Quadratic 3x^2 + 2x + 1>
|
||||
>>> P.a
|
||||
<MOnumber 3>
|
||||
<Integer 3>
|
||||
>>> P.b
|
||||
<MOnumber 2>
|
||||
<Integer 2>
|
||||
>>> P.c
|
||||
<MOnumber 1>
|
||||
<Integer 1>
|
||||
>>> P.delta
|
||||
<Integer - 8>
|
||||
>>> for s in P.delta.explain():
|
||||
@ -231,6 +236,7 @@ class Quadratic(Polynomial):
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@to_be_token
|
||||
def a(self):
|
||||
try:
|
||||
return self[2]
|
||||
@ -238,6 +244,7 @@ class Quadratic(Polynomial):
|
||||
return 0
|
||||
|
||||
@property
|
||||
@to_be_token
|
||||
def b(self):
|
||||
try:
|
||||
return self[1]
|
||||
@ -245,6 +252,7 @@ class Quadratic(Polynomial):
|
||||
return 0
|
||||
|
||||
@property
|
||||
@to_be_token
|
||||
def c(self):
|
||||
try:
|
||||
return self[0]
|
||||
@ -252,10 +260,12 @@ class Quadratic(Polynomial):
|
||||
return 0
|
||||
|
||||
@property
|
||||
@to_be_token
|
||||
def delta(self):
|
||||
return Expression.from_str(f"{self.b}^2-4*{self.a}*{self.c}").simplify()
|
||||
|
||||
@property
|
||||
@to_be_token
|
||||
def roots(self):
|
||||
""" Roots of the polynom
|
||||
|
||||
@ -266,10 +276,10 @@ class Quadratic(Polynomial):
|
||||
[]
|
||||
>>> P = Quadratic(MOpolynomial('x', [4, -4, 1]))
|
||||
>>> P.roots
|
||||
[2.0]
|
||||
[<Integer 2>]
|
||||
>>> P = Quadratic(MOpolynomial('x', [1, 0, -1]))
|
||||
>>> P.roots
|
||||
[-1.0, 1.0]
|
||||
[<Integer - 1>, <Integer 1>]
|
||||
"""
|
||||
if self.delta._mo < 0:
|
||||
return []
|
||||
|
@ -123,10 +123,13 @@ class MOnumber(Atom):
|
||||
"""
|
||||
if isinstance(value, Atom) and isinstance(value.value, (int, Decimal, float)):
|
||||
Atom.__init__(self, value.value)
|
||||
elif isinstance(value, (int, Decimal)):
|
||||
elif isinstance(value, (float, Decimal)):
|
||||
if int(value) == value:
|
||||
Atom.__init__(self, int(value))
|
||||
else:
|
||||
Atom.__init__(self, Decimal(value))
|
||||
elif isinstance(value, int):
|
||||
Atom.__init__(self, value)
|
||||
elif isinstance(value, float):
|
||||
Atom.__init__(self, Decimal(value))
|
||||
else:
|
||||
try:
|
||||
float(value)
|
||||
@ -165,7 +168,7 @@ class MOnumber(Atom):
|
||||
>>> MOnumber(-3).__tex__
|
||||
'- 3'
|
||||
"""
|
||||
if self.value > 0:
|
||||
if self.value >= 0:
|
||||
return str(self.value)
|
||||
|
||||
return f"- {abs(self.value)}"
|
||||
|
Loading…
Reference in New Issue
Block a user