Repository: sympy/sympy

Issue:
lack definite integral of |x^2-1|
```
Example:
  x=Symbol('x')
  integrate( abs(x^2-1), (x,-2,2))
```

Original issue for #5658: http://code.google.com/p/sympy/issues/detail?id=2559
Original author: https://code.google.com/u/115080472962774676419/


Discussion:

Patch:
diff --git a/sympy/integrals/integrals.py b/sympy/integrals/integrals.py
index 74931be911..ea787ea94b 100644
--- a/sympy/integrals/integrals.py
+++ b/sympy/integrals/integrals.py
@@ -20,6 +20,7 @@
 from sympy.utilities.misc import filldedent
 from sympy.polys import Poly, PolynomialError
 from sympy.functions import Piecewise, sqrt, sign, piecewise_fold
+from sympy.functions.elementary.complexes import Abs, sign
 from sympy.functions.elementary.exponential import log
 from sympy.functions.elementary.miscellaneous import Min, Max
 from sympy.series import limit
@@ -444,7 +445,15 @@ def doit(self, **hints):
                     function = factored_function
                 continue
 
-            if function.has(Min, Max):
+            if function.has(Abs, sign) and (
+                (len(xab) < 3 and all(x.is_real for x in xab)) or
+                (len(xab) == 3 and all(x.is_real and x.is_finite for
+                 x in xab[1:]))):
+                    # some improper integrals are better off with Abs
+                    xr = Dummy("xr", real=True)
+                    function = (function.xreplace({xab[0]: xr})
+                        .rewrite(Piecewise).xreplace({xr: xab[0]}))
+            elif function.has(Min, Max):
                 function = function.rewrite(Piecewise)
             if function.has(Piecewise) and \
                 not isinstance(function, Piecewise):


Test patch:
diff --git a/sympy/functions/elementary/tests/test_piecewise.py b/sympy/functions/elementary/tests/test_piecewise.py
index 9704209b81..d65e89af8f 100644
--- a/sympy/functions/elementary/tests/test_piecewise.py
+++ b/sympy/functions/elementary/tests/test_piecewise.py
@@ -854,16 +854,11 @@ def test_issue_12557():
     True))*cos(_n*x)/pi, (_n, 1, oo)), SeqFormula(0, (_k, 1, oo))))
     '''
     x = symbols("x", real=True)
-    k = symbols('k',  integer=True)
+    k = symbols('k', integer=True)
     abs2 = lambda x: Piecewise((-x, x <= 0), (x, x > 0))
     assert integrate(abs2(x), (x, -pi, pi)) == pi**2
-    # attempting a Piecewise rewrite is not automatic so this needs
-    # help
     func = cos(k*x)*sqrt(x**2)
-    assert integrate(func, (x, -pi, pi)
-        ) == Integral(cos(k*x)*Abs(x), (x, -pi, pi))
-    assert factor_terms(integrate(func.rewrite(Piecewise), (x, -pi, pi)
-        )) == Piecewise(
+    assert factor_terms(integrate(func, (x, -pi, pi))) == Piecewise(
         (pi**2, Eq(k, 0)), (((-1)**k - 1)/k**2*2, True))
 
 
diff --git a/sympy/integrals/tests/test_integrals.py b/sympy/integrals/tests/test_integrals.py
index 0397939ee6..a7d671a305 100644
--- a/sympy/integrals/tests/test_integrals.py
+++ b/sympy/integrals/tests/test_integrals.py
@@ -1,10 +1,11 @@
 from sympy import (
-    Abs, acos, acosh, Add, asin, asinh, atan, Ci, cos, sinh,
-    cosh, tanh, Derivative, diff, DiracDelta, E, exp, erf, erfi, EulerGamma,
-    Expr, factor, Function, I, Integral, integrate, Interval, Lambda,
-    LambertW, log, Matrix, O, oo, pi, Piecewise, Poly, Rational, S, simplify,
-    sin, tan, sqrt, sstr, Sum, Symbol, symbols, sympify, trigsimp, Tuple, nan,
-    And, Eq, Ne, re, im, polar_lift, meijerg, SingularityFunction, Max, Min
+    Abs, acos, acosh, Add, And, asin, asinh, atan, Ci, cos, sinh, cosh,
+    tanh, Derivative, diff, DiracDelta, E, Eq, exp, erf, erfi,
+    EulerGamma, Expr, factor, Function, I, im, Integral, integrate,
+    Interval, Lambda, LambertW, log, Matrix, Max, meijerg, Min, nan,
+    Ne, O, oo, pi, Piecewise, polar_lift, Poly, Rational, re, S, sign,
+    simplify, sin, SingularityFunction, sqrt, sstr, Sum, Symbol,
+    symbols, sympify, tan, trigsimp, Tuple
 )
 from sympy.functions.elementary.complexes import periodic_argument
 from sympy.integrals.risch import NonElementaryIntegral
@@ -529,7 +530,7 @@ def test_integrate_returns_piecewise():
         (z, Eq(y,0)), (exp(y*z)/y - 1/y, True))
 
 
-def test_max_min():
+def test_integrate_max_min():
     assert integrate(Min(x, 2), (x, 0, 3)) == 4
     assert integrate(Max(x**2, x**3), (x, 0, 2)) == S(49)/12
     assert integrate(Min(exp(x), exp(-x))**2, x) == Piecewise( \
@@ -543,6 +544,33 @@ def test_max_min():
         sqrt(pi)*c/2 + exp(-c**2)/2
 
 
+def test_integrate_Abs_sign():
+    assert integrate(Abs(x), (x, -2, 1)) == S(5)/2
+    assert integrate(Abs(x), (x, 0, 1)) == S(1)/2
+    assert integrate(Abs(x + 1), (x, 0, 1)) == S(3)/2
+    assert integrate(Abs(x**2 - 1), (x, -2, 2)) == 4
+    assert integrate(Abs(x**2 - 3*x), (x, -15, 15)) == 2259
+    assert integrate(sign(x), (x, -1, 2)) == 1
+    assert integrate(sign(x)*sin(x), (x, -pi, pi)) == 4
+    assert integrate(sign(x - 2) * x**2, (x, 0, 3)) == S(11)/3
+
+    t, s = symbols('t s', real=True)
+    assert integrate(Abs(t), t) == Piecewise(
+        (-t**2/2, t <= 0), (t**2/2, True))
+    assert integrate(Abs(2*t - 6), t) == Piecewise(
+        (-t**2 + 6*t, t <= 3), (t**2 - 6*t + 18, True))
+    assert (integrate(abs(t - s**2), (t, 0, 2)) ==
+        2*s**2*Min(2, s**2) - 2*s**2 - Min(2, s**2)**2 + 2)
+    assert integrate(exp(-Abs(t)), t) == Piecewise(
+        (exp(t), t <= 0), (2 - exp(-t), True))
+    assert integrate(sign(2*t - 6), t) == Piecewise(
+        (-t, t < 3), (t - 6, True))
+    assert integrate(2*t*sign(t**2 - 1), t) == Piecewise(
+        (t**2, t < -1), (-t**2 + 2, t < 1), (t**2, True))
+    assert integrate(sign(t), (t, s + 1)) == Piecewise(
+        (s + 1, s + 1 > 0), (-s - 1, s + 1 < 0), (0, True))
+
+
 def test_subs1():
     e = Integral(exp(x - y), x)
     assert e.subs(y, 3) == Integral(exp(x - 3), x)