From d72d931c9e2b090942deb48fc52c9d1021f6604d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Tue, 28 Feb 2017 20:57:19 +0100 Subject: [PATCH 1/2] Variadic template version of `rtengine::(min|max)()` This change allows for an arbitrary number of arguments to `min()` and `max()` by using recursion on variadic template functions. The disassembly of GCC 6.3 was carefully checked for regressions, but nothing was found other than the flipping of arguments (recursion is now `(((a,b),c),d)` and was `(d,(c,(a,b)))` before). I also unified the common type `_Tp` to to the even more common `T`. --- rtengine/rt_math.h | 68 ++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 41 deletions(-) diff --git a/rtengine/rt_math.h b/rtengine/rt_math.h index a7cbbf301..32db8e92f 100644 --- a/rtengine/rt_math.h +++ b/rtengine/rt_math.h @@ -27,71 +27,57 @@ constexpr float RT_PI_F_2 = RT_PI_2; constexpr float RT_INFINITY_F = std::numeric_limits::infinity(); constexpr float RT_NAN_F = std::numeric_limits::quiet_NaN(); -template -inline _Tp SQR (_Tp x) +template +inline T SQR (T x) { // return std::pow(x,2); Slower than: return x * x; } -template -inline const _Tp& min(const _Tp& a, const _Tp& b) +template +inline const T& min(const T& a, const T& b) { return std::min(a, b); } -template -inline const _Tp& max(const _Tp& a, const _Tp& b) +template +inline const T& min(const T& a, const T& b, const ARGS&... args) +{ + return min(min(a, b), args...); +} + +template +inline const T& max(const T& a, const T& b) { return std::max(a, b); } +template +inline const T& max(const T& a, const T& b, const ARGS&... args) +{ + return max(max(a, b), args...); +} -template -inline const _Tp& LIM(const _Tp& a, const _Tp& b, const _Tp& c) +template +inline const T& LIM(const T& a, const T& b, const T& c) { return std::max(b, std::min(a, c)); } -template -inline _Tp LIM01(const _Tp& a) +template +inline T LIM01(const T& a) { - return std::max(_Tp(0), std::min(a, _Tp(1))); + return std::max(T(0), std::min(a, T(1))); } -template -inline _Tp CLIP(const _Tp& a) +template +inline T CLIP(const T& a) { - return LIM(a, static_cast<_Tp>(0), static_cast<_Tp>(MAXVAL)); + return LIM(a, static_cast(0), static_cast(MAXVAL)); } - -template -inline const _Tp& min(const _Tp& a, const _Tp& b, const _Tp& c) -{ - return std::min(c, std::min(a, b)); -} - -template -inline const _Tp& max(const _Tp& a, const _Tp& b, const _Tp& c) -{ - return std::max(c, std::max(a, b)); -} - -template -inline const _Tp& min(const _Tp& a, const _Tp& b, const _Tp& c, const _Tp& d) -{ - return std::min(d, std::min(c, std::min(a, b))); -} - -template -inline const _Tp& max(const _Tp& a, const _Tp& b, const _Tp& c, const _Tp& d) -{ - return std::max(d, std::max(c, std::max(a, b))); -} - -template -inline _Tp intp(_Tp a, _Tp b, _Tp c) +template +inline T intp(T a, T b, T c) { // calculate a * b + (1 - a) * c // following is valid: From 6e7712831a5e146aa694165cc488a3b7230c669f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Wed, 1 Mar 2017 18:13:16 +0100 Subject: [PATCH 2/2] Break `min()` and `max()` parameter dependencies Also convert most functions in `rt_math.h` to `constexpr` by implementing `min()` and `max()` natively. `constexpr` indeed has a positive impact on the generated assembly. --- rtengine/rt_math.h | 53 ++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/rtengine/rt_math.h b/rtengine/rt_math.h index 32db8e92f..e1c01a94f 100644 --- a/rtengine/rt_math.h +++ b/rtengine/rt_math.h @@ -27,57 +27,68 @@ constexpr float RT_PI_F_2 = RT_PI_2; constexpr float RT_INFINITY_F = std::numeric_limits::infinity(); constexpr float RT_NAN_F = std::numeric_limits::quiet_NaN(); -template -inline T SQR (T x) +template +constexpr T SQR(T x) { -// return std::pow(x,2); Slower than: return x * x; } template -inline const T& min(const T& a, const T& b) +constexpr const T& min(const T& a) { - return std::min(a, b); + return a; +} + +template +constexpr const T& min(const T& a, const T& b) +{ + return a < b ? a : b; } template -inline const T& min(const T& a, const T& b, const ARGS&... args) +constexpr const T& min(const T& a, const T& b, const ARGS&... args) { - return min(min(a, b), args...); + return min(min(a, b), min(args...)); } template -inline const T& max(const T& a, const T& b) +constexpr const T& max(const T& a) { - return std::max(a, b); + return a; +} + +template +constexpr const T& max(const T& a, const T& b) +{ + return a < b ? b : a; } template -inline const T& max(const T& a, const T& b, const ARGS&... args) +constexpr const T& max(const T& a, const T& b, const ARGS&... args) { - return max(max(a, b), args...); + return max(max(a, b), max(args...)); } template -inline const T& LIM(const T& a, const T& b, const T& c) +constexpr const T& LIM(const T& a, const T& b, const T& c) { - return std::max(b, std::min(a, c)); + return max(b, min(a, c)); } template -inline T LIM01(const T& a) +constexpr T LIM01(const T& a) { - return std::max(T(0), std::min(a, T(1))); + return max(T(0), min(a, T(1))); } template -inline T CLIP(const T& a) +constexpr T CLIP(const T& a) { return LIM(a, static_cast(0), static_cast(MAXVAL)); } template -inline T intp(T a, T b, T c) +constexpr T intp(T a, T b, T c) { // calculate a * b + (1 - a) * c // following is valid: @@ -101,13 +112,13 @@ inline T norm2(const T& x, const T& y) template< typename T > inline T norminf(const T& x, const T& y) { - return std::max(std::abs(x), std::abs(y)); + return max(std::abs(x), std::abs(y)); } -inline int float2uint16range(float d) // clips input to [0;65535] and rounds +constexpr int float2uint16range(float d) { - d = CLIP(d); // clip to [0;65535] - return d + 0.5f; + // clips input to [0;65535] and rounds + return CLIP(d) + 0.5f; } constexpr std::uint8_t uint16ToUint8Rounded(std::uint16_t i)