Function Repository Resource:

LogAffineExpand

Source Notebook

Compute branch-correct expansions of Log for real univariate polynomial and rational functions

Contributed by: Jayanta Phadikar

ResourceFunction["LogAffineExpand"][Log[p], x]

rewrites the logarithm of a univariate polynomial or rational function p with real coefficients, for real x, as a sum of logarithms of affine factors.

Details

An affine factor is a degree-one polynomial of the form ax+b with a != 0. In this function we use the normalized affine form 1+αx.
An affine log expansion is a representation of Log of a polynomial/rational function that replaces the original expression by a constant plus a sum of logs of normalized affine factors, together with a piecewise integer multiple of 2πⅈ so that the result coincides exactly with the principal branch value of the original expression on the real line.
Works for univariate polynomials or rational functions in x.
The coefficients must be real-valued and numeric. Inputs with complex or symbolic coefficients are left unevaluated.
For a rational function ℛ(x)=κΠi(1-x/ri)mi/Πj(1-x/pj)nj, the expansion is: Log[ℛ(x)]=Log[κ]+ΣimiLog[(1-x/ri)]-ΣjnjLog[(1-x/pj)] plus a piecewise multiples of 2πⅈ ensuring equality on the principal branch.
The correctness of the expansion using LogAffineExpand is guaranteed for real x only, where branch jumps occur only when real affine factors become negative. For complex x, the current implementation may miss 2πⅈ adjustments when non-real affine factors map x onto the negative real axis; in such cases the result can differ from Log[expr] by integer multiples of 2πⅈ.

Examples

Basic Examples (2) 

Expand a simple quadratic polynomial:

In[1]:=
ResourceFunction["LogAffineExpand"][Log[1 - x^2], x]
Out[1]=

Expand a simple rational function:

In[2]:=
ResourceFunction["LogAffineExpand"][Log[(1 - x)/(1 + x)], x]
Out[2]=

Scope (5) 

Complex-conjugate factorization of a real quadratic:

In[3]:=
res = ResourceFunction["LogAffineExpand"][Log[x^2 + x + 1], x]
Out[3]=

Verify that the expansion correctly represents the original function in the real line:

In[4]:=
Plot[Chop[Log[x^2 + x + 1] - res], {x, -100, 100}]
Out[4]=

Branch-corrected expansion near a real root:

In[5]:=
ResourceFunction["LogAffineExpand"][Log[(x - 2)^2], x]
Out[5]=

On the principal branch, when x>2 the factor 1-x/2 is negative real, each Log contributes πⅈ. LogAffineExpand automatically inserts a compensating piecewise constant term -2πⅈ so the result is exactly equal to the original input on the principal branch.

A similar branch correction for a simple rational function:

In[6]:=
ResourceFunction["LogAffineExpand"][Log[1/x], x]
Out[6]=

Expansion for a rational input - zeros minus poles, with sign and branch corrections:

In[7]:=
res = ResourceFunction["LogAffineExpand"][Log[(x^2 - 1)/(x^2)], x]
Out[7]=

Verify that the result is correct:

In[8]:=
Plot[Chop[Log[(x^2 - 1)/(x^2)] - res], {x, -100, 100}]
Out[8]=

Root objects may appear in the result:

In[9]:=
ResourceFunction["LogAffineExpand"][Log[x^3 - 3 x + 10], x]
Out[9]=

Use ToRadicals to express using radicals (may not work always):

In[10]:=
ResourceFunction["LogAffineExpand"][Log[x^3 - 3 x + 10], x] // ToRadicals
Out[10]=

Root objects in the expansion of a rational function:

In[11]:=
ResourceFunction["LogAffineExpand"][Log[(x^6 - 3 x + 10)/(x - 2)], x]
Out[11]=

Applications (3) 

The canonical form of Log[polynomial] or Log[rational] is helpful for various symbolic and numeric computations.

Sum can compute faster with the affine expansion:

In[12]:=
AbsoluteTiming[
  Sum[Log[(x^12 + 6 x^10 - 3 x + 10)/((x^2 - 2) (x^3 + 3 x + 1) (x^9 + 1))], {x, 1, k}]][[1]]
Out[12]=
In[13]:=
AbsoluteTiming[
  Sum[#, {x, 1, k}] & /@ ResourceFunction["LogAffineExpand"][
    Log[(x^12 + 6 x^10 - 3 x + 10)/((x^2 - 2) (x^3 + 3 x + 1) (x^9 + 1))], x]][[1]]
Out[13]=

Integrate can compute faster with the affine expansion:

In[14]:=
AbsoluteTiming[
  Integrate[
   Log[(x^12 + 6 x^10 - 3 x + 10)/((x^2 - 2) (x^3 + 3 x + 1) (x^9 + 1))], x]][[1]]
Out[14]=
In[15]:=
AbsoluteTiming[
  Integrate[#, x] & /@ ResourceFunction["LogAffineExpand"][
    Log[(x^12 + 6 x^10 - 3 x + 10)/((x^2 - 2) (x^3 + 3 x + 1) (x^9 + 1))], x]][[1]]
Out[15]=

Conversion of a Log[polynomial] or Log[rational] expression to generalized polylogarithm form becomes straightforward through the affine expansion:

In[16]:=
ResourceFunction["LogAffineExpand"][Log[x/(1 + x + x^2)], x] /. {Log[x] :> generalizedPolyLog[{0}, x], Log[1 + c_.*x] :> generalizedPolyLog[{-1/c}, x]}
Out[16]=

Properties and Relations (3) 

PowerExpand applies identities like Log(ab)=Log(a)+Log(b) under generic assumptions and without managing branches, so it may stop at non-affine factors and either omit necessary 2πⅈ corrections or emit complex corrections:

In[17]:=
PowerExpand[Log[x (x^2 - 1)]]
Out[17]=
In[18]:=
PowerExpand[Log[x (x^2 - 1)], Assumptions -> True]
Out[18]=

LogAffineExpand always expands into affine factors and simplified 2πⅈ corrections:

In[19]:=
ResourceFunction["LogAffineExpand"][Log[x (x^2 - 1)], x]
Out[19]=

Similarly for rational expressions:

In[20]:=
PowerExpand[Log[(x^2 - 1)/(x^4 + x^3 - 10)]]
Out[20]=
In[21]:=
PowerExpand[Log[(x^2 - 1)/(x^4 + x^3 - 10)], Assumptions -> True]
Out[21]=
In[22]:=
ResourceFunction["LogAffineExpand"][Log[(x^2 - 1)/(x^4 + x^3 - 10)],
  x]
Out[22]=

Possible Issues (2) 

For LogAffineExpand to work all constants appearing in the expression should be real and numeric. It won't work for symbolic or complex parameters:

In[23]:=
ResourceFunction["LogAffineExpand"][Log[(k x^2 - 1)], x]
Out[23]=
In[24]:=
ResourceFunction["LogAffineExpand"][Log[(I x^2 - 1)], x]
Out[24]=

LogAffineExpand gives an expansion which is guaranteed to be correct for real x only. It may not be valid for complex x:

In[25]:=
Log[1 + 2 x + 2 x^2] /. x -> -1 + I // N
Out[25]=
In[26]:=
ResourceFunction["LogAffineExpand"][Log[1 + 2 x + 2 x^2], x] /. x -> -1 + I // N
Out[26]=

Neat Examples (6) 

Expansion of a high degree polynomial:

In[27]:=
ResourceFunction["LogAffineExpand"][Log[x^8 - 8 x^3 + 2 x^2 + 5 x - 1],
  x]
Out[27]=

Builds a polynomial as ten times six factors. LogAffineExpand reduces its log to a constant plus one affine log per factor, inserting a piecewise 2πⅈ term for principal-branch correctness:

In[28]:=
ResourceFunction["LogAffineExpand"][
 Log[10*Times @@ Table[1 - x/k, {k, 1, 6}]], x]
Out[28]=

For a polynomial with repeated roots, the multiplicities reflect in the coefficients of the affine-log factors:

In[29]:=
ResourceFunction["LogAffineExpand"][Log[(x - 2)^5 (x + 5)^8], x]
Out[29]=

For real quadratics with negative discriminant, the two affine-log terms are complex conjugates. Their imaginary parts cancel for real x, so the result is purely real with no branch correction needed:

In[30]:=
ResourceFunction["LogAffineExpand"][Log[x^2 + 2 x + 2], x]
Out[30]=

On rationals like (x^2-1)/(x-1)=1+x, the expansion cancels the common factor and reduces to Log[1+x] (up to the usual constant/branch bookkeeping):

In[31]:=
ResourceFunction["LogAffineExpand"][Log[(x^2 - 1)/(x - 1)], x]
Out[31]=

For a random 3 x 3 integer matrix, LogAffineExpand rewrites Log[Det[I-xA]] as a constant plus one affine log per eigenvalue, adding a piecewise 2πⅈ term for principal-branch correctness on the real line. Nice for spectral checks and trace expansions:

In[32]:=
SeedRandom[1];
A = RandomInteger[{-10, 10}, {3, 3}];
lam = Eigenvalues[A];
In[33]:=
lhs = ResourceFunction["LogAffineExpand"][
  Log[Det[IdentityMatrix[3] - x A]], x]
Out[33]=
In[34]:=
rhs = ResourceFunction["LogAffineExpand"][Log[Times @@ (1 - lam x)], x]
Out[34]=

Publisher

Jayanta Kumar Phadikar

Requirements

Wolfram Language 13.0 (December 2021) or above

Version History

  • 1.0.0 – 03 September 2025

Related Resources

License Information