Repository: sympy/sympy

Issue:
ZeroDivisionError in inverse_laplace_transform
`inverse_laplace_transform(3/(s**4 + 11*s**2 + 18*s + 10),s,t)` raises `ZeroDivisionError`.

Discussion:

Patch:
diff --git a/.mailmap b/.mailmap
index 55ff28f9f6..f58d7b351b 100644
--- a/.mailmap
+++ b/.mailmap
@@ -907,6 +907,7 @@ Lee Johnston <lee.johnston.100@gmail.com>
 Lejla Metohajrova <l.metohajrova@gmail.com>
 Lennart Fricke <lennart@die-frickes.eu>
 Leo Battle <leowbattle@gmail.com>
+Leonardo Mangani <leomangani4@gmail.com> Leonardo Mangani <88255254+leomanga@users.noreply.github.com>
 Leonid Blouvshtein <leonidbl91@gmail.com>
 Leonid Kovalev <leonidvkovalev@gmail.com> <leonid.traveling@gmail.com>
 Leonid Kovalev <leonidvkovalev@gmail.com> <normalhuman@users.noreply.github.com>
@@ -1173,7 +1174,6 @@ Pranjal Tale <pranjaltale16@gmail.com>
 Prashant Tyagi <prashanttyagi221295@gmail.com>
 Prasoon Shukla <prasoon92.iitr@gmail.com>
 Prateek Papriwal <papriwalprateek@gmail.com>
-Pratyksh Gupta <pratykshgupta9999@gmail.com> Pg999999 <pratykshgupta9999@gmail.com>
 Praveen Perumal <ppraveen98841@gmail.com> Praveen Perumal <58477724+solvedbiscuit71@users.noreply.github.com>
 Praveen Sahu <povinsahu@gmail.com> povinsahu1909 <povinsahu@gmail.com>
 Prayag <v.prayag2005@gmail.com> vprayag2005 <v.prayag2005@gamil.com>
diff --git a/sympy/polys/densetools.py b/sympy/polys/densetools.py
index 907e229048..122bf778a4 100644
--- a/sympy/polys/densetools.py
+++ b/sympy/polys/densetools.py
@@ -926,15 +926,20 @@ def dmp_shift(f, a, u, K):
 
     a0, a1 = a[0], a[1:]
 
-    f = [ dmp_shift(c, a1, u-1, K) for c in f ]
-    n = len(f) - 1
+    if any(a1):
+        f = [ dmp_shift(c, a1, u-1, K) for c in f ]
+    else:
+        f = list(f)
 
-    for i in range(n, 0, -1):
-        for j in range(0, i):
-            afj = dmp_mul_ground(f[j], a0, u-1, K)
-            f[j + 1] = dmp_add(f[j + 1], afj, u-1, K)
+    if a0:
+        n = len(f) - 1
 
-    return f
+        for i in range(n, 0, -1):
+            for j in range(0, i):
+                afj = dmp_mul_ground(f[j], a0, u-1, K)
+                f[j + 1] = dmp_add(f[j + 1], afj, u-1, K)
+
+    return dmp_strip(f, u)
 
 
 def dup_transform(f, p, q, K):
diff --git a/sympy/utilities/autowrap.py b/sympy/utilities/autowrap.py
index d09a544869..feff051ded 100644
--- a/sympy/utilities/autowrap.py
+++ b/sympy/utilities/autowrap.py
@@ -572,13 +572,13 @@ def autowrap(expr, language=None, backend='f2py', tempdir=None, args=None,
         If True, autowrap will not mute the command line backends. This can be
         helpful for debugging.
     helpers : 3-tuple or iterable of 3-tuples, optional
-        Used to define auxiliary functions needed for the main expression.
-        Each tuple should be of the form (name, expr, args) where:
-
-        - name : str, the function name
-        - expr : sympy expression, the function
-        - args : iterable, the function arguments (can be any iterable of symbols)
-
+        Used to define auxiliary expressions needed for the main expr. If the
+        main expression needs to call a specialized function it should be
+        passed in via ``helpers``. Autowrap will then make sure that the
+        compiled main expression can link to the helper routine. Items should
+        be 3-tuples with (<function_name>, <sympy_expression>,
+        <argument_tuple>). It is mandatory to supply an argument sequence to
+        helper routines.
     code_gen : CodeGen instance
         An instance of a CodeGen subclass. Overrides ``language``.
     include_dirs : [string]
@@ -602,8 +602,6 @@ def autowrap(expr, language=None, backend='f2py', tempdir=None, args=None,
     Examples
     ========
 
-    Basic usage:
-
     >>> from sympy.abc import x, y, z
     >>> from sympy.utilities.autowrap import autowrap
     >>> expr = ((x - y + z)**(13)).expand()
@@ -611,35 +609,6 @@ def autowrap(expr, language=None, backend='f2py', tempdir=None, args=None,
     >>> binary_func(1, 4, 2)
     -1.0
 
-    Using helper functions:
-
-    >>> from sympy.abc import x, t
-    >>> from sympy import Function
-    >>> helper_func = Function('helper_func')  # Define symbolic function
-    >>> expr = 3*x + helper_func(t)  # Main expression using helper function
-    >>> # Define helper_func(x) = 4*x using f2py backend
-    >>> binary_func = autowrap(expr, args=[x, t],
-    ...                       helpers=('helper_func', 4*x, [x]))
-    >>> binary_func(2, 5)  # 3*2 + helper_func(5) = 6 + 20
-    26.0
-    >>> # Same example using cython backend
-    >>> binary_func = autowrap(expr, args=[x, t], backend='cython',
-    ...                       helpers=[('helper_func', 4*x, [x])])
-    >>> binary_func(2, 5)  # 3*2 + helper_func(5) = 6 + 20
-    26.0
-
-    Type handling example:
-
-    >>> import numpy as np
-    >>> expr = x + y
-    >>> f_cython = autowrap(expr, backend='cython')
-    >>> f_cython(1, 2)  # doctest: +ELLIPSIS
-    Traceback (most recent call last):
-      ...
-    TypeError: Argument '_x' has incorrect type (expected numpy.ndarray, got int)
-    >>> f_cython(np.array([1.0]), np.array([2.0]))
-    array([ 3.])
-
     """
     if language:
         if not isinstance(language, type):
@@ -1054,14 +1023,14 @@ def ufuncify(args, expr, language=None, backend='numpy', tempdir=None,
     verbose : bool, optional
         If True, autowrap will not mute the command line backends. This can
         be helpful for debugging.
-    helpers : 3-tuple or iterable of 3-tuples, optional
-        Used to define auxiliary functions needed for the main expression.
-        Each tuple should be of the form (name, expr, args) where:
-
-        - name : str, the function name
-        - expr : sympy expression, the function
-        - args : iterable, the function arguments (can be any iterable of symbols)
-
+    helpers : iterable, optional
+        Used to define auxiliary expressions needed for the main expr. If
+        the main expression needs to call a specialized function it should
+        be put in the ``helpers`` iterable. Autowrap will then make sure
+        that the compiled main expression can link to the helper routine.
+        Items should be tuples with (<funtion_name>, <sympy_expression>,
+        <arguments>). It is mandatory to supply an argument sequence to
+        helper routines.
     kwargs : dict
         These kwargs will be passed to autowrap if the `f2py` or `cython`
         backend is used and ignored if the `numpy` backend is used.
@@ -1083,8 +1052,6 @@ def ufuncify(args, expr, language=None, backend='numpy', tempdir=None,
     Examples
     ========
 
-    Basic usage:
-
     >>> from sympy.utilities.autowrap import ufuncify
     >>> from sympy.abc import x, y
     >>> import numpy as np
@@ -1096,18 +1063,6 @@ def ufuncify(args, expr, language=None, backend='numpy', tempdir=None,
     >>> f(np.arange(5), 3)
     array([  3.,   4.,   7.,  12.,  19.])
 
-    Using helper functions:
-
-    >>> from sympy import Function
-    >>> helper_func = Function('helper_func')  # Define symbolic function
-    >>> expr = x**2 + y*helper_func(x)  # Main expression using helper function
-    >>> # Define helper_func(x) = x**3
-    >>> f = ufuncify((x, y), expr, helpers=[('helper_func', x**3, [x])])
-    >>> f([1, 2], [3, 4])
-    array([  4.,  36.])
-
-    Type handling with different backends:
-
     For the 'f2py' and 'cython' backends, inputs are required to be equal length
     1-dimensional arrays. The 'f2py' backend will perform type conversion, but
     the Cython backend will error if the inputs are not of the expected type.


Test patch:
diff --git a/sympy/polys/tests/test_polytools.py b/sympy/polys/tests/test_polytools.py
index 0b6da5dbd4..845df66850 100644
--- a/sympy/polys/tests/test_polytools.py
+++ b/sympy/polys/tests/test_polytools.py
@@ -2792,6 +2792,14 @@ def test_factor():
     )
     assert factor(e) == -(y - I)**3*(y + I)*(x**2 + 2*x + y**2 + 2)/(y**2 + 1)
 
+    # issue 27506
+    e = (I*t*x*y - 3*I*t - I*x*y*z - 6*x*y + 3*I*z + 18)
+    assert factor(e) == -I*(x*y - 3)*(-t + z - 6*I)
+
+    e = (8*x**2*z**2 - 32*x**2*z*t + 24*x**2*t**2 - 4*I*x*y*z**2 + 16*I*x*y*z*t -
+         12*I*x*y*t**2 + z**4 - 8*z**3*t + 22*z**2*t**2 - 24*z*t**3 + 9*t**4)
+    assert factor(e) == (-3*t + z)*(-t + z)*(3*t**2 - 4*t*z + 8*x**2 - 4*I*x*y + z**2)
+
 
 def test_factor_large():
     f = (x**2 + 4*x + 4)**10000000*(x**2 + 1)*(x**2 + 2*x + 1)**1234567