Common/Matrix: Allow TVec classes to be used in constexpr contexts

Much of these classes are operating on integral types and are pretty
standard behavior as far as vectors go. Some member functions can be
made constexpr to make them more flexible and allow them to be used in
constexpr contexts.
This commit is contained in:
Lioncash 2020-10-21 17:41:38 -04:00
parent de96fe0860
commit dcb0c910af
1 changed files with 46 additions and 43 deletions

View File

@ -17,24 +17,24 @@ namespace Common
template <typename T>
union TVec3
{
TVec3() = default;
TVec3(T _x, T _y, T _z) : data{_x, _y, _z} {}
constexpr TVec3() = default;
constexpr TVec3(T _x, T _y, T _z) : data{_x, _y, _z} {}
template <typename OtherT>
explicit TVec3(const TVec3<OtherT>& other) : TVec3(other.x, other.y, other.z)
constexpr explicit TVec3(const TVec3<OtherT>& other) : TVec3(other.x, other.y, other.z)
{
}
TVec3 Cross(const TVec3& rhs) const
constexpr TVec3 Cross(const TVec3& rhs) const
{
return {(y * rhs.z) - (rhs.y * z), (z * rhs.x) - (rhs.z * x), (x * rhs.y) - (rhs.x * y)};
}
T Dot(const TVec3& other) const { return x * other.x + y * other.y + z * other.z; }
T LengthSquared() const { return Dot(*this); }
constexpr T Dot(const TVec3& other) const { return x * other.x + y * other.y + z * other.z; }
constexpr T LengthSquared() const { return Dot(*this); }
T Length() const { return std::sqrt(LengthSquared()); }
TVec3 Normalized() const { return *this / Length(); }
TVec3& operator+=(const TVec3& rhs)
constexpr TVec3& operator+=(const TVec3& rhs)
{
x += rhs.x;
y += rhs.y;
@ -42,7 +42,7 @@ union TVec3
return *this;
}
TVec3& operator-=(const TVec3& rhs)
constexpr TVec3& operator-=(const TVec3& rhs)
{
x -= rhs.x;
y -= rhs.y;
@ -50,7 +50,7 @@ union TVec3
return *this;
}
TVec3& operator*=(const TVec3& rhs)
constexpr TVec3& operator*=(const TVec3& rhs)
{
x *= rhs.x;
y *= rhs.y;
@ -58,7 +58,7 @@ union TVec3
return *this;
}
TVec3& operator/=(const TVec3& rhs)
constexpr TVec3& operator/=(const TVec3& rhs)
{
x /= rhs.x;
y /= rhs.y;
@ -66,7 +66,7 @@ union TVec3
return *this;
}
TVec3 operator-() const { return {-x, -y, -z}; }
constexpr TVec3 operator-() const { return {-x, -y, -z}; }
// Apply function to each element and return the result.
template <typename F>
@ -103,7 +103,7 @@ TVec3<bool> operator<(const TVec3<T>& lhs, const TVec3<T>& rhs)
return lhs.Map(std::less<T>{}, rhs);
}
inline TVec3<bool> operator!(const TVec3<bool>& vec)
constexpr TVec3<bool> operator!(const TVec3<bool>& vec)
{
return {!vec.x, !vec.y, !vec.z};
}
@ -150,13 +150,16 @@ using DVec3 = TVec3<double>;
template <typename T>
union TVec4
{
TVec4() = default;
TVec4(TVec3<T> _vec, T _w) : TVec4{_vec.x, _vec.y, _vec.z, _w} {}
TVec4(T _x, T _y, T _z, T _w) : data{_x, _y, _z, _w} {}
constexpr TVec4() = default;
constexpr TVec4(TVec3<T> _vec, T _w) : TVec4{_vec.x, _vec.y, _vec.z, _w} {}
constexpr TVec4(T _x, T _y, T _z, T _w) : data{_x, _y, _z, _w} {}
T Dot(const TVec4& other) const { return x * other.x + y * other.y + z * other.z + w * other.w; }
constexpr T Dot(const TVec4& other) const
{
return x * other.x + y * other.y + z * other.z + w * other.w;
}
TVec4& operator*=(const TVec4& rhs)
constexpr TVec4& operator*=(const TVec4& rhs)
{
x *= rhs.x;
y *= rhs.y;
@ -165,7 +168,7 @@ union TVec4
return *this;
}
TVec4& operator/=(const TVec4& rhs)
constexpr TVec4& operator/=(const TVec4& rhs)
{
x /= rhs.x;
y /= rhs.y;
@ -174,8 +177,8 @@ union TVec4
return *this;
}
TVec4& operator*=(T scalar) { return *this *= TVec4{scalar, scalar, scalar, scalar}; }
TVec4& operator/=(T scalar) { return *this /= TVec4{scalar, scalar, scalar, scalar}; }
constexpr TVec4& operator*=(T scalar) { return *this *= TVec4{scalar, scalar, scalar, scalar}; }
constexpr TVec4& operator/=(T scalar) { return *this /= TVec4{scalar, scalar, scalar, scalar}; }
std::array<T, 4> data = {};
@ -189,13 +192,13 @@ union TVec4
};
template <typename T>
TVec4<T> operator*(TVec4<T> lhs, std::common_type_t<T> scalar)
constexpr TVec4<T> operator*(TVec4<T> lhs, std::common_type_t<T> scalar)
{
return lhs *= scalar;
}
template <typename T>
TVec4<T> operator/(TVec4<T> lhs, std::common_type_t<T> scalar)
constexpr TVec4<T> operator/(TVec4<T> lhs, std::common_type_t<T> scalar)
{
return lhs /= scalar;
}
@ -206,63 +209,63 @@ using DVec4 = TVec4<double>;
template <typename T>
union TVec2
{
TVec2() = default;
TVec2(T _x, T _y) : data{_x, _y} {}
constexpr TVec2() = default;
constexpr TVec2(T _x, T _y) : data{_x, _y} {}
template <typename OtherT>
explicit TVec2(const TVec2<OtherT>& other) : TVec2(other.x, other.y)
constexpr explicit TVec2(const TVec2<OtherT>& other) : TVec2(other.x, other.y)
{
}
T Cross(const TVec2& rhs) const { return (x * rhs.y) - (y * rhs.x); }
T Dot(const TVec2& rhs) const { return (x * rhs.x) + (y * rhs.y); }
T LengthSquared() const { return Dot(*this); }
constexpr T Cross(const TVec2& rhs) const { return (x * rhs.y) - (y * rhs.x); }
constexpr T Dot(const TVec2& rhs) const { return (x * rhs.x) + (y * rhs.y); }
constexpr T LengthSquared() const { return Dot(*this); }
T Length() const { return std::sqrt(LengthSquared()); }
TVec2 Normalized() const { return *this / Length(); }
TVec2& operator+=(const TVec2& rhs)
constexpr TVec2& operator+=(const TVec2& rhs)
{
x += rhs.x;
y += rhs.y;
return *this;
}
TVec2& operator-=(const TVec2& rhs)
constexpr TVec2& operator-=(const TVec2& rhs)
{
x -= rhs.x;
y -= rhs.y;
return *this;
}
TVec2& operator*=(const TVec2& rhs)
constexpr TVec2& operator*=(const TVec2& rhs)
{
x *= rhs.x;
y *= rhs.y;
return *this;
}
TVec2& operator/=(const TVec2& rhs)
constexpr TVec2& operator/=(const TVec2& rhs)
{
x /= rhs.x;
y /= rhs.y;
return *this;
}
TVec2& operator*=(T scalar)
constexpr TVec2& operator*=(T scalar)
{
x *= scalar;
y *= scalar;
return *this;
}
TVec2& operator/=(T scalar)
constexpr TVec2& operator/=(T scalar)
{
x /= scalar;
y /= scalar;
return *this;
}
TVec2 operator-() const { return {-x, -y}; }
constexpr TVec2 operator-() const { return {-x, -y}; }
std::array<T, 2> data = {};
@ -274,48 +277,48 @@ union TVec2
};
template <typename T>
TVec2<bool> operator<(const TVec2<T>& lhs, const TVec2<T>& rhs)
constexpr TVec2<bool> operator<(const TVec2<T>& lhs, const TVec2<T>& rhs)
{
return {lhs.x < rhs.x, lhs.y < rhs.y};
}
inline TVec2<bool> operator!(const TVec2<bool>& vec)
constexpr TVec2<bool> operator!(const TVec2<bool>& vec)
{
return {!vec.x, !vec.y};
}
template <typename T>
TVec2<T> operator+(TVec2<T> lhs, const TVec2<T>& rhs)
constexpr TVec2<T> operator+(TVec2<T> lhs, const TVec2<T>& rhs)
{
return lhs += rhs;
}
template <typename T>
TVec2<T> operator-(TVec2<T> lhs, const TVec2<T>& rhs)
constexpr TVec2<T> operator-(TVec2<T> lhs, const TVec2<T>& rhs)
{
return lhs -= rhs;
}
template <typename T>
TVec2<T> operator*(TVec2<T> lhs, const TVec2<T>& rhs)
constexpr TVec2<T> operator*(TVec2<T> lhs, const TVec2<T>& rhs)
{
return lhs *= rhs;
}
template <typename T>
TVec2<T> operator/(TVec2<T> lhs, const TVec2<T>& rhs)
constexpr TVec2<T> operator/(TVec2<T> lhs, const TVec2<T>& rhs)
{
return lhs /= rhs;
}
template <typename T, typename T2>
auto operator*(TVec2<T> lhs, T2 scalar)
constexpr auto operator*(TVec2<T> lhs, T2 scalar)
{
return TVec2<decltype(lhs.x * scalar)>(lhs) *= scalar;
}
template <typename T, typename T2>
auto operator/(TVec2<T> lhs, T2 scalar)
constexpr auto operator/(TVec2<T> lhs, T2 scalar)
{
return TVec2<decltype(lhs.x / scalar)>(lhs) /= scalar;
}