Skip to content

Commit 0e417b5

Browse files
committed
Adding root polishing step to polysolve function.
At the very largest scales and with coefficient reduction off, found blobs had roots drifting from <0 to >0 like solve_quartic() prior the previous commit. The solution drift is due the berstein / bezeier, normalization / de-normalization maths for root existence testing in blob.cpp and not the polysolve / sturm chaining code itself.
1 parent 9bf5d64 commit 0e417b5

File tree

1 file changed

+47
-18
lines changed

1 file changed

+47
-18
lines changed

source/core/math/polynomialsolver.cpp

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,8 +1544,8 @@ static int polysolve(int order, const DBL *Coeffs, DBL *roots)
15441544
//---
15451545
// Reverse coefficients into order used herein.
15461546
// Drop any leading original order coefficients meaningfully 0.0.
1547-
// Set any remaining coefficients meaningfully 0.0 to exactly 0.0.
1548-
//
1547+
// (Commented below) Set any remaining coefficients meaningfully 0.0 to exactly 0.0.
1548+
15491549
np = 0;
15501550
for (i = 0; i <= order; i++)
15511551
{
@@ -1556,14 +1556,14 @@ static int polysolve(int order, const DBL *Coeffs, DBL *roots)
15561556
else
15571557
{
15581558
potentialLeadingZero = false;
1559-
if (fabs(Coeffs[i]) < POV_DBL_EPSILON)
1560-
{
1561-
sseq[0].coef[order-i] = (PRECISE_FLOAT)0.0;
1562-
}
1563-
else
1564-
{
1559+
//if (fabs(Coeffs[i]) < POV_DBL_EPSILON)
1560+
//{
1561+
// sseq[0].coef[order-i] = (PRECISE_FLOAT)0.0;
1562+
//}
1563+
//else
1564+
//{
15651565
sseq[0].coef[order-i] = (PRECISE_FLOAT)Coeffs[i];
1566-
}
1566+
//}
15671567
}
15681568
}
15691569
order -= np;
@@ -1580,23 +1580,23 @@ static int polysolve(int order, const DBL *Coeffs, DBL *roots)
15801580

15811581
//---
15821582
// Build the Sturm sequence
1583-
//
1583+
15841584
np = buildsturm(order, &sseq[0]);
15851585

15861586
//---
15871587
// Calculate the total number of visible roots.
15881588
// NOTE: Changed to <=0 test over ==0 due sphere_sweep b_spline
15891589
// going negative when the modp leading coef filter set lower.
15901590
// Similar change to the numchanges based test below.
1591-
//
1591+
15921592
if ((nroots = visible_roots(np, sseq)) <= 0)
15931593
{
15941594
return(0);
15951595
}
15961596

15971597
//---
15981598
// Bracket the roots
1599-
//
1599+
16001600
min_value = 0.0;
16011601
max_value = MAX_DISTANCE;
16021602

@@ -1608,7 +1608,7 @@ static int polysolve(int order, const DBL *Coeffs, DBL *roots)
16081608
// Cohen, Alan M. (2009). "Bounds for the roots of polynomial equations".
16091609
// Mathematical Gazette. 93: 87-88.
16101610
// NOTE: Had to use > 1.0 in max_value2 calculation in practice...
1611-
//
1611+
16121612
Abs_Coeff_n = fabs(Coeffs[0]); // Leading zeros dropped above.
16131613
max_value2 = 1.1 + fabs(Coeffs[1]/Abs_Coeff_n);
16141614
max_value = fabs(Coeffs[2]);
@@ -1623,7 +1623,7 @@ static int polysolve(int order, const DBL *Coeffs, DBL *roots)
16231623
// Perhaps related to how the sturm chain is pruned in modp(). Until sorted adding
16241624
// the following sanity check which restores a MAX_DISTANCE upper bound where
16251625
// root(s) exists above estimated upper bound.
1626-
//
1626+
16271627
atmin = numchanges(np, sseq, (PRECISE_FLOAT)max_value);
16281628
atmax = numchanges(np, sseq, (PRECISE_FLOAT)MAX_DISTANCE);
16291629
if ((atmin - atmax) != 0)
@@ -1643,10 +1643,39 @@ static int polysolve(int order, const DBL *Coeffs, DBL *roots)
16431643
return(0);
16441644
}
16451645

1646-
// perform the bisection.
1647-
//
1648-
return(sbisect(np, sseq, (PRECISE_FLOAT)min_value, (PRECISE_FLOAT)max_value,
1649-
atmin, atmax, roots));
1646+
// Perform the bisection.
1647+
1648+
nroots = sbisect(np, sseq, (PRECISE_FLOAT)min_value, (PRECISE_FLOAT)max_value,
1649+
atmin, atmax, roots);
1650+
1651+
// Newton Raphson root polishing step. Using SMALL_ENOUGH value currently
1652+
// to limit to one pass, but could try for more accuracy if need be.
1653+
// See similar code in solve_quartic for additional comment.
1654+
1655+
DBL pv, dpv, t, dt;
1656+
for (int c = 0; c < nroots; c++)
1657+
{
1658+
t = roots[c];
1659+
for (int j = 0; j < 7; j++)
1660+
{
1661+
pv = sseq[0].coef[order] * t + sseq[0].coef[order-1];
1662+
dpv = sseq[0].coef[order];
1663+
for (int k=order-2; k>=0; k--)
1664+
{
1665+
dpv = dpv * t + pv;
1666+
pv = pv * t + sseq[0].coef[k];
1667+
}
1668+
1669+
dt = pv / dpv;
1670+
t -= dt;
1671+
if (fabs(dt) < SMALL_ENOUGH)
1672+
{
1673+
roots[c] = t;
1674+
break;
1675+
}
1676+
}
1677+
}
1678+
return(nroots);
16501679
}
16511680

16521681

0 commit comments

Comments
 (0)