From a7762a70ef003b56b0fa6fd7a20b9ca9bad15d2a Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sat, 18 Jun 2022 16:42:29 +0200 Subject: [PATCH] Improve LaTeX-printing of Prefix --- sympy/physics/units/prefixes.py | 16 +++++++++++----- sympy/printing/latex.py | 26 +++++++++++++++----------- sympy/printing/tests/test_latex.py | 5 ++++- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/sympy/physics/units/prefixes.py b/sympy/physics/units/prefixes.py index 0fe8fbe7dac3..c1e7a6232228 100644 --- a/sympy/physics/units/prefixes.py +++ b/sympy/physics/units/prefixes.py @@ -30,7 +30,7 @@ class Prefix(Expr): _op_priority = 13.0 is_commutative = True - def __new__(cls, name, abbrev, exponent, base=sympify(10)): + def __new__(cls, name, abbrev, exponent, base=sympify(10), latex_repr=None): name = sympify(name) abbrev = sympify(abbrev) @@ -43,6 +43,7 @@ def __new__(cls, name, abbrev, exponent, base=sympify(10)): obj._scale_factor = base**exponent obj._exponent = exponent obj._base = base + obj._latex_repr = latex_repr return obj @property @@ -57,12 +58,19 @@ def abbrev(self): def scale_factor(self): return self._scale_factor + def _latex(self, printer): + if self._latex_repr is None: + return r'\text{%s}' % self._abbrev + return self._latex_repr + @property def base(self): return self._base def __str__(self): - # TODO: add proper printers and tests: + return str(self._abbrev) + + def __repr__(self): if self.base == 10: return "Prefix(%r, %r, %r)" % ( str(self.name), str(self.abbrev), self._exponent) @@ -70,8 +78,6 @@ def __str__(self): return "Prefix(%r, %r, %r, %r)" % ( str(self.name), str(self.abbrev), self._exponent, self.base) - __repr__ = __str__ - def __mul__(self, other): from sympy.physics.units import Quantity if not isinstance(other, (Quantity, Prefix)): @@ -160,7 +166,7 @@ def prefix_unit(unit, prefixes): deci = Prefix('deci', 'd', -1) centi = Prefix('centi', 'c', -2) milli = Prefix('milli', 'm', -3) -micro = Prefix('micro', 'mu', -6) +micro = Prefix('micro', 'mu', -6, latex_repr=r"\mu") nano = Prefix('nano', 'n', -9) pico = Prefix('pico', 'p', -12) femto = Prefix('femto', 'f', -15) diff --git a/sympy/printing/latex.py b/sympy/printing/latex.py index 82bfdad842b1..b629844622aa 100644 --- a/sympy/printing/latex.py +++ b/sympy/printing/latex.py @@ -25,7 +25,7 @@ from mpmath.libmp.libmpf import prec_to_dps, to_str as mlib_to_str -from sympy.utilities.iterables import has_variety +from sympy.utilities.iterables import has_variety, sift import re @@ -516,6 +516,7 @@ def _print_Laplacian(self, expr): def _print_Mul(self, expr: Expr): from sympy.physics.units import Quantity + from sympy.physics.units.prefixes import Prefix from sympy.simplify import fraction separator: str = self._settings['mul_symbol_latex'] numbersep: str = self._settings['mul_symbol_latex_numbers'] @@ -530,11 +531,11 @@ def convert(expr) -> str: args = list(expr.args) # If quantities are present append them at the back - args = sorted(args, key=lambda x: isinstance(x, Quantity) or + units, nonunits = sift(args, lambda x: isinstance(x, (Quantity, Prefix)) or (isinstance(x, Pow) and - isinstance(x.base, Quantity))) - - return convert_args(args) + isinstance(x.base, Quantity)), binary=True) + prefixes, units = sift(units, lambda x: isinstance(x, Prefix), binary=True) + return convert_args(nonunits + prefixes + units) def convert_args(args) -> str: _tex = last_term_tex = "" @@ -542,14 +543,17 @@ def convert_args(args) -> str: for i, term in enumerate(args): term_tex = self._print(term) - if self._needs_mul_brackets(term, first=(i == 0), - last=(i == len(args) - 1)): - term_tex = r"\left(%s\right)" % term_tex + if not isinstance(term, (Quantity, Prefix)): + if self._needs_mul_brackets(term, first=(i == 0), + last=(i == len(args) - 1)): + term_tex = r"\left(%s\right)" % term_tex - if _between_two_numbers_p[0].search(last_term_tex) and \ + if _between_two_numbers_p[0].search(last_term_tex) and \ _between_two_numbers_p[1].match(str(term)): - # between two numbers - _tex += numbersep + # between two numbers + _tex += numbersep + elif _tex: + _tex += separator elif _tex: _tex += separator diff --git a/sympy/printing/tests/test_latex.py b/sympy/printing/tests/test_latex.py index ea92baa72a45..23043f2f9b0f 100644 --- a/sympy/printing/tests/test_latex.py +++ b/sympy/printing/tests/test_latex.py @@ -48,7 +48,7 @@ from sympy.ntheory.factor_ import (divisor_sigma, primenu, primeomega, reduced_totient, totient, udivisor_sigma) from sympy.physics.quantum import Commutator, Operator from sympy.physics.quantum.trace import Tr -from sympy.physics.units import meter, gibibyte, microgram, second +from sympy.physics.units import meter, gibibyte, gram, microgram, second, milli, micro from sympy.polys.domains.integerring import ZZ from sympy.polys.fields import field from sympy.polys.polytools import Poly @@ -2983,6 +2983,9 @@ def test_unit_printing(): assert latex(5*meter) == r'5 \text{m}' assert latex(3*gibibyte) == r'3 \text{gibibyte}' assert latex(4*microgram/second) == r'\frac{4 \mu\text{g}}{\text{s}}' + assert latex(4*micro*gram/second) == r'\frac{4 \mu \text{g}}{\text{s}}' + assert latex(5*milli*meter) == r'5 \text{m} \text{m}' + assert latex(milli) == r'\text{m}' def test_issue_17092():