Skip to content

Commit fab23d8

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 9800ada commit fab23d8

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
@@ -399,15 +399,22 @@ constexpr int CX_STRCMP(char const* lhs, char const* rhs)
399399
/// Where @ref PRECISE_FLOAT a C++11 standard floating point type this should be
400400
/// the default fabs. When using, for example, __float128 with GNU g++ in a supported 64 bit
401401
/// environment the value would defined to be __builtin_fabsq - as that function is a built-in
402-
/// for 64 bit compiles. It might be set to fabsq if using GNU g++'s quadmath library.
403-
///
404-
/// @note
405-
/// At present PRECISE_FABS, like @ref PRECISE_FLOAT, applies only within polysolve().
402+
/// for 64 bit compiles. It would be set to fabsq if using GNU g++'s quadmath library.
406403
///
407404
#ifndef PRECISE_FABS
408405
#define PRECISE_FABS fabs
409406
#endif
410407

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

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

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

460495
/// @}
461496
///

0 commit comments

Comments
 (0)