From 12fa5648944db2d72795de73fe00019ee4af8c2e Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Tue, 8 Apr 2025 23:06:21 +0200 Subject: [PATCH 1/4] Base: Require clamp to take arithmetic values use std::clamp internally, function should probably be removed --- src/Base/Tools.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Base/Tools.h b/src/Base/Tools.h index 182d804000..fba72f2890 100644 --- a/src/Base/Tools.h +++ b/src/Base/Tools.h @@ -113,9 +113,10 @@ inline manipulator blanks(int n) // ---------------------------------------------------------------------------- template + requires std::is_arithmetic_v inline T clamp(T num, T lower, T upper) { - return std::max(std::min(upper, num), lower); + return std::clamp(num, lower, upper); } template From 16a7bf420c5c246df2cf27cb31081aafa2483cbf Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Tue, 8 Apr 2025 23:10:10 +0200 Subject: [PATCH 2/4] Base: Make sgn branchless --- src/Base/Tools.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Base/Tools.h b/src/Base/Tools.h index fba72f2890..895f7922dc 100644 --- a/src/Base/Tools.h +++ b/src/Base/Tools.h @@ -119,14 +119,16 @@ inline T clamp(T num, T lower, T upper) return std::clamp(num, lower, upper); } -template -inline T sgn(T t) +/// Returns -1, 0 or 1 depending on if the value is negative, zero or positive +/// As this function might be used in hot paths, it uses branchless implementation +template +constexpr std::enable_if_t && std::is_signed_v, T> sgn(T val) { - if (t == 0) { - return T(0); - } + int oneIfPositive = int(0 < val); + int oneIfNegative = int(val < 0); + return T(oneIfPositive - oneIfNegative); // 0/1 - 0/1 = -1/0/1 +} - return (t > 0) ? T(1) : T(-1); } template From 1370c2101f35069a4cdb992c8adb11cbeace57b6 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Tue, 8 Apr 2025 23:12:12 +0200 Subject: [PATCH 3/4] Base: Make degrees and radians convertions safer and faster --- src/Base/Tools.h | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/Base/Tools.h b/src/Base/Tools.h index 895f7922dc..567814191c 100644 --- a/src/Base/Tools.h +++ b/src/Base/Tools.h @@ -129,18 +129,38 @@ constexpr std::enable_if_t && std::is_signed_v, T> sg return T(oneIfPositive - oneIfNegative); // 0/1 - 0/1 = -1/0/1 } +/// Convert degrees to radians, allow deduction for floating point types +template +constexpr T toRadians(T degrees) +{ + constexpr auto degToRad = std::numbers::pi_v / T(180); + return degrees * degToRad; } -template -inline T toRadians(T d) +/// Convert degrees to radians, allow **explicit-only** for any arithmetic type +template + requires(std::is_arithmetic_v && !std::floating_point) +constexpr T toRadians(std::type_identity_t degrees) { - return static_cast((d * std::numbers::pi) / 180.0); + using ResultT = std::conditional_t, double, T>; + return static_cast(toRadians(static_cast(degrees))); } -template -inline T toDegrees(T r) +/// Convert radians to degrees, allow deduction for floating point types +template +constexpr T toDegrees(T radians) { - return static_cast((r / std::numbers::pi) * 180.0); + constexpr auto radToDeg = T(180) / std::numbers::pi_v; + return radians * radToDeg; +} + +/// Convert radians to degrees, allow **explicit-only** for any arithmetic type +template + requires(std::is_arithmetic_v && !std::floating_point) +constexpr T toDegrees(std::type_identity_t radians) +{ + using ResultT = std::conditional_t, double, T>; + return static_cast(toDegrees(static_cast(radians))); } inline float fromPercent(const long value) From cc40e522de75f29b5986c53d0a24f0d2b5ef1617 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Tue, 8 Apr 2025 23:12:48 +0200 Subject: [PATCH 4/4] Base: make our fmod require floating point values --- src/Base/Tools.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Base/Tools.h b/src/Base/Tools.h index 567814191c..88982c0ae6 100644 --- a/src/Base/Tools.h +++ b/src/Base/Tools.h @@ -173,7 +173,7 @@ inline long toPercent(float value) return std::lround(100.0 * value); } -template +template inline T fmod(T numerator, T denominator) { T modulo = std::fmod(numerator, denominator);