Function Repository Resource:

IntegrateRational

Source Notebook

Compute the indefinite integral of a rational function

Contributed by: Sam Blake

ResourceFunction["IntegrateRational"][f,x]

gives the indefinite integral of the rational function, f, with respect to x.

Details and Options

IntegrateRational uses Mack's "linear" Hermite reduction for the rational part of the integral, the Lazard-Rioboo-Trager algorithm for the logarithmic part of the integral, and Rioboo's algorithm for expressing complex logarithms as real arc-tangents and real logarithms.
ResourceFunction["IntegrateRational"] will convert sums of real logarithms to hyperbolic arc-tangents where possible, providing the conversion does not introduce any discontinuities.
ResourceFunction["IntegrateRational"] may give different results depending on the assumptions of the signs of parameters in the integrand.
ExtensionAutomaticspecifies the generators for the algebraic number field to be used in the factorization of the integrand’s denominator prior to decomposition into partial fractions
"PartialFractions"Truespecifies if a partial fraction decomposition is used on the integrand after Hermite reduction and prior to computing the logarithmic terms
"LogToArcTan"Truespecifies if Rioboo’s algorithm is used for expressing complex logarithms as real arc-tangents and real logarithms, and an algorithm for converting sums of real logarithms to hyperbolic arc-tangents where possible providing the conversion does not introduce any discontinuities. If the integrand contains parameters, then Rioboo’s algorithm is not used
"Radicals"Truespecifies if the integral is left as a RootSum object, or converted into radicals where possible

Examples

Basic Examples (3) 

Compute the integral of a rational function:

In[1]:=
ResourceFunction["IntegrateRational"][1/(1 - x^6), x]
Out[1]=

Compute the integral of a rational function (using Mack's Hermite reduction) where the solution does not contain any logarithmic terms:

In[2]:=
ResourceFunction["IntegrateRational"][(
 x^3 (2 + x^2))/(-2 + Sqrt[3] + (-2 + Sqrt[3]) x^2 - x^4)^2, x]
Out[2]=

Computes a continuous solution to rational integral given in Symbolic Integration I by Manuel Bronstein:

In[3]:=
ResourceFunction["IntegrateRational"][(x^4 - 3 x^2 + 6)/(
 x^6 - 5 x^4 + 5 x^2 + 4), x]
Out[3]=

Scope (6) 

IntegrateRational can compute many integrals for which Integrate fails to return an elementary form:

In[4]:=
ResourceFunction["IntegrateRational"][(
 4 - 2 x - 2 x^2 + 6 x^3 + 2 x^4 - 3 x^5)/(-1 - 2 x^2 + 3 x^4 - x^6),
  x]
Out[4]=

In comparison, here's the result from Integrate:

In[5]:=
Integrate[(
 4 - 2 x - 2 x^2 + 6 x^3 + 2 x^4 - 3 x^5)/(-1 - 2 x^2 + 3 x^4 - x^6),
  x]
Out[5]=

Similarly, the following integral has a concise form from IntegrateRational:

In[6]:=
ResourceFunction["IntegrateRational"][(
 2 + 4 x + 4 x^2 + 12 x^3 + 4 x^4 - 6 x^5)/(
 1 + 2 x + 2 x^2 - x^4 + x^6), x]
Out[6]=

While Integrate expresses the result as a RootSum:

In[7]:=
Integrate[(2 + 4 x + 4 x^2 + 12 x^3 + 4 x^4 - 6 x^5)/(
 1 + 2 x + 2 x^2 - x^4 + x^6), x]
Out[7]=

Some integrals will be expressed in finite terms by IntegrateRational, whereas Integrate returns unevaluated:

In[8]:=
ResourceFunction["IntegrateRational"][(
 32 - 16 Sqrt[3] + 4 x^2 + 2 x^4 + Sqrt[3] x^4)/((4 + x^2) (144 - 80 Sqrt[3] + 24 x^2 + 9 x^4 + 5 Sqrt[3] x^4)), x]
Out[8]=
In[9]:=
Integrate[(
 32 - 16 Sqrt[3] + 4 u^2 + 2 u^4 + Sqrt[3] u^4)/((4 + u^2) (144 - 80 Sqrt[3] + 24 u^2 + 9 u^4 + 5 Sqrt[3] u^4)), u]
Out[9]=

Integrating some rational functions will introduce algebraic numbers. The solution from IntegrateRational is in the minimal algebraic extension field:

In[10]:=
ResourceFunction["IntegrateRational"][(-1 + x^2)/(1 - 2 x^2 + 2 x^4),
  x]
Out[10]=
In[11]:=
ResourceFunction["IntegrateRational"][(
 5 - 6 x^2 - 12 x^5 - 15 x^6 + 10 x^9)/(
 1 + 5 x^2 - 4 x^3 - 3 x^4 - 10 x^5 + 6 x^6 + 5 x^8 - 4 x^9 + x^12),
  x]
Out[11]=

Other integrals will be expressed with hyperbolic arc-tangents:

In[12]:=
ResourceFunction[
 "IntegrateRational"][(-72 Sqrt[2] + 480 Sqrt[3] x + 24 Sqrt[2] x^2)/(-564 - 144 Sqrt[6] x + 840 x^2 + 48 Sqrt[6] x^3 - 144 x^4), x]
Out[12]=

IntegrateRational works with integrands that contain parameters:

In[13]:=
ResourceFunction["IntegrateRational"][(a x + b)/(b^4 x^4 - a^4), x]
Out[13]=

Options (4) 

PartialFractions (1) 

The option "PartialFractions" specifies if a partial fraction decomposition (with Apart) and term-by-term integration should be used:

In[14]:=
ResourceFunction["IntegrateRational"][(2 x + x^2)/(
 2 + 4 x + 2 x^2 + x^4), x, "PartialFractions" -> False]
Out[14]=
In[15]:=
ResourceFunction["IntegrateRational"][(2 x + x^2)/(
 2 + 4 x + 2 x^2 + x^4), x, "PartialFractions" -> True, Extension -> Sqrt[3 + 2 Sqrt[2]]]
Out[15]=

Extension (1) 

Computing integrals of rational functions using partial fraction decompositions with factorizations over different algebraic extension fields can give alternative forms:

In[16]:=
ResourceFunction["IntegrateRational"][x/(x^8 + 1), x, "PartialFractions" -> True, Extension -> Sqrt[2]]
Out[16]=
In[17]:=
ResourceFunction["IntegrateRational"][x/(x^8 + 1), x, "PartialFractions" -> True, Extension -> Sqrt[2 - Sqrt[2]]]
Out[17]=

LogToArcTan (2) 

By default, sums of complex logarithms are converted into arc-tangents, and sums of real logarithms are converted into hyperbolic arc-tangents:

In[18]:=
ResourceFunction["IntegrateRational"][1/(x^8 - 1), x]
Out[18]=

This feature can be turned off:

In[19]:=
ResourceFunction["IntegrateRational"][1/(x^8 - 1), x, "LogToArcTan" -> False]
Out[19]=

Applications (3) 

The output from IntegrateRational will be real and continuous on the real line where possible:

In[20]:=
case = ResourceFunction[
  "IntegrateRational"][(-4 + 2 x + 2 x^2 - 6 x^3 - 2 x^4 + 3 x^5)/(-1 - 2 x^2 + 3 x^4 - x^6), x]

Now evaluate at the endpoints 0 and 1, thus effectively computing a closed form for the definite integral using the Newton-Leibniz theorem:

In[21]:=
(case /. x -> 1) - (case /. x -> 0)
Out[22]=

By comparison, Integrate gives a substantially more complicated (though equivalent) result:

In[23]:=
case2 = Integrate[(-4 + 2 x + 2 x^2 - 6 x^3 - 2 x^4 + 3 x^5)/(-1 - 2 x^2 + 3 x^4 - x^6), {x, 0, 1}]
Out[23]=

Verify numerically that this is π:

In[24]:=
case2 // N
Out[24]=

Use the Newton-Leibniz method to compute alternative forms to Integrate for definite integrals:

In[25]:=
case = ResourceFunction["IntegrateRational"][(-1 + 2 x^2)/(
   1 - x^2 + x^4), x];
res1 = (case /. x -> 1) - (case /. x -> -1)
Out[26]=

Compare to Integrate:

In[27]:=
res2 = Integrate[(-1 + 2 x^2)/(1 - x^2 + x^4), {x, -1, 1}]
Out[27]=

Verify equivalence:

In[28]:=
FullSimplify[res1 - res2]
Out[28]=

As the result from IntegrateRational is in the minimal algebraic extension field, we know the following integral cannot be expressed without introducing the algebraic number :

In[29]:=
ResourceFunction["IntegrateRational"][(1 - 3 x^2 - 3 x^4 + x^6)/(
 1 - 5 x^2 + 9 x^4 - 5 x^6 + x^8), x]
Out[29]=

Properties and Relations (3) 

For many simple rational integrals, the result from IntegrateRational and Integrate will often be the same:

In[30]:=
integrateRationalResult = ResourceFunction["IntegrateRational"][x^3/(1 - x)^4, x]
Out[30]=
In[31]:=
integrateResult = Integrate[x^3/(1 - x)^4, x]
Out[31]=
In[32]:=
integrateRationalResult == integrateResult // Simplify
Out[32]=

Even though a partial fraction decomposition is not immediately possible (via Apart), a concise form for this integral is still possible with IntegrateRational:

In[33]:=
ResourceFunction["IntegrateRational"][(
 1 + x)/(-2 + 3 x + 3 x^2 + x^3), x]
Out[33]=

Whereas Integrate requires a complete factorization of the denominator of the integrand:

In[34]:=
Integrate[(1 + x)/(-2 + 3 x + 3 x^2 + x^3), x]
Out[34]=

Some integrals will be expressed using Root and RootSum:

In[35]:=
ResourceFunction[
 "IntegrateRational"][(-1 + 5 x + 12 x^2 + 8 x^3 + 2 x^4)/(-3 - 3 x + 6 x^2 + 17 x^3 + 15 x^4 + 6 x^5 + x^6), x]
Out[35]=
In[36]:=
ResourceFunction["IntegrateRational"][1/(x^11 - x - 1), x]
Out[36]=

Possible Issues (5) 

IntegrateRational expands polynomials prior to integration:

In[37]:=
ResourceFunction["IntegrateRational"][(x + 4)^12, x]
Out[37]=
In[38]:=
Integrate[(x + 4)^12, x]
Out[38]=

The algorithms used by IntegrateRational requires either exact expressions or expressions which rationalize to exact expressions:

In[39]:=
ResourceFunction["IntegrateRational"][1/(4.5 x^4 - N[Pi]), x]
Out[39]=
In[40]:=
ResourceFunction["IntegrateRational"][1/(4.5 x^4 - 3.125), x]
Out[40]=

The integral of many rational functions will be significantly larger than the integrand:

In[41]:=
ResourceFunction[
 "IntegrateRational"][(-2 - 4 x + x^2)/(-4 - 8 x + x^2 + 5 x^3 + 10 x^4), x]
Out[41]=

Sometimes additional simplification is required to express the integral in the minimal algebraic extension field:

In[42]:=
ResourceFunction["IntegrateRational"][x/(
 2 + 4 x + 5 x^2 + 2 x^3 + x^4), x]
Out[42]=

Compare the result above to the following result obtained with Rubi:

In[43]:=
D[-(ArcTan[(1 + 2 x)/Sqrt[7 - 4 Sqrt[2]]]/(
    2 Sqrt[2 (7 - 4 Sqrt[2])])) + ArcTan[(1 + 2 x)/Sqrt[7 + 4 Sqrt[2]]]/(2 Sqrt[2 (7 + 4 Sqrt[2])]) -
    ArcTanh[(7 + 4 (1/2 + x)^2)/(4 Sqrt[2])]/(2 Sqrt[2]), x] // Simplify
Out[43]=

For some integrals, especially integrals that contain algebraic number coefficients, IntegrateRational may take significantly longer than Integrate:

In[44]:=
ResourceFunction["IntegrateRational"][(-8 Sqrt[30] - 8 Sqrt[3] x)/(
  12 Sqrt[5] + 12 Sqrt[2] x - 8 x^2), x] // Timing
Out[44]=
In[45]:=
Integrate[(-8 Sqrt[30] - 8 Sqrt[3] x)/(
  12 Sqrt[5] + 12 Sqrt[2] x - 8 x^2), x] // Timing
Out[45]=

Further simplification of the result from IntegrateRational may be possible:

In[46]:=
integrateRationalResult = ResourceFunction["IntegrateRational"][(-8 Sqrt[30] - 8 Sqrt[3] x)/(
  12 Sqrt[5] + 12 Sqrt[2] x - 8 x^2), x]
Out[46]=
In[47]:=
integrateRationalResult // FullSimplify
Out[47]=

Neat Examples (3) 

Integrating some rational functions will introduce many logarithms and arc-tangents:

In[48]:=
ResourceFunction["IntegrateRational"][(x^4 + x^6)/(
 3 - 18 x^2 + 45 x^4 - 61 x^6 + 45 x^8 - 18 x^10 + 3 x^12), x]
Out[48]=

While other rational functions are integrable in terms of algebraic functions without the introduction of new logarithms or arc-tangents:

In[49]:=
ResourceFunction["IntegrateRational"][(
 16 - 429 x^8 + 1287 x^10 - 1287 x^12 + 429 x^14)/(
 x^8 (1 - 4 x^2 + 6 x^4 - 4 x^6 + x^8)), x]
Out[49]=

The following integral cannot be solved without introducing the algebraic number :

In[50]:=
ResourceFunction[
  "IntegrateRational"][(-4 - 6 x^2 + 4 x^4 - 2 x^6 - 40 x^8 + 14 x^10 - 6 x^12)/(
  1 + 2 x^2 + x^4 - 16 x^6 + 2 x^8 - 2 x^10 + 4 x^12 - 4 x^14 + x^16),
   x] // ToRadicals
Out[50]=

Many rational integrals (and algebraic integrals) will have symmetric instances of ArcTan and ArcTanh:

In[51]:=
ResourceFunction[
 "IntegrateRational"][(-80 (-3 + 2 Sqrt[3]) x - 80 (3 - 2 Sqrt[3]) x^3 - 80 (90 + 30 Sqrt[3]) x^5 - 960 Sqrt[3] x^7 - 7440 Sqrt[3] x^9 - 1440 Sqrt[3] x^11)/(14 - 8 Sqrt[3] + (-28 + 20 Sqrt[3]) x^2 + (-1110 - 418 Sqrt[3]) x^4 + (296 - 268 Sqrt[3]) x^6 + (434 - 2401 Sqrt[3]) x^8 + (204 - 828 Sqrt[3]) x^10 + (-324 - 468 Sqrt[3]) x^12 - 432 x^14 + 648 x^16), x]
Out[51]=

Publisher

Sam Blake

Requirements

Wolfram Language 13.0 (December 2021) or above

Version History

  • 1.0.0 – 10 April 2024

Source Metadata

Related Resources

Author Notes

Unlike the rational function integration algorithms in Integrate, this code has not been battle hardened for 30+ years, however it does offer some improved algorithms for computing the logarithmic part of the rational integral, and options to control the use of a partial fraction decomposition, the extension field of the factorisation etc.

Method options will be available in the future to control different rational function integration algorithms.

Bugs:

In[1]:=
(*IntegrateRational[(8 (Sqrt[3]-Sqrt[6])+8 (6-Sqrt[2]+2 Sqrt[3]-Sqrt[6]) x+8 (-2 Sqrt[2]-Sqrt[6]) x^2+8 Sqrt[6] x^3)/(-12+4 Sqrt[3]-4 Sqrt[6]+(8+8 Sqrt[6]) x+(-8-8 Sqrt[3]+4 Sqrt[6]) x^2-8 x^3+4 Sqrt[3] x^4),x]*)
In[2]:=
(*IntegrateRational[(8 (-1-Sqrt[6])+8 (-2+Sqrt[2]+2 Sqrt[3]-Sqrt[6]) x+8 (2 Sqrt[2]-Sqrt[6]) x^2+8 Sqrt[6] x^3)/(4+4 Sqrt[2]+4 Sqrt[3]+(-8-8 Sqrt[2]) x+(8-4 Sqrt[2]-8 Sqrt[3]) x^2+8 x^3+4 Sqrt[3] x^4),x]*)
In[3]:=
IntegrateRational[(x^3 + 4 x - 1)/(
 6 x^4 - x^2 + 1), x](* BUG! Compare to the real-valued solution from Rubi! *)
D[1/2 Sqrt[1/23 (1 + 2 Sqrt[6])]
     ArcTan[(Sqrt[6 (1 + 2 Sqrt[6])] - 12 x)/Sqrt[
     6 (-1 + 2 Sqrt[6])]] - 1/2 Sqrt[1/23 (1 + 2 Sqrt[6])]
     ArcTan[(Sqrt[6 (1 + 2 Sqrt[6])] + 12 x)/Sqrt[
     6 (-1 + 2 Sqrt[6])]] - (49 ArcTan[(1 - 12 x^2)/Sqrt[23]])/(
   12 Sqrt[23]) + Log[Sqrt[6] - Sqrt[6 (1 + 2 Sqrt[6])] x + 6 x^2]/(
   4 Sqrt[1 + 2 Sqrt[6]]) - Log[Sqrt[6] + Sqrt[6 (1 + 2 Sqrt[6])] x + 6 x^2]/(
   4 Sqrt[1 + 2 Sqrt[6]]) + 1/24 Log[1 - x^2 + 6 x^4], x] // Simplify (* Rubi result. *)

This is an issue/limitation with my ArcTan and ArcTanh conversion routines:

In[4]:=
IntegrateRational[x^4/(x^8 - a)^2, x]
D[%, x] - x^4/(x^8 - a)^2 // Simplify
D[x^5/(8 a (a - x^8)) + (3 ArcTan[x/a^(1/8)])/(32 a^(11/8)) + (
    3 ArcTan[1 - (Sqrt[2] x)/a^(1/8)])/(32 Sqrt[2] a^(11/8)) - (
    3 ArcTan[1 + (Sqrt[2] x)/a^(1/8)])/(32 Sqrt[2] a^(11/8)) + (
    3 ArcTanh[x/a^(1/8)])/(32 a^(11/8)) + (
    3 Log[a^(1/4) - Sqrt[2] a^(1/8) x + x^2])/(
    64 Sqrt[2] a^(11/8)) - (
    3 Log[a^(1/4) + Sqrt[2] a^(1/8) x + x^2])/(64 Sqrt[2] a^(11/8)), x] - x^4/(x^8 - a)^2 // Simplify (* Rubi. *)

Does Horowitz reduction compute this faster than Mack's Hermite reduction?

In[5]:=
(* HermiteReduce[1/((x^2-a)^2(x^2+Sqrt[2]a)^2(x^2+Sqrt[3]a)^2),x] *)

License Information