improve mixed-precision vector operations
We now follow the same rules than for basic types, when performing mixed-precision operations, e.g.: float3 + double3 -> double3 double3 + float3 -> double3 dot(float3, double3) -> double In particular, e.g. swapping the arguments to arithmetic operations now always yields to the same result type (before, float3 + double3 would not return the same type than double3 + float3).
This commit is contained in:
committed by
Mathias Agopian
parent
48b73ad998
commit
cf950a8d6f
@@ -22,10 +22,9 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <iostream>
|
||||
#include <cmath> // for std:: namespace
|
||||
#include <functional> // for appl() and map()
|
||||
#include <iostream> // for operator<<
|
||||
|
||||
#include <math/compiler.h>
|
||||
|
||||
@@ -44,6 +43,15 @@ inline constexpr U max(U a, U b) noexcept {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
struct arithmetic_result {
|
||||
using type = decltype(std::declval<T>() + std::declval<U>());
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
using arithmetic_result_t = typename arithmetic_result<T, U>::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<typename RT>
|
||||
friend inline constexpr VECTOR<T> MATH_PURE operator+(VECTOR<T> lv, const VECTOR<RT>& rv) {
|
||||
// don't pass lv by reference because we need a copy anyways
|
||||
return lv += rv;
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator+(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<arithmetic_result_t<T, U>> res(lv);
|
||||
res += rv;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
friend inline constexpr VECTOR<T> MATH_PURE operator-(VECTOR<T> lv, const VECTOR<RT>& rv) {
|
||||
// don't pass lv by reference because we need a copy anyways
|
||||
return lv -= rv;
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator-(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<arithmetic_result_t<T, U>> 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<typename RT>
|
||||
friend inline constexpr VECTOR<T> MATH_PURE operator*(VECTOR<T> lv, const VECTOR<RT>& rv) {
|
||||
// don't pass lv by reference because we need a copy anyways
|
||||
return lv *= rv;
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator*(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<arithmetic_result_t<T, U>> res(lv);
|
||||
res *= rv;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
friend inline constexpr VECTOR<T> MATH_PURE operator/(VECTOR<T> lv, const VECTOR<RT>& rv) {
|
||||
// don't pass lv by reference because we need a copy anyways
|
||||
return lv /= rv;
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<arithmetic_result_t<T, U>> MATH_PURE operator/(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
arithmetic_result_t<T, U> 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<T> being known).
|
||||
*/
|
||||
template<typename RT>
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
bool MATH_PURE operator==(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
|
||||
bool MATH_PURE operator==(const VECTOR<T>& lv, const VECTOR<U>& 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<typename RT>
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
bool MATH_PURE operator!=(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
|
||||
bool MATH_PURE operator!=(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
return !operator==(lv, rv);
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<bool> MATH_PURE equal(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
|
||||
VECTOR<bool> MATH_PURE equal(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<bool> r{};
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r[i] = lv[i] == rv[i];
|
||||
@@ -298,9 +314,9 @@ public:
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<bool> MATH_PURE notEqual(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
|
||||
VECTOR<bool> MATH_PURE notEqual(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<bool> r{};
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r[i] = lv[i] != rv[i];
|
||||
@@ -308,9 +324,9 @@ public:
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<bool> MATH_PURE lessThan(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
|
||||
VECTOR<bool> MATH_PURE lessThan(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<bool> r{};
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r[i] = lv[i] < rv[i];
|
||||
@@ -318,9 +334,9 @@ public:
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<bool> MATH_PURE lessThanEqual(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
|
||||
VECTOR<bool> MATH_PURE lessThanEqual(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<bool> r{};
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r[i] = lv[i] <= rv[i];
|
||||
@@ -328,9 +344,9 @@ public:
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
VECTOR<bool> MATH_PURE greaterThan(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
|
||||
VECTOR<bool> MATH_PURE greaterThan(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<bool> r;
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r[i] = lv[i] > rv[i];
|
||||
@@ -338,9 +354,9 @@ public:
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
template<typename U>
|
||||
friend inline
|
||||
VECTOR<bool> MATH_PURE greaterThanEqual(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
|
||||
VECTOR<bool> MATH_PURE greaterThanEqual(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
VECTOR<bool> 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<T> being known).
|
||||
*/
|
||||
template<typename RT>
|
||||
friend constexpr inline T MATH_PURE dot(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
|
||||
T r(0);
|
||||
template<typename U>
|
||||
friend constexpr inline
|
||||
arithmetic_result_t<T, U> MATH_PURE dot(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
arithmetic_result_t<T, U> r{};
|
||||
for (size_t i = 0; i < lv.size(); i++) {
|
||||
r += lv[i] * rv[i];
|
||||
}
|
||||
@@ -391,13 +408,15 @@ public:
|
||||
return norm2(lv);
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
friend inline constexpr T MATH_PURE distance(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
arithmetic_result_t<T, U> MATH_PURE distance(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
return length(rv - lv);
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
friend inline constexpr T MATH_PURE distance2(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
arithmetic_result_t<T, U> MATH_PURE distance2(const VECTOR<T>& lv, const VECTOR<U>& rv) {
|
||||
return length2(rv - lv);
|
||||
}
|
||||
|
||||
@@ -499,16 +518,16 @@ public:
|
||||
}
|
||||
|
||||
friend inline constexpr T MATH_PURE max(const VECTOR<T>& v) {
|
||||
T r(std::numeric_limits<T>::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<T>& v) {
|
||||
T r(std::numeric_limits<T>::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;
|
||||
|
||||
@@ -83,10 +83,10 @@ public:
|
||||
constexpr TVec2(const TVec2<A>& v) : v{ T(v[0]), T(v[1]) } {}
|
||||
|
||||
// cross product works only on vectors of size 2 or 3
|
||||
template<typename RT>
|
||||
friend inline
|
||||
constexpr value_type cross(const TVec2& u, const TVec2<RT>& v) {
|
||||
return value_type(u[0] * v[1] - u[1] * v[0]);
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
arithmetic_result_t<T, U> cross(const TVec2& u, const TVec2<U>& v) {
|
||||
return u[0] * v[1] - u[1] * v[0];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -99,12 +99,13 @@ public:
|
||||
constexpr TVec3(const TVec3<A>& v) : v{ T(v[0]), T(v[1]), T(v[2]) } {}
|
||||
|
||||
// cross product works only on vectors of size 3
|
||||
template<typename RT>
|
||||
friend inline constexpr TVec3 cross(const TVec3& u, const TVec3<RT>& v) {
|
||||
return TVec3(
|
||||
template<typename U>
|
||||
friend inline constexpr
|
||||
TVec3<arithmetic_result_t<T, U>> cross(const TVec3& u, const TVec3<U>& 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] };
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user