|
263 | 263 | // Compiler flags -fno-signed-zeros -ffinite-math-only also cover 'f * 1.0', 'f - f', etc.
|
264 | 264 | #define PLUS_TERN0(O,A) _TERN(_ENA_1(O),,+ (A)) // OPTION ? '+ (A)' : '<nul>'
|
265 | 265 | #define MINUS_TERN0(O,A) _TERN(_ENA_1(O),,- (A)) // OPTION ? '- (A)' : '<nul>'
|
| 266 | +#define MUL_TERN1(O,A) _TERN(_ENA_1(O),,* (A)) // OPTION ? '* (A)' : '<nul>' |
| 267 | +#define DIV_TERN1(O,A) _TERN(_ENA_1(O),,/ (A)) // OPTION ? '/ (A)' : '<nul>' |
266 | 268 | #define SUM_TERN(O,B,A) ((B) PLUS_TERN0(O,A)) // ((B) (OPTION ? '+ (A)' : '<nul>'))
|
267 | 269 | #define DIFF_TERN(O,B,A) ((B) MINUS_TERN0(O,A)) // ((B) (OPTION ? '- (A)' : '<nul>'))
|
| 270 | +#define MUL_TERN(O,B,A) ((B) MUL_TERN1(O,A)) // ((B) (OPTION ? '* (A)' : '<nul>')) |
| 271 | +#define DIV_TERN(O,B,A) ((B) DIV_TERN1(O,A)) // ((B) (OPTION ? '/ (A)' : '<nul>')) |
268 | 272 |
|
269 | 273 | #define IF_ENABLED TERN_
|
270 | 274 | #define IF_DISABLED(O,A) TERN(O,,A)
|
|
434 | 438 | extern "C++" {
|
435 | 439 |
|
436 | 440 | // C++11 solution that is standards compliant. Return type is deduced automatically
|
| 441 | + template <class N> static constexpr N _MIN(const N val) { return val; } |
| 442 | + template <class N> static constexpr N _MAX(const N val) { return val; } |
437 | 443 | template <class L, class R> static constexpr auto _MIN(const L lhs, const R rhs) -> decltype(lhs + rhs) {
|
438 | 444 | return lhs < rhs ? lhs : rhs;
|
439 | 445 | }
|
|
453 | 459 | FORCE_INLINE constexpr T operator|(T x, T y) { return static_cast<T>(static_cast<int>(x) | static_cast<int>(y)); } \
|
454 | 460 | FORCE_INLINE constexpr T operator^(T x, T y) { return static_cast<T>(static_cast<int>(x) ^ static_cast<int>(y)); } \
|
455 | 461 | FORCE_INLINE constexpr T operator~(T x) { return static_cast<T>(~static_cast<int>(x)); } \
|
456 |
| - FORCE_INLINE T & operator&=(T &x, T y) { return x &= y; } \ |
457 |
| - FORCE_INLINE T & operator|=(T &x, T y) { return x |= y; } \ |
458 |
| - FORCE_INLINE T & operator^=(T &x, T y) { return x ^= y; } |
| 462 | + FORCE_INLINE T & operator&=(T &x, T y) { x = x & y; return x; } \ |
| 463 | + FORCE_INLINE T & operator|=(T &x, T y) { x = x | y; return x; } \ |
| 464 | + FORCE_INLINE T & operator^=(T &x, T y) { x = x ^ y; return x; } |
459 | 465 |
|
460 | 466 | // C++11 solution that is standard compliant. <type_traits> is not available on all platform
|
461 | 467 | namespace Private {
|
|
467 | 473 |
|
468 | 474 | template <typename T, typename ... Args> struct first_type_of { typedef T type; };
|
469 | 475 | template <typename T> struct first_type_of<T> { typedef T type; };
|
| 476 | + |
| 477 | + // remove const/volatile type qualifiers |
| 478 | + template<typename T> struct remove_const { typedef T type; }; |
| 479 | + template<typename T> struct remove_const<T const> { typedef T type; }; |
| 480 | + |
| 481 | + template<typename T> struct remove_volatile { typedef T type; }; |
| 482 | + template<typename T> struct remove_volatile<T volatile> { typedef T type; }; |
| 483 | + |
| 484 | + template<typename T> struct remove_cv { typedef typename remove_const<typename remove_volatile<T>::type>::type type; }; |
| 485 | + |
| 486 | + // test if type is integral |
| 487 | + template<typename> struct _is_integral { enum { value = false }; }; |
| 488 | + template<> struct _is_integral<unsigned char> { enum { value = true }; }; |
| 489 | + template<> struct _is_integral<unsigned short> { enum { value = true }; }; |
| 490 | + template<> struct _is_integral<unsigned int> { enum { value = true }; }; |
| 491 | + template<> struct _is_integral<unsigned long> { enum { value = true }; }; |
| 492 | + template<> struct _is_integral<unsigned long long> { enum { value = true }; }; |
| 493 | + template<> struct _is_integral<char> { enum { value = true }; }; |
| 494 | + template<> struct _is_integral<short> { enum { value = true }; }; |
| 495 | + template<> struct _is_integral<int> { enum { value = true }; }; |
| 496 | + template<> struct _is_integral<long> { enum { value = true }; }; |
| 497 | + template<> struct _is_integral<long long> { enum { value = true }; }; |
| 498 | + template<typename T> struct is_integral : public _is_integral<typename remove_cv<T>::type> {}; |
| 499 | + } |
| 500 | + |
| 501 | + // enum type check and regression to its underlying integral. |
| 502 | + namespace Private { |
| 503 | + template<typename T> struct is_enum { enum { value = __is_enum(T) }; }; |
| 504 | + |
| 505 | + template<typename T, bool = is_enum<T>::value> struct _underlying_type { using type = __underlying_type(T); }; |
| 506 | + template<typename T> struct _underlying_type<T, false> { }; |
| 507 | + |
| 508 | + template<typename T> struct underlying_type : public _underlying_type<T> { }; |
470 | 509 | }
|
471 | 510 |
|
472 | 511 | // C++11 solution using SFINAE to detect the existence of a member in a class at compile time.
|
|
726 | 765 | #define RREPEAT2_S(S,N,OP,V...) EVAL1024(_RREPEAT2(S,SUB##S(N),OP,V))
|
727 | 766 | #define RREPEAT2(N,OP,V...) RREPEAT2_S(0,N,OP,V)
|
728 | 767 |
|
| 768 | +// Emit a list of N OP(I) items with ascending counter. |
| 769 | +#define _REPLIST(_RPT_I,_RPT_N,_RPT_OP) \ |
| 770 | + _RPT_OP(_RPT_I) \ |
| 771 | + IF_ELSE(SUB1(_RPT_N)) \ |
| 772 | + ( , DEFER2(__REPLIST)()(ADD1(_RPT_I),SUB1(_RPT_N),_RPT_OP) ) \ |
| 773 | + ( /* Do nothing */ ) |
| 774 | +#define __REPLIST() _REPLIST |
| 775 | + |
| 776 | +// Repeat a macro, comma-separated, passing S...N-1. |
| 777 | +#define REPLIST_S(S,N,OP) EVAL(_REPLIST(S,SUB##S(N),OP)) |
| 778 | +#define REPLIST(N,OP) REPLIST_S(0,N,OP) |
| 779 | +#define REPLIST_1(N,OP) REPLIST_S(1,INCREMENT(N),OP) |
| 780 | + |
729 | 781 | // Call OP(A) with each item as an argument
|
730 | 782 | #define _MAP(_MAP_OP,A,V...) \
|
731 | 783 | _MAP_OP(A) \
|
|
0 commit comments