Skip to content

Commit a5a1e6a

Browse files
committed
Removing difficult_coeffs() and related code in Solve_Polynomial().
Code not completely effective where sturm / polysolve needed and very costly in most scenes with 4th order equations due use of sturm over solve_quartic() where solver_quartic works fine and is much faster.
1 parent 55f11b0 commit a5a1e6a

File tree

1 file changed

+69
-192
lines changed

1 file changed

+69
-192
lines changed

source/core/math/polynomialsolver.cpp

Lines changed: 69 additions & 192 deletions
Original file line numberDiff line numberDiff line change
@@ -50,70 +50,87 @@ namespace pov
5050
* Local preprocessor defines
5151
******************************************************************************/
5252

53-
/* WARNING WARNING WARNING
54-
55-
The following three constants have been defined so that quartic equations
56-
will properly render on fpu/compiler combinations that only have 64 bit
57-
IEEE precision. Do not arbitrarily change any of these values.
58-
59-
If you have a machine with a proper fpu/compiler combo - like a Mac with
60-
a 68881, then use the native floating format (96 bits) and tune the
61-
values for a little less tolerance: something like: factor1 = 1.0e15,
62-
factor2 = -1.0e-7, factor3 = 1.0e-10.
63-
64-
The meaning of the three constants are:
65-
factor1 - the magnitude of difference between coefficients in a
66-
quartic equation at which the Sturmian root solver will
67-
kick in. The Sturm solver is quite a bit slower than
68-
the algebraic solver, so the bigger this is, the faster
69-
the root solving will go. The algebraic solver is less
70-
accurate so the bigger this is, the more likely you will
71-
get bad roots.
72-
73-
factor2 - Tolerance value that defines how close the quartic equation
74-
is to being a square of a quadratic. The closer this can
75-
get to zero before roots disappear, the less the chance
76-
you will get spurious roots.
77-
78-
factor3 - Similar to factor2 at a later stage of the algebraic solver.
79-
*/
80-
81-
#ifndef FUDGE_FACTOR1
82-
#define FUDGE_FACTOR1 1.0e12
83-
#endif
84-
#ifndef FUDGE_FACTOR2
85-
#define FUDGE_FACTOR2 -1.0e-5
86-
#endif
87-
#ifndef FUDGE_FACTOR3
88-
#define FUDGE_FACTOR3 1.0e-7
89-
#endif
53+
/// @def FUDGE_FACTOR2
54+
/// Value defining how close the quartic equation is to being a square
55+
/// of a quadratic.
56+
///
57+
/// @note
58+
/// The closer this can get to zero before roots disappear, the less the chance
59+
/// you will get spurious roots.
60+
///
61+
const DBL FUDGE_FACTOR2 = -1.0e-5;
62+
63+
/// @def FUDGE_FACTOR3
64+
/// Similar to @ref FUDGE_FACTOR2 at a later stage of the algebraic solver.
65+
///
66+
/// @note
67+
///
68+
/// @ref FUDGE_FACTOR2 and @ref FUDGE_FACTOR3 have been defined so that quartic
69+
/// equations will properly render on fpu/compiler combinations that only have
70+
/// 64 bit IEEE precision. Do not arbitrarily change any of these values.
71+
///
72+
/// If you have a machine with a proper fpu/compiler combo - like a Mac with a
73+
/// 68881, then use the native floating format (96 bits) and tune the values for
74+
/// a little less tolerance: something like: factor2 = -1.0e-7, factor3 =
75+
/// 1.0e-10. Twenty five years later the reality is still double accuracy
76+
/// due use of fastmath (not IEEE compliant) compiling, use of SSE Fused
77+
/// Multiply Add instructions, etc.
78+
///
79+
const DBL FUDGE_FACTOR3 = 1.0e-7;
9080

91-
/* Constants. */
81+
/// @def TWO_M_PI_3
82+
/// Value used in solve_cubic() equal to 2.0 * pi / 3.0.
83+
///
9284
const DBL TWO_M_PI_3 = 2.0943951023931954923084;
85+
86+
/// @def FOUR_M_PI_3
87+
/// Value used in solve_cubic() equal to 4.0 * pi / 3.0.
88+
///
9389
const DBL FOUR_M_PI_3 = 4.1887902047863909846168;
9490

95-
/* Max number of iterations. */
91+
/// @def MAX_ITERATIONS
92+
/// Max number of polysolve sturm chain based bisections.
93+
///
94+
/// @note
95+
/// regula_falsa() uses twice this value internally as it can be
96+
/// quite slow to converge in the worst case.
97+
///
9698
const int MAX_ITERATIONS = 65;
9799

98-
// NOTE: Value below which multiple roots ignored. Rays near tangent to surface
99-
// create extremely close roots and instability in sturm chain sign change
100-
// results from numchanges(). Also where the diagonal line of missed roots in
101-
// formed polynomials appears due root collapsing toward each other in
102-
// directions parallel to the ray.
100+
/// @def SBISECT_MULT_ROOT_THRESHOLD
101+
/// Value below which multiple roots ignored in sturm chained based bisection
102+
/// and a sigle root at the middle of the current interval is returned.
103+
///
104+
/// @note
105+
/// Rays near tangent to surface create extremely close roots and instability
106+
/// in sturm chain sign change results from numchanges(). Threshold often
107+
/// tripped in sphere_sweep polynomials where the roots frequently collapse
108+
/// inward due equation set up.
109+
///
103110
const DBL SBISECT_MULT_ROOT_THRESHOLD = 1e-6;
104111

105-
// NOTE: max_value - min_value threshold below which regula_falsa function is
106-
// tried when there is a single root. Single roots happen often. Rays continued
107-
// by transparency or internal reflection for example will have just one root.
108-
// Idea is to delay use of regula_falsa method until the ray domain is small.
112+
/// @def REGULA_FALSA_THRESHOLD
113+
/// Threshold below which regula_falsa function is tried when there is a single root.
114+
///
115+
/// @note
116+
/// Ray interval max_value - min_value threshold below which regula_falsa
117+
/// function is tried when there is a single root. Single roots happen often.
118+
/// Rays continued by transparency or internal reflection for example will have
119+
/// just one root. Idea is to delay use of regula_falsa method until the ray
120+
/// domain is small given regula-falsi method can converge very, very slowly
121+
/// with common enough ray-surface equations.
122+
///
109123
const DBL REGULA_FALSA_THRESHOLD = 1.0;
110124

125+
/// @def RELERROR
126+
/// Smallest relative error along the ray when using the polysolve(), sturm
127+
/// chain bisection / regula-falsi method.
128+
///
129+
const DBL RELERROR = 1.0e-12;
130+
111131
/* A coefficient smaller than SMALL_ENOUGH is considered to be zero (0.0). */
112132
const DBL SMALL_ENOUGH = 1.0e-10;
113133

114-
/* Smallest relative error we want. */
115-
const DBL RELERROR = 1.0e-12;
116-
117134

118135
/*****************************************************************************
119136
* Local typedefs
@@ -141,7 +158,6 @@ static int numchanges (int np, const polynomial *sseq, DBL a);
141158
static DBL polyeval (DBL x, int n, const DBL *Coeffs);
142159
static int buildsturm (int ord, polynomial *sseq);
143160
static int visible_roots (int np, const polynomial *sseq);
144-
static int difficult_coeffs (int n, const DBL *x);
145161

146162

147163
/*****************************************************************************
@@ -728,7 +744,7 @@ static bool regula_falsa(const int order, const DBL *coef, DBL a, DBL b, DBL *va
728744

729745
break;
730746
}
731-
else if (fabs(fx) < (RELERROR/1000))
747+
else if (fabs(fx) < (1/std::numeric_limits<DBL>::digits10))
732748
{
733749
*val = x;
734750

@@ -1006,138 +1022,6 @@ static int solve_cubic(const DBL *x, DBL *y)
10061022
}
10071023
}
10081024

1009-
#ifdef USE_NEW_DIFFICULT_COEFFS
1010-
1011-
/*****************************************************************************
1012-
*
1013-
* FUNCTION
1014-
*
1015-
* difficult_coeffs
1016-
*
1017-
* INPUT
1018-
*
1019-
* OUTPUT
1020-
*
1021-
* RETURNS
1022-
*
1023-
* AUTHOR
1024-
*
1025-
* Alexander Enzmann
1026-
*
1027-
* DESCRIPTION
1028-
*
1029-
* Test to see if any coeffs are more than 6 orders of magnitude
1030-
* larger than the smallest.
1031-
*
1032-
* CHANGES
1033-
*
1034-
* -
1035-
*
1036-
******************************************************************************/
1037-
1038-
static int difficult_coeffs(int n, DBL *x)
1039-
{
1040-
int i, flag = 0;
1041-
DBL t, biggest;
1042-
1043-
biggest = fabs(x[0]);
1044-
1045-
for (i = 1; i <= n; i++)
1046-
{
1047-
t = fabs(x[i]);
1048-
1049-
if (t > biggest)
1050-
{
1051-
biggest = t;
1052-
}
1053-
}
1054-
1055-
/* Everything is zero no sense in doing any more */
1056-
1057-
if (biggest == 0.0)
1058-
{
1059-
return(0);
1060-
}
1061-
1062-
for (i = 0; i <= n; i++)
1063-
{
1064-
if (x[i] != 0.0)
1065-
{
1066-
if (fabs(biggest / x[i]) > FUDGE_FACTOR1)
1067-
{
1068-
x[i] = 0.0;
1069-
flag = 1;
1070-
}
1071-
}
1072-
}
1073-
1074-
return(flag);
1075-
}
1076-
#else
1077-
/*****************************************************************************
1078-
*
1079-
* FUNCTION
1080-
*
1081-
* difficult_coeffs
1082-
*
1083-
* INPUT
1084-
*
1085-
* OUTPUT
1086-
*
1087-
* RETURNS
1088-
*
1089-
* AUTHOR
1090-
*
1091-
* Alexander Enzmann
1092-
*
1093-
* DESCRIPTION
1094-
*
1095-
* Test to see if any coeffs are more than 6 orders of magnitude
1096-
* larger than the smallest (function from POV-Ray v1.0) [DB 8/94].
1097-
*
1098-
* CHANGES
1099-
*
1100-
* -
1101-
*
1102-
******************************************************************************/
1103-
1104-
static int difficult_coeffs(int n, const DBL *x)
1105-
{
1106-
int i;
1107-
DBL biggest;
1108-
1109-
biggest = 0.0;
1110-
1111-
for (i = 0; i <= n; i++)
1112-
{
1113-
if (fabs(x[i]) > biggest)
1114-
{
1115-
biggest = x[i];
1116-
}
1117-
}
1118-
1119-
/* Everything is zero no sense in doing any more */
1120-
1121-
if (biggest == 0.0)
1122-
{
1123-
return(0);
1124-
}
1125-
1126-
for (i = 0; i <= n; i++)
1127-
{
1128-
if (x[i] != 0.0)
1129-
{
1130-
if (fabs(biggest / x[i]) > FUDGE_FACTOR1)
1131-
{
1132-
return(1);
1133-
}
1134-
}
1135-
}
1136-
1137-
return(0);
1138-
}
1139-
1140-
#endif
11411025

11421026
#ifdef TEST_SOLVER
11431027
/*****************************************************************************
@@ -1748,13 +1632,6 @@ int Solve_Polynomial(int n, const DBL *c0, DBL *r, int sturm, DBL epsilon, Rende
17481632
}
17491633
}
17501634

1751-
/* Test for difficult coeffs. */
1752-
1753-
if ((!sturm) && (difficult_coeffs(4, c)))
1754-
{
1755-
sturm = true;
1756-
}
1757-
17581635
/* Solve quartic polynomial. */
17591636

17601637
if (sturm)

0 commit comments

Comments
 (0)