11
$\begingroup$

Try the following codes

n = 500; precision = MachinePrecision; l = RandomReal[{}, n, WorkingPrecision -> precision]; poly = Times @@ (x - l); 

Now try to expand this polynomial using different methods.

p1 = Expand[poly]; // AbsoluteTiming (*{0.1714865`,Null}*) ClearSystemCache[]; p2 = poly + O[x]^(n + 1) // Normal; // AbsoluteTiming (*{0.0340022`,Null}*) p1 == p2 (*True*) 

It can be seen that truncating with O is much faster than Expand. Can anyone explain it? Is there any other faster method?

$\endgroup$
1
  • $\begingroup$ Expand[] beats O[x] for n=2500 for me, but O[x] is quite a bit faster up to around n=2000, which is remarkable. $\endgroup$ Commented Dec 18, 2024 at 15:12

1 Answer 1

12
$\begingroup$

The Series-based method works from the inside out by creating a SeriesData from each factor and then multiplying them. For the multiplication it effectively uses ListConvolve iteratively (not maximally efficient) on lists of approximate numbers. This is fast vector arithmetic.

Here is more or less the process, shown outside of Series. We set up the example.

n = 500; precision = MachinePrecision; l = RandomReal[{}, n, WorkingPrecision -> precision]; poly = Times @@ (x - l); 

Reference expansion timing.

AbsoluteTiming[p1 = Expand[poly];] (* Out[53]= {0.094142, Null} *) 

Timing to convert all factors of poly to lists.

AbsoluteTiming[ poly2 = Map[CoefficientList[#, x] &, Apply[List, poly]];] (* Out[18]= {0.000607, Null} *) 

Timing to convolve iteratively.

AbsoluteTiming[ plist = Fold[ListConvolve[#1, #2, {1, -1}, 0] &, First[poly2], Rest[poly2]];] (* Out[54]= {0.002722, Null} *) 

Timing for converting back to a polynomial.

AbsoluteTiming[p3 = plist . x^Range[0, n];] (* Out[55]= {0.000479, Null} *) 

Check that they are (more or less) equal.

In[73]:= p1 - p3 Out[73]= 0. 

Here is the Series timing for comparison.

AbsoluteTiming[p2 = Normal[poly + O[x]^(n + 1)];] (* Out[77]= {0.021734, Null} *) 

This is notably faster than direct expansion but also notably slower than the sum of the individual steps shown above. The difference is unavoidable Series overhead.

$\endgroup$
1
  • $\begingroup$ Yes, I have considered ListConvolve. It is very fast for MachinePrecision, but relatively slow for high accuracy. $\endgroup$ Commented Dec 19, 2024 at 4:51

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.