@@ -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+ // /
9284const 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+ // /
9389const 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+ // /
9698const 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+ // /
103110const 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+ // /
109123const 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). */
112132const 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);
141158static DBL polyeval (DBL x, int n, const DBL *Coeffs);
142159static int buildsturm (int ord, polynomial *sseq);
143160static 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