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