For the part f(x) it starts by dividing the polynomial
This solved for b gives an algorithm to calculate the b parameters in a loop:
This might not look too interesting, but if we set x = p and look further above, we see that the polynomial becomes equal bn in this case. That means if x = p we just have to run through the loop and get the value of the polynomial at the end in bn. O.k. that’s still not that interesting
If we have a look about the differentiation of f(x), things might become somewhat more interesting.
For the part f’(x) we first substitute
partially differentiated
and at the end of the loop we get P’(x) = cn-1.
Now the loop for the b parameters from above and the loop for the c parameters can be put together.
The first step is
With this we start a loop looking like
For the c part we have to skip the last cycle of the loop. In C# that looks like
bn
= a[0];
cn = bn;
for (i = 1; i < order; i++)
{
bn = xk * bn + a[i];
if (i < order - 1)
cn = xk * cn + bn;
}
cn = bn;
for (i = 1; i < order; i++)
{
bn = xk * bn + a[i];
if (i < order - 1)
cn = xk * cn + bn;
}
Whit a[0] as the first supporting point of the polynomial which is defined in the float array[1..order] a.
At the end of the first loop we get the next point xk by subtracting bn/cn from the starting point. At the end of the following loops we get the next xk by subtracting bn/cn from the last xk.
In my sample for a polynomial of the 5. degree with a0 = 1.0, a1 = -4.0, a2 = 0.0, a3 = 10.0, a4 = -1.0 and a5 = -6.0 I start at 5.0 and get xk = 4.29411 after one cycle, xk = 3.765 after the second and xk = 3.00… as one first root of the polynomial.
Now we got one root, but there are more than just one. To find the others it would be a possible solution, to divide the starting polynomial by (x-xk) and start the root finding algorithm again and do this for each root we find. That’s called deflation.
As xk is not the exact root of the polynomial, the division by (x-xk) brings a inaccuracy into the polynomial that increases for each root we find. That’s not the best solution.
Therefore Maehly modified the algorithm a bit.
To understand his idea we have a look at a polynomial that has 3 roots. With the roots z1, z2, z3 this looks like
And the differentiation of it is
The Division P‘(x)/ P(x) becomes
That means in the algorithm we have to distinguish between “now root found jet” and “found at least one root” and use the unmodified formula for the first case and the modified for the second case. That looks like
if (n == 0)
{
if (cn != 0) // no root found jet => go the the next P
{
dx = bn / cn;
xk = xk - dx;
}
else
if(Math.Abs(bn) < 1E-8) // that's already a root point
dx = 0.0;
}
else
{
if (bn != 0) // one root found => keep it and subtract it from the polynomial
{
xz = 0;
for (j = 0; j < n; j++)
xz = xz + 1.0 / (xk - x[j]);
dx = 1.0 / (cn / bn - xz);
xk = xk - dx;
}
else
xk = xk + 0.5; // we started right at one root point just move a bit
}
{
if (cn != 0) // no root found jet => go the the next P
{
dx = bn / cn;
xk = xk - dx;
}
else
if(Math.Abs(bn) < 1E-8) // that's already a root point
dx = 0.0;
}
else
{
if (bn != 0) // one root found => keep it and subtract it from the polynomial
{
xz = 0;
for (j = 0; j < n; j++)
xz = xz + 1.0 / (xk - x[j]);
dx = 1.0 / (cn / bn - xz);
xk = xk - dx;
}
else
xk = xk + 0.5; // we started right at one root point just move a bit
}
With n holding the number of found roots and x[j] the found roots themselves.
Now we just have to take care that our algorithm converges and does not run mad. This can be done by checking for delta(xk) <= delta(xk-1) and delta(xk) <> 0 and xk does not become huge.
Another point is the case that cn or bn is 0:
If we don’t have at least one root found and cn and bn both are 0, then our starting point is a first root already and we can take this one right away.
If we have one or more roots already found and bn is 0, we don’t use that as the next xk will be calculated including all the found roots. In this case we just have to move a little bit by increasing (or decreasing) xk to get away from this point. I do this by adding 0.5 to xk arbitrary.
To avoid running into roots we already have found, I move the starting point after each found root to the mean of the last starting point and the newly found root.
In this manner the root finding algorithm by Newton-Meahly works quite fine. It found all the roots of different sample polynomials of the 5. and the 4. degree
I implemented a little online solver in JavaqScript. That's here