Repository: sympy/sympy

Issue:
Latex output of vector error
The latex output drops the B.x parenthesis squared in a vector expression i.e. L*(phi' + theta')**2*B.x. 
See code,
```python
import sympy as sp
import sympy.physics.mechanics as me


N_frame = me.ReferenceFrame('N')
A_frame = me.ReferenceFrame('A')
B_frame = me.ReferenceFrame('B')

R_length = sp.symbols('R')
L_length = sp.symbols('L')

theta, phi  = me.dynamicsymbols('theta, phi')
thetad, phid  = me.dynamicsymbols('theta, phi', 1)
t = sp.Symbol('t')

A_frame.orient(N_frame, 'Axis', (theta, N_frame.z))
B_frame.orient(A_frame, 'Axis', (phi, A_frame.z))

O_point = me.Point('O')
O_point.set_vel(N_frame, 0)

O_point = me.Point('O')
O_point.set_vel(N_frame, 0)

Q_point = O_point.locatenew('A', R_length*A_frame.x)
P_point = Q_point.locatenew('B', L_length*B_frame.x)

r = P_point.pos_from(O_point)
print(r)
r_dot = r.diff(t,N_frame).simplify()
print(r_dot)
print(sp.latex(r_dot))
r_ddot = r_dot.diff(t,N_frame).simplify()

# These two should be the same, r_ddot is correct:
print(r_ddot)
print(sp.latex(r_ddot))
```


Discussion:

Patch:
diff --git a/sympy/discrete/__init__.py b/sympy/discrete/__init__.py
index ea589a2c43..23f7f87056 100644
--- a/sympy/discrete/__init__.py
+++ b/sympy/discrete/__init__.py
@@ -1,10 +1,11 @@
 """A module containing discrete functions.
 
 Transforms - fft, ifft, ntt, intt, fwht, ifwht, fzt, ifzt, fmt, ifmt
-Convolution - convolution, convolution_fft, convolution_ntt, convolution_fwht,
-    convolution_subset, covering_product, intersecting_product
-Recurrence evaluation - reval_hcc
+Convolution - convolution, convolution_fft, convolution_ntt,
+    convolution_xor, convolution_and, convolution_or, convolution_subset
+Recurrence Evaluation - reval_hcc
 """
 
+
 from .transforms import (fft, ifft, ntt, intt, fwht, ifwht)
 from .convolution import convolution
diff --git a/sympy/discrete/convolution.py b/sympy/discrete/convolution.py
index 3edf813605..fbad43d3e9 100644
--- a/sympy/discrete/convolution.py
+++ b/sympy/discrete/convolution.py
@@ -1,14 +1,14 @@
 """
-Convolution (using FFT, NTT, FWHT), Subset Convolution,
-Covering Product, Intersecting Product
+Convolution (using FFT, NTT),
+Arithmetic Convolution (bitwise XOR, AND, OR),
+Subset Convolution
 """
 from __future__ import print_function, division
 
 from sympy.core import S
 from sympy.core.compatibility import range, as_int
 from sympy.core.function import expand_mul
-from sympy.discrete.transforms import (
-    fft, ifft, ntt, intt, fwht, ifwht)
+from sympy.discrete.transforms import fft, ifft, ntt, intt
 
 
 def convolution(a, b, **hints):
@@ -35,14 +35,11 @@ def convolution(a, b, **hints):
             performing NTT on the sequence.
         cycle : Integer
             Specifies the length for doing cyclic convolution.
-        dyadic : bool
-            Identifies the convolution type as dyadic (XOR)
-            convolution, which is performed using FWHT.
 
     Examples
     ========
 
-    >>> from sympy import convolution, symbols, S, I
+    >>> from sympy import S, I, convolution
 
     >>> convolution([1 + 2*I, 4 + 3*I], [S(5)/4, 6], dps=3)
     [1.25 + 2.5*I, 11.0 + 15.8*I, 24.0 + 18.0*I]
@@ -56,25 +53,16 @@ def convolution(a, b, **hints):
     >>> convolution([111, 777], [888, 444], prime=19*2**10 + 1, cycle=2)
     [15502, 19351]
 
-    >>> u, v, x, y, z = symbols('u v x y z')
-    >>> convolution([u, v], [x, y, z], dyadic=True)
-    [u*x + v*y, u*y + v*x, u*z, v*z]
-
     """
 
-    fft = hints.pop('fft', None)
     dps = hints.pop('dps', None)
     p = hints.pop('prime', None)
     c = as_int(hints.pop('cycle', 0))
-    dyadic = hints.pop('dyadic', None)
 
     if c < 0:
         raise ValueError("The length for cyclic convolution must be non-negative")
 
-    fft = True if fft else None
-    dyadic = True if dyadic else None
-    if sum(x is not None for x in (p, dps, dyadic)) > 1 or \
-            sum(x is not None for x in (fft, dyadic)) > 1:
+    if sum(x is not None for x in (p, dps)) > 1:
         raise TypeError("Ambiguity in determining the convolution type")
 
     if p is not None:
@@ -84,10 +72,7 @@ def convolution(a, b, **hints):
     elif hints.pop('ntt', False):
         raise TypeError("Prime modulus must be specified for performing NTT")
 
-    if dyadic:
-        ls = convolution_fwht(a, b)
-    else:
-        ls = convolution_fft(a, b, dps=dps)
+    ls = convolution_fft(a, b, dps=dps)
 
     return ls if not c else [sum(ls[i::c]) for i in range(c)]
 
@@ -202,68 +187,3 @@ def convolution_ntt(a, b, prime):
     a = intt(a, p)[:m]
 
     return a
-
-
-#----------------------------------------------------------------------------#
-#                                                                            #
-#                         Convolution for 2**n-group                         #
-#                                                                            #
-#----------------------------------------------------------------------------#
-
-def convolution_fwht(a, b):
-    """
-    Performs dyadic (XOR) convolution using Fast Walsh Hadamard Transform.
-
-    The convolution is automatically padded to the right with zeros, as the
-    radix 2 FWHT requires the number of sample points to be a power of 2.
-
-    Parameters
-    ==========
-
-    a, b : iterables
-        The sequences for which convolution is performed.
-
-    Examples
-    ========
-
-    >>> from sympy import symbols, S, I
-    >>> from sympy.discrete.convolution import convolution_fwht
-
-    >>> u, v, x, y = symbols('u v x y')
-    >>> convolution_fwht([u, v], [x, y])
-    [u*x + v*y, u*y + v*x]
-
-    >>> convolution_fwht([2, 3], [4, 5])
-    [23, 22]
-    >>> convolution_fwht([2, 5 + 4*I, 7], [6*I, 7, 3 + 4*I])
-    [56 + 68*I, -10 + 30*I, 6 + 50*I, 48 + 32*I]
-
-    >>> convolution_fwht([S(33)/7, S(55)/6, S(7)/4], [S(2)/3, 5])
-    [2057/42, 1870/63, 7/6, 35/4]
-
-    References
-    ==========
-
-    .. [1] https://researchgate.net/publication/26511536_Walsh_-_Hadamard_Transformation_of_a_Convolution
-    .. [2] https://en.wikipedia.org/wiki/Hadamard_transform
-
-    """
-
-    if not a or not b:
-        return []
-
-    a, b = a[:], b[:]
-    n = max(len(a), len(b))
-
-    if n&(n - 1): # not a power of 2
-        n = 2**n.bit_length()
-
-    # padding with zeros
-    a += [S.Zero]*(n - len(a))
-    b += [S.Zero]*(n - len(b))
-
-    a, b = fwht(a), fwht(b)
-    a = [expand_mul(x*y) for x, y in zip(a, b)]
-    a = ifwht(a)
-
-    return a
diff --git a/sympy/physics/units/definitions.py b/sympy/physics/units/definitions.py
index e573797aa6..61f2b2b926 100644
--- a/sympy/physics/units/definitions.py
+++ b/sympy/physics/units/definitions.py
@@ -50,22 +50,9 @@
 meter.set_dimension(length)
 meter.set_scale_factor(One)
 
-# gram; used to define its prefixed units
-g = gram = grams = Quantity("gram", abbrev="g")
-gram.set_dimension(mass)
-gram.set_scale_factor(One)
-
-# NOTE: the `kilogram` has scale factor 1000. In SI, kg is a base unit, but
-# nonetheless we are trying to be compatible with the `kilo` prefix. In a
-# similar manner, people using CGS or gaussian units could argue that the
-# `centimeter` rather than `meter` is the fundamental unit for length, but the
-# scale factor of `centimeter` will be kept as 1/100 to be compatible with the
-# `centi` prefix.  The current state of the code assumes SI unit dimensions, in
-# the future this module will be modified in order to be unit system-neutral
-# (that is, support all kinds of unit systems).
 kg = kilogram = kilograms = Quantity("kilogram", abbrev="kg")
 kilogram.set_dimension(mass)
-kilogram.set_scale_factor(kilo*gram)
+kilogram.set_scale_factor(kilo)
 
 s = second = seconds = Quantity("second", abbrev="s")
 second.set_dimension(time)
@@ -88,6 +75,12 @@
 candela.set_scale_factor(One)
 
 
+# gram; used to define its prefixed units
+
+g = gram = grams = Quantity("gram", abbrev="g")
+gram.set_dimension(mass)
+gram.set_scale_factor(One)
+
 mg = milligram = milligrams = Quantity("milligram", abbrev="mg")
 milligram.set_dimension(mass)
 milligram.set_scale_factor(milli*gram)
diff --git a/sympy/physics/vector/printing.py b/sympy/physics/vector/printing.py
index 559551c7c6..851ed411da 100644
--- a/sympy/physics/vector/printing.py
+++ b/sympy/physics/vector/printing.py
@@ -152,13 +152,6 @@ def _print_Derivative(self, der_expr):
             base += '_' + base_split[1]
         return base
 
-    def parenthesize(self, item, level, strict=False):
-        item_latex = self._print(item)
-        if item_latex.startswith(r"\dot") or item_latex.startswith(r"\ddot") or item_latex.startswith(r"\dddot"):
-            return self._print(item)
-        else:
-            return LatexPrinter.parenthesize(self, item, level, strict)
-
 
 class VectorPrettyPrinter(PrettyPrinter):
     """Pretty Printer for vectorialexpressions. """
diff --git a/sympy/printing/latex.py b/sympy/printing/latex.py
index 8b49ce60d0..095980736c 100644
--- a/sympy/printing/latex.py
+++ b/sympy/printing/latex.py
@@ -7,13 +7,13 @@
 import itertools
 
 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
 from sympy.core.operations import AssocOp
 from sympy.core.containers import Tuple
 from sympy.logic.boolalg import true
-from sympy.core.function import UndefinedFunction, AppliedUndef
+from sympy.core.function import (_coeff_isneg,
+    UndefinedFunction, AppliedUndef, Derivative)
 
 ## sympy.printing imports
 from sympy.printing.precedence import precedence_traditional
@@ -507,35 +507,31 @@ def _print_Pow(self, expr):
             and expr.exp.is_Rational \
                 and expr.exp.q != 1:
             base, p, q = self.parenthesize(expr.base, PRECEDENCE['Pow']), expr.exp.p, expr.exp.q
-            #fixes issue #12886, adds parentheses before superscripts raised to powers
+            # issue #12886: add parentheses for superscripts raised to powers
             if '^' in base and expr.base.is_Symbol:
                 base = r"\left(%s\right)" % base
             if expr.base.is_Function:
                 return self._print(expr.base, "%s/%s" % (p, q))
             return r"%s^{%s/%s}" % (base, p, q)
         elif expr.exp.is_Rational and expr.exp.is_negative and expr.base.is_commutative:
-            # Things like 1/x
+            # things like 1/x
             return self._print_Mul(expr)
         else:
             if expr.base.is_Function:
                 return self._print(expr.base, self._print(expr.exp))
             else:
-                if expr.is_commutative and expr.exp == -1:
-                    #solves issue 4129
-                    #As Mul always simplify 1/x to x**-1
-                    #The objective is achieved with this hack
-                    #first we get the latex for -1 * expr,
-                    #which is a Mul expression
-                    tex = self._print(S.NegativeOne * expr).strip()
-                    #the result comes with a minus and a space, so we remove
-                    if tex[:1] == "-":
-                        return tex[1:].strip()
                 tex = r"%s^{%s}"
-                #fixes issue #12886, adds parentheses before superscripts raised to powers
+                exp = self._print(expr.exp)
+                # issue #12886: add parentheses around superscripts raised to powers
                 base = self.parenthesize(expr.base, PRECEDENCE['Pow'])
                 if '^' in base and expr.base.is_Symbol:
                     base = r"\left(%s\right)" % base
-                exp = self._print(expr.exp)
+                elif isinstance(expr.base, Derivative
+                        ) and base.startswith(r'\left('
+                        ) and re.match(r'\\left\(\\d?d?dot', base
+                        ) and base.endswith(r'\right)'):
+                    # don't use parentheses around dotted derivative
+                    base = base[6: -7]  # remove outermost added parens
 
                 return tex % (base, exp)
 
diff --git a/sympy/utilities/autowrap.py b/sympy/utilities/autowrap.py
index d1ceecfe25..c14cec18ad 100644
--- a/sympy/utilities/autowrap.py
+++ b/sympy/utilities/autowrap.py
@@ -817,7 +817,7 @@ def wrap_code(self, routines, helpers=None):
             os.chdir(oldwork)
             if not self.filepath:
                 try:
-                    shutil.rmtree(workdir)
+                    pass # shutil.rmtree(workdir)
                 except OSError:
                     # Could be some issues on Windows
                     pass


Test patch:
diff --git a/sympy/discrete/tests/test_convolution.py b/sympy/discrete/tests/test_convolution.py
index 8c2fa92990..71f30b0de1 100644
--- a/sympy/discrete/tests/test_convolution.py
+++ b/sympy/discrete/tests/test_convolution.py
@@ -1,15 +1,14 @@
 from __future__ import print_function, division
 
 from sympy import sqrt, pi, E, exp
-from sympy.core import S, Symbol, symbols, I
+from sympy.core import S, Symbol, I
 from sympy.core.compatibility import range
-from sympy.discrete.convolution import (
-    convolution, convolution_fft, convolution_ntt, convolution_fwht)
+from sympy.discrete.convolution import (convolution,
+    convolution_fft, convolution_ntt)
 from sympy.utilities.pytest import raises
 from sympy.abc import x, y
 
 def test_convolution():
-    # fft
     a = [1, S(5)/3, sqrt(3), S(7)/5]
     b = [9, 5, 5, 4, 3, 2]
     c = [3, 5, 3, 7, 8]
@@ -24,29 +23,20 @@ def test_convolution():
     # should be a divisor of 2**k
     p = 7*17*2**23 + 1
     q = 19*2**10 + 1
-
-    # ntt
     assert convolution(d, b, ntt=True, prime=q) == convolution_ntt(b, d, prime=q)
     assert convolution(c, b, prime=p) == convolution_ntt(b, c, prime=p)
     assert convolution(d, c, prime=p, ntt=True) == convolution_ntt(c, d, prime=p)
+
     raises(TypeError, lambda: convolution(b, d, ntt=True))
     raises(TypeError, lambda: convolution(b, d, ntt=True, cycle=0))
     raises(TypeError, lambda: convolution(b, d, dps=5, prime=q))
     raises(TypeError, lambda: convolution(b, d, dps=6, ntt=True, prime=q))
     raises(TypeError, lambda: convolution(b, d, fft=True, dps=7, ntt=True, prime=q))
+
     # ntt is a specialized variant of fft, TypeError should not be raised
     assert convolution(b, d, fft=True, ntt=True, prime=q) == \
             convolution_ntt(b, d, prime=q)
 
-    # fwht
-    assert convolution(a, b, dyadic=True) == convolution_fwht(a, b)
-    assert convolution(a, b, dyadic=False) == convolution(a, b)
-    raises(TypeError, lambda: convolution(b, d, fft=True, dps=2, dyadic=True))
-    raises(TypeError, lambda: convolution(b, d, ntt=True, prime=p, dyadic=True))
-    raises(TypeError, lambda: convolution(b, d, fft=True, dyadic=True))
-    raises(TypeError, lambda: convolution(a, b, dps=2, dyadic=True))
-    raises(TypeError, lambda: convolution(b, c, prime=p, dyadic=True))
-
 
 def test_cyclic_convolution():
     # fft
@@ -97,12 +87,6 @@ def test_cyclic_convolution():
     assert convolution(a, b, prime=19*2**10 + 1, cycle=9) == \
             convolution(a, b, prime=19*2**10 + 1) + [0]
 
-    # fwht
-    assert convolution(a, b, dyadic=True, cycle=3) == [2499522285783,
-                                        19861417974796, 4702176579021]
-    assert convolution(a, b, dyadic=True, cycle=5) == [2718149225143,
-            2114320852171, 20571217906407, 246166418903, 1413262436976]
-
 
 def test_convolution_fft():
     assert all(convolution_fft([], x, dps=y) == [] for x in ([], [1]) for y in (None, 3))
@@ -158,45 +142,3 @@ def test_convolution_ntt():
     raises(ValueError, lambda: convolution_ntt([2, 3], [4, 5], r))
     raises(ValueError, lambda: convolution_ntt([x, y], [y, x], q))
     raises(TypeError, lambda: convolution_ntt(x, y, p))
-
-
-def test_convolution_fwht():
-    assert convolution_fwht([], []) == []
-    assert convolution_fwht([], [1]) == []
-    assert convolution_fwht([1, 2, 3], [4, 5, 6]) == [32, 13, 18, 27]
-
-    assert convolution_fwht([S(5)/7, S(6)/8, S(7)/3], [2, 4, S(6)/7]) == \
-                                    [S(45)/7, S(61)/14, S(776)/147, S(419)/42]
-
-    a = [1, S(5)/3, sqrt(3), S(7)/5, 4 + 5*I]
-    b = [94, 51, 53, 45, 31, 27, 13]
-    c = [3 + 4*I, 5 + 7*I, 3, S(7)/6, 8]
-
-    assert convolution_fwht(a, b) == [53*sqrt(3) + 366 + 155*I,
-                                    45*sqrt(3) + 5848/15 + 135*I,
-                                    94*sqrt(3) + 1257/5 + 65*I,
-                                    51*sqrt(3) + 3974/15,
-                                    13*sqrt(3) + 452 + 470*I,
-                                    4513/15 + 255*I,
-                                    31*sqrt(3) + 1314/5 + 265*I,
-                                    27*sqrt(3) + 3676/15 + 225*I]
-
-    assert convolution_fwht(b, c) == [1993/S(2) + 733*I, 6215/S(6) + 862*I,
-        1659/S(2) + 527*I, 1988/S(3) + 551*I, 1019 + 313*I, 3955/S(6) + 325*I,
-        1175/S(2) + 52*I, 3253/S(6) + 91*I]
-
-    assert convolution_fwht(a[3:], c) == [-54/5 + 293*I/5, -1 + 204*I/5,
-            133/S(15) + 35*I/6, 409/S(30) + 15*I, 56/S(5), 32 + 40*I, 0, 0]
-
-    u, v, w, x, y, z = symbols('u v w x y z')
-
-    assert convolution_fwht([u, v], [x, y]) == [u*x + v*y, u*y + v*x]
-
-    assert convolution_fwht([u, v, w], [x, y]) == \
-        [u*x + v*y, u*y + v*x, w*x, w*y]
-
-    assert convolution_fwht([u, v, w], [x, y, z]) == \
-        [u*x + v*y + w*z, u*y + v*x, u*z + w*x, v*z + w*y]
-
-    raises(TypeError, lambda: convolution_fwht(x, y))
-    raises(TypeError, lambda: convolution_fwht(x*y, u + v))
diff --git a/sympy/printing/tests/test_latex.py b/sympy/printing/tests/test_latex.py
index e44757ccf8..6ec13e9d18 100644
--- a/sympy/printing/tests/test_latex.py
+++ b/sympy/printing/tests/test_latex.py
@@ -1759,3 +1759,18 @@ def test_WedgeProduct_printing():
     from sympy.diffgeom import WedgeProduct
     wp = WedgeProduct(R2.dx, R2.dy)
     assert latex(wp) == r"\mathrm{d}x \wedge \mathrm{d}y"
+
+
+def test_issue_14041():
+    import sympy.physics.mechanics as me
+
+    A_frame = me.ReferenceFrame('A')
+    thetad, phid  = me.dynamicsymbols('theta, phi', 1)
+    L = Symbol('L')
+
+    assert latex(L*(phid + thetad)**2*A_frame.x) == \
+        r"L \left(\dot{\phi} + \dot{\theta}\right)^{2}\mathbf{\hat{a}_x}"
+    assert latex((phid + thetad)**2*A_frame.x) == \
+        r"\left(\dot{\phi} + \dot{\theta}\right)^{2}\mathbf{\hat{a}_x}"
+    assert latex((phid*thetad)**a*A_frame.x) == \
+        r"\left(\dot{\phi} \dot{\theta}\right)^{a}\mathbf{\hat{a}_x}"