Repository: sympy/sympy

Issue:
lambdify throws error with abs
This is from #7767 and there is a potential fix in #7779.

Just found a bug in lambdify

```py
k = symbols('k', complex=True)
lambdify([k], abs(k**2))(10.01+0.1j)
```
throws 

```

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-144-4ad0dd2e940e> in <module>()
      1 k = symbols('k', complex=True)
----> 2 lambdify([k], abs(k**2))(10.01+0.1j)

/usr/lib64/python2.7/site-packages/numpy/__init__.pyc in <lambda>(_Dummy_82)

TypeError: can't convert complex to float
```

using ``sympy.Abs`` leads to the same exception.

Discussion:

Patch:
diff --git a/setup.py b/setup.py
index d171a6301a..9a8755d543 100755
--- a/setup.py
+++ b/setup.py
@@ -292,7 +292,6 @@ def run(self):
     'sympy.polys.tests',
     'sympy.printing.pretty.tests',
     'sympy.printing.tests',
-    'sympy.sandbox.tests',
     'sympy.series.tests',
     'sympy.sets.tests',
     'sympy.simplify.tests',
@@ -300,12 +299,11 @@ def run(self):
     'sympy.stats.tests',
     'sympy.strategies.branch.tests',
     'sympy.strategies.tests',
-    'sympy.tensor.array.tests',
     'sympy.tensor.tests',
     'sympy.unify.tests',
     'sympy.utilities.tests',
     'sympy.vector.tests',
-]
+    ]
 
 long_description = '''SymPy is a Python library for symbolic mathematics. It aims
 to become a full-featured computer algebra system (CAS) while keeping the code
diff --git a/sympy/functions/combinatorial/factorials.py b/sympy/functions/combinatorial/factorials.py
index 48ea175555..ea9e5a5ec0 100644
--- a/sympy/functions/combinatorial/factorials.py
+++ b/sympy/functions/combinatorial/factorials.py
@@ -330,8 +330,8 @@ def eval(cls, arg):
         # TODO: extend this to complex numbers?
 
         if arg.is_Number:
-            if not arg.is_Integer:
-                raise ValueError("argument must be nonnegative integer or negative odd integer")
+            if arg.is_infinite:
+                return
 
             # This implementation is faster than the recursive one
             # It also avoids "maximum recursion depth exceeded" runtime error
@@ -339,13 +339,13 @@ def eval(cls, arg):
                 if arg.is_even:
                     k = arg / 2
                     return 2 ** k * factorial(k)
-                return factorial(arg) / factorial2(arg - 1)
 
+                return factorial(arg) / factorial2(arg - 1)
 
-            if arg.is_odd:
-                return arg * (S.NegativeOne) ** ((1 - arg) / 2) / factorial2(-arg)
-            raise ValueError("argument must be nonnegative integer or negative odd integer")
+            if arg.is_even:
+                raise ValueError("argument must be nonnegative or odd")
 
+            return arg * (S.NegativeOne) ** ((1 - arg) / 2) / factorial2(-arg)
 
     def _eval_is_even(self):
         # Double factorial is even for every positive even input
diff --git a/sympy/printing/lambdarepr.py b/sympy/printing/lambdarepr.py
index bc8756a1f0..e0d80fbcc2 100644
--- a/sympy/printing/lambdarepr.py
+++ b/sympy/printing/lambdarepr.py
@@ -244,7 +244,7 @@ def blacklisted(self, expr):
 
     def doprint(self, expr):
         lstr = super(NumExprPrinter, self).doprint(expr)
-        return "evaluate('%s')" % lstr
+        return "evaluate('%s', truediv=True)" % lstr
 
 def lambdarepr(expr, **settings):
     """
diff --git a/sympy/utilities/lambdify.py b/sympy/utilities/lambdify.py
index aae43e458e..f282738ff5 100644
--- a/sympy/utilities/lambdify.py
+++ b/sympy/utilities/lambdify.py
@@ -31,7 +31,6 @@
 
 # Mappings between sympy and other modules function names.
 MATH_TRANSLATIONS = {
-    "Abs": "fabs",
     "ceiling": "ceil",
     "E": "e",
     "ln": "log",
@@ -65,7 +64,6 @@
 }
 
 NUMPY_TRANSLATIONS = {
-    "Abs": "abs",
     "acos": "arccos",
     "acosh": "arccosh",
     "arg": "angle",
@@ -151,10 +149,20 @@ def _import(module, reload="False"):
     for sympyname, translation in translations.items():
         namespace[sympyname] = namespace[translation]
 
+    # For computing the modulus of a sympy expression we use the builtin abs
+    # function, instead of the previously used fabs function for all
+    # translation modules. This is because the fabs function in the math
+    # module does not accept complex valued arguments. (see issue 9474). The
+    # only exception, where we don't use the builtin abs function is the
+    # mpmath translation module, because mpmath.fabs returns mpf objects in
+    # contrast to abs().
+    if 'Abs' not in namespace:
+        namespace['Abs'] = abs
+
 
 @doctest_depends_on(modules=('numpy'))
 def lambdify(args, expr, modules=None, printer=None, use_imps=True,
-        dummify=True):
+             dummify=True):
     """
     Returns a lambda function for fast calculation of numerical values.
 


Test patch:
diff --git a/sympy/functions/combinatorial/tests/test_comb_factorials.py b/sympy/functions/combinatorial/tests/test_comb_factorials.py
index 1886a053ba..9b54ea1019 100644
--- a/sympy/functions/combinatorial/tests/test_comb_factorials.py
+++ b/sympy/functions/combinatorial/tests/test_comb_factorials.py
@@ -3,9 +3,8 @@
                    oo, zoo, simplify, expand_func, Product, I, Piecewise, Mod, Eq, sqrt)
 from sympy.functions.combinatorial.factorials import subfactorial
 from sympy.functions.special.gamma_functions import uppergamma
-from sympy.utilities.pytest import XFAIL, raises
+from sympy.utilities.pytest import XFAIL
 
-#Solves and Fixes Issue #10388 - This is the updated test for the same solved issue
 
 def test_rf_eval_apply():
     x, y = symbols('x,y')
@@ -195,9 +194,7 @@ def test_factorial2():
     nt = Symbol('nt', nonnegative=True)
     nf = Symbol('nf', nonnegative=False)
     nn = Symbol('nn')
-    #Solves and Fixes Issue #10388 - This is the updated test for the same solved issue
-    raises (ValueError, lambda: factorial2(oo))
-    raises (ValueError, lambda: factorial2(S(5)/2))
+
     assert factorial2(n).is_integer is None
     assert factorial2(tt - 1).is_integer
     assert factorial2(tte - 1).is_integer
diff --git a/sympy/utilities/tests/test_lambdify.py b/sympy/utilities/tests/test_lambdify.py
index 7953638841..199a160b08 100644
--- a/sympy/utilities/tests/test_lambdify.py
+++ b/sympy/utilities/tests/test_lambdify.py
@@ -1,15 +1,18 @@
+from itertools import product
+import math
+
+import mpmath
+
 from sympy.utilities.pytest import XFAIL, raises
 from sympy import (
     symbols, lambdify, sqrt, sin, cos, tan, pi, acos, acosh, Rational,
     Float, Matrix, Lambda, Piecewise, exp, Integral, oo, I, Abs, Function,
-    true, false, And, Or, Not, ITE, Min, Max)
+    true, false, And, Or, Not, ITE, Min, Max, floor, diff)
 from sympy.printing.lambdarepr import LambdaPrinter
-import mpmath
 from sympy.utilities.lambdify import implemented_function
 from sympy.utilities.pytest import skip
 from sympy.utilities.decorator import conserve_mpmath_dps
 from sympy.external import import_module
-import math
 import sympy
 
 
@@ -328,6 +331,49 @@ def test_numpy_old_matrix():
     numpy.testing.assert_allclose(f(1, 2, 3), sol_arr)
     assert isinstance(f(1, 2, 3), numpy.matrix)
 
+
+def test_issue9474():
+    mods = [None, 'math']
+    if numpy:
+        mods.append('numpy')
+    if mpmath:
+        mods.append('mpmath')
+    for mod in mods:
+        f = lambdify(x, sympy.S(1)/x, modules=mod)
+        assert f(2) == 0.5
+        f = lambdify(x, floor(sympy.S(1)/x), modules=mod)
+        assert f(2) == 0
+
+    if mpmath:
+        f = lambdify(x, sympy.S(1)/sympy.Abs(x), modules=['mpmath'])
+        assert isinstance(f(2), mpmath.mpf)
+
+    for absfunc, modules in product([Abs, abs], mods):
+        f = lambdify(x, absfunc(x), modules=modules)
+        assert f(-1) == 1
+        assert f(1) == 1
+        assert f(3+4j) == 5
+
+
+def test_issue_9871():
+    if not numexpr:
+        skip("numexpr not installed.")
+    if not numpy:
+        skip("numpy not installed.")
+
+    r = sqrt(x**2 + y**2)
+    expr = diff(1/r, x)
+
+    xn = yn = numpy.linspace(1, 10, 16)
+    # expr(xn, xn) = -xn/(sqrt(2)*xn)^3
+    fv_exact = -numpy.sqrt(2.)**-3 * xn**-2
+
+    fv_numpy = lambdify((x, y), expr, modules='numpy')(xn, yn)
+    fv_numexpr = lambdify((x, y), expr, modules='numexpr')(xn, yn)
+    numpy.testing.assert_allclose(fv_numpy, fv_exact, rtol=1e-10)
+    numpy.testing.assert_allclose(fv_numexpr, fv_exact, rtol=1e-10)
+
+
 def test_numpy_piecewise():
     if not numpy:
         skip("numpy not installed.")