114
114
#define POV_CPP11_SUPPORTED (__cplusplus >= 201103L )
115
115
#endif
116
116
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
-
155
117
// / @}
156
118
// /
157
119
// ******************************************************************************
@@ -358,9 +320,72 @@ constexpr int CX_STRCMP(char const* lhs, char const* rhs)
358
320
#ifndef SNGL
359
321
#define SNGL float
360
322
#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
+ }
361
386
362
387
// / @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 .
364
389
// /
365
390
// / Normally PRECISE_FLOAT will be set to @ref DBL. However, 'long double' is a
366
391
// / 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)
371
396
// / data types. Recent GNU g++ compilers, for example, offer the __float128
372
397
// / data type which coorresponds to the IEEE 754-2008 binary128 type.
373
398
// /
399
+ // / The following functions support PRECISE_FLOAT:
400
+ // / * polysolve(). Known to users as sturm.
401
+ // / * solve_quadratic()
402
+ // /
374
403
// / @note
375
404
// / The setting is used to set internal 'constextr int PRECISE_DIG' and
376
405
// / 'constexpr DBL PRECISE_EPSILON' typed values.
@@ -379,14 +408,10 @@ constexpr int CX_STRCMP(char const* lhs, char const* rhs)
379
408
// / If @ref PRECISE_FLOAT is set to 'float', 'double' or 'long double', the C++11 standard
380
409
// / itself defines via cfloat include the macros: FLT_DIG, DBL_DIG, LDBL_DIG, FLT_EPSILON,
381
410
// / 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.
387
412
// /
388
413
// / @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
390
415
// / respect to the running computer's data bus size will run substantially slower.
391
416
// /
392
417
#ifndef PRECISE_FLOAT
@@ -410,6 +435,9 @@ constexpr int CX_STRCMP(char const* lhs, char const* rhs)
410
435
// /
411
436
// / Where @ref PRECISE_FLOAT a C++11 standard floating point type this should be
412
437
// / 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'.
413
441
// /
414
442
#ifndef PRECISE_SQRT
415
443
#define PRECISE_SQRT sqrt
@@ -435,8 +463,17 @@ constexpr int CX_STRCMP(char const* lhs, char const* rhs)
435
463
#define PRECISE_EPSLN 1.92592994438724e-34
436
464
#endif
437
465
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.
440
477
// /
441
478
// / Set to C+11 standard value where defined and to @ref PRECISE_DIGITS otherwise.
442
479
// /
@@ -451,25 +488,48 @@ constexpr int PRECISE_DIG = PRECISE_FLT ?
451
488
: DBL_DIG
452
489
: FLT_DIG;
453
490
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.
456
493
// /
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.
458
495
// /
459
496
// / @note
460
497
// / Using 2.0 multiplier due maths calculating coefficients for higher order polynomials
461
498
// / introducing more than single bit/step error in practice.
462
499
// /
463
-
464
500
constexpr DBL PRECISE_EPSILON = PRECISE_FLT ?
465
501
PRECISE_DBL ?
466
502
PRECISE_LDBL ? PRECISE_EPSLN*2.0
467
503
: LDBL_EPSILON*2.0
468
504
: DBL_EPSILON*2.0
469
505
: FLT_EPSILON*2.0 ;
470
506
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.
473
533
// /
474
534
// / Set to C+11 standard value*2.0 where defined and to @ref PRECISE_EPSLN*2.0 otherwise.
475
535
// /
@@ -481,17 +541,25 @@ constexpr DBL PRECISE_EPSILON = PRECISE_FLT ?
481
541
// / Using 2.0 multiplier due maths calculating coefficients for higher order polynomials
482
542
// / introducing more than single bit/step error in practice.
483
543
// /
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
544
constexpr DBL POV_DBL_EPSILON = POV_DBL_IS_FLT ?
489
545
POV_DBL_IS_DBL ?
490
546
POV_DBL_IS_LDBL ? PRECISE_EPSLN*2.0
491
547
: LDBL_EPSILON*2.0
492
548
: DBL_EPSILON*2.0
493
549
: FLT_EPSILON*2.0 ;
494
550
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
+
495
563
// / @}
496
564
// /
497
565
// ******************************************************************************
0 commit comments