diff --git a/libs/math/include/math/TVecHelpers.h b/libs/math/include/math/TVecHelpers.h index 438a4a9275..4c89413569 100644 --- a/libs/math/include/math/TVecHelpers.h +++ b/libs/math/include/math/TVecHelpers.h @@ -22,10 +22,9 @@ #include #include -#include -#include -#include -#include +#include // for std:: namespace +#include // for appl() and map() +#include // for operator<< #include @@ -44,6 +43,15 @@ inline constexpr U max(U a, U b) noexcept { return a > b ? a : b; } +template +struct arithmetic_result { + using type = decltype(std::declval() + std::declval()); +}; + +template +using arithmetic_result_t = typename arithmetic_result::type; + + /* * No user serviceable parts here. * @@ -115,16 +123,20 @@ public: /* The operators below handle operation between vectors of the same size * but of a different element type. */ - template - friend inline constexpr VECTOR MATH_PURE operator+(VECTOR lv, const VECTOR& rv) { - // don't pass lv by reference because we need a copy anyways - return lv += rv; + template + friend inline constexpr + VECTOR> MATH_PURE operator+(const VECTOR& lv, const VECTOR& rv) { + VECTOR> res(lv); + res += rv; + return res; } - template - friend inline constexpr VECTOR MATH_PURE operator-(VECTOR lv, const VECTOR& rv) { - // don't pass lv by reference because we need a copy anyways - return lv -= rv; + template + friend inline constexpr + VECTOR> MATH_PURE operator-(const VECTOR& lv, const VECTOR& rv) { + VECTOR> res(lv); + res -= rv; + return res; } /* The operators below (which are not templates once this class is instanced, @@ -200,16 +212,20 @@ public: /* The operators below handle operation between vectors of the same size * but of a different element type. */ - template - friend inline constexpr VECTOR MATH_PURE operator*(VECTOR lv, const VECTOR& rv) { - // don't pass lv by reference because we need a copy anyways - return lv *= rv; + template + friend inline constexpr + VECTOR> MATH_PURE operator*(const VECTOR& lv, const VECTOR& rv) { + VECTOR> res(lv); + res *= rv; + return res; } - template - friend inline constexpr VECTOR MATH_PURE operator/(VECTOR lv, const VECTOR& rv) { - // don't pass lv by reference because we need a copy anyways - return lv /= rv; + template + friend inline constexpr + VECTOR> MATH_PURE operator/(const VECTOR& lv, const VECTOR& rv) { + arithmetic_result_t res(lv); + res /= rv; + return res; } /* The operators below (which are not templates once this class is instanced, @@ -269,9 +285,9 @@ public: * is instantiated, at which point they're only templated on the 2nd parameter * (the first one, BASE being known). */ - template + template friend inline constexpr - bool MATH_PURE operator==(const VECTOR& lv, const VECTOR& rv) { + bool MATH_PURE operator==(const VECTOR& lv, const VECTOR& rv) { // w/ inlining we end-up with many branches that will pollute the BPU cache MATH_NOUNROLL for (size_t i = 0; i < lv.size(); i++) { @@ -282,15 +298,15 @@ public: return true; } - template + template friend inline constexpr - bool MATH_PURE operator!=(const VECTOR& lv, const VECTOR& rv) { + bool MATH_PURE operator!=(const VECTOR& lv, const VECTOR& rv) { return !operator==(lv, rv); } - template + template friend inline constexpr - VECTOR MATH_PURE equal(const VECTOR& lv, const VECTOR& rv) { + VECTOR MATH_PURE equal(const VECTOR& lv, const VECTOR& rv) { VECTOR r{}; for (size_t i = 0; i < lv.size(); i++) { r[i] = lv[i] == rv[i]; @@ -298,9 +314,9 @@ public: return r; } - template + template friend inline constexpr - VECTOR MATH_PURE notEqual(const VECTOR& lv, const VECTOR& rv) { + VECTOR MATH_PURE notEqual(const VECTOR& lv, const VECTOR& rv) { VECTOR r{}; for (size_t i = 0; i < lv.size(); i++) { r[i] = lv[i] != rv[i]; @@ -308,9 +324,9 @@ public: return r; } - template + template friend inline constexpr - VECTOR MATH_PURE lessThan(const VECTOR& lv, const VECTOR& rv) { + VECTOR MATH_PURE lessThan(const VECTOR& lv, const VECTOR& rv) { VECTOR r{}; for (size_t i = 0; i < lv.size(); i++) { r[i] = lv[i] < rv[i]; @@ -318,9 +334,9 @@ public: return r; } - template + template friend inline constexpr - VECTOR MATH_PURE lessThanEqual(const VECTOR& lv, const VECTOR& rv) { + VECTOR MATH_PURE lessThanEqual(const VECTOR& lv, const VECTOR& rv) { VECTOR r{}; for (size_t i = 0; i < lv.size(); i++) { r[i] = lv[i] <= rv[i]; @@ -328,9 +344,9 @@ public: return r; } - template + template friend inline constexpr - VECTOR MATH_PURE greaterThan(const VECTOR& lv, const VECTOR& rv) { + VECTOR MATH_PURE greaterThan(const VECTOR& lv, const VECTOR& rv) { VECTOR r; for (size_t i = 0; i < lv.size(); i++) { r[i] = lv[i] > rv[i]; @@ -338,9 +354,9 @@ public: return r; } - template + template friend inline - VECTOR MATH_PURE greaterThanEqual(const VECTOR& lv, const VECTOR& rv) { + VECTOR MATH_PURE greaterThanEqual(const VECTOR& lv, const VECTOR& rv) { VECTOR r{}; for (size_t i = 0; i < lv.size(); i++) { r[i] = lv[i] >= rv[i]; @@ -366,9 +382,10 @@ public: * is instantiated, at which point they're only templated on the 2nd parameter * (the first one, BASE being known). */ - template - friend constexpr inline T MATH_PURE dot(const VECTOR& lv, const VECTOR& rv) { - T r(0); + template + friend constexpr inline + arithmetic_result_t MATH_PURE dot(const VECTOR& lv, const VECTOR& rv) { + arithmetic_result_t r{}; for (size_t i = 0; i < lv.size(); i++) { r += lv[i] * rv[i]; } @@ -391,13 +408,15 @@ public: return norm2(lv); } - template - friend inline constexpr T MATH_PURE distance(const VECTOR& lv, const VECTOR& rv) { + template + friend inline constexpr + arithmetic_result_t MATH_PURE distance(const VECTOR& lv, const VECTOR& rv) { return length(rv - lv); } - template - friend inline constexpr T MATH_PURE distance2(const VECTOR& lv, const VECTOR& rv) { + template + friend inline constexpr + arithmetic_result_t MATH_PURE distance2(const VECTOR& lv, const VECTOR& rv) { return length2(rv - lv); } @@ -499,16 +518,16 @@ public: } friend inline constexpr T MATH_PURE max(const VECTOR& v) { - T r(std::numeric_limits::lowest()); - for (size_t i = 0; i < v.size(); i++) { + T r(v[0]); + for (size_t i = 1; i < v.size(); i++) { r = max(r, v[i]); } return r; } friend inline constexpr T MATH_PURE min(const VECTOR& v) { - T r(std::numeric_limits::max()); - for (size_t i = 0; i < v.size(); i++) { + T r(v[0]); + for (size_t i = 1; i < v.size(); i++) { r = min(r, v[i]); } return r; diff --git a/libs/math/include/math/vec2.h b/libs/math/include/math/vec2.h index 8aa0a315b2..fa71467078 100644 --- a/libs/math/include/math/vec2.h +++ b/libs/math/include/math/vec2.h @@ -83,10 +83,10 @@ public: constexpr TVec2(const TVec2& v) : v{ T(v[0]), T(v[1]) } {} // cross product works only on vectors of size 2 or 3 - template - friend inline - constexpr value_type cross(const TVec2& u, const TVec2& v) { - return value_type(u[0] * v[1] - u[1] * v[0]); + template + friend inline constexpr + arithmetic_result_t cross(const TVec2& u, const TVec2& v) { + return u[0] * v[1] - u[1] * v[0]; } }; diff --git a/libs/math/include/math/vec3.h b/libs/math/include/math/vec3.h index 4a1032ecfe..6b09835219 100644 --- a/libs/math/include/math/vec3.h +++ b/libs/math/include/math/vec3.h @@ -99,12 +99,13 @@ public: constexpr TVec3(const TVec3& v) : v{ T(v[0]), T(v[1]), T(v[2]) } {} // cross product works only on vectors of size 3 - template - friend inline constexpr TVec3 cross(const TVec3& u, const TVec3& v) { - return TVec3( + template + friend inline constexpr + TVec3> cross(const TVec3& u, const TVec3& v) { + return { u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], - u[0] * v[1] - u[1] * v[0]); + u[0] * v[1] - u[1] * v[0] }; } };