Mapytex/mapytex/calculus/abstract_polynom.py

755 lines
24 KiB
Python

#!/usr/bin/env python
# encoding: utf-8
from .explicable import Explicable
from .expression import Expression
from .step import Step
from .renderable import Renderable
from .operator import op
from .generic import spe_zip, isNumber, transpose_fill, flatten_list, isPolynom, postfix_op
from functools import wraps
def power_cache(fun):
"""Decorator which cache calculated powers of polynoms """
cache = {}
@wraps(fun)
def cached_fun(self, power):
if (tuple(self._coef), power) in cache.keys():
return cache[(tuple(self._coef), power)]
else:
poly_powered = fun(self, power)
cache[(tuple(self._coef), power)] = poly_powered
return poly_powered
return cached_fun
class AbstractPolynom(Explicable):
"""The mathematic definition of a polynom. It will be the parent class of Polynom (classical polynoms) and later of SquareRoot polynoms"""
def __init__(self, coefs=[1], letter="x", name="P"):
"""Initiate the polynom
:param coef: coefficients of the polynom (ascending degree sorted)
3 possibles type of coefficent:
- a : simple "number". [1,2] designate 1 + 2x
- [a,b,c]: list of coeficient for same degree. [1,[2,3],4] designate 1 + 2x + 3x + 4x^2
- a: a Expression. [1, Expression("2+3"), 4] designate 1 + (2+3)x + 4x^2
:param letter: the string describing the unknown
:param name: Name of the polynom
>>> P = AbstractPolynom([1, 2, 3])
>>> P.mainOp
+
>>> P.name
'P'
>>> P._letter
'x'
>>> AbstractPolynom([1]).mainOp
*
>>> AbstractPolynom([0, 0, 3]).mainOp
*
>>> AbstractPolynom([1, 2, 3])._letter
'x'
>>> AbstractPolynom([1, 2, 3], "y")._letter
'y'
>>> AbstractPolynom([1, 2, 3], name = "Q").name
'Q'
"""
try:
# Remove 0 at the end of the coefs
while coefs[-1] == 0:
coefs = coefs[:-1]
except IndexError:
pass
if coefs == []:
coefs = [0]
self.feed_coef(coefs)
self._letter = letter
self.name = name
if self.is_monom():
self.mainOp = op.mul
else:
self.mainOp = op.add
self._isPolynom = 1
pstf_tokens = self.compute_postfix_tokens()
super(AbstractPolynom, self).__init__(pstf_tokens)
def feed_coef(self, l_coef):
"""Feed coef of the polynom. Manage differently whether it's a number or an expression
:l_coef: list of coef
"""
self._coef = []
for coef in l_coef:
if isinstance(coef, list) and len(coef) == 1:
self._coef.append(coef[0])
else:
self._coef.append(coef)
@property
def degree(self):
"""Getting the degree fo the polynom
:returns: the degree of the polynom
>>> AbstractPolynom([1, 2, 3]).degree
2
>>> AbstractPolynom([1]).degree
0
"""
return len(self._coef) - 1
def is_monom(self):
"""is the polynom a monom (only one coefficent)
:returns: 1 if yes 0 otherwise
>>> AbstractPolynom([1, 2, 3]).is_monom()
0
>>> AbstractPolynom([1]).is_monom()
1
"""
if len([i for i in self._coef if i != 0]) == 1:
return 1
else:
return 0
def give_name(self, name):
self.name = name
def __str__(self):
return str(Expression(self.postfix_tokens))
def __repr__(self):
return "< {cls} {letter} {coefs}>".format(
cls = str(self.__class__).split('.')[-1][:-2],
letter = str(self._letter),
coefs = str(self._coef))
def coef_postfix(self, a, i):
"""Return the postfix display of a coeficient
:param a: value for the coeficient (/!\ as a postfix list)
:param i: power
:returns: postfix tokens of coef
>>> p = AbstractPolynom()
>>> p.coef_postfix([3],2)
[3, 'x', 2, ^, *]
>>> p.coef_postfix([0],1)
[]
>>> p.coef_postfix([3],0)
[3]
>>> p.coef_postfix([3],1)
[3, 'x', *]
>>> p.coef_postfix([1],1)
['x']
>>> p.coef_postfix([1],2)
['x', 2, ^]
"""
if a == [0]:
ans = []
elif i == 0:
ans = a
elif i == 1:
ans = a * (a not in [[1], [-1]]) + \
[self._letter] + \
[op.mul] * (a not in [[1], [-1]]) + \
[op.sub1] * (a == [-1])
else:
ans = a * (a not in [[1], [-1]]) + \
[self._letter, i, op.pw] + \
[op.mul] * (a not in [[1], [-1]]) + \
[op.sub1] * (a == [-1])
return ans
def coefs_postifx(self):
""" Return list of postfix coef with the the right power letter
>>> p = AbstractPolynom([1, 2])
>>> p.coefs_postifx()
[[1], [2, 'x', *]]
>>> p = AbstractPolynom([1, -2])
>>> p.coefs_postifx()
[[1], [-2, 'x', *]]
>>> p = AbstractPolynom([1,2,3])
>>> p.coefs_postifx()
[[1], [2, 'x', *], [3, 'x', 2, ^, *]]
>>> p = AbstractPolynom([1])
>>> p.coefs_postifx()
[[1]]
>>> p = AbstractPolynom([0])
>>> p.coefs_postifx()
[[0]]
>>> p = AbstractPolynom([0, 1, 1, 0])
>>> p.coefs_postifx()
[['x'], ['x', 2, ^]]
>>> p = AbstractPolynom([1,[2,3]])
>>> p.coefs_postifx()
[[1], [3, 'x', *], [2, 'x', *]]
>>> p = AbstractPolynom([1,[2,-3]])
>>> p.coefs_postifx()
[[1], [-3, 'x', *], [2, 'x', *]]
>>> p = AbstractPolynom([1,[-2,-3]])
>>> p.coefs_postifx()
[[1], [-3, 'x', *], [-2, 'x', *]]
>>> p = AbstractPolynom([1,[-2,0]])
>>> p.coefs_postifx()
[[1], [-2, 'x', *]]
>>> from mapytex.calculus.expression import Expression
>>> from mapytex.calculus.operator import op
>>> e = Expression([2,3,op.add])
>>> p = AbstractPolynom([1,e])
>>> p.coefs_postifx()
[[1], [2, 3, +, 'x', *]]
"""
if not [i for i in self._coef if i!= 0]:
return [[0]]
raw_coefs = []
for (pw, coef) in enumerate(self._coef):
if isinstance(coef, list):
for c in coef[::-1]:
try:
raw_coefs.append(self.coef_postfix(c.postfix_tokens, pw))
except AttributeError:
raw_coefs.append(self.coef_postfix([c], pw))
elif coef != 0:
try:
raw_coefs.append(self.coef_postfix(coef.postfix_tokens, pw))
except AttributeError:
raw_coefs.append(self.coef_postfix([coef], pw))
return [i for i in raw_coefs if i != []]
def compute_postfix_tokens(self):
"""Return the postfix form of the polynom
:returns: the postfix list of polynom's tokens
>>> p = AbstractPolynom([1, 2])
>>> p.postfix_tokens
[2, 'x', *, 1, +]
>>> p = AbstractPolynom([1, -2])
>>> p.postfix_tokens
[-2, 'x', *, 1, +]
>>> p = AbstractPolynom([1,2,3])
>>> p.postfix_tokens
[3, 'x', 2, ^, *, 2, 'x', *, +, 1, +]
>>> p = AbstractPolynom([1])
>>> p.postfix_tokens
[1]
>>> p = AbstractPolynom([0])
>>> p.postfix_tokens
[0]
>>> p = AbstractPolynom([1,[2,3]])
>>> p.postfix_tokens
[2, 'x', *, 3, 'x', *, +, 1, +]
>>> p = AbstractPolynom([1,[2,-3]])
>>> p.postfix_tokens
[2, 'x', *, -3, 'x', *, +, 1, +]
>>> p = AbstractPolynom([1,[-2,-3]])
>>> p.postfix_tokens
[-2, 'x', *, -3, 'x', *, +, 1, +]
>>> from mapytex.calculus.expression import Expression
>>> from mapytex.calculus.operator import op
>>> e = Expression([2,3,op.add])
>>> p = AbstractPolynom([1,e])
>>> p.postfix_tokens
[2, 3, +, 'x', *, 1, +]
"""
raw_coefs = self.coefs_postifx()
pstfx = postfix_op(raw_coefs[::-1], op.add)
return flatten_list(pstfx)
def conv2poly(self, other):
"""Convert anything number into a polynom
>>> P = AbstractPolynom([1,2,3])
>>> P.conv2poly(1)
< AbstractPolynom x [1]>
>>> P.conv2poly(0)
< AbstractPolynom x [0]>
>>> Q = AbstractPolynom([3, 2, 1], 'x')
>>> P.conv2poly(Q)
< AbstractPolynom x [3, 2, 1]>
>>> Q = AbstractPolynom([3, 2, 1], 'y')
>>> P.conv2poly(Q)
< AbstractPolynom x [< AbstractPolynom y [3, 2, 1]>]>
"""
if (isNumber(other) and not isPolynom(other)) or \
(isPolynom(other) and self._letter != other._letter):
#ans = self.__class__([other], letter=self._letter)
ans = AbstractPolynom([other], letter=self._letter)
ans.steal_history(other)
return ans
elif isPolynom(other):
return other
else:
raise ValueError(
type(other) +
" can't be converted into a polynom"
)
def reduce(self):
"""Compute coefficients which have same degree
:returns: new AbstractPolynom with numbers coefficients
>>> P = AbstractPolynom([1,2,3])
>>> Q = P.reduce()
>>> Q
< AbstractPolynom x [1, 2, 3]>
>>> Q.steps
[< Step [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +]>, < Step [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +]>]
>>> P = AbstractPolynom([[1,2], [3,4,5], 6])
>>> Q = P.reduce()
>>> Q
< AbstractPolynom x [3, 12, 6]>
>>> for i in Q.explain():
... print(i)
6 x^{ 2 } + 3 x + 4 x + 5 x + 1 + 2
6 x^{ 2 } + ( 3 + 4 + 5 ) x + 1 + 2
6 x^{ 2 } + ( 7 + 5 ) x + 3
6 x^{ 2 } + 12 x + 3
>>> Q.steps
[< Step [6, 'x', 2, ^, *, 3, 'x', *, +, 4, 'x', *, +, 5, 'x', *, +, 1, +, 2, +]>, < Step [6, 'x', 2, ^, *, 3, 4, +, 5, +, 'x', *, +, 1, 2, +, +]>, < Step [6, 'x', 2, ^, *, 7, 5, +, 'x', *, +, 3, +]>, < Step [6, 'x', 2, ^, *, 12, 'x', *, +, 3, +]>]
>>> P = AbstractPolynom([[1,2], [3,4,5], 6], 'y')
>>> Q = P.reduce()
>>> Q
< AbstractPolynom y [3, 12, 6]>
>>> for i in Q.explain():
... print(i)
6 y^{ 2 } + 3 y + 4 y + 5 y + 1 + 2
6 y^{ 2 } + ( 3 + 4 + 5 ) y + 1 + 2
6 y^{ 2 } + ( 7 + 5 ) y + 3
6 y^{ 2 } + 12 y + 3
>>> P = AbstractPolynom([1,2])
>>> Q = AbstractPolynom([P,3], 'y')
>>> Q
< AbstractPolynom y [< AbstractPolynom x [1, 2]>, 3]>
>>> Q = Q.reduce()
>>> for i in Q.explain():
... print(i)
3 y + 2 x + 1
>>> P = AbstractPolynom([1,2])
>>> Q = AbstractPolynom([[P,1],3], 'y')
>>> Q
< AbstractPolynom y [[< AbstractPolynom x [1, 2]>, 1], 3]>
>>> Q = Q.reduce()
>>> for i in Q.explain():
... print(i)
3 y + 2 x + 1 + 1
3 y + 2 x + 2
"""
smpl_coef = []
for coef in self._coef:
if isinstance(coef, list):
coef_exp = AbstractPolynom.smpl_coef_list(coef)
else:
try:
coef_exp = coef.simplify()
except AttributeError:
coef_exp = coef
smpl_coef.append(coef_exp)
ans = AbstractPolynom(smpl_coef, self._letter)
ini_step = [Step(self)]
for s in Explicable.merge_history(smpl_coef):
ini_step.append(Step(AbstractPolynom(s, self._letter)))
ans.this_append_before(
ini_step
#AbstractPolynom(s)
#for s in Expression.develop_steps(smpl_coef)
)
return ans
def simplify(self):
"""Same as reduce """
if isNumber(self._letter):
return self.replace_letter(self._letter).simplify()
return self.reduce()
@classmethod
def smpl_coef_list(cls, coef_list):
""" Simplify the coef when it is a list
:param coef_list: the list discribing the coef
:returns: the simplify coef
>>> c = AbstractPolynom.smpl_coef_list([1, 2, 3])
>>> c
6
>>> c.steps
[< Step [1, 2, +, 3, +]>, < Step [1, 2, +, 3, +]>, < Step [3, 3, +]>, < Step [3, 3, +]>, < Step [6]>]
>>> c = AbstractPolynom.smpl_coef_list([Expression('2*2'), 3])
>>> c
7
>>> c.steps
[< Step [2, 2, *, 3, +]>, < Step [4, 3, +]>, < Step [4, 3, +]>, < Step [7]>]
>>> c = AbstractPolynom.smpl_coef_list([0, 2, 0])
>>> c
2
>>> c.steps
[< Step [2]>]
"""
# Simplify each element before adding them
smpl_elem = []
for c in coef_list:
try:
smpl_c = c.simplify()
except AttributeError:
smpl_c = c
smpl_elem.append(smpl_c)
pstfx_add = postfix_op(
[i for i in smpl_elem if i != 0],
op.add
)
steps = Expression.develop_steps(pstfx_add)
ans = Expression(pstfx_add).simplify()
ans.this_append_before(steps)
return ans
def replace_letter(self, letter):
r""" Replace the letter in the expression
:param letter: the new letter.
:returns: The expression with the new letter.
>>> A = AbstractPolynom([1, 2])
>>> A
< AbstractPolynom x [1, 2]>
>>> B = A.replace_letter("y")
>>> B
< Expression [2, < Polynom y [0, 1]>, *, 1, +]>
>>> C = A.replace_letter(2)
>>> C
< Expression [2, 2, *, 1, +]>
>>> e = Expression('2+3').simplify()
>>> D = A.replace_letter(e)
>>> D
< Expression [2, 5, *, 1, +]>
>>> for i in D.explain():
... print(i)
2 ( 2 + 3 ) + 1
2 \times 5 + 1
"""
exp_to_replace = Expression(letter)
exp_to_replace.steal_history(letter)
postfix_exp = [
exp_to_replace if i == self._letter
else i
for i in self.postfix_tokens
]
ini_step = Expression.develop_steps(postfix_exp)
ans = Expression(postfix_exp)
ans.this_append_before(ini_step)
return ans
def __eq__(self, other):
try:
o_poly = self.conv2poly(other)
return self._coef == o_poly._coef
except TypeError:
return 0
def __add__(self, other):
""" Overload +
>>> P = AbstractPolynom([1,2,3])
>>> Q = AbstractPolynom([4,5])
>>> R = P+Q
>>> R
< AbstractPolynom x [5, 7, 3]>
>>> for i in R.explain():
... print(i)
3 x^{ 2 } + 2 x + 1 + 5 x + 4
3 x^{ 2 } + 2 x + 5 x + 1 + 4
3 x^{ 2 } + ( 2 + 5 ) x + 1 + 4
3 x^{ 2 } + 7 x + 5
>>> R.steps
[< Step [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +, 5, 'x', *, 4, +, +]>, < Step [3, 'x', 2, ^, *, 2, 'x', *, +, 5, 'x', *, +, 1, +, 4, +]>, < Step [3, 'x', 2, ^, *, 2, 5, +, 'x', *, +, 1, 4, +, +]>, < Step [3, 'x', 2, ^, *, 7, 'x', *, +, 5, +]>]
>>> Q = AbstractPolynom([4,5], letter = 'y')
>>> R = P+Q
>>> R
< AbstractPolynom x [< AbstractPolynom y [5, 5]>, 2, 3]>
>>> for i in R.explain():
... print(i)
3 x^{ 2 } + 2 x + 1 + 5 y + 4
3 x^{ 2 } + 2 x + 5 y + 1 + 4
3 x^{ 2 } + 2 x + 5 y + 5
"""
o_poly = self.conv2poly(other)
n_coef = spe_zip(self._coef, o_poly._coef)
p = AbstractPolynom(n_coef, letter=self._letter)
ini_step = [Step([self, o_poly, op.add])]
ans = p.simplify()
ans.this_append_before(ini_step)
return ans
def __radd__(self, other):
o_poly = self.conv2poly(other)
return o_poly.__add__(self)
def __neg__(self):
""" overload - (as arity 1 operator)
>>> P = AbstractPolynom([1,2,3])
>>> Q = -P
>>> Q
< AbstractPolynom x [-1, -2, -3]>
>>> for i in Q.explain():
... print(i)
- ( 3 x^{ 2 } + 2 x + 1 )
-3 x^{ 2 } - 2 x - 1
>>> Q.steps
[< Step [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +, -]>, < Step [-3, 'x', 2, ^, *, -2, 'x', *, +, -1, +]>, < Step [-3, 'x', 2, ^, *, -2, 'x', *, +, -1, +]>]
"""
ini_step = [Step(self.postfix_tokens + [op.sub1])]
ans = AbstractPolynom([-i for i in self._coef],
letter=self._letter).simplify()
ans.this_append_before(ini_step)
return ans
def __sub__(self, other):
""" overload -
>>> P = AbstractPolynom([1,2,3])
>>> Q = AbstractPolynom([4,5,6])
>>> R = P - Q
>>> R
< AbstractPolynom x [-3, -3, -3]>
>>> for i in R.explain():
... print(i)
3 x^{ 2 } + 2 x + 1 - ( 6 x^{ 2 } + 5 x + 4 )
3 x^{ 2 } + 2 x + 1 - 6 x^{ 2 } - 5 x - 4
3 x^{ 2 } - 6 x^{ 2 } + 2 x - 5 x + 1 - 4
( 3 - 6 ) x^{ 2 } + ( 2 - 5 ) x + 1 - 4
-3 x^{ 2 } - 3 x - 3
>>> R.steps
[< Step [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +, 6, 'x', 2, ^, *, 5, 'x', *, +, 4, +, -]>, < Step [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +, -6, 'x', 2, ^, *, -5, 'x', *, +, -4, +, +]>, < Step [3, 'x', 2, ^, *, -6, 'x', 2, ^, *, +, 2, 'x', *, +, -5, 'x', *, +, 1, +, -4, +]>, < Step [3, -6, +, 'x', 2, ^, *, 2, -5, +, 'x', *, +, 1, -4, +, +]>, < Step [-3, 'x', 2, ^, *, -3, 'x', *, +, -3, +]>]
"""
o_poly = self.conv2poly(other)
ini_step = [Step(self.postfix_tokens +
o_poly.postfix_tokens + [op.sub])]
o_poly = -o_poly
ans = self + o_poly
ans.this_append_before(ini_step)
return ans
def __rsub__(self, other):
o_poly = self.conv2poly(other)
return o_poly.__sub__(self)
def __mul__(self, other):
r""" Overload *
>>> p = AbstractPolynom([1,2])
>>> p*3
< AbstractPolynom x [3, 6]>
>>> for i in (p*3).explain():
... print(i)
( 2 x + 1 ) \times 3
2 \times 3 x + 3
6 x + 3
>>> (p*3).steps
[< Step [2, 'x', *, 1, +, 3, *]>, < Step [2, 3, *, 'x', *, 3, +]>, < Step [2, 3, *, 'x', *, 3, +]>, < Step [6, 'x', *, 3, +]>]
>>> q = AbstractPolynom([0,0,4])
>>> q*3
< AbstractPolynom x [0, 0, 12]>
>>> for i in (q*3).explain():
... print(i)
4 x^{ 2 } \times 3
4 \times 3 x^{ 2 }
12 x^{ 2 }
>>> (q*3).steps
[< Step [4, 'x', 2, ^, *, 3, *]>, < Step [4, 3, *, 'x', 2, ^, *]>, < Step [4, 3, *, 'x', 2, ^, *]>, < Step [12, 'x', 2, ^, *]>]
>>> r = AbstractPolynom([0,1])
>>> r*3
< AbstractPolynom x [0, 3]>
>>> (r*3).steps
[< Step ['x', 3, *]>, < Step [3, 'x', *]>, < Step [3, 'x', *]>]
>>> p*q
< AbstractPolynom x [0, 0, 4, 8]>
>>> (p*q).steps
[< Step [2, 'x', *, 1, +, 4, 'x', 2, ^, *, *]>, < Step [2, 4, *, 'x', 3, ^, *, 4, 'x', 2, ^, *, +]>, < Step [2, 4, *, 'x', 3, ^, *, 4, 'x', 2, ^, *, +]>, < Step [8, 'x', 3, ^, *, 4, 'x', 2, ^, *, +]>]
>>> for i in (p*q).explain():
... print(i)
( 2 x + 1 ) \times 4 x^{ 2 }
2 \times 4 x^{ 3 } + 4 x^{ 2 }
8 x^{ 3 } + 4 x^{ 2 }
>>> p*r
< AbstractPolynom x [0, 1, 2]>
>>> P = AbstractPolynom([1,2,3])
>>> Q = AbstractPolynom([4,5,6])
>>> P*Q
< AbstractPolynom x [4, 13, 28, 27, 18]>
"""
o_poly = self.conv2poly(other)
coefs = [0] * (self.degree + o_poly.degree + 1)
for (i, a) in enumerate(self._coef):
for (j, b) in enumerate(o_poly._coef):
if a == 0 or b == 0:
elem = 0
elif a == 1:
elem = b
elif b == 1:
elem = a
else:
elem = Expression([a, b, op.mul])
if coefs[i + j] == 0:
coefs[i + j] = elem
elif elem != 0:
if isinstance(coefs[i + j], list):
coefs[i + j] += [elem]
else:
coefs[i + j] = [coefs[i + j], elem]
p = AbstractPolynom(coefs, letter=self._letter)
ini_step = [Step(self.postfix_tokens +
o_poly.postfix_tokens + [op.mul])]
ans = p.simplify()
ans.this_append_before(ini_step)
return ans
def __rmul__(self, other):
o_poly = self.conv2poly(other)
return o_poly.__mul__(self)
def __truediv__(self, other):
r""" Overload /
>>> P = AbstractPolynom([1, 2, 4])
>>> P / 2
< AbstractPolynom x [< Fraction 1 / 2>, 1, 2]>
>>> for i in (P/2).explain():
... print(i)
\frac{ 4 x^{ 2 } + 2 x + 1 }{ 2 }
\frac{ 4 }{ 2 } x^{ 2 } + \frac{ 2 }{ 2 } x + \frac{ 1 }{ 2 }
2 x^{ 2 } + x + \frac{ 1 }{ 2 }
"""
ans_coefs = [Expression([c, other, op.div]) if c != 0
else 0
for c in self._coef
]
ans = AbstractPolynom(ans_coefs, letter=self._letter)
ini_step = [Step(
self.postfix_tokens +
[other, op.div]
)]
ans = ans.simplify()
ans.this_append_before(ini_step)
return ans
@power_cache
def __pow__(self, power):
r""" Overload **
>>> p = AbstractPolynom([0,0,3])
>>> p**2
< AbstractPolynom x [0, 0, 0, 0, 9]>
>>> (p**2).steps
[< Step [3, 'x', 2, ^, *, 2, ^]>, < Step [3, 2, ^, 'x', 4, ^, *]>, < Step [3, 2, ^, 'x', 4, ^, *]>, < Step [9, 'x', 4, ^, *]>]
>>> for i in (p**2).explain():
... print(i)
( 3 x^{ 2 } )^{ 2 }
3^{ 2 } x^{ 4 }
9 x^{ 4 }
>>> p = AbstractPolynom([1,2])
>>> p**2
< AbstractPolynom x [1, 4, 4]>
>>> (p**2).steps
[< Step [2, 'x', *, 1, +, 2, ^]>, < Step [2, 'x', *, 1, +, 2, 'x', *, 1, +, *]>, < Step [2, 2, *, 'x', 2, ^, *, 2, 'x', *, +, 2, 'x', *, +, 1, +]>, < Step [2, 2, *, 'x', 2, ^, *, 2, 2, +, 'x', *, +, 1, +]>, < Step [4, 'x', 2, ^, *, 4, 'x', *, +, 1, +]>]
>>> for i in (p**2).explain():
... print(i)
( 2 x + 1 )^{ 2 }
( 2 x + 1 ) ( 2 x + 1 )
2 \times 2 x^{ 2 } + 2 x + 2 x + 1
2 \times 2 x^{ 2 } + ( 2 + 2 ) x + 1
4 x^{ 2 } + 4 x + 1
>>> p = AbstractPolynom([0,0,1])
>>> p**3
< AbstractPolynom x [0, 0, 0, 0, 0, 0, 1]>
>>> p = AbstractPolynom([1,2,3])
>>> p**2
< AbstractPolynom x [1, 4, 10, 12, 9]>
"""
if not type(power):
raise ValueError(
"Can't raise {obj} to {pw} power".format(
obj=self.__class__, pw=str(power)))
ini_step = [Step(self.postfix_tokens + [power, op.pw])]
if self.is_monom():
if self._coef[self.degree] == 1:
coefs = [0] * self.degree * power + [1]
p = AbstractPolynom(coefs, letter=self._letter)
ans = p
else:
coefs = [0] * self.degree * power + \
[Expression([self._coef[self.degree], power, op.pw])]
p = AbstractPolynom(coefs, letter=self._letter)
ans = p.simplify()
else:
if power == 2:
ans = self * self
else:
# TODO: faudrait changer ça c'est pas très sérieux |ven. févr.
# 27 22:08:00 CET 2015
raise AttributeError(
"__pw__ not implemented yet when power is greatter than 2")
ans.this_append_before(ini_step)
return ans
def __xor__(self, power):
return self.__pow__(power)
# -----------------------------
# Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
# cursor: 16 del