Repository: sympy/sympy

Issue:
Pretty printing of Mod
Mod should have pretty printing. I guess the mathematical way to print `Mod(x, n)` is `x mod n`, with parentheses around the whole thing if it is in a larger expression, like `1 + (x mod n)`.  We need pretty printing and LaTeX printing. 

Discussion:

Patch:
diff --git a/sympy/printing/latex.py b/sympy/printing/latex.py
index 266e9d5e88..7cf377601d 100644
--- a/sympy/printing/latex.py
+++ b/sympy/printing/latex.py
@@ -4,7 +4,7 @@
 
 from __future__ import print_function, division
 
-from sympy.core import S, Add, Symbol
+from sympy.core import S, Add, Symbol, Mod
 from sympy.core.function import _coeff_isneg
 from sympy.core.sympify import SympifyError
 from sympy.core.alphabets import greeks
@@ -216,7 +216,8 @@ def _needs_mul_brackets(self, expr, first=False, last=False):
         elif expr.is_Mul:
             if not first and _coeff_isneg(expr):
                 return True
-
+        if any([expr.has(x) for x in (Mod,)]):
+            return True
         if (not last and
             any([expr.has(x) for x in (Integral, Piecewise, Product, Sum)])):
             return True
@@ -232,6 +233,8 @@ def _needs_add_brackets(self, expr):
         """
         if expr.is_Relational:
             return True
+        if any([expr.has(x) for x in (Mod,)]):
+            return True
         return False
 
 
@@ -1380,6 +1383,13 @@ def parens(x):
             return self._print(x)
         return ' '.join(map(parens, expr.args))
 
+    def _print_Mod(self, expr, exp=None):
+        if exp is not None:
+            return r'\left(%s\bmod{%s}\right)^{%s}' % (self.parenthesize(expr.args[0],
+                    PRECEDENCE['Mul'], strict=True), self._print(expr.args[1]), self._print(exp))
+        return r'%s\bmod{%s}' % (self.parenthesize(expr.args[0],
+                PRECEDENCE['Mul'], strict=True), self._print(expr.args[1]))
+
     def _print_HadamardProduct(self, expr):
         from sympy import Add, MatAdd, MatMul
 
diff --git a/sympy/printing/pretty/pretty.py b/sympy/printing/pretty/pretty.py
index 15383a6d0d..c88f64bb13 100644
--- a/sympy/printing/pretty/pretty.py
+++ b/sympy/printing/pretty/pretty.py
@@ -3,6 +3,7 @@
 from sympy.core import S
 from sympy.core.containers import Tuple
 from sympy.core.function import _coeff_isneg
+from sympy.core.mod import Mod
 from sympy.core.mul import Mul
 from sympy.core.numbers import Rational
 from sympy.core.power import Pow
@@ -1271,6 +1272,15 @@ def _print_EulerGamma(self, expr):
             return prettyForm(pretty_symbol('gamma'))
         return self._print(Symbol("EulerGamma"))
 
+    def _print_Mod(self, expr):
+        pform = self._print(expr.args[0])
+        if pform.binding > prettyForm.MUL:
+            pform = prettyForm(*pform.parens())
+        pform = prettyForm(*pform.right(' mod '))
+        pform = prettyForm(*pform.right(self._print(expr.args[1])))
+        pform.binding = prettyForm.OPEN
+        return pform
+
     def _print_Add(self, expr, order=None):
         if self.order == 'none':
             terms = list(expr.args)


Test patch:
diff --git a/sympy/printing/pretty/tests/test_pretty.py b/sympy/printing/pretty/tests/test_pretty.py
index 884bd35ad9..a4321a6dbb 100644
--- a/sympy/printing/pretty/tests/test_pretty.py
+++ b/sympy/printing/pretty/tests/test_pretty.py
@@ -5507,3 +5507,34 @@ def test_pretty_primeomega():
     n = symbols('n', integer=True)
     assert pretty(primeomega(n)) == ascii_str1
     assert upretty(primeomega(n)) == ucode_str1
+
+
+def test_pretty_Mod():
+    from sympy.core import Mod
+
+    ascii_str1 = "x mod 7"
+    ucode_str1 = u("x mod 7")
+
+    ascii_str2 = "(x + 1) mod 7"
+    ucode_str2 = u("(x + 1) mod 7")
+
+    ascii_str3 = "2*x mod 7"
+    ucode_str3 = u("2⋅x mod 7")
+
+    ascii_str4 = "(x mod 7) + 1"
+    ucode_str4 = u("(x mod 7) + 1")
+
+    ascii_str5 = "2*(x mod 7)"
+    ucode_str5 = u("2⋅(x mod 7)")
+
+    x = symbols('x', integer=True)
+    assert pretty(Mod(x, 7)) == ascii_str1
+    assert upretty(Mod(x, 7)) == ucode_str1
+    assert pretty(Mod(x + 1, 7)) == ascii_str2
+    assert upretty(Mod(x + 1, 7)) == ucode_str2
+    assert pretty(Mod(2 * x, 7)) == ascii_str3
+    assert upretty(Mod(2 * x, 7)) == ucode_str3
+    assert pretty(Mod(x, 7) + 1) == ascii_str4
+    assert upretty(Mod(x, 7) + 1) == ucode_str4
+    assert pretty(2 * Mod(x, 7)) == ascii_str5
+    assert upretty(2 * Mod(x, 7)) == ucode_str5
diff --git a/sympy/printing/tests/test_latex.py b/sympy/printing/tests/test_latex.py
index 238ec637b2..f0f42bc48f 100644
--- a/sympy/printing/tests/test_latex.py
+++ b/sympy/printing/tests/test_latex.py
@@ -6,7 +6,7 @@
     Lambda, LaplaceTransform, Limit, Matrix, Max, MellinTransform, Min, Mul,
     Order, Piecewise, Poly, ring, field, ZZ, Pow, Product, Range, Rational,
     RisingFactorial, rootof, RootSum, S, Shi, Si, SineTransform, Subs,
-    Sum, Symbol, ImageSet, Tuple, Union, Ynm, Znm, arg, asin,
+    Sum, Symbol, ImageSet, Tuple, Union, Ynm, Znm, arg, asin, Mod,
     assoc_laguerre, assoc_legendre, binomial, catalan, ceiling, Complement,
     chebyshevt, chebyshevu, conjugate, cot, coth, diff, dirichlet_eta,
     exp, expint, factorial, factorial2, floor, gamma, gegenbauer, hermite,
@@ -382,6 +382,12 @@ def test_latex_functions():
     assert latex(primeomega(n)) == r'\Omega\left(n\right)'
     assert latex(primeomega(n) ** 2) == r'\left(\Omega\left(n\right)\right)^{2}'
 
+    assert latex(Mod(x, 7)) == r'x\bmod{7}'
+    assert latex(Mod(x + 1, 7)) == r'\left(x + 1\right)\bmod{7}'
+    assert latex(Mod(2 * x, 7)) == r'2 x\bmod{7}'
+    assert latex(Mod(x, 7) + 1) == r'\left(x\bmod{7}\right) + 1'
+    assert latex(2 * Mod(x, 7)) == r'2 \left(x\bmod{7}\right)'
+
     # some unknown function name should get rendered with \operatorname
     fjlkd = Function('fjlkd')
     assert latex(fjlkd(x)) == r'\operatorname{fjlkd}{\left (x \right )}'