X-Git-Url: https://svn.cri.ensmp.fr/git/linpy.git/blobdiff_plain/2bad3743bd25bbcfe12db50e2b18ab8d070f2354..1695c920d030869b3a842736fe5bcf963f2ffc52:/pypol/linexprs.py diff --git a/pypol/linexprs.py b/pypol/linexprs.py index e73449e..b74628b 100644 --- a/pypol/linexprs.py +++ b/pypol/linexprs.py @@ -44,11 +44,11 @@ class Expression: if not isinstance(symbol, Symbol): raise TypeError('symbols must be Symbol instances') if not isinstance(coefficient, numbers.Rational): - raise TypeError('coefficients must be Rational instances') + raise TypeError('coefficients must be rational numbers') coefficients = [(symbol, Fraction(coefficient)) for symbol, coefficient in coefficients if coefficient != 0] if not isinstance(constant, numbers.Rational): - raise TypeError('constant must be a Rational instance') + raise TypeError('constant must be a rational number') constant = Fraction(constant) if len(coefficients) == 0: return Rational(constant) @@ -134,22 +134,27 @@ class Expression: def __rsub__(self, other): return -(self - other) - @_polymorphic def __mul__(self, other): - if isinstance(other, Rational): - return other.__rmul__(self) + if isinstance(other, numbers.Rational): + coefficients = dict(self._coefficients) + for symbol in coefficients: + coefficients[symbol] *= other + constant = self._constant * other + return Expression(coefficients, constant) return NotImplemented __rmul__ = __mul__ - @_polymorphic def __truediv__(self, other): - if isinstance(other, Rational): - return other.__rtruediv__(self) + if isinstance(other, numbers.Rational): + coefficients = dict(self._coefficients) + for symbol in coefficients: + coefficients[symbol] /= other + constant = self._constant / other + # import pdb; pdb.set_trace() + return Expression(coefficients, constant) return NotImplemented - __rtruediv__ = __truediv__ - @_polymorphic def __eq__(self, other): # "normal" equality @@ -240,18 +245,17 @@ class Expression: string = '' for i, (symbol, coefficient) in enumerate(self.coefficients()): if coefficient == 1: - string += '' if i == 0 else ' + ' - string += '{!r}'.format(symbol) + if i != 0: + string += ' + ' elif coefficient == -1: string += '-' if i == 0 else ' - ' - string += '{!r}'.format(symbol) + elif i == 0: + string += '{}*'.format(coefficient) + elif coefficient > 0: + string += ' + {}*'.format(coefficient) else: - if i == 0: - string += '{}*{!r}'.format(coefficient, symbol) - elif coefficient > 0: - string += ' + {}*{!r}'.format(coefficient, symbol) - else: - string += ' - {}*{!r}'.format(-coefficient, symbol) + string += ' - {}*'.format(-coefficient) + string += '{}'.format(symbol) constant = self.constant if len(string) == 0: string += '{}'.format(constant) @@ -261,6 +265,30 @@ class Expression: string += ' - {}'.format(-constant) return string + def _repr_latex_(self): + string = '' + for i, (symbol, coefficient) in enumerate(self.coefficients()): + if coefficient == 1: + if i != 0: + string += ' + ' + elif coefficient == -1: + string += '-' if i == 0 else ' - ' + elif i == 0: + string += '{}'.format(coefficient._repr_latex_().strip('$')) + elif coefficient > 0: + string += ' + {}'.format(coefficient._repr_latex_().strip('$')) + elif coefficient < 0: + string += ' - {}'.format((-coefficient)._repr_latex_().strip('$')) + string += '{}'.format(symbol._repr_latex_().strip('$')) + constant = self.constant + if len(string) == 0: + string += '{}'.format(constant._repr_latex_().strip('$')) + elif constant > 0: + string += ' + {}'.format(constant._repr_latex_().strip('$')) + elif constant < 0: + string += ' - {}'.format((-constant)._repr_latex_().strip('$')) + return '${}$'.format(string) + def _parenstr(self, always=False): string = str(self) if not always and (self.isconstant() or self.issymbol()): @@ -301,8 +329,8 @@ class Symbol(Expression): raise TypeError('name must be a string') self = object().__new__(cls) self._name = name.strip() - self._coefficients = {self: 1} - self._constant = 0 + self._coefficients = {self: Fraction(1)} + self._constant = Fraction(0) self._symbols = (self,) self._dimension = 1 return self @@ -340,6 +368,9 @@ class Symbol(Expression): def __repr__(self): return self.name + def _repr_latex_(self): + return '${}$'.format(self.name) + @classmethod def fromsympy(cls, expr): import sympy @@ -359,8 +390,8 @@ class Dummy(Symbol): self = object().__new__(cls) self._index = Dummy._count self._name = name.strip() - self._coefficients = {self: 1} - self._constant = 0 + self._coefficients = {self: Fraction(1)} + self._constant = Fraction(0) self._symbols = (self,) self._dimension = 1 Dummy._count += 1 @@ -378,6 +409,9 @@ class Dummy(Symbol): def __repr__(self): return '_{}'.format(self.name) + def _repr_latex_(self): + return '${}_{{{}}}$'.format(self.name, self._index) + def symbols(names): if isinstance(names, str): @@ -408,29 +442,27 @@ class Rational(Expression, Fraction): def __bool__(self): return Fraction.__bool__(self) - @_polymorphic - def __mul__(self, other): - coefficients = dict(other._coefficients) - for symbol in coefficients: - coefficients[symbol] *= self._constant - constant = other._constant * self._constant - return Expression(coefficients, constant) - - __rmul__ = __mul__ - - @_polymorphic - def __rtruediv__(self, other): - coefficients = dict(other._coefficients) - for symbol in coefficients: - coefficients[symbol] /= self._constant - constant = other._constant / self._constant - return Expression(coefficients, constant) - @classmethod def fromstring(cls, string): if not isinstance(string, str): raise TypeError('string must be a string instance') - return Rational(Fraction(string)) + return Rational(string) + + def __repr__(self): + if self.denominator == 1: + return '{!r}'.format(self.numerator) + else: + return '{!r}/{!r}'.format(self.numerator, self.denominator) + + def _repr_latex_(self): + if self.denominator == 1: + return '${}$'.format(self.numerator) + elif self.numerator < 0: + return '$-\\frac{{{}}}{{{}}}$'.format(-self.numerator, + self.denominator) + else: + return '$\\frac{{{}}}{{{}}}$'.format(self.numerator, + self.denominator) @classmethod def fromsympy(cls, expr):