From ec5f308bd3b69183359e6a16a151acca4fa69f46 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Fri, 6 Mar 2020 00:16:15 +0100 Subject: [PATCH] Clean up abs/fabs discrepancies here and there. --- include/lol/image/color.h | 22 ++++++++++++++++------ include/lol/math/private/matrix.h | 7 +++++-- include/lol/math/vector.h | 17 +++++++++++++++-- include/lol/types/half.h | 2 +- include/lol/types/private/real.ipp | 5 ----- include/lol/types/real.h | 1 - legacy/lol/math/functions.h | 8 ++++---- legacy/lol/math/geometry.h | 6 +++++- legacy/lol/math/noise/simplex.h | 23 ++++++++++++++--------- 9 files changed, 60 insertions(+), 31 deletions(-) diff --git a/include/lol/image/color.h b/include/lol/image/color.h index 54d52486..30d0691b 100644 --- a/include/lol/image/color.h +++ b/include/lol/image/color.h @@ -22,6 +22,9 @@ #include // vec_t #include // mat_t +#include // std::fabs +#include // std::min + namespace lol { @@ -125,9 +128,10 @@ public: */ static vec3_t hsv_to_rgb(vec3_t src) { - vec3_t tmp = vec3_t(-1.f + abs(6.f * src.x - 3.f), - 2.f - abs(6.f * src.x - 2.f), - 2.f - abs(6.f * src.x - 4.f)); + using std::fabs; + vec3_t tmp = vec3_t(-1.f + fabs(6.f * src.x - 3.f), + 2.f - fabs(6.f * src.x - 2.f), + 2.f - fabs(6.f * src.x - 4.f)); return src.z * mix(vec3_t(1.f), clamp(tmp, 0.f, 1.f), src.y); } @@ -141,6 +145,8 @@ public: */ static vec3_t rgb_to_hsv(vec3_t src) { + using std::fabs, std::min; + float K = 0.f; if (src.g < src.b) @@ -152,7 +158,7 @@ public: float chroma = src.r - min(src.g, src.b); /* XXX: we use min() here because numerical stability is not * guaranteed with -ffast-math, I’ve seen it fail on i386. */ - return vec3_t(min(abs(K + (src.g - src.b) / (6.f * chroma)), 1.f), + return vec3_t(min(fabs(K + (src.g - src.b) / (6.f * chroma)), 1.f), chroma / (src.r + 1e-20f), src.r); } @@ -167,6 +173,8 @@ public: */ static vec3_t rgb_to_hsl(vec3_t src) { + using std::fabs, std::min; + float K = 0.f; if (src.g < src.b) @@ -179,7 +187,7 @@ public: float luma = src.r + min(src.g, src.b); /* XXX: we use min() here because numerical stability is not * guaranteed with -ffast-math, I’ve seen it fail on i386. */ - float h = min(abs(K + (src.g - src.b) / (6.f * chroma)), 1.f); + float h = min(fabs(K + (src.g - src.b) / (6.f * chroma)), 1.f); float s = clamp(chroma / (min(luma, 2.f - luma)), 0.f, 1.f); return vec3_t(h, s, 0.5f * luma); } @@ -194,6 +202,8 @@ public: */ static vec3_t hsv_to_hsl(vec3_t src) { + using std::min; + float tmp = (2 - src.y) * src.z; return vec3_t(src.x, src.y * src.z / (min(tmp, 2.f - tmp) + 1e-20f), @@ -210,7 +220,7 @@ public: */ static vec3_t hsl_to_hsv(vec3_t src) { - float tmp = src.y * (0.5f - abs(0.5f - src.z)); + float tmp = src.y * (0.5f - fabs(0.5f - src.z)); return vec3_t(src.x, 2.f * tmp / (src.z + tmp + 1e-20f), src.z + tmp); } diff --git a/include/lol/math/private/matrix.h b/include/lol/math/private/matrix.h index ca0b9bfa..632a700b 100644 --- a/include/lol/math/private/matrix.h +++ b/include/lol/math/private/matrix.h @@ -17,11 +17,12 @@ // —————————————————— // -#include - #include "ops.h" #include +#include // std::ostream +#include // std::fabs + #if _WIN32 # pragma push_macro("near") # pragma push_macro("far") @@ -402,6 +403,8 @@ T cofactor(mat_t const &m, int i, int j) template [[nodiscard]] std::tuple, vec_t, int> lu_decomposition(mat_t const &m) { + using std::fabs; + mat_t lu = m; vec_t perm; int sign = 1; diff --git a/include/lol/math/vector.h b/include/lol/math/vector.h index 149510ba..c54d8923 100644 --- a/include/lol/math/vector.h +++ b/include/lol/math/vector.h @@ -20,6 +20,7 @@ #include #include // std::ostream #include +#include // std::min, std::max #include // std::fabs, std::cos… // FIXME: get rid of this, too @@ -1004,6 +1005,7 @@ operator *(T const &val, vec_t const &a) inline vec_t fun(vec_t const &a, \ vec_t const &b) \ { \ + using std::fun; \ vec_t ret; \ for (int i = 0; i < N; ++i) \ ret[i] = fun(a[i], b[i]); \ @@ -1013,6 +1015,7 @@ operator *(T const &val, vec_t const &a) template \ inline vec_t fun(vec_t const &a, T const &b) \ { \ + using std::fun; \ vec_t ret; \ for (int i = 0; i < N; ++i) \ ret[i] = fun(a[i], b); \ @@ -1022,6 +1025,7 @@ operator *(T const &val, vec_t const &a) template \ inline vec_t fun(T const &a, vec_t const &b) \ { \ + using std::fun; \ vec_t ret; \ for (int i = 0; i < N; ++i) \ ret[i] = fun(a, b[i]); \ @@ -1165,15 +1169,24 @@ static inline vec_t normalize(vec_t const &a) return norm ? a / norm : vec_t(T(0)); } +// We define fabs() because that’s the C++ std library uses for +// floating-point numbers, and abs() because GLSL does. template -static inline vec_t abs(vec_t const &a) +static inline vec_t fabs(vec_t const &a) { + using std::fabs; vec_t ret; for (int i = 0; i < N; ++i) - ret[i] = abs(a[i]); + ret[i] = fabs(a[i]); return ret; } +template +static inline vec_t abs(vec_t const &a) +{ + return fabs(a); +} + template static inline vec_t degrees(vec_t const &a) { diff --git a/include/lol/types/half.h b/include/lol/types/half.h index 1ca1dc59..27165bdf 100644 --- a/include/lol/types/half.h +++ b/include/lol/types/half.h @@ -243,7 +243,7 @@ static inline float fmod(half a, half b) static inline float fract(half a) { return fract((float)a); } static inline float degrees(half a) { return degrees((float)a); } static inline float radians(half a) { return radians((float)a); } -static inline half abs(half a) { return half::frombits(a.bits() & 0x7fffu); } +static inline half fabs(half a) { return half::frombits(a.bits() & 0x7fffu); } static inline half clamp(half x, half a, half b) { diff --git a/include/lol/types/private/real.ipp b/include/lol/types/private/real.ipp index 5ea862ee..26f3f1e9 100644 --- a/include/lol/types/private/real.ipp +++ b/include/lol/types/private/real.ipp @@ -970,11 +970,6 @@ template real_t fabs(real_t const &x) return ret; } -template real_t abs(real_t const &x) -{ - return fabs(x); -} - template real_t fract(real_t const &x) { return x - floor(x); diff --git a/include/lol/types/real.h b/include/lol/types/real.h index c8ff1f39..e65f9c8b 100644 --- a/include/lol/types/real.h +++ b/include/lol/types/real.h @@ -161,7 +161,6 @@ public: real_t const &y); // Functions inherited from GLSL - template friend real_t abs(real_t const &x); template friend real_t fract(real_t const &x); template friend real_t degrees(real_t const &x); template friend real_t radians(real_t const &x); diff --git a/legacy/lol/math/functions.h b/legacy/lol/math/functions.h index 60ccd895..3f0240f0 100644 --- a/legacy/lol/math/functions.h +++ b/legacy/lol/math/functions.h @@ -149,12 +149,12 @@ template return mix(a, b, x); } -// C++ doesn't define abs() or fmod() for all types; we add these for +// C++ doesn't define fabs() or fmod() for all types; we add these for // convenience to avoid adding complexity to vector.h. template -[[nodiscard]] static inline T2 abs(T x) { return std::abs(x); } +[[nodiscard]] static inline T2 fabs(T x) { return std::abs(x); } template -[[nodiscard]] static inline T2 abs(T x) { return x; } +[[nodiscard]] static inline T2 fabs(T x) { return x; } template [[nodiscard]] static inline T2 fmod(T x, T y) { return x % y; } @@ -175,7 +175,7 @@ template template [[nodiscard]] static inline T2 saturate(T x) { return clamp(x, (T)0, (T)1); } template -[[nodiscard]] static inline T2 gcd(T x, T y) { return y == (T)0 ? lol::abs(x) : lol::gcd(y, lol::fmod(x, y)); } +[[nodiscard]] static inline T2 gcd(T x, T y) { return y == (T)0 ? lol::fabs(x) : lol::gcd(y, lol::fmod(x, y)); } template [[nodiscard]] static inline T2 sign(T x) { return (T)(((T)0 < x) - (x < (T)0)); } diff --git a/legacy/lol/math/geometry.h b/legacy/lol/math/geometry.h index 94641443..b0475274 100644 --- a/legacy/lol/math/geometry.h +++ b/legacy/lol/math/geometry.h @@ -25,7 +25,7 @@ #include #include -#include +#include // std::fabs #include #include @@ -213,6 +213,8 @@ public: //-- static inline bool TestAABBVsAABB(box2 const &b1, box2 const &b2) { + using std::fabs; + vec2 c = b1.center() - b2.center(); vec2 e1 = 0.5f * b1.extent(); vec2 e2 = 0.5f * b2.extent(); @@ -227,6 +229,8 @@ static inline bool TestAABBVsPoint(box2 const &b1, vec2 const &p) static inline bool TestAABBVsAABB(box3 const &b1, box3 const &b2) { + using std::fabs; + vec3 c = b1.center() - b2.center(); vec3 e1 = 0.5f * b1.extent(); vec3 e2 = 0.5f * b2.extent(); diff --git a/legacy/lol/math/noise/simplex.h b/legacy/lol/math/noise/simplex.h index b234b9c7..264dfa02 100644 --- a/legacy/lol/math/noise/simplex.h +++ b/legacy/lol/math/noise/simplex.h @@ -19,6 +19,7 @@ #include // mat_t #include // std::vector +#include // std::fabs #include // std::min, std::max namespace lol @@ -88,6 +89,8 @@ protected: inline float get_noise(vec_t origin, vec_t const & pos) const { + using std::min; + /* For a given position [0…1]^N inside a regular N-hypercube, find * the N-simplex which contains that position, and return a path * along the hypercube edges from (0,0,…,0) to (1,1,…,1) which @@ -141,9 +144,9 @@ protected: // -4.f: centre (-2.f), // -3.f: r=0.38 sphere of influence (contribution = 1/4) // -2.f: r=0.52 sphere of influence (contribution = 1/24) - if (d > 0.99f) special = std::min(special, -4.f); - if (d > 0.7f && d < 0.72f) special = std::min(special, -3.f); - if (d > 0.44f && d < 0.46f) special = std::min(special, -2.f); + if (d > 0.99f) special = min(special, -4.f); + if (d > 0.7f && d < 0.72f) special = min(special, -3.f); + if (d > 0.44f && d < 0.46f) special = min(special, -2.f); #endif if (d > 0) @@ -230,6 +233,8 @@ protected: private: void debugprint() { + using std::min, std::max, std::fabs; + // Print some debug information printf("Simplex Noise of Dimension %d\n", N); @@ -281,8 +286,8 @@ private: continue; float l = length(vertices[i] - vertices[j]); - minlength = std::min(minlength, l); - maxlength = std::max(maxlength, l); + minlength = min(minlength, l); + maxlength = max(maxlength, l); } printf(" · edge lengths between %f and %f\n", minlength, maxlength); @@ -306,7 +311,7 @@ private: p += k * vertices[j]; sum += k; } - mindist = std::min(mindist, distance(vertices[i], p / sum)); + mindist = min(mindist, distance(vertices[i], p / sum)); } printf(" · approx. dist. to opposite hyperplane: %f\n", mindist); #endif @@ -388,11 +393,11 @@ private: t = best_t2; } } - minval = std::min(t, minval); - maxval = std::max(t, maxval); + minval = min(t, minval); + maxval = max(t, maxval); } printf(" - noise value min/max: %f %f\n", minval, maxval); - float newscale = 1.f / std::max(-minval, maxval); + float newscale = 1.f / max(-minval, maxval); if (newscale < 1.f) printf(" - could replace scale %f with %f\n", get_scale(), newscale * get_scale());