Merge pull request #6 from BlackMATov/dev

Dev
This commit is contained in:
2020-12-08 00:48:40 +07:00
committed by GitHub
10 changed files with 1408 additions and 399 deletions

484
README.md
View File

@@ -188,9 +188,9 @@ using size2 = vec<size_t, 2>;
using size3 = vec<size_t, 3>;
using size4 = vec<size_t, 4>;
using ptrdiff2 = vec<std::ptrdiff_t, 2>;
using ptrdiff3 = vec<std::ptrdiff_t, 3>;
using ptrdiff4 = vec<std::ptrdiff_t, 4>;
using ptrdiff2 = vec<ptrdiff_t, 2>;
using ptrdiff3 = vec<ptrdiff_t, 3>;
using ptrdiff4 = vec<ptrdiff_t, 4>;
```
### Matrix Types
@@ -360,9 +360,9 @@ using size2x2 = mat<size_t, 2>;
using size3x3 = mat<size_t, 3>;
using size4x4 = mat<size_t, 4>;
using ptrdiff2x2 = mat<std::ptrdiff_t, 2>;
using ptrdiff3x3 = mat<std::ptrdiff_t, 3>;
using ptrdiff4x4 = mat<std::ptrdiff_t, 4>;
using ptrdiff2x2 = mat<ptrdiff_t, 2>;
using ptrdiff3x3 = mat<ptrdiff_t, 3>;
using ptrdiff4x4 = mat<ptrdiff_t, 4>;
```
### Vector Operators
@@ -373,6 +373,16 @@ using ptrdiff4x4 = mat<std::ptrdiff_t, 4>;
template < typename T, size_t Size >
constexpr vec<T, Size> operator-(const vec<T, Size>& xs);
// ~operator
template < typename T, size_t Size >
constexpr vec<T, Size> operator~(const vec<T, Size>& xs);
// !operator
template < typename T, size_t Size >
constexpr vec<bool, Size> operator!(const vec<T, Size>& xs);
// operator+
template < typename T, size_t Size >
@@ -449,11 +459,92 @@ constexpr vec<T, Size>& operator/=(vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<T, Size>& operator/=(vec<T, Size>& xs, const vec<T, Size>& ys);
// operator&
template < typename T, size_t Size >
constexpr vec<T, Size> operator&(const vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<T, Size> operator&(T x, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<T, Size> operator&(const vec<T, Size>& xs, const vec<T, Size>& ys);
// operator&=
template < typename T, size_t Size >
constexpr vec<T, Size>& operator&=(vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<T, Size>& operator&=(vec<T, Size>& xs, const vec<T, Size>& ys);
// operator|
template < typename T, size_t Size >
constexpr vec<T, Size> operator|(const vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<T, Size> operator|(T x, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<T, Size> operator|(const vec<T, Size>& xs, const vec<T, Size>& ys);
// operator|=
template < typename T, size_t Size >
constexpr vec<T, Size>& operator|=(vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<T, Size>& operator|=(vec<T, Size>& xs, const vec<T, Size>& ys);
// operator^
template < typename T, size_t Size >
constexpr vec<T, Size> operator^(const vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<T, Size> operator^(T x, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<T, Size> operator^(const vec<T, Size>& xs, const vec<T, Size>& ys);
// operator^=
template < typename T, size_t Size >
constexpr vec<T, Size>& operator^=(vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<T, Size>& operator^=(vec<T, Size>& xs, const vec<T, Size>& ys);
// operator&&
template < typename T, size_t Size >
constexpr vec<bool, Size> operator&&(const vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<bool, Size> operator&&(T x, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> operator&&(const vec<T, Size>& xs, const vec<T, Size>& ys);
// operator||
template < typename T, size_t Size >
constexpr vec<bool, Size> operator||(const vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<bool, Size> operator||(T x, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> operator||(const vec<T, Size>& xs, const vec<T, Size>& ys);
// operator==
template < typename T, size_t Size >
constexpr bool operator==(const vec<T, Size>& xs, const vec<T, Size>& ys);
// operator!=
template < typename T, size_t Size >
constexpr bool operator!=(const vec<T, Size>& xs, const vec<T, Size>& ys);
@@ -471,6 +562,16 @@ constexpr bool operator<(const vec<T, Size>& xs, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr mat<T, Size> operator-(const mat<T, Size>& xs);
// ~operator
template < typename T, size_t Size >
constexpr mat<T, Size> operator~(const mat<T, Size>& xs);
// !operator
template < typename T, size_t Size >
constexpr mat<bool, Size> operator!(const mat<T, Size>& xs);
// operator+
template < typename T, size_t Size >
@@ -542,22 +643,97 @@ constexpr mat<T, Size> operator/(const mat<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr mat<T, Size> operator/(T x, const mat<T, Size>& ys);
template < typename T, size_t Size >
constexpr mat<T, Size> operator/(const mat<T, Size>& xs, const mat<T, Size>& ys);
// operator/=
template < typename T, size_t Size >
constexpr mat<T, Size>& operator/=(mat<T, Size>& xs, T y);
// operator&
template < typename T, size_t Size >
constexpr mat<T, Size>& operator/=(mat<T, Size>& xs, const mat<T, Size>& ys);
constexpr mat<T, Size> operator&(const mat<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr mat<T, Size> operator&(T x, const mat<T, Size>& ys);
template < typename T, size_t Size >
constexpr mat<T, Size> operator&(const mat<T, Size>& xs, const mat<T, Size>& ys);
// operator&=
template < typename T, size_t Size >
constexpr mat<T, Size>& operator&=(mat<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr mat<T, Size>& operator&=(mat<T, Size>& xs, const mat<T, Size>& ys);
// operator|
template < typename T, size_t Size >
constexpr mat<T, Size> operator|(const mat<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr mat<T, Size> operator|(T x, const mat<T, Size>& ys);
template < typename T, size_t Size >
constexpr mat<T, Size> operator|(const mat<T, Size>& xs, const mat<T, Size>& ys);
// operator|=
template < typename T, size_t Size >
constexpr mat<T, Size>& operator|=(mat<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr mat<T, Size>& operator|=(mat<T, Size>& xs, const mat<T, Size>& ys);
// operator^
template < typename T, size_t Size >
constexpr mat<T, Size> operator^(const mat<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr mat<T, Size> operator^(T x, const mat<T, Size>& ys);
template < typename T, size_t Size >
constexpr mat<T, Size> operator^(const mat<T, Size>& xs, const mat<T, Size>& ys);
// operator^=
template < typename T, size_t Size >
constexpr mat<T, Size>& operator^=(mat<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr mat<T, Size>& operator^=(mat<T, Size>& xs, const mat<T, Size>& ys);
// operator&&
template < typename T, size_t Size >
constexpr mat<bool, Size> operator&&(const mat<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr mat<bool, Size> operator&&(T x, const mat<T, Size>& ys);
template < typename T, size_t Size >
constexpr mat<bool, Size> operator&&(const mat<T, Size>& xs, const mat<T, Size>& ys);
// operator||
template < typename T, size_t Size >
constexpr mat<bool, Size> operator||(const mat<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr mat<bool, Size> operator||(T x, const mat<T, Size>& ys);
template < typename T, size_t Size >
constexpr mat<bool, Size> operator||(const mat<T, Size>& xs, const mat<T, Size>& ys);
// operator==
template < typename T, size_t Size >
constexpr bool operator==(const mat<T, Size>& xs, const mat<T, Size>& ys);
// operator!=
template < typename T, size_t Size >
constexpr bool operator!=(const mat<T, Size>& xs, const mat<T, Size>& ys);
@@ -569,9 +745,9 @@ constexpr bool operator<(const mat<T, Size>& xs, const mat<T, Size>& ys);
### Angle and Trigonometry Functions
```cpp
// Scalar
#### Scalar
```cpp
template < floating_point T >
constexpr T radians(T degrees) noexcept;
@@ -618,13 +794,15 @@ template < floating_point T >
T atanh(T x) noexcept;
template < floating_point T >
std::pair<T, T> sincos(T x) noexcept;
pair<T, T> sincos(T x) noexcept;
template < floating_point T >
void sincos(T x, T* s, T* c) noexcept;
```
// Vector
#### Vector
```cpp
template < typename T, size_t Size >
constexpr vec<T, Size> radians(const vec<T, Size>& degrees);
@@ -676,9 +854,9 @@ void sincos(const vec<T, Size>& xs, vec<T, Size>* ss, vec<T, Size>* cs);
### Exponential Functions
```cpp
// Scalar
#### Scalar
```cpp
template < floating_point T >
T pow(T x, T y) noexcept;
@@ -699,9 +877,11 @@ T sqrt(T x) noexcept;
template < floating_point T >
T rsqrt(T x) noexcept;
```
// Vector
#### Vector
```cpp
template < typename T, size_t Size >
vec<T, Size> pow(const vec<T, Size>& xs, const vec<T, Size>& ys);
@@ -726,9 +906,9 @@ vec<T, Size> rsqrt(const vec<T, Size>& xs);
### Common Functions
```cpp
// Scalar
#### Scalar
```cpp
template < arithmetic T >
constexpr T abs(T x) noexcept;
@@ -736,7 +916,7 @@ template < arithmetic T >
constexpr T sign(T x) noexcept;
template < floating_point T >
constexpr T reciprocal(T x) noexcept;
constexpr T rcp(T x) noexcept;
template < floating_point T >
T floor(T x) noexcept;
@@ -763,13 +943,13 @@ template < arithmetic T >
constexpr T min(T x, T y) noexcept;
template < arithmetic T, arithmetic... Ts >
constexpr std::common_type_t<T, Ts...> min(T x, T y, Ts... ts) noexcept;
constexpr common_type_t<T, Ts...> min(T x, T y, Ts... ts) noexcept;
template < arithmetic T >
constexpr T max(T x, T y) noexcept;
template < arithmetic T, arithmetic... Ts >
constexpr std::common_type_t<T, Ts...> max(T x, T y, Ts... ts) noexcept;
constexpr common_type_t<T, Ts...> max(T x, T y, Ts... ts) noexcept;
template < arithmetic T >
constexpr T clamp(T x, T min_x, T max_x) noexcept;
@@ -803,9 +983,11 @@ T frexp(T x, int* exp) noexcept;
template < floating_point T >
T ldexp(T x, int exp) noexcept;
```
// Vector
#### Vector
```cpp
template < typename T, size_t Size >
constexpr vec<T, Size> abs(const vec<T, Size>& xs);
@@ -813,7 +995,7 @@ template < typename T, size_t Size >
constexpr vec<T, Size> sign(const vec<T, Size>& xs);
template < typename T, size_t Size >
constexpr vec<T, Size> reciprocal(const vec<T, Size>& xs);
constexpr vec<T, Size> rcp(const vec<T, Size>& xs);
template < typename T, size_t Size >
vec<T, Size> floor(const vec<T, Size>& xs);
@@ -905,9 +1087,9 @@ vec<T, Size> ldexp(const vec<T, Size>& xs, const vec<int, Size>& exps);
### Geometric Functions
```cpp
// Scalar
#### Scalar
```cpp
template < arithmetic T >
constexpr T dot(T x, T y) noexcept;
@@ -934,9 +1116,11 @@ constexpr T reflect(T i, T n) noexcept;
template < floating_point T >
T refract(T i, T n, T eta) noexcept;
```
// Vector
#### Vector
```cpp
template < typename T, size_t Size >
constexpr T dot(const vec<T, Size>& xs, const vec<T, Size>& ys);
@@ -973,8 +1157,20 @@ vec<T, Size> refract(const vec<T, Size>& i, const vec<T, Size>& n, T eta);
### Relational Functions
#### Scalar
```cpp
// Scalar
template < arithmetic T >
constexpr bool any(T x) noexcept;
template < arithmetic T >
constexpr bool all(T x) noexcept;
template < arithmetic T >
constexpr bool approx(T x, T y) noexcept;
template < arithmetic T >
constexpr bool approx(T x, T y, T epsilon) noexcept;
template < arithmetic T >
constexpr bool less(T x, T y) noexcept;
@@ -991,52 +1187,208 @@ constexpr bool greater_equal(T x, T y) noexcept;
template < arithmetic T >
constexpr bool equal_to(T x, T y) noexcept;
template < arithmetic T >
constexpr bool equal_to(T x, T y, T epsilon) noexcept;
template < arithmetic T >
constexpr bool not_equal_to(T x, T y) noexcept;
```
template < arithmetic T >
constexpr bool not_equal_to(T x, T y, T epsilon) noexcept;
#### Vector
template < arithmetic T >
constexpr bool any(T x) noexcept;
template < arithmetic T >
constexpr bool all(T x) noexcept;
// Vector
template < typename T, size_t Size >
constexpr vec<bool, Size> less(const vec<T, Size>& xs, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> less_equal(const vec<T, Size>& xs, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> greater(const vec<T, Size>& xs, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> greater_equal(const vec<T, Size>& xs, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys, T epsilon);
template < typename T, size_t Size >
constexpr vec<bool, Size> not_equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> not_equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys, T epsilon);
```cpp
// any
template < typename T, size_t Size >
constexpr bool any(const vec<T, Size>& xs);
// all
template < typename T, size_t Size >
constexpr bool all(const vec<T, Size>& xs);
// approx
template < typename T, size_t Size >
constexpr vec<bool, Size> approx(const vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<bool, Size> approx(T x, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> approx(const vec<T, Size>& xs, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> approx(const vec<T, Size>& xs, T y, T epsilon);
template < typename T, size_t Size >
constexpr vec<bool, Size> approx(T x, const vec<T, Size>& ys, T epsilon);
template < typename T, size_t Size >
constexpr vec<bool, Size> approx(const vec<T, Size>& xs, const vec<T, Size>& ys, T epsilon);
// less
template < typename T, size_t Size >
constexpr vec<bool, Size> less(const vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<bool, Size> less(T x, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> less(const vec<T, Size>& xs, const vec<T, Size>& ys);
// less_equal
template < typename T, size_t Size >
constexpr vec<bool, Size> less_equal(const vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<bool, Size> less_equal(T x, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> less_equal(const vec<T, Size>& xs, const vec<T, Size>& ys);
// greater
template < typename T, size_t Size >
constexpr vec<bool, Size> greater(const vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<bool, Size> greater(T x, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> greater(const vec<T, Size>& xs, const vec<T, Size>& ys);
// greater_equal
template < typename T, size_t Size >
constexpr vec<bool, Size> greater_equal(const vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<bool, Size> greater_equal(T x, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> greater_equal(const vec<T, Size>& xs, const vec<T, Size>& ys);
// equal_to
template < typename T, size_t Size >
constexpr vec<bool, Size> equal_to(const vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<bool, Size> equal_to(T x, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys);
// not_equal_to
template < typename T, size_t Size >
constexpr vec<bool, Size> not_equal_to(const vec<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr vec<bool, Size> not_equal_to(T x, const vec<T, Size>& ys);
template < typename T, size_t Size >
constexpr vec<bool, Size> not_equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys);
```
#### Matrix
```cpp
// any
template < typename T, size_t Size >
constexpr bool any(const mat<T, Size>& xs);
// all
template < typename T, size_t Size >
constexpr bool all(const mat<T, Size>& xs);
// approx
template < typename T, size_t Size >
constexpr mat<bool, Size> approx(const mat<T, Size>& xs, T y);
template < typename T, size_t Size >
constexpr mat<bool, Size> approx(T x, const mat<T, Size>& ys);
template < typename T, size_t Size >
constexpr mat<bool, Size> approx(const mat<T, Size>& xs, const mat<T, Size>& ys);
template < typename T, size_t Size >
constexpr mat<bool, Size> approx(const mat<T, Size>& xs, T y, T epsilon);
template < typename T, size_t Size >
constexpr mat<bool, Size> approx(T x, const mat<T, Size>& ys, T epsilon);
template < typename T, size_t Size >
constexpr mat<bool, Size> approx(const mat<T, Size>& xs, const mat<T, Size>& ys, T epsilon);
// less
template < typename T, std::size_t Size >
constexpr mat<bool, Size> less(const mat<T, Size>& xs, T y);
template < typename T, std::size_t Size >
constexpr mat<bool, Size> less(T x, const mat<T, Size>& ys);
template < typename T, std::size_t Size >
constexpr mat<bool, Size> less(const mat<T, Size>& xs, const mat<T, Size>& ys);
// less_equal
template < typename T, std::size_t Size >
constexpr mat<bool, Size> less_equal(const mat<T, Size>& xs, T y);
template < typename T, std::size_t Size >
constexpr mat<bool, Size> less_equal(T x, const mat<T, Size>& ys);
template < typename T, std::size_t Size >
constexpr mat<bool, Size> less_equal(const mat<T, Size>& xs, const mat<T, Size>& ys);
// greater
template < typename T, std::size_t Size >
constexpr mat<bool, Size> greater(const mat<T, Size>& xs, T y);
template < typename T, std::size_t Size >
constexpr mat<bool, Size> greater(T x, const mat<T, Size>& ys);
template < typename T, std::size_t Size >
constexpr mat<bool, Size> greater(const mat<T, Size>& xs, const mat<T, Size>& ys);
// greater_equal
template < typename T, std::size_t Size >
constexpr mat<bool, Size> greater_equal(const mat<T, Size>& xs, T y);
template < typename T, std::size_t Size >
constexpr mat<bool, Size> greater_equal(T x, const mat<T, Size>& ys);
template < typename T, std::size_t Size >
constexpr mat<bool, Size> greater_equal(const mat<T, Size>& xs, const mat<T, Size>& ys);
// equal_to
template < typename T, std::size_t Size >
constexpr mat<bool, Size> equal_to(const mat<T, Size>& xs, T y);
template < typename T, std::size_t Size >
constexpr mat<bool, Size> equal_to(T x, const mat<T, Size>& ys);
template < typename T, std::size_t Size >
constexpr mat<bool, Size> equal_to(const mat<T, Size>& xs, const mat<T, Size>& ys);
// not_equal_to
template < typename T, std::size_t Size >
constexpr mat<bool, Size> not_equal_to(const mat<T, Size>& xs, T y);
template < typename T, std::size_t Size >
constexpr mat<bool, Size> not_equal_to(T x, const mat<T, Size>& ys);
template < typename T, std::size_t Size >
constexpr mat<bool, Size> not_equal_to(const mat<T, Size>& xs, const mat<T, Size>& ys);
```
### Matrix Functions
@@ -1192,8 +1544,6 @@ constexpr mat<T, 4> scale(const mat<T, 4>& m, T x, T y, T z);
template < typename T >
constexpr mat<T, 4> scale(const mat<T, 4>& m, const vec<T, 3>& v);
// look_at
template < typename T >
mat<T, 4> look_at_lh(const vec<T, 3>& eye, const vec<T, 3>& at, const vec<T, 3>& up);
@@ -1302,7 +1652,7 @@ vec<T, 3> rotate(const vec<T, 3>& v, T angle, const vec<T, 3>& normal);
template < typename T >
vec<T, 4> rotate(const vec<T, 4>& v, T angle, const vec<T, 3>& normal);
template < typename T, std::size_t Size >
template < typename T, size_t Size >
vec<T, Size> project(const vec<T, Size>& v, const vec<T, Size>& normal);
```

View File

@@ -483,9 +483,9 @@ namespace vmath_hpp
template < typename T >
[[nodiscard]] mat<T, 4> orthographic_lh_zo(T left, T right, T bottom, T top, T znear, T zfar) {
const T sx = T(2) * reciprocal(right - left);
const T sy = T(2) * reciprocal(top - bottom);
const T sz = T(1) * reciprocal(zfar - znear);
const T sx = T(2) * rcp(right - left);
const T sy = T(2) * rcp(top - bottom);
const T sz = T(1) * rcp(zfar - znear);
const T tx = - (right + left) / (right - left);
const T ty = - (top + bottom) / (top - bottom);
@@ -500,9 +500,9 @@ namespace vmath_hpp
template < typename T >
[[nodiscard]] mat<T, 4> orthographic_lh_no(T left, T right, T bottom, T top, T znear, T zfar) {
const T sx = T(2) * reciprocal(right - left);
const T sy = T(2) * reciprocal(top - bottom);
const T sz = T(2) * reciprocal(zfar - znear);
const T sx = T(2) * rcp(right - left);
const T sy = T(2) * rcp(top - bottom);
const T sz = T(2) * rcp(zfar - znear);
const T tx = - (right + left) / (right - left);
const T ty = - (top + bottom) / (top - bottom);
@@ -517,9 +517,9 @@ namespace vmath_hpp
template < typename T >
[[nodiscard]] mat<T, 4> orthographic_rh_zo(T left, T right, T bottom, T top, T znear, T zfar) {
const T sx = T(2) * reciprocal(right - left);
const T sy = T(2) * reciprocal(top - bottom);
const T sz = -T(1) * reciprocal(zfar - znear);
const T sx = T(2) * rcp(right - left);
const T sy = T(2) * rcp(top - bottom);
const T sz = -T(1) * rcp(zfar - znear);
const T tx = - (right + left) / (right - left);
const T ty = - (top + bottom) / (top - bottom);
@@ -534,9 +534,9 @@ namespace vmath_hpp
template < typename T >
[[nodiscard]] mat<T, 4> orthographic_rh_no(T left, T right, T bottom, T top, T znear, T zfar) {
const T sx = T(2) * reciprocal(right - left);
const T sy = T(2) * reciprocal(top - bottom);
const T sz = -T(2) * reciprocal(zfar - znear);
const T sx = T(2) * rcp(right - left);
const T sy = T(2) * rcp(top - bottom);
const T sz = -T(2) * rcp(zfar - znear);
const T tx = - (right + left) / (right - left);
const T ty = - (top + bottom) / (top - bottom);
@@ -553,7 +553,7 @@ namespace vmath_hpp
template < typename T >
[[nodiscard]] mat<T, 4> perspective_lh_zo(T fov, T aspect, T znear, T zfar) {
const T sy = reciprocal(tan(fov * T(0.5)));
const T sy = rcp(tan(fov * T(0.5)));
const T sx = sy / aspect;
const T sz = zfar / (zfar - znear);
const T tz = (znear * zfar) / (znear - zfar);
@@ -566,7 +566,7 @@ namespace vmath_hpp
template < typename T >
[[nodiscard]] mat<T, 4> perspective_lh_no(T fov, T aspect, T znear, T zfar) {
const T sy = reciprocal(tan(fov * T(0.5)));
const T sy = rcp(tan(fov * T(0.5)));
const T sx = sy / aspect;
const T sz = (zfar + znear) / (zfar - znear);
const T tz = (T(2) * znear * zfar) / (znear - zfar);
@@ -579,7 +579,7 @@ namespace vmath_hpp
template < typename T >
[[nodiscard]] mat<T, 4> perspective_rh_zo(T fov, T aspect, T znear, T zfar) {
const T sy = reciprocal(tan(fov * T(0.5)));
const T sy = rcp(tan(fov * T(0.5)));
const T sx = sy / aspect;
const T sz = zfar / (znear - zfar);
const T tz = (znear * zfar) / (znear - zfar);
@@ -592,7 +592,7 @@ namespace vmath_hpp
template < typename T >
[[nodiscard]] mat<T, 4> perspective_rh_no(T fov, T aspect, T znear, T zfar) {
const T sy = reciprocal(tan(fov * T(0.5)));
const T sy = rcp(tan(fov * T(0.5)));
const T sx = sy / aspect;
const T sz = (zfar + znear) / (znear - zfar);
const T tz = (T(2) * znear * zfar) / (znear - zfar);

View File

@@ -34,7 +34,7 @@ namespace vmath_hpp
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
constexpr reciprocal(T x) noexcept {
constexpr rcp(T x) noexcept {
return T(1) / x;
}
@@ -331,7 +331,7 @@ namespace vmath_hpp
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
rsqrt(T x) noexcept {
return reciprocal(sqrt(x));
return rcp(sqrt(x));
}
}
@@ -399,11 +399,46 @@ namespace vmath_hpp
}
//
// Scalar Relational Functions
// Relational Functions
//
namespace vmath_hpp
{
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
constexpr any(T x) noexcept {
return !!x;
}
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
constexpr all(T x) noexcept {
return !!x;
}
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
constexpr approx(T x, T y) noexcept {
if constexpr ( std::is_floating_point_v<T> ) {
// http://www.realtimecollisiondetection.net/pubs/Tolerances
const T epsilon = std::numeric_limits<T>::epsilon();
return abs(x - y) <= epsilon * max(T(1), abs(x), abs(y));
} else {
return x == y;
}
}
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
constexpr approx(T x, T y, T epsilon) noexcept {
if constexpr ( std::is_floating_point_v<T> ) {
// http://www.realtimecollisiondetection.net/pubs/Tolerances
return abs(x - y) <= epsilon * max(T(1), abs(x), abs(y));
} else {
return abs(x - y) <= epsilon;
}
}
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
constexpr less(T x, T y) noexcept {
@@ -431,47 +466,12 @@ namespace vmath_hpp
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
constexpr equal_to(T x, T y) noexcept {
if constexpr ( std::is_floating_point_v<T> ) {
// http://www.realtimecollisiondetection.net/pubs/Tolerances
const T epsilon = std::numeric_limits<T>::epsilon();
return abs(x - y) <= epsilon * max(T(1), abs(x), abs(y));
} else {
return x == y;
}
}
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
constexpr equal_to(T x, T y, T epsilon) noexcept {
if constexpr ( std::is_floating_point_v<T> ) {
// http://www.realtimecollisiondetection.net/pubs/Tolerances
return abs(x - y) <= epsilon * max(T(1), abs(x), abs(y));
} else {
return abs(x - y) <= epsilon;
}
return x == y;
}
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
constexpr not_equal_to(T x, T y) noexcept {
return !equal_to(x, y);
}
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
constexpr not_equal_to(T x, T y, T epsilon) noexcept {
return !equal_to(x, y, epsilon);
}
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
constexpr any(T x) noexcept {
return !!x;
}
template < typename T >
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
constexpr all(T x) noexcept {
return !!x;
return x != y;
}
}

View File

@@ -199,6 +199,20 @@ namespace vmath_hpp
return map_join([](const vec<T, Size>& x){ return -x; }, xs);
}
// ~operator
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<T, Size> operator~(const mat<T, Size>& xs) {
return map_join([](const vec<T, Size>& x){ return ~x; }, xs);
}
// !operator
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> operator!(const mat<T, Size>& xs) {
return map_join([](const vec<T, Size>& x){ return !x; }, xs);
}
// operator+
template < typename T, std::size_t Size >
@@ -220,12 +234,12 @@ namespace vmath_hpp
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator+=(mat<T, Size>& xs, T y) {
return (xs = xs + y);
return (xs = (xs + y));
}
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator+=(mat<T, Size>& xs, const mat<T, Size>& ys) {
return (xs = xs + ys);
return (xs = (xs + ys));
}
// operator-
@@ -249,12 +263,12 @@ namespace vmath_hpp
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator-=(mat<T, Size>& xs, T y) {
return (xs = xs - y);
return (xs = (xs - y));
}
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator-=(mat<T, Size>& xs, const mat<T, Size>& ys) {
return (xs = xs - ys);
return (xs = (xs - ys));
}
// operator*
@@ -287,17 +301,17 @@ namespace vmath_hpp
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator*=(mat<T, Size>& xs, T y) {
return (xs = xs * y);
return (xs = (xs * y));
}
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator*=(vec<T, Size>& xs, const mat<T, Size>& ys) {
return (xs = xs * ys);
return (xs = (xs * ys));
}
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator*=(mat<T, Size>& xs, const mat<T, Size>& ys) {
return (xs = xs * ys);
return (xs = (xs * ys));
}
// operator/
@@ -312,21 +326,132 @@ namespace vmath_hpp
return map_join([x](const vec<T, Size>& y){ return x / y; }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<T, Size> operator/(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return x / y; }, xs, ys);
}
// operator/=
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator/=(mat<T, Size>& xs, T y) {
return (xs = xs / y);
return (xs = (xs / y));
}
// operator&
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<T, Size> operator&(const mat<T, Size>& xs, T y) {
return map_join([y](const vec<T, Size>& x){ return x & y; }, xs);
}
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator/=(mat<T, Size>& xs, const mat<T, Size>& ys) {
return (xs = xs / ys);
[[nodiscard]] constexpr mat<T, Size> operator&(T x, const mat<T, Size>& ys) {
return map_join([x](const vec<T, Size>& y){ return x & y; }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<T, Size> operator&(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return x & y; }, xs, ys);
}
// operator&=
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator&=(mat<T, Size>& xs, T y) {
return (xs = (xs & y));
}
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator&=(mat<T, Size>& xs, const mat<T, Size>& ys) {
return (xs = (xs & ys));
}
// operator|
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<T, Size> operator|(const mat<T, Size>& xs, T y) {
return map_join([y](const vec<T, Size>& x){ return x | y; }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<T, Size> operator|(T x, const mat<T, Size>& ys) {
return map_join([x](const vec<T, Size>& y){ return x | y; }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<T, Size> operator|(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return x | y; }, xs, ys);
}
// operator|=
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator|=(mat<T, Size>& xs, T y) {
return (xs = (xs | y));
}
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator|=(mat<T, Size>& xs, const mat<T, Size>& ys) {
return (xs = (xs | ys));
}
// operator^
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<T, Size> operator^(const mat<T, Size>& xs, T y) {
return map_join([y](const vec<T, Size>& x){ return x ^ y; }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<T, Size> operator^(T x, const mat<T, Size>& ys) {
return map_join([x](const vec<T, Size>& y){ return x ^ y; }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<T, Size> operator^(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return x ^ y; }, xs, ys);
}
// operator^=
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator^=(mat<T, Size>& xs, T y) {
return (xs = (xs ^ y));
}
template < typename T, std::size_t Size >
constexpr mat<T, Size>& operator^=(mat<T, Size>& xs, const mat<T, Size>& ys) {
return (xs = (xs ^ ys));
}
// operator&&
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> operator&&(const mat<T, Size>& xs, T y) {
return map_join([y](const vec<T, Size>& x){ return x && y; }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> operator&&(T x, const mat<T, Size>& ys) {
return map_join([x](const vec<T, Size>& y){ return x && y; }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> operator&&(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return x && y; }, xs, ys);
}
// operator||
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> operator||(const mat<T, Size>& xs, T y) {
return map_join([y](const vec<T, Size>& x){ return x || y; }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> operator||(T x, const mat<T, Size>& ys) {
return map_join([x](const vec<T, Size>& y){ return x || y; }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> operator||(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return x || y; }, xs, ys);
}
// operator==
@@ -338,9 +463,13 @@ namespace vmath_hpp
}, true, xs, ys);
}
// operator!=
template < typename T, std::size_t Size >
[[nodiscard]] constexpr bool operator!=(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return !(xs == ys);
return fold_join([](bool acc, const vec<T, Size>& x, const vec<T, Size>& y){
return acc || (x != y);
}, false, xs, ys);
}
// operator<
@@ -359,6 +488,161 @@ namespace vmath_hpp
}
}
//
// Relational Functions
//
namespace vmath_hpp
{
// any
template < typename T, std::size_t Size >
[[nodiscard]] constexpr bool any(const mat<T, Size>& xs) {
return fold_join([](bool acc, const vec<T, Size>& x){ return acc || any(x); }, false, xs);
}
// all
template < typename T, std::size_t Size >
[[nodiscard]] constexpr bool all(const mat<T, Size>& xs) {
return fold_join([](bool acc, const vec<T, Size>& x){ return acc && all(x); }, true, xs);
}
// approx
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> approx(const mat<T, Size>& xs, T y) {
return map_join([y](const vec<T, Size>& x){ return approx(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> approx(T x, const mat<T, Size>& ys) {
return map_join([x](const vec<T, Size>& y){ return approx(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> approx(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return approx(x, y); }, xs, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> approx(const mat<T, Size>& xs, T y, T epsilon) {
return map_join([y, epsilon](const vec<T, Size>& x){ return approx(x, y, epsilon); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> approx(T x, const mat<T, Size>& ys, T epsilon) {
return map_join([x, epsilon](const vec<T, Size>& y){ return approx(x, y, epsilon); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> approx(const mat<T, Size>& xs, const mat<T, Size>& ys, T epsilon) {
return map_join([epsilon](const vec<T, Size>& x, const vec<T, Size>& y){ return approx(x, y, epsilon); }, xs, ys);
}
// less
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> less(const mat<T, Size>& xs, T y) {
return map_join([y](const vec<T, Size>& x){ return less(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> less(T x, const mat<T, Size>& ys) {
return map_join([x](const vec<T, Size>& y){ return less(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> less(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return less(x, y); }, xs, ys);
}
// less_equal
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> less_equal(const mat<T, Size>& xs, T y) {
return map_join([y](const vec<T, Size>& x){ return less_equal(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> less_equal(T x, const mat<T, Size>& ys) {
return map_join([x](const vec<T, Size>& y){ return less_equal(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> less_equal(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return less_equal(x, y); }, xs, ys);
}
// greater
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> greater(const mat<T, Size>& xs, T y) {
return map_join([y](const vec<T, Size>& x){ return greater(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> greater(T x, const mat<T, Size>& ys) {
return map_join([x](const vec<T, Size>& y){ return greater(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> greater(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return greater(x, y); }, xs, ys);
}
// greater_equal
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> greater_equal(const mat<T, Size>& xs, T y) {
return map_join([y](const vec<T, Size>& x){ return greater_equal(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> greater_equal(T x, const mat<T, Size>& ys) {
return map_join([x](const vec<T, Size>& y){ return greater_equal(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> greater_equal(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return greater_equal(x, y); }, xs, ys);
}
// equal_to
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> equal_to(const mat<T, Size>& xs, T y) {
return map_join([y](const vec<T, Size>& x){ return equal_to(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> equal_to(T x, const mat<T, Size>& ys) {
return map_join([x](const vec<T, Size>& y){ return equal_to(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> equal_to(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return equal_to(x, y); }, xs, ys);
}
// not_equal_to
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> not_equal_to(const mat<T, Size>& xs, T y) {
return map_join([y](const vec<T, Size>& x){ return not_equal_to(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> not_equal_to(T x, const mat<T, Size>& ys) {
return map_join([x](const vec<T, Size>& y){ return not_equal_to(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr mat<bool, Size> not_equal_to(const mat<T, Size>& xs, const mat<T, Size>& ys) {
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return not_equal_to(x, y); }, xs, ys);
}
}
//
// Matrix Functions
//
@@ -506,7 +790,7 @@ namespace vmath_hpp
T a, T b,
T c, T d)
{
const T inv_det = reciprocal(determinant_2x2_impl(
const T inv_det = rcp(determinant_2x2_impl(
a, b,
c, d));
@@ -524,7 +808,7 @@ namespace vmath_hpp
T d, T e, T f,
T g, T h, T i)
{
const T inv_det = reciprocal(determinant_3x3_impl(
const T inv_det = rcp(determinant_3x3_impl(
a, b, c,
d, e, f,
g, h, i));
@@ -551,7 +835,7 @@ namespace vmath_hpp
T i, T j, T k, T l,
T m, T n, T o, T p)
{
const T inv_det = reciprocal(determinant_4x4_impl(
const T inv_det = rcp(determinant_4x4_impl(
a, b, c, d,
e, f, g, h,
i, j, k, l,

View File

@@ -172,6 +172,20 @@ namespace vmath_hpp
return map_join([](T x){ return -x; }, xs);
}
// ~operator
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<T, Size> operator~(const vec<T, Size>& xs) {
return map_join([](T x){ return ~x; }, xs);
}
// !operator
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> operator!(const vec<T, Size>& xs) {
return map_join([](T x){ return !x; }, xs);
}
// operator+
template < typename T, std::size_t Size >
@@ -193,12 +207,12 @@ namespace vmath_hpp
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator+=(vec<T, Size>& xs, T y) {
return (xs = xs + y);
return (xs = (xs + y));
}
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator+=(vec<T, Size>& xs, const vec<T, Size>& ys) {
return (xs = xs + ys);
return (xs = (xs + ys));
}
// operator-
@@ -222,12 +236,12 @@ namespace vmath_hpp
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator-=(vec<T, Size>& xs, T y) {
return (xs = xs - y);
return (xs = (xs - y));
}
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator-=(vec<T, Size>& xs, const vec<T, Size>& ys) {
return (xs = xs - ys);
return (xs = (xs - ys));
}
// operator*
@@ -251,12 +265,12 @@ namespace vmath_hpp
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator*=(vec<T, Size>& xs, T y) {
return (xs = xs * y);
return (xs = (xs * y));
}
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator*=(vec<T, Size>& xs, const vec<T, Size>& ys) {
return (xs = xs * ys);
return (xs = (xs * ys));
}
// operator/
@@ -280,12 +294,133 @@ namespace vmath_hpp
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator/=(vec<T, Size>& xs, T y) {
return (xs = xs / y);
return (xs = (xs / y));
}
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator/=(vec<T, Size>& xs, const vec<T, Size>& ys) {
return (xs = xs / ys);
return (xs = (xs / ys));
}
// operator&
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<T, Size> operator&(const vec<T, Size>& xs, T y) {
return map_join([y](T x){ return x & y; }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<T, Size> operator&(T x, const vec<T, Size>& ys) {
return map_join([x](T y){ return x & y; }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<T, Size> operator&(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return map_join([](T x, T y){ return x & y; }, xs, ys);
}
// operator&=
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator&=(vec<T, Size>& xs, T y) {
return (xs = (xs & y));
}
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator&=(vec<T, Size>& xs, const vec<T, Size>& ys) {
return (xs = (xs & ys));
}
// operator|
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<T, Size> operator|(const vec<T, Size>& xs, T y) {
return map_join([y](T x){ return x | y; }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<T, Size> operator|(T x, const vec<T, Size>& ys) {
return map_join([x](T y){ return x | y; }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<T, Size> operator|(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return map_join([](T x, T y){ return x | y; }, xs, ys);
}
// operator|=
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator|=(vec<T, Size>& xs, T y) {
return (xs = (xs | y));
}
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator|=(vec<T, Size>& xs, const vec<T, Size>& ys) {
return (xs = (xs | ys));
}
// operator^
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<T, Size> operator^(const vec<T, Size>& xs, T y) {
return map_join([y](T x){ return x ^ y; }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<T, Size> operator^(T x, const vec<T, Size>& ys) {
return map_join([x](T y){ return x ^ y; }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<T, Size> operator^(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return map_join([](T x, T y){ return x ^ y; }, xs, ys);
}
// operator^=
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator^=(vec<T, Size>& xs, T y) {
return (xs = (xs ^ y));
}
template < typename T, std::size_t Size >
constexpr vec<T, Size>& operator^=(vec<T, Size>& xs, const vec<T, Size>& ys) {
return (xs = (xs ^ ys));
}
// operator&&
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> operator&&(const vec<T, Size>& xs, T y) {
return map_join([y](T x){ return x && y; }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> operator&&(T x, const vec<T, Size>& ys) {
return map_join([x](T y){ return x && y; }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> operator&&(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return map_join([](T x, T y){ return x && y; }, xs, ys);
}
// operator||
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> operator||(const vec<T, Size>& xs, T y) {
return map_join([y](T x){ return x || y; }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> operator||(T x, const vec<T, Size>& ys) {
return map_join([x](T y){ return x || y; }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> operator||(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return map_join([](T x, T y){ return x || y; }, xs, ys);
}
// operator==
@@ -293,13 +428,17 @@ namespace vmath_hpp
template < typename T, std::size_t Size >
[[nodiscard]] constexpr bool operator==(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return fold_join([](bool acc, T x, T y){
return acc && equal_to(x, y);
return acc && x == y;
}, true, xs, ys);
}
// operator!=
template < typename T, std::size_t Size >
[[nodiscard]] constexpr bool operator!=(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return !(xs == ys);
return fold_join([](bool acc, T x, T y){
return acc || x != y;
}, false, xs, ys);
}
// operator<
@@ -465,8 +604,8 @@ namespace vmath_hpp
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<T, Size> reciprocal(const vec<T, Size>& xs) {
return map_join([](T x) { return reciprocal(x); }, xs);
[[nodiscard]] constexpr vec<T, Size> rcp(const vec<T, Size>& xs) {
return map_join([](T x) { return rcp(x); }, xs);
}
template < typename T, std::size_t Size >
@@ -703,58 +842,156 @@ namespace vmath_hpp
}
//
// Vector Relational Functions
// Relational Functions
//
namespace vmath_hpp
{
// any
template < typename T, std::size_t Size >
[[nodiscard]] constexpr bool any(const vec<T, Size>& xs) {
return fold_join([](bool acc, T x){ return acc || any(x); }, false, xs);
}
// all
template < typename T, std::size_t Size >
[[nodiscard]] constexpr bool all(const vec<T, Size>& xs) {
return fold_join([](bool acc, T x){ return acc && all(x); }, true, xs);
}
// approx
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> approx(const vec<T, Size>& xs, T y) {
return map_join([y](T x){ return approx(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> approx(T x, const vec<T, Size>& ys) {
return map_join([x](T y){ return approx(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> approx(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return map_join([](T x, T y){ return approx(x, y); }, xs, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> approx(const vec<T, Size>& xs, T y, T epsilon) {
return map_join([y, epsilon](T x){ return approx(x, y, epsilon); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> approx(T x, const vec<T, Size>& ys, T epsilon) {
return map_join([x, epsilon](T y){ return approx(x, y, epsilon); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> approx(const vec<T, Size>& xs, const vec<T, Size>& ys, T epsilon) {
return map_join([epsilon](T x, T y){ return approx(x, y, epsilon); }, xs, ys);
}
// less
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> less(const vec<T, Size>& xs, T y) {
return map_join([y](T x){ return less(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> less(T x, const vec<T, Size>& ys) {
return map_join([x](T y){ return less(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> less(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return map_join([](T x, T y){ return less(x, y); }, xs, ys);
}
// less_equal
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> less_equal(const vec<T, Size>& xs, T y) {
return map_join([y](T x){ return less_equal(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> less_equal(T x, const vec<T, Size>& ys) {
return map_join([x](T y){ return less_equal(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> less_equal(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return map_join([](T x, T y){ return less_equal(x, y); }, xs, ys);
}
// greater
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> greater(const vec<T, Size>& xs, T y) {
return map_join([y](T x){ return greater(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> greater(T x, const vec<T, Size>& ys) {
return map_join([x](T y){ return greater(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> greater(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return map_join([](T x, T y){ return greater(x, y); }, xs, ys);
}
// greater_equal
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> greater_equal(const vec<T, Size>& xs, T y) {
return map_join([y](T x){ return greater_equal(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> greater_equal(T x, const vec<T, Size>& ys) {
return map_join([x](T y){ return greater_equal(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> greater_equal(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return map_join([](T x, T y){ return greater_equal(x, y); }, xs, ys);
}
// equal_to
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> equal_to(const vec<T, Size>& xs, T y) {
return map_join([y](T x){ return equal_to(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> equal_to(T x, const vec<T, Size>& ys) {
return map_join([x](T y){ return equal_to(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return map_join([](T x, T y){ return equal_to(x, y); }, xs, ys);
}
// not_equal_to
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys, T epsilon) {
return map_join([epsilon](T x, T y){ return equal_to(x, y, epsilon); }, xs, ys);
[[nodiscard]] constexpr vec<bool, Size> not_equal_to(const vec<T, Size>& xs, T y) {
return map_join([y](T x){ return not_equal_to(x, y); }, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> not_equal_to(T x, const vec<T, Size>& ys) {
return map_join([x](T y){ return not_equal_to(x, y); }, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> not_equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys) {
return map_join([](T x, T y){ return not_equal_to(x, y); }, xs, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr vec<bool, Size> not_equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys, T epsilon) {
return map_join([epsilon](T x, T y){ return not_equal_to(x, y, epsilon); }, xs, ys);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr bool any(const vec<T, Size>& xs) {
return fold_join([](bool acc, T x){ return acc || any(x); }, false, xs);
}
template < typename T, std::size_t Size >
[[nodiscard]] constexpr bool all(const vec<T, Size>& xs) {
return fold_join([](bool acc, T x){ return acc && all(x); }, true, xs);
}
}

View File

@@ -135,11 +135,11 @@ TEST_CASE("vmath/ext") {
}
SUBCASE("matrix translate") {
STATIC_REQUIRE(float3(2.f,3.f,1.f) * translate(float2{1.f,2.f}) == approx3(3.f,5.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * translate(translate(float2{1.f,2.f}), float2{1.f,2.f}) == approx3(4.f,7.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * translate(float2{1.f,2.f}) == uapprox3(3.f,5.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * translate(translate(float2{1.f,2.f}), float2{1.f,2.f}) == uapprox3(4.f,7.f,1.f));
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(float3{1.f,2.f,3.f}) == approx4(3.f,5.f,7.f,1.f));
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(float3{1.f,2.f,3.f}), float3{1.f,2.f,3.f}) == approx4(4.f,7.f,10.f,1.f));
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(float3{1.f,2.f,3.f}) == uapprox4(3.f,5.f,7.f,1.f));
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(float3{1.f,2.f,3.f}), float3{1.f,2.f,3.f}) == uapprox4(4.f,7.f,10.f,1.f));
}
SUBCASE("matrix rotate") {
@@ -147,47 +147,47 @@ TEST_CASE("vmath/ext") {
constexpr float pi_2 = radians(90.f);
constexpr float pi_4 = radians(45.f);
REQUIRE(float4(0.f,1.f,0.f,1.f) * rotate_x(pi_2) == approx4(0.f,0.f,1.f,1.f));
REQUIRE(float4(0.f,0.f,1.f,1.f) * rotate_y(pi_2) == approx4(1.f,0.f,0.f,1.f));
REQUIRE(float4(1.f,0.f,0.f,1.f) * rotate_z(pi_2) == approx4(0.f,1.f,0.f,1.f));
REQUIRE(float4(0.f,1.f,0.f,1.f) * rotate_x(pi_2) == uapprox4(0.f,0.f,1.f,1.f));
REQUIRE(float4(0.f,0.f,1.f,1.f) * rotate_y(pi_2) == uapprox4(1.f,0.f,0.f,1.f));
REQUIRE(float4(1.f,0.f,0.f,1.f) * rotate_z(pi_2) == uapprox4(0.f,1.f,0.f,1.f));
REQUIRE(float4(0.f,1.f,0.f,1.f) * rotate_x(rotate_x(pi_4),pi_4) == approx4(0.f,0.f,1.f,1.f));
REQUIRE(float4(0.f,0.f,1.f,1.f) * rotate_y(rotate_y(pi_4),pi_4) == approx4(1.f,0.f,0.f,1.f));
REQUIRE(float4(1.f,0.f,0.f,1.f) * rotate_z(rotate_z(pi_4),pi_4) == approx4(0.f,1.f,0.f,1.f));
REQUIRE(float4(0.f,1.f,0.f,1.f) * rotate_x(rotate_x(pi_4),pi_4) == uapprox4(0.f,0.f,1.f,1.f));
REQUIRE(float4(0.f,0.f,1.f,1.f) * rotate_y(rotate_y(pi_4),pi_4) == uapprox4(1.f,0.f,0.f,1.f));
REQUIRE(float4(1.f,0.f,0.f,1.f) * rotate_z(rotate_z(pi_4),pi_4) == uapprox4(0.f,1.f,0.f,1.f));
REQUIRE(float3(2.f,3.f,1.f) * rotate(pi) == approx3(-2.f,-3.f,1.f));
REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f));
REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f));
REQUIRE(float3(2.f,3.f,1.f) * rotate(pi) == uapprox3(-2.f,-3.f,1.f));
REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f));
REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,float3{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f));
REQUIRE(float3(2.f,3.f,1.f) * rotate(rotate(pi_2),pi_2) == approx3(-2.f,-3.f,1.f));
REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,{0.f,0.f,1.f}),pi_2,{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f));
REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,float3{0.f,0.f,1.f}),pi_2,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f));
REQUIRE(float3(2.f,3.f,1.f) * rotate(rotate(pi_2),pi_2) == uapprox3(-2.f,-3.f,1.f));
REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,{0.f,0.f,1.f}),pi_2,{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f));
REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,float3{0.f,0.f,1.f}),pi_2,float3{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f));
}
SUBCASE("matrix scale") {
STATIC_REQUIRE(float3(2.f,3.f,1.f) * scale(float2{2.f,3.f}) == approx3(4.f,9.f,1.f));
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f));
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * scale(float2{2.f,3.f}) == uapprox3(4.f,9.f,1.f));
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == uapprox4(4.f,9.f,16.f,1.f));
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == uapprox4(4.f,9.f,16.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * scale(scale(float2{2.f,2.f}), {2.f,3.f}) == approx3(8.f,18.f,1.f));
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), {2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f));
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), float3{2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * scale(scale(float2{2.f,2.f}), {2.f,3.f}) == uapprox3(8.f,18.f,1.f));
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), {2.f,3.f,4.f}) == uapprox4(8.f,18.f,32.f,1.f));
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), float3{2.f,3.f,4.f}) == uapprox4(8.f,18.f,32.f,1.f));
}
SUBCASE("matrix shear") {
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_x(0.f) == approx3(2.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_x(1.f) == approx3(5.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_x(shear_x(1.f),1.f) == approx3(8.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_x(0.f) == uapprox3(2.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_x(1.f) == uapprox3(5.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_x(shear_x(1.f),1.f) == uapprox3(8.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_y(0.f) == approx3(2.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_y(1.f) == approx3(2.f,5.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_y(shear_y(1.f),1.f) == approx3(2.f,7.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_y(0.f) == uapprox3(2.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_y(1.f) == uapprox3(2.f,5.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_y(shear_y(1.f),1.f) == uapprox3(2.f,7.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(float2(0.f,0.f)) == approx3(2.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(float2(1.f,0.f)) == approx3(5.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(float2(0.f,1.f)) == approx3(2.f,5.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(shear(float2(1.f,0.f)),float2(1.f,0.f)) == approx3(8.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(shear(float2(0.f,1.f)),float2(0.f,1.f)) == approx3(2.f,7.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(float2(0.f,0.f)) == uapprox3(2.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(float2(1.f,0.f)) == uapprox3(5.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(float2(0.f,1.f)) == uapprox3(2.f,5.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(shear(float2(1.f,0.f)),float2(1.f,0.f)) == uapprox3(8.f,3.f,1.f));
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(shear(float2(0.f,1.f)),float2(0.f,1.f)) == uapprox3(2.f,7.f,1.f));
}
SUBCASE("matrix look_at") {
@@ -206,24 +206,24 @@ TEST_CASE("vmath/ext") {
}
SUBCASE("vector angle") {
REQUIRE(angle(float2(2.f,0.f), float2(0.f,1.f)) == approx(radians(90.f)));
REQUIRE(angle(float2(0.f,3.f), float2(1.f,0.f)) == approx(radians(90.f)));
REQUIRE(angle(float2(0.5f,0.f), float2(-1.f,0.f)) == approx(radians(180.f)));
REQUIRE(angle(float2(-0.2f,0.f), float2(1.f,0.f)) == approx(radians(180.f)));
REQUIRE(angle(float3(0.f,2.f,0.f), float3(0.f,0.f,1.f)) == approx(radians(90.f)));
REQUIRE(angle(float3(0.f,0.f,3.f), float3(0.f,1.f,0.f)) == approx(radians(90.f)));
REQUIRE(angle(float2(2.f,0.f), float2(0.f,1.f)) == uapprox(radians(90.f)));
REQUIRE(angle(float2(0.f,3.f), float2(1.f,0.f)) == uapprox(radians(90.f)));
REQUIRE(angle(float2(0.5f,0.f), float2(-1.f,0.f)) == uapprox(radians(180.f)));
REQUIRE(angle(float2(-0.2f,0.f), float2(1.f,0.f)) == uapprox(radians(180.f)));
REQUIRE(angle(float3(0.f,2.f,0.f), float3(0.f,0.f,1.f)) == uapprox(radians(90.f)));
REQUIRE(angle(float3(0.f,0.f,3.f), float3(0.f,1.f,0.f)) == uapprox(radians(90.f)));
}
SUBCASE("vector rotate") {
REQUIRE(rotate(float2(2.f,0.f), radians(90.f)) == approx2(0.f,2.f));
REQUIRE(rotate(float2(1.5f,0.f), radians(-90.f)) == approx2(0.f,-1.5f));
REQUIRE(rotate(float2(2.f,0.f), radians(90.f)) == uapprox2(0.f,2.f));
REQUIRE(rotate(float2(1.5f,0.f), radians(-90.f)) == uapprox2(0.f,-1.5f));
REQUIRE(rotate(float3(1.5f,0.f,0.f), radians(90.f), float3(0,0,1)) == approx3(0.f,1.5f,0.f));
REQUIRE(rotate(float4(1.5f,0.f,0.f,1.f), radians(90.f), float3(0,0,1)) == approx4(0.f,1.5f,0.f,1.f));
REQUIRE(rotate(float3(1.5f,0.f,0.f), radians(90.f), float3(0,0,1)) == uapprox3(0.f,1.5f,0.f));
REQUIRE(rotate(float4(1.5f,0.f,0.f,1.f), radians(90.f), float3(0,0,1)) == uapprox4(0.f,1.5f,0.f,1.f));
}
SUBCASE("vector project") {
REQUIRE(project(float2(2.f, 2.f), float2(0.f, 1.f)) == approx2(0.f, 2.f));
REQUIRE(project(float3(2.f, 2.f, 2.f), float3(0.f, 0.f, 1.f)) == approx3(0.f, 0.f, 2.f));
REQUIRE(project(float2(2.f, 2.f), float2(0.f, 1.f)) == uapprox2(0.f, 2.f));
REQUIRE(project(float3(2.f, 2.f, 2.f), float3(0.f, 0.f, 1.f)) == uapprox3(0.f, 0.f, 2.f));
}
}

View File

@@ -15,8 +15,8 @@ namespace
TEST_CASE("vmath/fun") {
SUBCASE("Angle and Trigonometry Functions") {
STATIC_REQUIRE(radians(degrees(12.13f)) == approx(12.13f));
STATIC_REQUIRE(degrees(radians(12.13f)) == approx(12.13f));
STATIC_REQUIRE(radians(degrees(12.13f)) == uapprox(12.13f));
STATIC_REQUIRE(degrees(radians(12.13f)) == uapprox(12.13f));
(void)sin(0.f);
(void)cos(0.f);
@@ -38,8 +38,8 @@ TEST_CASE("vmath/fun") {
{
float out_s{}, out_c{};
sincos(15.f, &out_s, &out_c);
REQUIRE(out_s == approx(sin(15.f)));
REQUIRE(out_c == approx(cos(15.f)));
REQUIRE(out_s == uapprox(sin(15.f)));
REQUIRE(out_c == uapprox(cos(15.f)));
}
}
@@ -56,125 +56,93 @@ TEST_CASE("vmath/fun") {
SUBCASE("Common Functions") {
STATIC_REQUIRE(vmath_hpp::abs(1) == 1);
STATIC_REQUIRE(vmath_hpp::abs(-1) == 1);
STATIC_REQUIRE(vmath_hpp::abs(1.f) == approx(1.f));
STATIC_REQUIRE(vmath_hpp::abs(-1.f) == approx(1.f));
STATIC_REQUIRE(vmath_hpp::abs(1.f) == uapprox(1.f));
STATIC_REQUIRE(vmath_hpp::abs(-1.f) == uapprox(1.f));
STATIC_REQUIRE(sign(2) == 1);
STATIC_REQUIRE(sign(-2) == -1);
STATIC_REQUIRE(sign(0) == 0);
STATIC_REQUIRE(sign(2.f) == approx(1.f));
STATIC_REQUIRE(sign(-2.f) == approx(-1.f));
STATIC_REQUIRE(sign(0.f) == approx(0.f));
STATIC_REQUIRE(sign(2.f) == uapprox(1.f));
STATIC_REQUIRE(sign(-2.f) == uapprox(-1.f));
STATIC_REQUIRE(sign(0.f) == uapprox(0.f));
STATIC_REQUIRE(reciprocal(2.f) == approx(0.5f));
STATIC_REQUIRE(reciprocal(4.f) == approx(0.25f));
STATIC_REQUIRE(rcp(2.f) == uapprox(0.5f));
STATIC_REQUIRE(rcp(4.f) == uapprox(0.25f));
REQUIRE(floor(1.7f) == approx(1.f));
REQUIRE(trunc(1.7f) == approx(1.f));
REQUIRE(round(1.7f) == approx(2.f));
REQUIRE(ceil(1.7f) == approx(2.f));
REQUIRE(floor(1.7f) == uapprox(1.f));
REQUIRE(trunc(1.7f) == uapprox(1.f));
REQUIRE(round(1.7f) == uapprox(2.f));
REQUIRE(ceil(1.7f) == uapprox(2.f));
REQUIRE(fract(1.7f) == approx(0.7f));
REQUIRE(fract(-2.3f) == approx(0.7f));
REQUIRE(fract(1.7f) == uapprox(0.7f));
REQUIRE(fract(-2.3f) == uapprox(0.7f));
REQUIRE(fmod(1.7f, 1.2f) == approx(0.5f));
REQUIRE(fmod(1.7f, 1.2f) == uapprox(0.5f));
{
float out_i{};
REQUIRE(modf(1.7f, &out_i) == approx(0.7f));
REQUIRE(out_i == approx(1.f));
REQUIRE(modf(1.7f, &out_i) == uapprox(0.7f));
REQUIRE(out_i == uapprox(1.f));
}
STATIC_REQUIRE(min(0.f, 1.f) == approx(0.f));
STATIC_REQUIRE(min(3.f, 2.f, 1.f) == approx(1.f));
STATIC_REQUIRE(min(4.f, 3.f, 2.f, 1.f) == approx(1.f));
STATIC_REQUIRE(min(0.f, 1.f) == uapprox(0.f));
STATIC_REQUIRE(min(3.f, 2.f, 1.f) == uapprox(1.f));
STATIC_REQUIRE(min(4.f, 3.f, 2.f, 1.f) == uapprox(1.f));
STATIC_REQUIRE(max(0.f, 1.f) == approx(1.f));
STATIC_REQUIRE(max(3.f, 2.f, 1.f) == approx(3.f));
STATIC_REQUIRE(max(4.f, 3.f, 2.f, 1.f) == approx(4.f));
STATIC_REQUIRE(max(0.f, 1.f) == uapprox(1.f));
STATIC_REQUIRE(max(3.f, 2.f, 1.f) == uapprox(3.f));
STATIC_REQUIRE(max(4.f, 3.f, 2.f, 1.f) == uapprox(4.f));
STATIC_REQUIRE(clamp(1.0f, 2.f, 3.f) == approx(2.0f));
STATIC_REQUIRE(clamp(2.5f, 2.f, 3.f) == approx(2.5f));
STATIC_REQUIRE(clamp(3.5f, 2.f, 3.f) == approx(3.0f));
STATIC_REQUIRE(clamp(1.0f, 2.f, 3.f) == uapprox(2.0f));
STATIC_REQUIRE(clamp(2.5f, 2.f, 3.f) == uapprox(2.5f));
STATIC_REQUIRE(clamp(3.5f, 2.f, 3.f) == uapprox(3.0f));
STATIC_REQUIRE(saturate(-0.5f) == approx(0.f));
STATIC_REQUIRE(saturate(0.5f) == approx(0.5f));
STATIC_REQUIRE(saturate(1.5f) == approx(1.f));
STATIC_REQUIRE(saturate(-0.5f) == uapprox(0.f));
STATIC_REQUIRE(saturate(0.5f) == uapprox(0.5f));
STATIC_REQUIRE(saturate(1.5f) == uapprox(1.f));
STATIC_REQUIRE(lerp(0.f, 10.f, 0.5f) == approx(5.f));
STATIC_REQUIRE(step(0.5f, 0.4f) == approx(0.f));
STATIC_REQUIRE(step(0.5f, 0.6f) == approx(1.f));
STATIC_REQUIRE(smoothstep(0.f, 1.f, 0.1f) == approx(0.028f));
STATIC_REQUIRE(lerp(0.f, 10.f, 0.5f) == uapprox(5.f));
STATIC_REQUIRE(step(0.5f, 0.4f) == uapprox(0.f));
STATIC_REQUIRE(step(0.5f, 0.6f) == uapprox(1.f));
STATIC_REQUIRE(smoothstep(0.f, 1.f, 0.1f) == uapprox(0.028f));
REQUIRE_FALSE(vmath_hpp::isnan(1.f));
REQUIRE_FALSE(vmath_hpp::isinf(1.f));
REQUIRE(vmath_hpp::isfinite(1.f));
REQUIRE(fma(2.f, 3.f, 4.f) == approx(10.f));
REQUIRE(fma(2.f, 3.f, 4.f) == uapprox(10.f));
{
int out_exp{};
REQUIRE(frexp(1.7f, &out_exp) == approx(0.85f));
REQUIRE(frexp(1.7f, &out_exp) == uapprox(0.85f));
REQUIRE(out_exp == 1);
}
REQUIRE(ldexp(0.85f, 1) == approx(1.7f));
REQUIRE(ldexp(0.85f, 1) == uapprox(1.7f));
}
SUBCASE("Geometric Functions") {
STATIC_REQUIRE(length(10.f) == approx(10.f));
STATIC_REQUIRE(length(-10.f) == approx(10.f));
STATIC_REQUIRE(length(10.f) == uapprox(10.f));
STATIC_REQUIRE(length(-10.f) == uapprox(10.f));
STATIC_REQUIRE(length2(10.f) == approx(100.f));
STATIC_REQUIRE(length2(-10.f) == approx(100.f));
STATIC_REQUIRE(length2(10.f) == uapprox(100.f));
STATIC_REQUIRE(length2(-10.f) == uapprox(100.f));
STATIC_REQUIRE(distance(5.f, 10.f) == approx(5.f));
STATIC_REQUIRE(distance(-5.f, -10.f) == approx(5.f));
STATIC_REQUIRE(distance(5.f, 10.f) == uapprox(5.f));
STATIC_REQUIRE(distance(-5.f, -10.f) == uapprox(5.f));
STATIC_REQUIRE(distance2(5.f, 10.f) == approx(25.f));
STATIC_REQUIRE(distance2(-5.f, -10.f) == approx(25.f));
STATIC_REQUIRE(distance2(5.f, 10.f) == uapprox(25.f));
STATIC_REQUIRE(distance2(-5.f, -10.f) == uapprox(25.f));
STATIC_REQUIRE(dot(2.f, 5.f) == approx(10.f));
REQUIRE(normalize(0.5f) == approx(1.f));
STATIC_REQUIRE(dot(2.f, 5.f) == uapprox(10.f));
REQUIRE(normalize(0.5f) == uapprox(1.f));
STATIC_REQUIRE(faceforward(1.f, 2.f, 3.f) == approx(-1.f));
STATIC_REQUIRE(reflect(1.f, 2.f) == approx(-7.f));
REQUIRE(refract(1.f, 2.f, 1.f) == approx(-7.f));
STATIC_REQUIRE(faceforward(1.f, 2.f, 3.f) == uapprox(-1.f));
STATIC_REQUIRE(reflect(1.f, 2.f) == uapprox(-7.f));
REQUIRE(refract(1.f, 2.f, 1.f) == uapprox(-7.f));
}
SUBCASE("Scalar Relational Functions") {
STATIC_REQUIRE(less(0, 1));
STATIC_REQUIRE(less_equal(0, 1));
STATIC_REQUIRE_FALSE(less(1, 1));
STATIC_REQUIRE(less_equal(1, 1));
STATIC_REQUIRE(greater(1, 0));
STATIC_REQUIRE(greater_equal(1, 0));
STATIC_REQUIRE_FALSE(greater(1, 1));
STATIC_REQUIRE(greater_equal(1, 1));
STATIC_REQUIRE(equal_to(1, 1));
STATIC_REQUIRE_FALSE(equal_to(0, 1));
STATIC_REQUIRE_FALSE(equal_to(0, 1, 0));
STATIC_REQUIRE(equal_to(0, 1, 1));
STATIC_REQUIRE(not_equal_to(0, 1));
STATIC_REQUIRE(not_equal_to(0, 1, 0));
STATIC_REQUIRE_FALSE(not_equal_to(0, 1, 1));
STATIC_REQUIRE_FALSE(not_equal_to(1, 1));
STATIC_REQUIRE_FALSE(not_equal_to(1, 1, 0));
STATIC_REQUIRE_FALSE(not_equal_to(1, 1, 1));
STATIC_REQUIRE(equal_to(1.f, 1.f + std::numeric_limits<float>::epsilon() * 0.5f));
STATIC_REQUIRE_FALSE(equal_to(1.f, 1.f + std::numeric_limits<float>::epsilon() * 1.5f));
STATIC_REQUIRE(equal_to(100.f, 100.f + std::numeric_limits<float>::epsilon() * 90.f));
STATIC_REQUIRE_FALSE(equal_to(100.f, 100.f + std::numeric_limits<float>::epsilon() * 110.f));
STATIC_REQUIRE_FALSE(not_equal_to(1.f, 1.f + std::numeric_limits<float>::epsilon() * 0.5f));
STATIC_REQUIRE(not_equal_to(1.f, 1.f + std::numeric_limits<float>::epsilon() * 1.5f));
STATIC_REQUIRE_FALSE(not_equal_to(100.f, 100.f + std::numeric_limits<float>::epsilon() * 90.f));
STATIC_REQUIRE(not_equal_to(100.f, 100.f + std::numeric_limits<float>::epsilon() * 110.f));
SUBCASE("Relational Functions") {
STATIC_REQUIRE_FALSE(any(false));
STATIC_REQUIRE_FALSE(any(0));
STATIC_REQUIRE(any(true));
@@ -184,5 +152,15 @@ TEST_CASE("vmath/fun") {
STATIC_REQUIRE_FALSE(all(0));
STATIC_REQUIRE(all(true));
STATIC_REQUIRE(all(1));
STATIC_REQUIRE(approx(1, 1));
STATIC_REQUIRE_FALSE(approx(0, 1));
STATIC_REQUIRE_FALSE(approx(0, 1, 0));
STATIC_REQUIRE(approx(0, 1, 1));
STATIC_REQUIRE(approx(1.f, 1.f + std::numeric_limits<float>::epsilon() * 0.5f));
STATIC_REQUIRE_FALSE(approx(1.f, 1.f + std::numeric_limits<float>::epsilon() * 1.5f));
STATIC_REQUIRE(approx(100.f, 100.f + std::numeric_limits<float>::epsilon() * 90.f));
STATIC_REQUIRE_FALSE(approx(100.f, 100.f + std::numeric_limits<float>::epsilon() * 110.f));
}
}

View File

@@ -59,20 +59,31 @@ TEST_CASE("vmath/mat_fun") {
SUBCASE("operators") {
STATIC_REQUIRE(-int2x2(1,2,3,4) == int2x2(-1,-2,-3,-4));
STATIC_REQUIRE(~uint2x2(0xF0F0F0F0,0x0F0F0F0F,0xF0F0F0F0,0x0F0F0F0F) == uint2x2(0x0F0F0F0F,0xF0F0F0F0,0x0F0F0F0F,0xF0F0F0F0));
STATIC_REQUIRE(!int2x2(-1,0,1,2) == bool2x2(false,true,false,false));
STATIC_REQUIRE(int2x2(1,2,3,4) + 2 == int2x2(3,4,5,6));
STATIC_REQUIRE(int2x2(1,2,3,4) - 2 == int2x2(-1,0,1,2));
STATIC_REQUIRE(int2x2(1,2,3,4) * 2 == int2x2(2,4,6,8));
STATIC_REQUIRE(int2x2(1,2,3,4) / 2 == int2x2(0,1,1,2));
STATIC_REQUIRE((int2x2(11,12,11,12) & 6) == int2x2(2,4,2,4));
STATIC_REQUIRE((int2x2(11,12,11,12) | 6) == int2x2(15,14,15,14));
STATIC_REQUIRE((int2x2(11,12,11,12) ^ 6) == int2x2(13,10,13,10));
STATIC_REQUIRE((int2x2(1,0,1,0) && 1) == bool2x2(1,0,1,0));
STATIC_REQUIRE((int2x2(1,0,1,0) || 1) == bool2x2(1,1,1,1));
STATIC_REQUIRE(4 + int2x2(1,2,3,4) == int2x2(5,6,7,8));
STATIC_REQUIRE(4 - int2x2(1,2,3,4) == int2x2(3,2,1,0));
STATIC_REQUIRE(4 * int2x2(1,2,3,4) == int2x2(4,8,12,16));
STATIC_REQUIRE(4 / int2x2(1,2,3,4) == int2x2(4,2,1,1));
STATIC_REQUIRE((6 &int2x2(11,12,11,12)) == int2x2(2,4,2,4));
STATIC_REQUIRE((6 |int2x2(11,12,11,12)) == int2x2(15,14,15,14));
STATIC_REQUIRE((6 ^ int2x2(11,12,11,12)) == int2x2(13,10,13,10));
STATIC_REQUIRE((1 && int2x2(1,0,1,0)) == bool2x2(1,0,1,0));
STATIC_REQUIRE((1 || int2x2(1,0,1,0)) == bool2x2(1,1,1,1));
STATIC_REQUIRE(int2x2(1,2,3,4) + int2x2(5,6,7,8) == int2x2(6,8,10,12));
STATIC_REQUIRE(int2x2(1,2,3,4) - int2x2(5,6,7,8) == int2x2(-4,-4,-4,-4));
STATIC_REQUIRE(int2x2(5,6,7,8) / int2x2(1,2,3,4) == int2x2(5,3,2,2));
STATIC_REQUIRE(int2x2() * int2x2() == int2x2());
STATIC_REQUIRE(int3x3() * int3x3() == int3x3());
@@ -81,6 +92,12 @@ TEST_CASE("vmath/mat_fun") {
STATIC_REQUIRE(int3(1,2,3) * int3x3() == int3(1,2,3));
STATIC_REQUIRE(int4(1,2,3,4) * int4x4() == int4(1,2,3,4));
STATIC_REQUIRE((int2x2(6,7,6,7) & int2x2(11,12,11,12)) == int2x2(2,4,2,4));
STATIC_REQUIRE((int2x2(6,7,6,7) | int2x2(11,12,11,12)) == int2x2(15,15,15,15));
STATIC_REQUIRE((int2x2(6,7,6,7) ^ int2x2(11,12,11,12)) == int2x2(13,11,13,11));
STATIC_REQUIRE((int2x2(0,1,0,1) && int2x2(1,0,1,0)) == bool2x2(0,0,0,0));
STATIC_REQUIRE((int2x2(0,1,0,1) || int2x2(1,0,1,0)) == bool2x2(1,1,1,1));
{
int2x2 v{1,2,3,4};
REQUIRE(&v == &(v += 3));
@@ -100,18 +117,10 @@ TEST_CASE("vmath/mat_fun") {
REQUIRE(&v == &(v *= 3));
REQUIRE(v == int2x2{3,6,9,12});
}
{
int2x2 v{6,18,36,60};
REQUIRE(&v == &(v /= 2));
REQUIRE(v == int2x2{3,9,18,30});
REQUIRE(&v == &(v /= int2x2{3,4,3,10}));
REQUIRE(v == int2x2{1,2,6,3});
}
{
int4 v{0, 0, 0, 1};
REQUIRE(&v == &(v *= translate(int3{1,2,3})));
REQUIRE(v == approx4(1,2,3,1));
REQUIRE(v == uapprox4(1,2,3,1));
}
{
int3 v{1, 2, 3};
@@ -128,6 +137,92 @@ TEST_CASE("vmath/mat_fun") {
REQUIRE(&v == &(v *= int3x3(scale(int3{2,3,4}))));
REQUIRE(v == int3x3(scale(int3{2,6,12})));
}
{
int2x2 v1{11,12,11,12};
REQUIRE(&v1 == &(v1 &= 6));
REQUIRE(v1 == int2x2(2,4,2,4));
int2x2 v2{6,7,6,7};
REQUIRE(&v2 == &(v2 &= int2x2(11,12,11,12)));
REQUIRE(v2 == int2x2(2,4,2,4));
}
{
int2x2 v1{11,12,11,12};
REQUIRE(&v1 == &(v1 |= 6));
REQUIRE(v1 == int2x2(15,14,15,14));
int2x2 v2{6,7,6,7};
REQUIRE(&v2 == &(v2 |= int2x2(11,12,11,12)));
REQUIRE(v2 == int2x2(15,15,15,15));
}
{
int2x2 v1{11,12,11,12};
REQUIRE(&v1 == &(v1 ^= 6));
REQUIRE(v1 == int2x2(13,10,13,10));
int2x2 v2{6,7,6,7};
REQUIRE(&v2 == &(v2 ^= int2x2(11,12,11,12)));
REQUIRE(v2 == int2x2(13,11,13,11));
}
}
SUBCASE("relational functions") {
STATIC_REQUIRE_FALSE(any(bool2x2(false, false, false, false)));
STATIC_REQUIRE(any(bool2x2(true, false, true, false)));
STATIC_REQUIRE(any(bool2x2(false, true, false, true)));
STATIC_REQUIRE(any(bool2x2(true, true, true, true)));
STATIC_REQUIRE_FALSE(any(int2x2(0, 0, 0, 0)));
STATIC_REQUIRE(any(int2x2(1, 0, 1, 0)));
STATIC_REQUIRE(any(int2x2(0, 1, 0, 1)));
STATIC_REQUIRE(any(int2x2(1, 1, 1, 1)));
STATIC_REQUIRE_FALSE(all(bool2x2(false, false, false, false)));
STATIC_REQUIRE_FALSE(all(bool2x2(true, false, true, false)));
STATIC_REQUIRE_FALSE(all(bool2x2(false, true, false, true)));
STATIC_REQUIRE(all(bool2x2(true, true, true, true)));
STATIC_REQUIRE_FALSE(all(int2x2(0, 0, 0, 0)));
STATIC_REQUIRE_FALSE(all(int2x2(1, 0, 1, 0)));
STATIC_REQUIRE_FALSE(all(int2x2(0, 1, 0, 1)));
STATIC_REQUIRE(all(int2x2(1, 1, 1, 1)));
STATIC_REQUIRE(approx(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(false, true, false, false));
STATIC_REQUIRE(approx(int2x2(0,1,2,3),1) == bool2x2(false, true, false, false));
STATIC_REQUIRE(approx(1,int2x2(0,1,2,3)) == bool2x2(false, true, false, false));
STATIC_REQUIRE(approx(int2x2(1,1,1,1), int2x2(0,1,2,3), 0) == bool2x2(false, true, false, false));
STATIC_REQUIRE(approx(int2x2(0,1,2,3), 1, 0) == bool2x2(false, true, false, false));
STATIC_REQUIRE(approx(1, int2x2(0,1,2,3), 0) == bool2x2(false, true, false, false));
STATIC_REQUIRE(approx(int2x2(1,1,1,1), int2x2(0,1,2,3), 1) == bool2x2(true, true, true, false));
STATIC_REQUIRE(approx(int2x2(0,1,2,3), 1, 1) == bool2x2(true, true, true, false));
STATIC_REQUIRE(approx(1, int2x2(0,1,2,3), 1) == bool2x2(true, true, true, false));
STATIC_REQUIRE(approx(int2x2(1,1,1,1), int2x2(0,1,2,3), 2) == bool2x2(true, true, true, true));
STATIC_REQUIRE(approx(int2x2(0,1,2,3), 1, 2) == bool2x2(true, true, true, true));
STATIC_REQUIRE(approx(1, int2x2(0,1,2,3), 2) == bool2x2(true, true, true, true));
STATIC_REQUIRE(less(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(false, false, true, true));
STATIC_REQUIRE(less(int2x2(0,1,2,3), 1) == bool2x2(true, false, false, false));
STATIC_REQUIRE(less(1, int2x2(0,1,2,3)) == bool2x2(false, false, true, true));
STATIC_REQUIRE(less_equal(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(false, true, true, true));
STATIC_REQUIRE(less_equal(int2x2(0,1,2,3), 1) == bool2x2(true, true, false, false));
STATIC_REQUIRE(less_equal(1, int2x2(0,1,2,3)) == bool2x2(false, true, true, true));
STATIC_REQUIRE(greater(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(true, false, false, false));
STATIC_REQUIRE(greater(int2x2(0,1,2,3), 1) == bool2x2(false, false, true, true));
STATIC_REQUIRE(greater(1, int2x2(0,1,2,3)) == bool2x2(true, false, false, false));
STATIC_REQUIRE(greater_equal(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(true, true, false, false));
STATIC_REQUIRE(greater_equal(int2x2(0,1,2,3), 1) == bool2x2(false, true, true, true));
STATIC_REQUIRE(greater_equal(1, int2x2(0,1,2,3)) == bool2x2(true, true, false, false));
STATIC_REQUIRE(equal_to(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(false, true, false, false));
STATIC_REQUIRE(equal_to(int2x2(0,1,2,3),1) == bool2x2(false, true, false, false));
STATIC_REQUIRE(equal_to(1,int2x2(0,1,2,3)) == bool2x2(false, true, false, false));
STATIC_REQUIRE(not_equal_to(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(true, false, true, true));
STATIC_REQUIRE(not_equal_to(int2x2(0,1,2,3),1) == bool2x2(true, false, true, true));
STATIC_REQUIRE(not_equal_to(1,int2x2(0,1,2,3)) == bool2x2(true, false, true, true));
}
SUBCASE("transpose") {
@@ -191,40 +286,40 @@ TEST_CASE("vmath/mat_fun") {
{
constexpr float4x4 m1 = translate(float3(1.f, 2.f, 3.f));
constexpr float4x4 rm1 = inverse(m1);
STATIC_REQUIRE(all(equal_to(
STATIC_REQUIRE(all(approx(
unit4_z<float> * m1 * rm1,
unit4_z<float>,
approx_epsilon_v<float>)));
uapprox_epsilon_v<float>)));
}
{
const float3 axis2 = normalize(float3(1.f, 2.f, 3.f));
const float4x4 m2 = rotate(0.5f,axis2);
const float4x4 rm2 = inverse(m2);
REQUIRE(all(equal_to(
REQUIRE(all(approx(
unit4_z<float> * m2 * rm2,
unit4_z<float>,
approx_epsilon_v<float>)));
uapprox_epsilon_v<float>)));
}
{
const float3 axis3 = normalize(float3(1.f, 2.f, 3.f));
const float3x3 m3 = float3x3(rotate(0.5f,axis3));
const float3x3 rm3 = inverse(m3);
REQUIRE(all(equal_to(
REQUIRE(all(approx(
unit3_z<float> * m3 * rm3,
unit3_z<float>,
approx_epsilon_v<float>)));
uapprox_epsilon_v<float>)));
}
{
const float3 axis4 = normalize(float3(0.f, 0.f, 3.f));
const float2x2 m4 = float2x2(rotate(0.5f,axis4));
const float2x2 rm4 = inverse(m4);
REQUIRE(all(equal_to(
REQUIRE(all(approx(
unit2_y<float> * m4 * rm4,
unit2_y<float>,
approx_epsilon_v<float>)));
uapprox_epsilon_v<float>)));
}
}
}

View File

@@ -13,58 +13,58 @@ namespace vmath_tests
using namespace vmath_hpp;
template < typename T >
struct approx_epsilon;
struct uapprox_epsilon;
template <>
struct approx_epsilon<int> {
struct uapprox_epsilon<int> {
static constexpr int value = 0;
};
template <>
struct approx_epsilon<float> {
struct uapprox_epsilon<float> {
static constexpr float value = FLT_EPSILON * 100;
};
template <>
struct approx_epsilon<double> {
struct uapprox_epsilon<double> {
static constexpr float value = DBL_EPSILON * 100;
};
template < typename T >
inline constexpr T approx_epsilon_v = approx_epsilon<T>::value;
inline constexpr T uapprox_epsilon_v = uapprox_epsilon<T>::value;
//
//
//
template < typename T >
struct approx {
struct uapprox {
T value;
explicit constexpr approx(T v) : value(v) {}
explicit constexpr uapprox(T v) : value(v) {}
};
template < typename T >
struct approx2 {
struct uapprox2 {
vec<T, 2> value;
constexpr explicit approx2(T v) : value(v) {}
constexpr explicit approx2(T x, T y) : value(x, y) {}
constexpr explicit approx2(const vec<T, 2>& v) : value(v) {}
constexpr explicit uapprox2(T v) : value(v) {}
constexpr explicit uapprox2(T x, T y) : value(x, y) {}
constexpr explicit uapprox2(const vec<T, 2>& v) : value(v) {}
};
template < typename T >
struct approx3 {
struct uapprox3 {
vec<T, 3> value;
constexpr explicit approx3(T v) : value(v) {}
constexpr explicit approx3(T x, T y, T z) : value(x, y, z) {}
constexpr explicit approx3(const vec<T, 3>& v) : value(v) {}
constexpr explicit uapprox3(T v) : value(v) {}
constexpr explicit uapprox3(T x, T y, T z) : value(x, y, z) {}
constexpr explicit uapprox3(const vec<T, 3>& v) : value(v) {}
};
template < typename T >
struct approx4 {
struct uapprox4 {
vec<T, 4> value;
constexpr explicit approx4(T v) : value(v) {}
constexpr explicit approx4(T x, T y, T z, T w) : value(x, y, z, w) {}
constexpr explicit approx4(const vec<T, 4>& v) : value(v) {}
constexpr explicit uapprox4(T v) : value(v) {}
constexpr explicit uapprox4(T x, T y, T z, T w) : value(x, y, z, w) {}
constexpr explicit uapprox4(const vec<T, 4>& v) : value(v) {}
};
//
@@ -72,22 +72,22 @@ namespace vmath_tests
//
template < typename T >
constexpr bool operator==(const T& l, const approx<T>& r) {
return equal_to(l, r.value, approx_epsilon_v<T>);
constexpr bool operator==(const T& l, const uapprox<T>& r) {
return approx(l, r.value, uapprox_epsilon_v<T>);
}
template < typename T >
constexpr bool operator==(const vec<T, 2>& l, const approx2<T>& r) {
return all(equal_to(l, r.value, approx_epsilon_v<T>));
constexpr bool operator==(const vec<T, 2>& l, const uapprox2<T>& r) {
return all(approx(l, r.value, uapprox_epsilon_v<T>));
}
template < typename T >
constexpr bool operator==(const vec<T, 3>& l, const approx3<T>& r) {
return all(equal_to(l, r.value, approx_epsilon_v<T>));
constexpr bool operator==(const vec<T, 3>& l, const uapprox3<T>& r) {
return all(approx(l, r.value, uapprox_epsilon_v<T>));
}
template < typename T >
constexpr bool operator==(const vec<T, 4>& l, const approx4<T>& r) {
return all(equal_to(l, r.value, approx_epsilon_v<T>));
constexpr bool operator==(const vec<T, 4>& l, const uapprox4<T>& r) {
return all(approx(l, r.value, uapprox_epsilon_v<T>));
}
}

View File

@@ -42,21 +42,38 @@ TEST_CASE("vmath/vec_fun") {
SUBCASE("Operators") {
STATIC_REQUIRE(-int2(1,-2) == int2(-1,2));
STATIC_REQUIRE(~uint2(0xF0F0F0F0,0x0F0F0F0F) == uint2(0x0F0F0F0F,0xF0F0F0F0));
STATIC_REQUIRE(!int3(-1,0,1) == bool3(false, true, false));
STATIC_REQUIRE(int2(1,2) + 3 == int2(4,5));
STATIC_REQUIRE(int2(1,2) - 3 == int2(-2,-1));
STATIC_REQUIRE(int2(1,2) * 3 == int2(3,6));
STATIC_REQUIRE(int2(2,4) / 2 == int2(1,2));
STATIC_REQUIRE((int2(11,12) & 6) == int2(2,4));
STATIC_REQUIRE((int2(11,12) | 6) == int2(15,14));
STATIC_REQUIRE((int2(11,12) ^ 6) == int2(13,10));
STATIC_REQUIRE((int2(1,0) && 1) == bool2(1,0));
STATIC_REQUIRE((int2(1,0) || 1) == bool2(1,1));
STATIC_REQUIRE(3 + int2(1,2) == int2(4,5));
STATIC_REQUIRE(3 - int2(1,2) == int2(2,1));
STATIC_REQUIRE(3 * int2(1,2) == int2(3,6));
STATIC_REQUIRE(4 / int2(2,4) == int2(2,1));
STATIC_REQUIRE((6 & int2(11,12)) == int2(2,4));
STATIC_REQUIRE((6 | int2(11,12)) == int2(15,14));
STATIC_REQUIRE((6 ^ int2(11,12)) == int2(13,10));
STATIC_REQUIRE((1 && int2(1,0)) == bool2(1,0));
STATIC_REQUIRE((1 || int2(1,0)) == bool2(1,1));
STATIC_REQUIRE(int2(1,2) + int2(3,4) == int2(4,6));
STATIC_REQUIRE(int2(1,2) - int2(3,4) == int2(-2,-2));
STATIC_REQUIRE(int2(1,2) * int2(3,4) == int2(3,8));
STATIC_REQUIRE(int2(3,4) / int2(1,2) == int2(3,2));
STATIC_REQUIRE((int2(6,7) & int2(11,12)) == int2(2,4));
STATIC_REQUIRE((int2(6,7) | int2(11,12)) == int2(15,15));
STATIC_REQUIRE((int2(6,7) ^ int2(11,12)) == int2(13,11));
STATIC_REQUIRE((int2(0,1) && int2(1,0)) == bool2(0,0));
STATIC_REQUIRE((int2(0,1) || int2(1,0)) == bool2(1,1));
{
int2 v{1,2};
@@ -86,11 +103,35 @@ TEST_CASE("vmath/vec_fun") {
REQUIRE(&v == &(v /= int2{3,4}));
REQUIRE(v == int2{1,2});
}
{
int2 v1{11,12};
REQUIRE(&v1 == &(v1 &= 6));
REQUIRE(v1 == int2(2,4));
int2 v2{6,7};
REQUIRE(&v2 == &(v2 &= int2(11,12)));
REQUIRE(v2 == int2(2,4));
}
{
int2 v1{11,12};
REQUIRE(&v1 == &(v1 |= 6));
REQUIRE(v1 == int2(15,14));
int2 v2{6,7};
REQUIRE(&v2 == &(v2 |= int2(11,12)));
REQUIRE(v2 == int2(15,15));
}
{
int2 v1{11,12};
REQUIRE(&v1 == &(v1 ^= 6));
REQUIRE(v1 == int2(13,10));
int2 v2{6,7};
REQUIRE(&v2 == &(v2 ^= int2(11,12)));
REQUIRE(v2 == int2(13,11));
}
}
SUBCASE("Angle and Trigonometry Functions") {
STATIC_REQUIRE(radians(degrees(float2(12.13f))) == approx2(12.13f));
STATIC_REQUIRE(degrees(radians(float2(12.13f))) == approx2(12.13f));
STATIC_REQUIRE(radians(degrees(float2(12.13f))) == uapprox2(12.13f));
STATIC_REQUIRE(degrees(radians(float2(12.13f))) == uapprox2(12.13f));
(void)sin(float2(1.f));
(void)cos(float2(1.f));
@@ -112,8 +153,8 @@ TEST_CASE("vmath/vec_fun") {
{
float2 out_ss{}, out_cs{};
sincos(float2(10.f,15.f), &out_ss, &out_cs);
REQUIRE(out_ss == approx2(sin(10.f), sin(15.f)));
REQUIRE(out_cs == approx2(cos(10.f), cos(15.f)));
REQUIRE(out_ss == uapprox2(sin(10.f), sin(15.f)));
REQUIRE(out_cs == uapprox2(cos(10.f), cos(15.f)));
}
}
@@ -128,9 +169,9 @@ TEST_CASE("vmath/vec_fun") {
}
SUBCASE("Common Functions") {
STATIC_REQUIRE(abs(float2(1.f, -1.f)) == approx2(1.f,1.f));
STATIC_REQUIRE(sign(float3(1.f, -1.f, 0.f)) == approx3(1.f,-1.f,0.f));
STATIC_REQUIRE(reciprocal(float2(2.f, 4.f)) == approx2(0.5f,0.25f));
STATIC_REQUIRE(abs(float2(1.f, -1.f)) == uapprox2(1.f,1.f));
STATIC_REQUIRE(sign(float3(1.f, -1.f, 0.f)) == uapprox3(1.f,-1.f,0.f));
STATIC_REQUIRE(rcp(float2(2.f, 4.f)) == uapprox2(0.5f,0.25f));
(void)floor(float2(1.f, -1.f));
(void)trunc(float2(1.f, -1.f));
@@ -138,13 +179,13 @@ TEST_CASE("vmath/vec_fun") {
(void)ceil(float2(1.f, -1.f));
(void)fract(float2(1.f, -1.f));
REQUIRE(fmod(float2(1.7f), 1.2f) == approx2(0.5f));
REQUIRE(fmod(float2(1.7f), float2(1.2f)) == approx2(0.5f));
REQUIRE(fmod(float2(1.7f), 1.2f) == uapprox2(0.5f));
REQUIRE(fmod(float2(1.7f), float2(1.2f)) == uapprox2(0.5f));
{
float2 out_i{};
REQUIRE(modf(float2(1.7f), &out_i) == approx2(0.7f));
REQUIRE(out_i.x == approx(1.f));
REQUIRE(modf(float2(1.7f), &out_i) == uapprox2(0.7f));
REQUIRE(out_i.x == uapprox(1.f));
}
STATIC_REQUIRE(min(int2(1,2)) == 1);
@@ -158,74 +199,58 @@ TEST_CASE("vmath/vec_fun") {
STATIC_REQUIRE(clamp(int2(1,2), 0, 1) == int2(1,1));
STATIC_REQUIRE(clamp(int2(1,2), int2(0), int2(1)) == int2(1,1));
STATIC_REQUIRE(saturate(float3(-1.f,0.5,1.5f)) == approx3(0.f,0.5f,1.f));
STATIC_REQUIRE(saturate(float3(-1.f,0.5,1.5f)) == uapprox3(0.f,0.5f,1.f));
STATIC_REQUIRE(lerp(float2(0.f), float2(10.f), 0.5f) == approx2(5.f));
STATIC_REQUIRE(lerp(float2(0.f), float2(10.f), float2(0.5f)) == approx2(5.f));
STATIC_REQUIRE(lerp(float2(0.f), float2(10.f), 0.5f) == uapprox2(5.f));
STATIC_REQUIRE(lerp(float2(0.f), float2(10.f), float2(0.5f)) == uapprox2(5.f));
STATIC_REQUIRE(step(0.5f, float2(0.4f)) == approx2(0.f));
STATIC_REQUIRE(step(0.5f, float2(0.6f)) == approx2(1.f));
STATIC_REQUIRE(step(float2(0.5f), float2(0.4f)) == approx2(0.f));
STATIC_REQUIRE(step(float2(0.5f), float2(0.6f)) == approx2(1.f));
STATIC_REQUIRE(step(0.5f, float2(0.4f)) == uapprox2(0.f));
STATIC_REQUIRE(step(0.5f, float2(0.6f)) == uapprox2(1.f));
STATIC_REQUIRE(step(float2(0.5f), float2(0.4f)) == uapprox2(0.f));
STATIC_REQUIRE(step(float2(0.5f), float2(0.6f)) == uapprox2(1.f));
STATIC_REQUIRE(smoothstep(0.f, 1.f, float2(0.1f)) == approx2(0.028f));
STATIC_REQUIRE(smoothstep(float2(0.f), float2(1.f), float2(0.1f)) == approx2(0.028f));
STATIC_REQUIRE(smoothstep(0.f, 1.f, float2(0.1f)) == uapprox2(0.028f));
STATIC_REQUIRE(smoothstep(float2(0.f), float2(1.f), float2(0.1f)) == uapprox2(0.028f));
REQUIRE_FALSE(isnan(float2(1.f)).x);
REQUIRE_FALSE(isinf(float2(1.f)).x);
REQUIRE(isfinite(float2(1.f)).x);
REQUIRE_FALSE(fma(float2(2.f), float2(3.f), float2(4.f)).x == approx(12.f));
REQUIRE_FALSE(fma(float2(2.f), float2(3.f), float2(4.f)).x == uapprox(12.f));
{
int2 out_exp{};
REQUIRE(frexp(float2(1.7f), &out_exp).x == approx(0.85f));
REQUIRE(frexp(float2(1.7f), &out_exp).x == uapprox(0.85f));
REQUIRE(out_exp == int2(1));
}
REQUIRE(ldexp(float2(0.85f), int2(1)).x == approx(1.7f));
REQUIRE(ldexp(float2(0.85f), int2(1)).x == uapprox(1.7f));
}
SUBCASE("Geometric Functions") {
REQUIRE(length(float2(10.f,0.f)) == approx(10.f));
REQUIRE(length(float2(-10.f,0.f)) == approx(10.f));
REQUIRE(length(float2(10.f,0.f)) == uapprox(10.f));
REQUIRE(length(float2(-10.f,0.f)) == uapprox(10.f));
STATIC_REQUIRE(length2(float2(10.f,0.f)) == approx(100.f));
STATIC_REQUIRE(length2(float2(-10.f,0.f)) == approx(100.f));
STATIC_REQUIRE(length2(float2(10.f,0.f)) == uapprox(100.f));
STATIC_REQUIRE(length2(float2(-10.f,0.f)) == uapprox(100.f));
REQUIRE(distance(float2(5.f,0.f), float2(10.f,0.f)) == approx(5.f));
REQUIRE(distance(float2(-5.f,0.f), float2(-10.f,0.f)) == approx(5.f));
REQUIRE(distance(float2(5.f,0.f), float2(10.f,0.f)) == uapprox(5.f));
REQUIRE(distance(float2(-5.f,0.f), float2(-10.f,0.f)) == uapprox(5.f));
STATIC_REQUIRE(distance2(float2(5.f,0.f), float2(10.f,0.f)) == approx(25.f));
STATIC_REQUIRE(distance2(float2(-5.f,0.f), float2(-10.f,0.f)) == approx(25.f));
STATIC_REQUIRE(distance2(float2(5.f,0.f), float2(10.f,0.f)) == uapprox(25.f));
STATIC_REQUIRE(distance2(float2(-5.f,0.f), float2(-10.f,0.f)) == uapprox(25.f));
STATIC_REQUIRE(dot(int2(1,2),int2(3,4)) == 11);
STATIC_REQUIRE(cross(int2(1,0),int2(0,1)) == 1);
STATIC_REQUIRE(cross(int3(1,0,0),int3(0,1,0)) == int3(0,0,1));
REQUIRE(normalize(float2(0.5f,0.f)).x == approx(1.f));
REQUIRE(normalize(float2(0.5f,0.f)).x == uapprox(1.f));
STATIC_REQUIRE(faceforward(float2(1.f), float2(2.f), float2(3.f)).x == approx(-1.f));
STATIC_REQUIRE(reflect(float2(1.f), float2(2.f)).x == approx(-15.f));
REQUIRE(refract(float2(1.f), float2(2.f), 1.f).x == approx(-15.f));
STATIC_REQUIRE(faceforward(float2(1.f), float2(2.f), float2(3.f)).x == uapprox(-1.f));
STATIC_REQUIRE(reflect(float2(1.f), float2(2.f)).x == uapprox(-15.f));
REQUIRE(refract(float2(1.f), float2(2.f), 1.f).x == uapprox(-15.f));
}
SUBCASE("Vector Relational Functions") {
STATIC_REQUIRE(less(int3(1,1,1), int3(0,1,2)) == bool3(false, false, true));
STATIC_REQUIRE(less_equal(int3(1,1,1), int3(0,1,2)) == bool3(false, true, true));
STATIC_REQUIRE(greater(int3(1,1,1), int3(0,1,2)) == bool3(true, false, false));
STATIC_REQUIRE(greater_equal(int3(1,1,1), int3(0,1,2)) == bool3(true, true, false));
STATIC_REQUIRE(equal_to(int3(1,1,1), int3(0,1,2)) == bool3(false, true, false));
STATIC_REQUIRE(equal_to(int4(1,1,1,1), int4(0,1,2,3), 0) == bool4(false, true, false, false));
STATIC_REQUIRE(equal_to(int4(1,1,1,1), int4(0,1,2,3), 1) == bool4(true, true, true, false));
STATIC_REQUIRE(equal_to(int4(1,1,1,1), int4(0,1,2,3), 2) == bool4(true, true, true, true));
STATIC_REQUIRE(not_equal_to(int3(1,1,1), int3(0,1,2)) == bool3(true, false, true));
STATIC_REQUIRE(not_equal_to(int4(1,1,1,1), int4(0,1,2,3), 0) == bool4(true, false, true, true));
STATIC_REQUIRE(not_equal_to(int4(1,1,1,1), int4(0,1,2,3), 1) == bool4(false, false, false, true));
STATIC_REQUIRE(not_equal_to(int4(1,1,1,1), int4(0,1,2,3), 2) == bool4(false, false, false, false));
SUBCASE("Relational Functions") {
STATIC_REQUIRE_FALSE(any(bool2(false, false)));
STATIC_REQUIRE(any(bool2(true, false)));
STATIC_REQUIRE(any(bool2(false, true)));
@@ -245,5 +270,45 @@ TEST_CASE("vmath/vec_fun") {
STATIC_REQUIRE_FALSE(all(int2(1, 0)));
STATIC_REQUIRE_FALSE(all(int2(0, 1)));
STATIC_REQUIRE(all(int2(1, 1)));
STATIC_REQUIRE(approx(int3(1,1,1), int3(0,1,2)) == bool3(false, true, false));
STATIC_REQUIRE(approx(int3(0,1,2),1) == bool3(false, true, false));
STATIC_REQUIRE(approx(1,int3(0,1,2)) == bool3(false, true, false));
STATIC_REQUIRE(approx(int4(1,1,1,1), int4(0,1,2,3), 0) == bool4(false, true, false, false));
STATIC_REQUIRE(approx(int4(0,1,2,3), 1, 0) == bool4(false, true, false, false));
STATIC_REQUIRE(approx(1, int4(0,1,2,3), 0) == bool4(false, true, false, false));
STATIC_REQUIRE(approx(int4(1,1,1,1), int4(0,1,2,3), 1) == bool4(true, true, true, false));
STATIC_REQUIRE(approx(int4(0,1,2,3), 1, 1) == bool4(true, true, true, false));
STATIC_REQUIRE(approx(1, int4(0,1,2,3), 1) == bool4(true, true, true, false));
STATIC_REQUIRE(approx(int4(1,1,1,1), int4(0,1,2,3), 2) == bool4(true, true, true, true));
STATIC_REQUIRE(approx(int4(0,1,2,3), 1, 2) == bool4(true, true, true, true));
STATIC_REQUIRE(approx(1, int4(0,1,2,3), 2) == bool4(true, true, true, true));
STATIC_REQUIRE(less(int3(1,1,1), int3(0,1,2)) == bool3(false, false, true));
STATIC_REQUIRE(less(int3(0,1,2), 1) == bool3(true, false, false));
STATIC_REQUIRE(less(1, int3(0,1,2)) == bool3(false, false, true));
STATIC_REQUIRE(less_equal(int3(1,1,1), int3(0,1,2)) == bool3(false, true, true));
STATIC_REQUIRE(less_equal(int3(0,1,2), 1) == bool3(true, true, false));
STATIC_REQUIRE(less_equal(1, int3(0,1,2)) == bool3(false, true, true));
STATIC_REQUIRE(greater(int3(1,1,1), int3(0,1,2)) == bool3(true, false, false));
STATIC_REQUIRE(greater(int3(0,1,2), 1) == bool3(false, false, true));
STATIC_REQUIRE(greater(1, int3(0,1,2)) == bool3(true, false, false));
STATIC_REQUIRE(greater_equal(int3(1,1,1), int3(0,1,2)) == bool3(true, true, false));
STATIC_REQUIRE(greater_equal(int3(0,1,2), 1) == bool3(false, true, true));
STATIC_REQUIRE(greater_equal(1, int3(0,1,2)) == bool3(true, true, false));
STATIC_REQUIRE(equal_to(int3(1,1,1), int3(0,1,2)) == bool3(false, true, false));
STATIC_REQUIRE(equal_to(int3(0,1,2),1) == bool3(false, true, false));
STATIC_REQUIRE(equal_to(1,int3(0,1,2)) == bool3(false, true, false));
STATIC_REQUIRE(not_equal_to(int3(1,1,1), int3(0,1,2)) == bool3(true, false, true));
STATIC_REQUIRE(not_equal_to(int3(0,1,2),1) == bool3(true, false, true));
STATIC_REQUIRE(not_equal_to(1,int3(0,1,2)) == bool3(true, false, true));
}
}