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