@@ -22,6 +22,9 @@ | |||||
#include <lol/math/vector.h> // vec_t | #include <lol/math/vector.h> // vec_t | ||||
#include <lol/math/transform.h> // mat_t | #include <lol/math/transform.h> // mat_t | ||||
#include <cmath> // std::fabs | |||||
#include <algorithm> // std::min | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -125,9 +128,10 @@ public: | |||||
*/ | */ | ||||
static vec3_t hsv_to_rgb(vec3_t src) | 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); | 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) | static vec3_t rgb_to_hsv(vec3_t src) | ||||
{ | { | ||||
using std::fabs, std::min; | |||||
float K = 0.f; | float K = 0.f; | ||||
if (src.g < src.b) | if (src.g < src.b) | ||||
@@ -152,7 +158,7 @@ public: | |||||
float chroma = src.r - min(src.g, src.b); | float chroma = src.r - min(src.g, src.b); | ||||
/* XXX: we use min() here because numerical stability is not | /* XXX: we use min() here because numerical stability is not | ||||
* guaranteed with -ffast-math, I’ve seen it fail on i386. */ | * 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), | chroma / (src.r + 1e-20f), | ||||
src.r); | src.r); | ||||
} | } | ||||
@@ -167,6 +173,8 @@ public: | |||||
*/ | */ | ||||
static vec3_t rgb_to_hsl(vec3_t src) | static vec3_t rgb_to_hsl(vec3_t src) | ||||
{ | { | ||||
using std::fabs, std::min; | |||||
float K = 0.f; | float K = 0.f; | ||||
if (src.g < src.b) | if (src.g < src.b) | ||||
@@ -179,7 +187,7 @@ public: | |||||
float luma = src.r + min(src.g, src.b); | float luma = src.r + min(src.g, src.b); | ||||
/* XXX: we use min() here because numerical stability is not | /* XXX: we use min() here because numerical stability is not | ||||
* guaranteed with -ffast-math, I’ve seen it fail on i386. */ | * 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); | float s = clamp(chroma / (min(luma, 2.f - luma)), 0.f, 1.f); | ||||
return vec3_t(h, s, 0.5f * luma); | return vec3_t(h, s, 0.5f * luma); | ||||
} | } | ||||
@@ -194,6 +202,8 @@ public: | |||||
*/ | */ | ||||
static vec3_t hsv_to_hsl(vec3_t src) | static vec3_t hsv_to_hsl(vec3_t src) | ||||
{ | { | ||||
using std::min; | |||||
float tmp = (2 - src.y) * src.z; | float tmp = (2 - src.y) * src.z; | ||||
return vec3_t(src.x, | return vec3_t(src.x, | ||||
src.y * src.z / (min(tmp, 2.f - tmp) + 1e-20f), | 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) | 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); | return vec3_t(src.x, 2.f * tmp / (src.z + tmp + 1e-20f), src.z + tmp); | ||||
} | } | ||||
@@ -17,11 +17,12 @@ | |||||
// —————————————————— | // —————————————————— | ||||
// | // | ||||
#include <ostream> | |||||
#include "ops.h" | #include "ops.h" | ||||
#include <lol/math/vector.h> | #include <lol/math/vector.h> | ||||
#include <ostream> // std::ostream | |||||
#include <cmath> // std::fabs | |||||
#if _WIN32 | #if _WIN32 | ||||
# pragma push_macro("near") | # pragma push_macro("near") | ||||
# pragma push_macro("far") | # pragma push_macro("far") | ||||
@@ -402,6 +403,8 @@ T cofactor(mat_t<T, 2, 2> const &m, int i, int j) | |||||
template<typename T, int N> [[nodiscard]] | template<typename T, int N> [[nodiscard]] | ||||
std::tuple<mat_t<T, N, N>, vec_t<int, N>, int> lu_decomposition(mat_t<T, N, N> const &m) | std::tuple<mat_t<T, N, N>, vec_t<int, N>, int> lu_decomposition(mat_t<T, N, N> const &m) | ||||
{ | { | ||||
using std::fabs; | |||||
mat_t<T, N, N> lu = m; | mat_t<T, N, N> lu = m; | ||||
vec_t<int, N> perm; | vec_t<int, N> perm; | ||||
int sign = 1; | int sign = 1; | ||||
@@ -20,6 +20,7 @@ | |||||
#include <cassert> | #include <cassert> | ||||
#include <ostream> // std::ostream | #include <ostream> // std::ostream | ||||
#include <type_traits> | #include <type_traits> | ||||
#include <algorithm> // std::min, std::max | |||||
#include <cmath> // std::fabs, std::cos… | #include <cmath> // std::fabs, std::cos… | ||||
// FIXME: get rid of this, too | // FIXME: get rid of this, too | ||||
@@ -1004,6 +1005,7 @@ operator *(T const &val, vec_t<T,N,SWIZZLE> const &a) | |||||
inline vec_t<T,N> fun(vec_t<T,N,SWIZZLE1> const &a, \ | inline vec_t<T,N> fun(vec_t<T,N,SWIZZLE1> const &a, \ | ||||
vec_t<T,N,SWIZZLE2> const &b) \ | vec_t<T,N,SWIZZLE2> const &b) \ | ||||
{ \ | { \ | ||||
using std::fun; \ | |||||
vec_t<T,N> ret; \ | vec_t<T,N> ret; \ | ||||
for (int i = 0; i < N; ++i) \ | for (int i = 0; i < N; ++i) \ | ||||
ret[i] = fun(a[i], b[i]); \ | ret[i] = fun(a[i], b[i]); \ | ||||
@@ -1013,6 +1015,7 @@ operator *(T const &val, vec_t<T,N,SWIZZLE> const &a) | |||||
template<typename T, int N, int SWIZZLE> \ | template<typename T, int N, int SWIZZLE> \ | ||||
inline vec_t<T,N> fun(vec_t<T,N,SWIZZLE> const &a, T const &b) \ | inline vec_t<T,N> fun(vec_t<T,N,SWIZZLE> const &a, T const &b) \ | ||||
{ \ | { \ | ||||
using std::fun; \ | |||||
vec_t<T,N> ret; \ | vec_t<T,N> ret; \ | ||||
for (int i = 0; i < N; ++i) \ | for (int i = 0; i < N; ++i) \ | ||||
ret[i] = fun(a[i], b); \ | ret[i] = fun(a[i], b); \ | ||||
@@ -1022,6 +1025,7 @@ operator *(T const &val, vec_t<T,N,SWIZZLE> const &a) | |||||
template<typename T, int N, int SWIZZLE> \ | template<typename T, int N, int SWIZZLE> \ | ||||
inline vec_t<T,N> fun(T const &a, vec_t<T,N,SWIZZLE> const &b) \ | inline vec_t<T,N> fun(T const &a, vec_t<T,N,SWIZZLE> const &b) \ | ||||
{ \ | { \ | ||||
using std::fun; \ | |||||
vec_t<T,N> ret; \ | vec_t<T,N> ret; \ | ||||
for (int i = 0; i < N; ++i) \ | for (int i = 0; i < N; ++i) \ | ||||
ret[i] = fun(a, b[i]); \ | ret[i] = fun(a, b[i]); \ | ||||
@@ -1165,15 +1169,24 @@ static inline vec_t<T,N> normalize(vec_t<T,N,SWIZZLE> const &a) | |||||
return norm ? a / norm : vec_t<T,N>(T(0)); | return norm ? a / norm : vec_t<T,N>(T(0)); | ||||
} | } | ||||
// We define fabs() because that’s the C++ std library uses for | |||||
// floating-point numbers, and abs() because GLSL does. | |||||
template<typename T, int N, int SWIZZLE> | template<typename T, int N, int SWIZZLE> | ||||
static inline vec_t<T,N> abs(vec_t<T,N,SWIZZLE> const &a) | |||||
static inline vec_t<T,N> fabs(vec_t<T,N,SWIZZLE> const &a) | |||||
{ | { | ||||
using std::fabs; | |||||
vec_t<T,N> ret; | vec_t<T,N> ret; | ||||
for (int i = 0; i < N; ++i) | for (int i = 0; i < N; ++i) | ||||
ret[i] = abs(a[i]); | |||||
ret[i] = fabs(a[i]); | |||||
return ret; | return ret; | ||||
} | } | ||||
template<typename T, int N, int SWIZZLE> | |||||
static inline vec_t<T,N> abs(vec_t<T,N,SWIZZLE> const &a) | |||||
{ | |||||
return fabs(a); | |||||
} | |||||
template<typename T, int N, int SWIZZLE> | template<typename T, int N, int SWIZZLE> | ||||
static inline vec_t<T,N> degrees(vec_t<T,N,SWIZZLE> const &a) | static inline vec_t<T,N> degrees(vec_t<T,N,SWIZZLE> const &a) | ||||
{ | { | ||||
@@ -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 fract(half a) { return fract((float)a); } | ||||
static inline float degrees(half a) { return degrees((float)a); } | static inline float degrees(half a) { return degrees((float)a); } | ||||
static inline float radians(half a) { return radians((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) | static inline half clamp(half x, half a, half b) | ||||
{ | { | ||||
@@ -970,11 +970,6 @@ template<typename T> real_t<T> fabs(real_t<T> const &x) | |||||
return ret; | return ret; | ||||
} | } | ||||
template<typename T> real_t<T> abs(real_t<T> const &x) | |||||
{ | |||||
return fabs(x); | |||||
} | |||||
template<typename T> real_t<T> fract(real_t<T> const &x) | template<typename T> real_t<T> fract(real_t<T> const &x) | ||||
{ | { | ||||
return x - floor(x); | return x - floor(x); | ||||
@@ -161,7 +161,6 @@ public: | |||||
real_t<U> const &y); | real_t<U> const &y); | ||||
// Functions inherited from GLSL | // Functions inherited from GLSL | ||||
template<typename U> friend real_t<U> abs(real_t<U> const &x); | |||||
template<typename U> friend real_t<U> fract(real_t<U> const &x); | template<typename U> friend real_t<U> fract(real_t<U> const &x); | ||||
template<typename U> friend real_t<U> degrees(real_t<U> const &x); | template<typename U> friend real_t<U> degrees(real_t<U> const &x); | ||||
template<typename U> friend real_t<U> radians(real_t<U> const &x); | template<typename U> friend real_t<U> radians(real_t<U> const &x); | ||||
@@ -149,12 +149,12 @@ template<typename T, typename T2 = LOL_T_FLOATING_POINT> | |||||
return mix(a, b, x); | 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. | // convenience to avoid adding complexity to vector.h. | ||||
template<typename T, typename T2 = LOL_T_SIGNED> | template<typename T, typename T2 = LOL_T_SIGNED> | ||||
[[nodiscard]] static inline T2 abs(T x) { return std::abs(x); } | |||||
[[nodiscard]] static inline T2 fabs(T x) { return std::abs(x); } | |||||
template<typename T, typename T2 = T, typename DUMMY = LOL_T_UNSIGNED> | template<typename T, typename T2 = T, typename DUMMY = LOL_T_UNSIGNED> | ||||
[[nodiscard]] static inline T2 abs(T x) { return x; } | |||||
[[nodiscard]] static inline T2 fabs(T x) { return x; } | |||||
template<typename T, typename T2 = LOL_T_INTEGRAL> | template<typename T, typename T2 = LOL_T_INTEGRAL> | ||||
[[nodiscard]] static inline T2 fmod(T x, T y) { return x % y; } | [[nodiscard]] static inline T2 fmod(T x, T y) { return x % y; } | ||||
@@ -175,7 +175,7 @@ template<typename T, typename T2 = LOL_T_ARITHMETIC> | |||||
template<typename T, typename T2 = LOL_T_ARITHMETIC> | template<typename T, typename T2 = LOL_T_ARITHMETIC> | ||||
[[nodiscard]] static inline T2 saturate(T x) { return clamp(x, (T)0, (T)1); } | [[nodiscard]] static inline T2 saturate(T x) { return clamp(x, (T)0, (T)1); } | ||||
template<typename T, typename T2 = LOL_T_ARITHMETIC> | template<typename T, typename T2 = LOL_T_ARITHMETIC> | ||||
[[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<typename T, typename T2 = LOL_T_SIGNED> | template<typename T, typename T2 = LOL_T_SIGNED> | ||||
[[nodiscard]] static inline T2 sign(T x) { return (T)(((T)0 < x) - (x < (T)0)); } | [[nodiscard]] static inline T2 sign(T x) { return (T)(((T)0 < x) - (x < (T)0)); } | ||||
@@ -25,7 +25,7 @@ | |||||
#include <algorithm> | #include <algorithm> | ||||
#include <map> | #include <map> | ||||
#include <cmath> | |||||
#include <cmath> // std::fabs | |||||
#include <cstdio> | #include <cstdio> | ||||
#include <stdint.h> | #include <stdint.h> | ||||
@@ -213,6 +213,8 @@ public: | |||||
//-- | //-- | ||||
static inline bool TestAABBVsAABB(box2 const &b1, box2 const &b2) | static inline bool TestAABBVsAABB(box2 const &b1, box2 const &b2) | ||||
{ | { | ||||
using std::fabs; | |||||
vec2 c = b1.center() - b2.center(); | vec2 c = b1.center() - b2.center(); | ||||
vec2 e1 = 0.5f * b1.extent(); | vec2 e1 = 0.5f * b1.extent(); | ||||
vec2 e2 = 0.5f * b2.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) | static inline bool TestAABBVsAABB(box3 const &b1, box3 const &b2) | ||||
{ | { | ||||
using std::fabs; | |||||
vec3 c = b1.center() - b2.center(); | vec3 c = b1.center() - b2.center(); | ||||
vec3 e1 = 0.5f * b1.extent(); | vec3 e1 = 0.5f * b1.extent(); | ||||
vec3 e2 = 0.5f * b2.extent(); | vec3 e2 = 0.5f * b2.extent(); | ||||
@@ -19,6 +19,7 @@ | |||||
#include <lol/math/transform.h> // mat_t | #include <lol/math/transform.h> // mat_t | ||||
#include <vector> // std::vector | #include <vector> // std::vector | ||||
#include <cmath> // std::fabs | |||||
#include <algorithm> // std::min, std::max | #include <algorithm> // std::min, std::max | ||||
namespace lol | namespace lol | ||||
@@ -88,6 +89,8 @@ protected: | |||||
inline float get_noise(vec_t<int, N> origin, | inline float get_noise(vec_t<int, N> origin, | ||||
vec_t<float, N> const & pos) const | vec_t<float, N> const & pos) const | ||||
{ | { | ||||
using std::min; | |||||
/* For a given position [0…1]^N inside a regular N-hypercube, find | /* For a given position [0…1]^N inside a regular N-hypercube, find | ||||
* the N-simplex which contains that position, and return a path | * the N-simplex which contains that position, and return a path | ||||
* along the hypercube edges from (0,0,…,0) to (1,1,…,1) which | * along the hypercube edges from (0,0,…,0) to (1,1,…,1) which | ||||
@@ -141,9 +144,9 @@ protected: | |||||
// -4.f: centre (-2.f), | // -4.f: centre (-2.f), | ||||
// -3.f: r=0.38 sphere of influence (contribution = 1/4) | // -3.f: r=0.38 sphere of influence (contribution = 1/4) | ||||
// -2.f: r=0.52 sphere of influence (contribution = 1/24) | // -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 | #endif | ||||
if (d > 0) | if (d > 0) | ||||
@@ -230,6 +233,8 @@ protected: | |||||
private: | private: | ||||
void debugprint() | void debugprint() | ||||
{ | { | ||||
using std::min, std::max, std::fabs; | |||||
// Print some debug information | // Print some debug information | ||||
printf("Simplex Noise of Dimension %d\n", N); | printf("Simplex Noise of Dimension %d\n", N); | ||||
@@ -281,8 +286,8 @@ private: | |||||
continue; | continue; | ||||
float l = length(vertices[i] - vertices[j]); | 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", | printf(" · edge lengths between %f and %f\n", | ||||
minlength, maxlength); | minlength, maxlength); | ||||
@@ -306,7 +311,7 @@ private: | |||||
p += k * vertices[j]; | p += k * vertices[j]; | ||||
sum += k; | 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); | printf(" · approx. dist. to opposite hyperplane: %f\n", mindist); | ||||
#endif | #endif | ||||
@@ -388,11 +393,11 @@ private: | |||||
t = best_t2; | 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); | 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) | if (newscale < 1.f) | ||||
printf(" - could replace scale %f with %f\n", | printf(" - could replace scale %f with %f\n", | ||||
get_scale(), newscale * get_scale()); | get_scale(), newscale * get_scale()); | ||||