114114 #define POV_CPP11_SUPPORTED (__cplusplus >= 201103L )
115115#endif
116116
117- // / @}
118- // /
119- // ******************************************************************************
120- // /
121- // / @name C++11 Constant Expression Support
122- // /
123- // / The following macros and constant expression (constexpr) functions enable the set up of
124- // / compile time typed contants.
125- // /
126- // / References in addtion to the C++11 standard itself:
127- // / * [sac10-constexpr.pdf](http://www.stroustrup.com/sac10-constexpr.pdf)
128- // / * [n2235.pdf](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf)
129- // /
130- // / @{
131-
132- // / @def CX_XSTR(A)
133- // / Macro converts preprocessor macro string to a contant string.
134- // /
135- // / @note
136- // / Itself using an macro internale macro called CX_STR(A).
137- // /
138- #define CX_XSTR (A ) CX_STR(A)
139- #define CX_STR (A ) #A
140-
141- // / @def CX_STRCMP(A,B)
142- // / constexpr function comparing two strings in compile time constant fashion.
143- // /
144- // / @param[in] A First string.
145- // / @param[in] B Second string.
146- // / @return Integer 0 on matching strings and non zero integer otherwise.
147- // /
148- constexpr int CX_STRCMP (char const * lhs, char const * rhs)
149- {
150- return ((' \0 ' == lhs[0 ]) && (' \0 ' == rhs[0 ])) ? 0
151- : (lhs[0 ] != rhs[0 ]) ? (lhs[0 ] - rhs[0 ])
152- : CX_STRCMP ( lhs+1 , rhs+1 );
153- }
154-
155117// / @}
156118// /
157119// ******************************************************************************
@@ -358,9 +320,72 @@ constexpr int CX_STRCMP(char const* lhs, char const* rhs)
358320#ifndef SNGL
359321 #define SNGL float
360322#endif
323+ // / @}
324+ // /
325+ // ******************************************************************************
326+ // /
327+ // / @name C++11 Constant Expression Support
328+ // /
329+ // / The following macros and constant expression (constexpr) functions enable the set up of
330+ // / compile time typed contants.
331+ // /
332+ // / References in addtion to the C++11 standard itself:
333+ // / * [sac10-constexpr.pdf](http://www.stroustrup.com/sac10-constexpr.pdf)
334+ // / * [n2235.pdf](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf)
335+ // / * [github constexpr function library](https://github.com/elbeno/constexpr)
336+ // /
337+ // / @attention
338+ // / Do NOT use any CX_ prefixed function at runtime. Use them carefully at
339+ // / compile time. Currently, no error checking is done. Aim is to move burden for
340+ // / complex macro definitions from build systems like autotools, cmake, etc into C++
341+ // / itself where the C++11 standard supports it. If found to fly well in
342+ // / practice, will look to make any constant expression functions more robust.
343+ // /
344+ // / @{
345+
346+ // / @def CX_STR(A)
347+ // / Macro used by @ref CX_XSTR(A) in conversion of definition to a string value.
348+ // /
349+ // / @def CX_XSTR(A)
350+ // / Macro converts preprocessor macro string to a contant string.
351+ // /
352+ // / @note
353+ // / Itself using an macro internal macro called CX_STR(A).
354+ // /
355+ #define CX_XSTR (A ) CX_STR(A)
356+ #define CX_STR (A ) #A
357+
358+ static constexpr int CX_STRCMP (char const * lhs, char const * rhs); // Doxygen requires.
359+ // / constexpr function comparing two strings in compile time constant fashion.
360+ // /
361+ // / @param[in] lhs First string.
362+ // / @param[in] rhs Second string.
363+ // / @return Integer 0 on matching strings and non zero integer otherwise.
364+ // /
365+ static constexpr int CX_STRCMP (char const * lhs, char const * rhs)
366+ {
367+ return ((' \0 ' == lhs[0 ]) && (' \0 ' == rhs[0 ])) ? 0
368+ : (lhs[0 ] != rhs[0 ]) ? (lhs[0 ] - rhs[0 ])
369+ : CX_STRCMP ( lhs+1 , rhs+1 );
370+ }
371+
372+ static constexpr POV_INT64 CX_IPOW (POV_INT64 base, int exp, POV_INT64 result = 1 ); // Doxygen requires.
373+ // / constexpr function implementing integer pow() in compile time constant fashion.
374+ // /
375+ // / @note
376+ // / Optional third argument part of implementation. Call as follows: CX_IPOW(10,3).
377+ // /
378+ // / @param[in] base
379+ // / @param[in] exp
380+ // / @param[in] result (do NOT specify on actual first call)
381+ // / @return Integer base raised to exponent.
382+ // /
383+ static constexpr POV_INT64 CX_IPOW (POV_INT64 base, int exp, POV_INT64 result) {
384+ return exp < 1 ? result : CX_IPOW (base*base, exp/2 , (exp % 2 ) ? result*base : result);
385+ }
361386
362387// / @def PRECISE_FLOAT
363- // / The foating-point data type to use within the polysolve() solver.
388+ // / Optionally more accurate foating-point data type to use within root solver related code .
364389// /
365390// / Normally PRECISE_FLOAT will be set to @ref DBL. However, 'long double' is a
366391// / precision guaranteed by the C++ standard to exist and to be at least of
@@ -371,6 +396,10 @@ constexpr int CX_STRCMP(char const* lhs, char const* rhs)
371396// / data types. Recent GNU g++ compilers, for example, offer the __float128
372397// / data type which coorresponds to the IEEE 754-2008 binary128 type.
373398// /
399+ // / The following functions support PRECISE_FLOAT:
400+ // / * polysolve(). Known to users as sturm.
401+ // / * solve_quadratic()
402+ // /
374403// / @note
375404// / The setting is used to set internal 'constextr int PRECISE_DIG' and
376405// / 'constexpr DBL PRECISE_EPSILON' typed values.
@@ -379,14 +408,10 @@ constexpr int CX_STRCMP(char const* lhs, char const* rhs)
379408// / If @ref PRECISE_FLOAT is set to 'float', 'double' or 'long double', the C++11 standard
380409// / itself defines via cfloat include the macros: FLT_DIG, DBL_DIG, LDBL_DIG, FLT_EPSILON,
381410// / DBL_EPSILON, LDBL_EPSILON. These macro values are used to set PRECISE_DIG and
382- // / PRECISE_EPSILON polysolve() values via the C++ constexpr mechanism.
383- // /
384- // / @note
385- // / Users access the polysolve() solver via the 'sturm' keyword though it's always
386- // / used for polynomials of order 5 or more.
411+ // / PRECISE_EPSILON values via the C++ constexpr mechanism.
387412// /
388413// / @attention
389- // / polysolve() math with data types not run in hardware or with awkward bit sizes with
414+ // / Math with data types not run in hardware or with awkward bit sizes with
390415// / respect to the running computer's data bus size will run substantially slower.
391416// /
392417#ifndef PRECISE_FLOAT
@@ -410,6 +435,9 @@ constexpr int CX_STRCMP(char const* lhs, char const* rhs)
410435// /
411436// / Where @ref PRECISE_FLOAT a C++11 standard floating point type this should be
412437// / the default sqrt. It would be set to sqrtq if using GNU g++'s quadmath library.
438+ // / If using the inbuilt g++ __float128 capability, set to cast to and from (long double)
439+ // / to avoid the use of quadmath - though this of course effectively limits sqrt()
440+ // / accuracy to 'long double'.
413441// /
414442#ifndef PRECISE_SQRT
415443 #define PRECISE_SQRT sqrt
@@ -435,8 +463,17 @@ constexpr int CX_STRCMP(char const* lhs, char const* rhs)
435463 #define PRECISE_EPSLN 1.92592994438724e-34
436464#endif
437465
438- // / @def PRECISE_DIG
439- // / Internal 'constexpr int' value for maximum decimal digits for given @ref PRECISE_FLOAT.
466+ // / @var PRECISE_FLT
467+ // / A 'constexpr int' 0 when @ref PRECISE_FLOAT resolves to float type or !=0 otherwise.
468+ // /
469+ // / @var PRECISE_DBL
470+ // / A 'constexpr int' 0 when @ref PRECISE_FLOAT resolves to double type or !=0 otherwise.
471+ // /
472+ // / @var PRECISE_LDBL
473+ // / A 'constexpr int' 0 when @ref PRECISE_FLOAT resolves to long double type or !=0 otherwise.
474+ // /
475+ // / @var PRECISE_DIG
476+ // / A 'constexpr int' maximum decimal digits given @ref PRECISE_FLOAT.
440477// /
441478// / Set to C+11 standard value where defined and to @ref PRECISE_DIGITS otherwise.
442479// /
@@ -451,25 +488,48 @@ constexpr int PRECISE_DIG = PRECISE_FLT ?
451488 : DBL_DIG
452489 : FLT_DIG;
453490
454- // / @def PRECISE_EPSILON
455- // / Internal 'constexpr DBL' value*2.0 for minimum epsilon step for given @ref PRECISE_FLOAT.
491+ // / @var PRECISE_EPSILON
492+ // / A 'constexpr DBL' value for minimum epsilon step given @ref PRECISE_FLOAT.
456493// /
457- // / Set to C+11 standard value where defined and to @ref PRECISE_EPSLN otherwise.
494+ // / Set to C+11 standard value*2.0 where defined and to @ref PRECISE_EPSLN*2.0 otherwise.
458495// /
459496// / @note
460497// / Using 2.0 multiplier due maths calculating coefficients for higher order polynomials
461498// / introducing more than single bit/step error in practice.
462499// /
463-
464500constexpr DBL PRECISE_EPSILON = PRECISE_FLT ?
465501 PRECISE_DBL ?
466502 PRECISE_LDBL ? PRECISE_EPSLN*2.0
467503 : LDBL_EPSILON*2.0
468504 : DBL_EPSILON*2.0
469505 : FLT_EPSILON*2.0 ;
470506
471- // / @def POV_DBL_EPSILON
472- // / Internal 'constexpr DBL' value for minimum epsilon step for given POV-Ray's @ref DBL.
507+ // / @var POV_DBL_IS_FLT
508+ // / A 'constexpr int' 0 when @ref DBL resolves to float type or !=0 otherwise.
509+ // /
510+ // / @var POV_DBL_IS_DBL
511+ // / A 'constexpr int' 0 when @ref DBL resolves to double type or !=0 otherwise.
512+ // /
513+ // / @var POV_DBL_IS_LDBL
514+ // / A 'constexpr int' 0 when @ref DBL resolves to long double type or !=0 otherwise.
515+ // /
516+ // / @var POV_DBL_DIG
517+ // / A 'constexpr int' value for maximum decimal digits for given @ref DBL.
518+ // /
519+ // / Set to C+11 standard value where defined and to @ref PRECISE_DIGITS otherwise.
520+ // /
521+ constexpr int POV_DBL_IS_FLT = CX_STRCMP(CX_XSTR(DBL), " float" );
522+ constexpr int POV_DBL_IS_DBL = CX_STRCMP(CX_XSTR(DBL), " double" );
523+ constexpr int POV_DBL_IS_LDBL = CX_STRCMP(CX_XSTR(DBL), " long double" );
524+ constexpr int POV_DBL_DIG = POV_DBL_IS_FLT ?
525+ POV_DBL_IS_DBL ?
526+ POV_DBL_IS_LDBL ? PRECISE_DIGITS
527+ : LDBL_DIG
528+ : DBL_DIG
529+ : FLT_DIG;
530+
531+ // / @var POV_DBL_EPSILON
532+ // / A 'constexpr DBL' value for minimum epsilon step for given POV-Ray's @ref DBL.
473533// /
474534// / Set to C+11 standard value*2.0 where defined and to @ref PRECISE_EPSLN*2.0 otherwise.
475535// /
@@ -481,17 +541,25 @@ constexpr DBL PRECISE_EPSILON = PRECISE_FLT ?
481541// / Using 2.0 multiplier due maths calculating coefficients for higher order polynomials
482542// / introducing more than single bit/step error in practice.
483543// /
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-
488544constexpr DBL POV_DBL_EPSILON = POV_DBL_IS_FLT ?
489545 POV_DBL_IS_DBL ?
490546 POV_DBL_IS_LDBL ? PRECISE_EPSLN*2.0
491547 : LDBL_EPSILON*2.0
492548 : DBL_EPSILON*2.0
493549 : FLT_EPSILON*2.0 ;
494550
551+
552+ // / @var MIN_ISECT_DEPTH_RETURNED
553+ // / A 'constexpr DBL' value below which roots from primitive objects are not returned.
554+ // /
555+ // / The value will track @ref DBL float type and is very roughly the square root
556+ // / of the determined POV_DBL_EPSILON. The plan is to migrate base shapes to
557+ // / this single value instead of the many different thresholds used today.
558+ // / Aiming for both more accuracy and something which automatically adjust to
559+ // / the DBL type used.
560+ // /
561+ constexpr DBL MIN_ISECT_DEPTH_RETURNED = POV_DBL_EPSILON*(DBL)CX_IPOW(10 ,POV_DBL_DIG/2 +1 );
562+
495563// / @}
496564// /
497565// ******************************************************************************
0 commit comments