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