Skip to content

Commit af78a9b

Browse files
committed
New zero coefficient stripping and solve_quadratic implementation.
General effort to implement better 'effective zero' coefficient handling. Created new POV_DBL_EPSILON macro value which is 2x the C++ standards <float type>_EPSILON value and updated PRECISE_EPSILON to be 2x the single bit epsilon as well. Zero filtering in polysolve now looks at all polynomial coefficients and either sets 'effective zeros' to exactly 0.0 or strips them if they are leading coefficients. The much more accurate near zero coefficients drove the need for a better solve_quadratic implementation included with this commit. Note it supports the PRECISE_FLOAT options like polysolve. Zero filtering in solve_quadratic, solve_cubic and solve_quartic now standardized both in implementation and use of POV_DBL_EPSILON.
1 parent 5e51b96 commit af78a9b

File tree

2 files changed

+195
-53
lines changed

2 files changed

+195
-53
lines changed

source/base/configbase.h

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -398,15 +398,22 @@ constexpr int CX_STRCMP(char const* lhs, char const* rhs)
398398
/// Where @ref PRECISE_FLOAT a C++11 standard floating point type this should be
399399
/// the default fabs. When using, for example, __float128 with GNU g++ in a supported 64 bit
400400
/// environment the value would defined to be __builtin_fabsq - as that function is a built-in
401-
/// for 64 bit compiles. It might be set to fabsq if using GNU g++'s quadmath library.
402-
///
403-
/// @note
404-
/// At present PRECISE_FABS, like @ref PRECISE_FLOAT, applies only within polysolve().
401+
/// for 64 bit compiles. It would be set to fabsq if using GNU g++'s quadmath library.
405402
///
406403
#ifndef PRECISE_FABS
407404
#define PRECISE_FABS fabs
408405
#endif
409406

407+
/// @def PRECISE_SQRT
408+
/// The floating point square root function name to use with @ref PRECISE_FLOAT.
409+
///
410+
/// Where @ref PRECISE_FLOAT a C++11 standard floating point type this should be
411+
/// the default sqrt. It would be set to sqrtq if using GNU g++'s quadmath library.
412+
///
413+
#ifndef PRECISE_SQRT
414+
#define PRECISE_SQRT sqrt
415+
#endif
416+
410417
/// @def PRECISE_DIGITS
411418
/// Base 10 digits where @ref PRECISE_FLOAT type not a C++11 floating point standard.
412419
///
@@ -444,17 +451,45 @@ constexpr int PRECISE_DIG = PRECISE_FLT ?
444451
: FLT_DIG;
445452

446453
/// @def PRECISE_EPSILON
447-
/// Internal 'constexpr DBL' value for minimum epsilon step for given @ref PRECISE_FLOAT.
454+
/// Internal 'constexpr DBL' value*2.0 for minimum epsilon step for given @ref PRECISE_FLOAT.
448455
///
449456
/// Set to C+11 standard value where defined and to @ref PRECISE_EPSLN otherwise.
450457
///
458+
/// @note
459+
/// Using 2.0 multiplier due maths calculating coefficients for higher order polynomials
460+
/// introducing more than single bit/step error in practice.
461+
///
451462

452463
constexpr DBL PRECISE_EPSILON = PRECISE_FLT ?
453464
PRECISE_DBL ?
454-
PRECISE_LDBL ? PRECISE_EPSLN
455-
: LDBL_EPSILON
456-
: DBL_EPSILON
457-
: FLT_EPSILON;
465+
PRECISE_LDBL ? PRECISE_EPSLN*2.0
466+
: LDBL_EPSILON*2.0
467+
: DBL_EPSILON*2.0
468+
: FLT_EPSILON*2.0;
469+
470+
/// @def POV_DBL_EPSILON
471+
/// Internal 'constexpr DBL' value for minimum epsilon step for given POV-Ray's @ref DBL.
472+
///
473+
/// Set to C+11 standard value*2.0 where defined and to @ref PRECISE_EPSLN*2.0 otherwise.
474+
///
475+
/// Using this value where we want a more accurate 'meaningful value not zero' tests than
476+
/// the EPSILON, SMALL_ENOUGH, etc. values which tend to be around 1e-10 which is much larger
477+
/// than, for example, the double DBL_EPSILON value of 2.2204460492503131e-16.
478+
///
479+
/// @note
480+
/// Using 2.0 multiplier due maths calculating coefficients for higher order polynomials
481+
/// introducing more than single bit/step error in practice.
482+
///
483+
constexpr int POV_DBL_IS_FLT = CX_STRCMP(CX_XSTR(DBL), "float");
484+
constexpr int POV_DBL_IS_DBL = CX_STRCMP(CX_XSTR(DBL), "double");
485+
constexpr int POV_DBL_IS_LDBL = CX_STRCMP(CX_XSTR(DBL), "long double");
486+
487+
constexpr DBL POV_DBL_EPSILON = POV_DBL_IS_FLT ?
488+
POV_DBL_IS_DBL ?
489+
POV_DBL_IS_LDBL ? PRECISE_EPSLN*2.0
490+
: LDBL_EPSILON*2.0
491+
: DBL_EPSILON*2.0
492+
: FLT_EPSILON*2.0;
458493

459494
/// @}
460495
///

0 commit comments

Comments
 (0)