mirror of
https://github.com/BlackMATov/vmath.hpp.git
synced 2026-09-30 02:46:58 +07:00
@@ -14,7 +14,7 @@ jobs:
|
||||
- { os: "windows-2016", vs: "Visual Studio 2017", arch: "x64" }
|
||||
- { os: "windows-2019", vs: "Visual Studio 2019", arch: "x86" }
|
||||
- { os: "windows-2019", vs: "Visual Studio 2019", arch: "x64" }
|
||||
name: "${{matrix.config.vs}}"
|
||||
name: "${{matrix.config.vs}} ${{matrix.config.arch}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build && Test
|
||||
|
||||
+238
-203
@@ -19,37 +19,72 @@
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T > inline constexpr vec<T, 2> zero2{0, 0};
|
||||
template < typename T > inline constexpr vec<T, 3> zero3{0, 0, 0};
|
||||
template < typename T > inline constexpr vec<T, 4> zero4{0, 0, 0, 0};
|
||||
template < typename T > inline constexpr vec<T, 2> zero2{T{0}, T{0}};
|
||||
template < typename T > inline constexpr vec<T, 3> zero3{T{0}, T{0}, T{0}};
|
||||
template < typename T > inline constexpr vec<T, 4> zero4{T{0}, T{0}, T{0}, T{0}};
|
||||
|
||||
template < typename T > inline constexpr vec<T, 2> unit2{1, 1};
|
||||
template < typename T > inline constexpr vec<T, 3> unit3{1, 1, 1};
|
||||
template < typename T > inline constexpr vec<T, 4> unit4{1, 1, 1, 1};
|
||||
template < typename T > inline constexpr vec<T, 2> unit2{T{1}, T{1}};
|
||||
template < typename T > inline constexpr vec<T, 3> unit3{T{1}, T{1}, T{1}};
|
||||
template < typename T > inline constexpr vec<T, 4> unit4{T{1}, T{1}, T{1}, T{1}};
|
||||
|
||||
template < typename T > inline constexpr vec<T, 2> unit2_x{1, 0};
|
||||
template < typename T > inline constexpr vec<T, 2> unit2_y{0, 1};
|
||||
template < typename T > inline constexpr vec<T, 2> unit2_x{T{1}, T{0}};
|
||||
template < typename T > inline constexpr vec<T, 2> unit2_y{T{0}, T{1}};
|
||||
|
||||
template < typename T > inline constexpr vec<T, 3> unit3_x{1, 0, 0};
|
||||
template < typename T > inline constexpr vec<T, 3> unit3_y{0, 1, 0};
|
||||
template < typename T > inline constexpr vec<T, 3> unit3_z{0, 0, 1};
|
||||
template < typename T > inline constexpr vec<T, 3> unit3_x{T{1}, T{0}, T{0}};
|
||||
template < typename T > inline constexpr vec<T, 3> unit3_y{T{0}, T{1}, T{0}};
|
||||
template < typename T > inline constexpr vec<T, 3> unit3_z{T{0}, T{0}, T{1}};
|
||||
|
||||
template < typename T > inline constexpr vec<T, 4> unit4_x{1, 0, 0, 0};
|
||||
template < typename T > inline constexpr vec<T, 4> unit4_y{0, 1, 0, 0};
|
||||
template < typename T > inline constexpr vec<T, 4> unit4_z{0, 0, 1, 0};
|
||||
template < typename T > inline constexpr vec<T, 4> unit4_w{0, 0, 0, 1};
|
||||
template < typename T > inline constexpr vec<T, 4> unit4_x{T{1}, T{0}, T{0}, T{0}};
|
||||
template < typename T > inline constexpr vec<T, 4> unit4_y{T{0}, T{1}, T{0}, T{0}};
|
||||
template < typename T > inline constexpr vec<T, 4> unit4_z{T{0}, T{0}, T{1}, T{0}};
|
||||
template < typename T > inline constexpr vec<T, 4> unit4_w{T{0}, T{0}, T{0}, T{1}};
|
||||
|
||||
template < typename T > inline constexpr mat<T, 2> zero2x2{0, 0, 0, 0};
|
||||
template < typename T > inline constexpr mat<T, 3> zero3x3{0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
template < typename T > inline constexpr mat<T, 4> zero4x4{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
template < typename T > inline constexpr mat<T, 2> zero2x2{
|
||||
T{0}, T{0},
|
||||
T{0}, T{0}};
|
||||
|
||||
template < typename T > inline constexpr mat<T, 2> unit2x2{1, 1, 1, 1};
|
||||
template < typename T > inline constexpr mat<T, 3> unit3x3{1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
template < typename T > inline constexpr mat<T, 4> unit4x4{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
template < typename T > inline constexpr mat<T, 3> zero3x3{
|
||||
T{0}, T{0}, T{0},
|
||||
T{0}, T{0}, T{0},
|
||||
T{0}, T{0}, T{0}};
|
||||
|
||||
template < typename T > inline constexpr mat<T, 2> identity2x2{1, 0, 0, 1};
|
||||
template < typename T > inline constexpr mat<T, 3> identity3x3{1, 0, 0, 0, 1, 0, 0, 0, 1};
|
||||
template < typename T > inline constexpr mat<T, 4> identity4x4{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
|
||||
template < typename T > inline constexpr mat<T, 4> zero4x4{
|
||||
T{0}, T{0}, T{0}, T{0},
|
||||
T{0}, T{0}, T{0}, T{0},
|
||||
T{0}, T{0}, T{0}, T{0},
|
||||
T{0}, T{0}, T{0}, T{0}};
|
||||
|
||||
template < typename T > inline constexpr mat<T, 2> unit2x2{
|
||||
T{1}, T{1},
|
||||
T{1}, T{1}};
|
||||
|
||||
template < typename T > inline constexpr mat<T, 3> unit3x3{
|
||||
T{1}, T{1}, T{1},
|
||||
T{1}, T{1}, T{1},
|
||||
T{1}, T{1}, T{1}};
|
||||
|
||||
template < typename T > inline constexpr mat<T, 4> unit4x4{
|
||||
T{1}, T{1}, T{1}, T{1},
|
||||
T{1}, T{1}, T{1}, T{1},
|
||||
T{1}, T{1}, T{1}, T{1},
|
||||
T{1}, T{1}, T{1}, T{1}};
|
||||
|
||||
template < typename T > inline constexpr mat<T, 2> identity2x2{
|
||||
T{1}, T{0},
|
||||
T{0}, T{1}};
|
||||
|
||||
template < typename T > inline constexpr mat<T, 3> identity3x3{
|
||||
T{1}, T{0}, T{0},
|
||||
T{0}, T{1}, T{0},
|
||||
T{0}, T{0}, T{1}};
|
||||
|
||||
template < typename T > inline constexpr mat<T, 4> identity4x4{
|
||||
T{1}, T{0}, T{0}, T{0},
|
||||
T{0}, T{1}, T{0}, T{0},
|
||||
T{0}, T{0}, T{1}, T{0},
|
||||
T{0}, T{0}, T{0}, T{1}};
|
||||
|
||||
template < typename T > inline constexpr qua<T> qidentity{T{0}, T{0}, T{0}, T{1}};
|
||||
}
|
||||
|
||||
//
|
||||
@@ -77,7 +112,7 @@ namespace vmath_hpp::detail
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::size_t hash(const qua<T>& q) noexcept {
|
||||
return hash(vec{q});
|
||||
return fold_join(hash_combiner{}, std::size_t{}, q);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,17 +156,17 @@ namespace vmath_hpp
|
||||
|
||||
template < typename To, typename From, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<To, Size> cast_to(const vec<From, Size>& v) {
|
||||
return detail::map_join([](From x){ return cast_to<To>(x); }, v);
|
||||
return map_join([](From x){ return cast_to<To>(x); }, v);
|
||||
}
|
||||
|
||||
template < typename To, typename From, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<To, Size> cast_to(const mat<From, Size>& m) {
|
||||
return detail::map_join([](const vec<From, Size>& v){ return cast_to<To>(v); }, m);
|
||||
return map_join([](const vec<From, Size>& v){ return cast_to<To>(v); }, m);
|
||||
}
|
||||
|
||||
template < typename To, typename From >
|
||||
[[nodiscard]] constexpr qua<To> cast_to(const qua<From>& q) {
|
||||
return qua(cast_to<To>(vec{q}));
|
||||
return map_join([](From x){ return cast_to<To>(x); }, q);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,10 +270,10 @@ namespace vmath_hpp
|
||||
/// https://en.wikipedia.org/wiki/Translation_(geometry)
|
||||
|
||||
return {
|
||||
{1, 0, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
{x, y, z, 1}};
|
||||
{T{1}, T{0}, T{0}, T{0}},
|
||||
{T{0}, T{1}, T{0}, T{0}},
|
||||
{T{0}, T{0}, T{1}, T{0}},
|
||||
{ x, y, z, T{1}}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -259,15 +294,15 @@ namespace vmath_hpp
|
||||
// rotate
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> rotate(const qua<T>& q) {
|
||||
[[nodiscard]] constexpr mat<T, 4> rotate(const qua<T>& q) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/
|
||||
|
||||
const auto [qv, qs] = normalize(q);
|
||||
|
||||
const T x2 = qv.x * T(2);
|
||||
const T y2 = qv.y * T(2);
|
||||
const T z2 = qv.z * T(2);
|
||||
const T x2 = qv.x * T{2};
|
||||
const T y2 = qv.y * T{2};
|
||||
const T z2 = qv.z * T{2};
|
||||
|
||||
const T sx2 = qs * x2;
|
||||
const T sy2 = qs * y2;
|
||||
@@ -282,19 +317,19 @@ namespace vmath_hpp
|
||||
const T zz2 = qv.z * z2;
|
||||
|
||||
return {
|
||||
T(1) - (yy2 + zz2), (xy2 + sz2), (xz2 - sy2), 0,
|
||||
(xy2 - sz2), T(1) - (xx2 + zz2), (yz2 + sx2), 0,
|
||||
(xz2 + sy2), (yz2 - sx2), T(1) - (xx2 + yy2), 0,
|
||||
0, 0, 0, 1};
|
||||
T{1} - (yy2 + zz2), (xy2 + sz2), (xz2 - sy2), T{0},
|
||||
(xy2 - sz2), T{1} - (xx2 + zz2), (yz2 + sx2), T{0},
|
||||
(xz2 + sy2), (yz2 - sx2), T{1} - (xx2 + yy2), T{0},
|
||||
T{0}, T{0}, T{0}, T{1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> rotate(const mat<T, 4>& m, const qua<T>& q) {
|
||||
[[nodiscard]] constexpr mat<T, 4> rotate(const mat<T, 4>& m, const qua<T>& q) {
|
||||
return m * rotate(q);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> rotate(T angle, const vec<T, 3>& axis) {
|
||||
[[nodiscard]] constexpr mat<T, 4> rotate(T angle, const vec<T, 3>& axis) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/
|
||||
|
||||
@@ -309,7 +344,7 @@ namespace vmath_hpp
|
||||
const T ys = y * s;
|
||||
const T zs = z * s;
|
||||
|
||||
const T ic = T(1) - c;
|
||||
const T ic = T{1} - c;
|
||||
|
||||
const T xxm = xx * ic;
|
||||
const T yym = yy * ic;
|
||||
@@ -320,71 +355,71 @@ namespace vmath_hpp
|
||||
const T yzm = y * z * ic;
|
||||
|
||||
return {
|
||||
xxm + c, xym + zs, xzm - ys, 0,
|
||||
xym - zs, yym + c, yzm + xs, 0,
|
||||
xzm + ys, yzm - xs, zzm + c, 0,
|
||||
0, 0, 0, 1};
|
||||
xxm + c, xym + zs, xzm - ys, T{0},
|
||||
xym - zs, yym + c, yzm + xs, T{0},
|
||||
xzm + ys, yzm - xs, zzm + c, T{0},
|
||||
T{0}, T{0}, T{0}, T{1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> rotate(const mat<T, 4>& m, T angle, const vec<T, 3>& axis) {
|
||||
[[nodiscard]] constexpr mat<T, 4> rotate(const mat<T, 4>& m, T angle, const vec<T, 3>& axis) {
|
||||
return m * rotate(angle, axis);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> rotate_x(T angle) {
|
||||
[[nodiscard]] constexpr mat<T, 4> rotate_x(T angle) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/matrix/orthogonal/rotation/
|
||||
|
||||
const auto [s, c] = sincos(angle);
|
||||
|
||||
return {
|
||||
1, 0, 0, 0,
|
||||
0, c, s, 0,
|
||||
0, -s, c, 0,
|
||||
0, 0, 0, 1};
|
||||
T{1}, T{0}, T{0}, T{0},
|
||||
T{0}, c, s, T{0},
|
||||
T{0}, -s, c, T{0},
|
||||
T{0}, T{0}, T{0}, T{1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> rotate_x(const mat<T, 4>& m, T angle) {
|
||||
[[nodiscard]] constexpr mat<T, 4> rotate_x(const mat<T, 4>& m, T angle) {
|
||||
return m * rotate_x(angle);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> rotate_y(T angle) {
|
||||
[[nodiscard]] constexpr mat<T, 4> rotate_y(T angle) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/matrix/orthogonal/rotation/
|
||||
|
||||
const auto [s, c] = sincos(angle);
|
||||
|
||||
return {
|
||||
c, 0, -s, 0,
|
||||
0, 1, 0, 0,
|
||||
s, 0, c, 0,
|
||||
0, 0, 0, 1};
|
||||
c, T{0}, -s, T{0},
|
||||
T{0}, T{1}, T{0}, T{0},
|
||||
s, T{0}, c, T{0},
|
||||
T{0}, T{0}, T{0}, T{1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> rotate_y(const mat<T, 4>& m, T angle) {
|
||||
[[nodiscard]] constexpr mat<T, 4> rotate_y(const mat<T, 4>& m, T angle) {
|
||||
return m * rotate_y(angle);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> rotate_z(T angle) {
|
||||
[[nodiscard]] constexpr mat<T, 4> rotate_z(T angle) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/matrix/orthogonal/rotation/
|
||||
|
||||
const auto [s, c] = sincos(angle);
|
||||
|
||||
return {
|
||||
c, s, 0, 0,
|
||||
-s, c, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1};
|
||||
c, s, T{0}, T{0},
|
||||
-s, c, T{0}, T{0},
|
||||
T{0}, T{0}, T{1}, T{0},
|
||||
T{0}, T{0}, T{0}, T{1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> rotate_z(const mat<T, 4>& m, T angle) {
|
||||
[[nodiscard]] constexpr mat<T, 4> rotate_z(const mat<T, 4>& m, T angle) {
|
||||
return m * rotate_z(angle);
|
||||
}
|
||||
|
||||
@@ -396,10 +431,10 @@ namespace vmath_hpp
|
||||
/// https://en.wikipedia.org/wiki/Scaling_(geometry)
|
||||
|
||||
return {
|
||||
{x, 0, 0, 0},
|
||||
{0, y, 0, 0},
|
||||
{0, 0, z, 0},
|
||||
{0, 0, 0, 1}};
|
||||
{ x, T{0}, T{0}, T{0}},
|
||||
{T{0}, y, T{0}, T{0}},
|
||||
{T{0}, T{0}, z, T{0}},
|
||||
{T{0}, T{0}, T{0}, T{1}}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -420,7 +455,7 @@ namespace vmath_hpp
|
||||
// look_at
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> look_at_lh(const vec<T, 3>& eye, const vec<T, 3>& at, const vec<T, 3>& up) {
|
||||
[[nodiscard]] constexpr mat<T, 4> look_at_lh(const vec<T, 3>& eye, const vec<T, 3>& at, const vec<T, 3>& up) {
|
||||
/// REFERENCE:
|
||||
/// https://www.euclideanspace.com/maths/algebra/vectors/lookat/
|
||||
|
||||
@@ -433,14 +468,14 @@ namespace vmath_hpp
|
||||
const T dz = dot(az, eye);
|
||||
|
||||
return {
|
||||
ax.x, ay.x, az.x, 0,
|
||||
ax.y, ay.y, az.y, 0,
|
||||
ax.z, ay.z, az.z, 0,
|
||||
-dx, -dy, -dz, 1};
|
||||
ax.x, ay.x, az.x, T{0},
|
||||
ax.y, ay.y, az.y, T{0},
|
||||
ax.z, ay.z, az.z, T{0},
|
||||
-dx, -dy, -dz, T{1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> look_at_rh(const vec<T, 3>& eye, const vec<T, 3>& at, const vec<T, 3>& up) {
|
||||
[[nodiscard]] constexpr mat<T, 4> look_at_rh(const vec<T, 3>& eye, const vec<T, 3>& at, const vec<T, 3>& up) {
|
||||
/// REFERENCE:
|
||||
/// https://www.euclideanspace.com/maths/algebra/vectors/lookat/
|
||||
|
||||
@@ -453,10 +488,10 @@ namespace vmath_hpp
|
||||
const T dz = dot(az, eye);
|
||||
|
||||
return {
|
||||
ax.x, ay.x, az.x, 0,
|
||||
ax.y, ay.y, az.y, 0,
|
||||
ax.z, ay.z, az.z, 0,
|
||||
-dx, -dy, -dz, 1};
|
||||
ax.x, ay.x, az.x, T{0},
|
||||
ax.y, ay.y, az.y, T{0},
|
||||
ax.z, ay.z, az.z, T{0},
|
||||
-dx, -dy, -dz, T{1}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,9 +509,9 @@ namespace vmath_hpp
|
||||
/// https://en.wikipedia.org/wiki/Translation_(geometry)
|
||||
|
||||
return {
|
||||
{1, 0, 0},
|
||||
{0, 1, 0},
|
||||
{x, y, 1}};
|
||||
{T{1}, T{0}, T{0}},
|
||||
{T{0}, T{1}, T{0}},
|
||||
{ x, y, T{1}}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -497,20 +532,20 @@ namespace vmath_hpp
|
||||
// rotate
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 3> rotate(T angle) {
|
||||
[[nodiscard]] constexpr mat<T, 3> rotate(T angle) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/matrix/orthogonal/rotation/
|
||||
|
||||
const auto [s, c] = sincos(angle);
|
||||
|
||||
return {
|
||||
c, s, 0,
|
||||
-s, c, 0,
|
||||
0, 0, 1};
|
||||
c, s, T{0},
|
||||
-s, c, T{0},
|
||||
T{0}, T{0}, T{1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 3> rotate(const mat<T, 3>& m, T angle) {
|
||||
[[nodiscard]] constexpr mat<T, 3> rotate(const mat<T, 3>& m, T angle) {
|
||||
return m * rotate(angle);
|
||||
}
|
||||
|
||||
@@ -522,9 +557,9 @@ namespace vmath_hpp
|
||||
/// https://en.wikipedia.org/wiki/Scaling_(geometry)
|
||||
|
||||
return {
|
||||
{x, 0, 0},
|
||||
{0, y, 0},
|
||||
{0, 0, 1}};
|
||||
{ x, T{0}, T{0}},
|
||||
{T{0}, y, T{0}},
|
||||
{T{0}, T{0}, T{1}}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -550,9 +585,9 @@ namespace vmath_hpp
|
||||
/// https://en.wikipedia.org/wiki/Shear_matrix
|
||||
|
||||
return {
|
||||
{1, y, 0},
|
||||
{x, 1, 0},
|
||||
{0, 0, 1}};
|
||||
{T{1}, y, T{0}},
|
||||
{ x, T{1}, T{0}},
|
||||
{T{0}, T{0}, T{1}}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -576,9 +611,9 @@ namespace vmath_hpp
|
||||
/// https://en.wikipedia.org/wiki/Shear_matrix
|
||||
|
||||
return {
|
||||
{1, 0, 0},
|
||||
{x, 1, 0},
|
||||
{0, 0, 1}};
|
||||
{T{1}, T{0}, T{0}},
|
||||
{ x, T{1}, T{0}},
|
||||
{T{0}, T{0}, T{1}}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -592,9 +627,9 @@ namespace vmath_hpp
|
||||
/// https://en.wikipedia.org/wiki/Shear_matrix
|
||||
|
||||
return {
|
||||
{1, y, 0},
|
||||
{0, 1, 0},
|
||||
{0, 0, 1}};
|
||||
{T{1}, y, T{0}},
|
||||
{T{0}, T{1}, T{0}},
|
||||
{T{0}, T{0}, T{1}}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -612,7 +647,7 @@ namespace vmath_hpp
|
||||
// orthographic
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> orthographic_lh(T width, T height, T znear, T zfar) {
|
||||
[[nodiscard]] constexpr mat<T, 4> orthographic_lh(T width, T height, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixortholh
|
||||
|
||||
@@ -620,20 +655,20 @@ namespace vmath_hpp
|
||||
const T rheight = rcp(height);
|
||||
const T frange = rcp(zfar - znear);
|
||||
|
||||
const T sx = T(2) * rwidth;
|
||||
const T sy = T(2) * rheight;
|
||||
const T sx = T{2} * rwidth;
|
||||
const T sy = T{2} * rheight;
|
||||
const T sz = frange;
|
||||
const T tz = -frange * znear;
|
||||
|
||||
return {
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, 0,
|
||||
0, 0, tz, 1};
|
||||
sx, T{0}, T{0}, T{0},
|
||||
T{0}, sy, T{0}, T{0},
|
||||
T{0}, T{0}, sz, T{0},
|
||||
T{0}, T{0}, tz, T{1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> orthographic_rh(T width, T height, T znear, T zfar) {
|
||||
[[nodiscard]] constexpr mat<T, 4> orthographic_rh(T width, T height, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthorh
|
||||
|
||||
@@ -641,20 +676,20 @@ namespace vmath_hpp
|
||||
const T rheight = rcp(height);
|
||||
const T frange = rcp(znear - zfar);
|
||||
|
||||
const T sx = T(2) * rwidth;
|
||||
const T sy = T(2) * rheight;
|
||||
const T sx = T{2} * rwidth;
|
||||
const T sy = T{2} * rheight;
|
||||
const T sz = frange;
|
||||
const T tz = frange * znear;
|
||||
|
||||
return {
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, 0,
|
||||
0, 0, tz, 1};
|
||||
sx, T{0}, T{0}, T{0},
|
||||
T{0}, sy, T{0}, T{0},
|
||||
T{0}, T{0}, sz, T{0},
|
||||
T{0}, T{0}, tz, T{1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> orthographic_lh(T left, T right, T bottom, T top, T znear, T zfar) {
|
||||
[[nodiscard]] constexpr mat<T, 4> orthographic_lh(T left, T right, T bottom, T top, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterlh
|
||||
|
||||
@@ -663,14 +698,14 @@ namespace vmath_hpp
|
||||
const T frange = rcp(zfar - znear);
|
||||
|
||||
return {
|
||||
T(2) * rwidth, 0, 0, 0,
|
||||
0, T(2) * rheight, 0, 0,
|
||||
0, 0, frange, 0,
|
||||
-(left + right) * rwidth, -(top + bottom) * rheight, -frange * znear, 1};
|
||||
T{2} * rwidth, T{0}, T{0}, T{0},
|
||||
T{0}, T{2} * rheight, T{0}, T{0},
|
||||
T{0}, T{0}, frange, T{0},
|
||||
-(left + right) * rwidth, -(top + bottom) * rheight, -frange * znear, T{1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> orthographic_rh(T left, T right, T bottom, T top, T znear, T zfar) {
|
||||
[[nodiscard]] constexpr mat<T, 4> orthographic_rh(T left, T right, T bottom, T top, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterrh
|
||||
|
||||
@@ -679,113 +714,113 @@ namespace vmath_hpp
|
||||
const T frange = rcp(znear - zfar);
|
||||
|
||||
return {
|
||||
T(2) * rwidth, 0, 0, 0,
|
||||
0, T(2) * rheight, 0, 0,
|
||||
0, 0, frange, 0,
|
||||
-(left + right) * rwidth, -(top + bottom) * rheight, frange * znear, 1};
|
||||
T{2} * rwidth, T{0}, T{0}, T{0},
|
||||
T{0}, T{2} * rheight, T{0}, T{0},
|
||||
T{0}, T{0}, frange, T{0},
|
||||
-(left + right) * rwidth, -(top + bottom) * rheight, frange * znear, T{1}};
|
||||
}
|
||||
|
||||
// perspective
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> perspective_lh(T width, T height, T znear, T zfar) {
|
||||
[[nodiscard]] constexpr mat<T, 4> perspective_lh(T width, T height, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivelh
|
||||
|
||||
const T sx = T(2) * znear * rcp(width);
|
||||
const T sy = T(2) * znear * rcp(height);
|
||||
const T sx = T{2} * znear * rcp(width);
|
||||
const T sy = T{2} * znear * rcp(height);
|
||||
const T sz = zfar * rcp(zfar - znear);
|
||||
const T tz = (znear * zfar) * rcp(znear - zfar);
|
||||
|
||||
return {
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, 1,
|
||||
0, 0, tz, 0};
|
||||
T{sx}, T{0}, T{0}, T{0},
|
||||
T{0}, T{sy}, T{0}, T{0},
|
||||
T{0}, T{0}, T{sz}, T{1},
|
||||
T{0}, T{0}, T{tz}, T{0}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> perspective_rh(T width, T height, T znear, T zfar) {
|
||||
[[nodiscard]] constexpr mat<T, 4> perspective_rh(T width, T height, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectiverh
|
||||
|
||||
const T sx = T(2) * znear * rcp(width);
|
||||
const T sy = T(2) * znear * rcp(height);
|
||||
const T sx = T{2} * znear * rcp(width);
|
||||
const T sy = T{2} * znear * rcp(height);
|
||||
const T sz = zfar * rcp(znear - zfar);
|
||||
const T tz = (znear * zfar) * rcp(znear - zfar);
|
||||
|
||||
return {
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, -1,
|
||||
0, 0, tz, 0};
|
||||
sx, T{0}, T{0}, T{0},
|
||||
T{0}, sy, T{0}, T{0},
|
||||
T{0}, T{0}, sz, -T{1},
|
||||
T{0}, T{0}, tz, T{0}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> perspective_lh(T left, T right, T bottom, T top, T znear, T zfar) {
|
||||
[[nodiscard]] constexpr mat<T, 4> perspective_lh(T left, T right, T bottom, T top, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectiveoffcenterlh
|
||||
|
||||
const T znear2 = T(2) * znear;
|
||||
const T znear2 = T{2} * znear;
|
||||
const T rwidth = rcp(right - left);
|
||||
const T rheight = rcp(top - bottom);
|
||||
const T frange = zfar * rcp(zfar - znear);
|
||||
|
||||
return {
|
||||
znear2 * rwidth, 0, 0, 0,
|
||||
0, znear2 * rheight, 0, 0,
|
||||
-(left + right) * rwidth, -(top + bottom) * rheight, frange, 1,
|
||||
0, 0, -frange * znear, 0};
|
||||
znear2 * rwidth, T{0}, T{0}, T{0},
|
||||
T{0}, znear2 * rheight, T{0}, T{0},
|
||||
-(left + right) * rwidth, -(top + bottom) * rheight, frange, T{1},
|
||||
T{0}, T{0}, -frange * znear, T{0}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> perspective_rh(T left, T right, T bottom, T top, T znear, T zfar) {
|
||||
[[nodiscard]] constexpr mat<T, 4> perspective_rh(T left, T right, T bottom, T top, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectiveoffcenterrh
|
||||
|
||||
const T znear2 = T(2) * znear;
|
||||
const T znear2 = T{2} * znear;
|
||||
const T rwidth = rcp(right - left);
|
||||
const T rheight = rcp(top - bottom);
|
||||
const T frange = zfar * rcp(znear - zfar);
|
||||
|
||||
return {
|
||||
znear2 * rwidth, 0, 0, 0,
|
||||
0, znear2 * rheight, 0, 0,
|
||||
(left + right) * rwidth, (top + bottom) * rheight, frange, -1,
|
||||
0, 0, frange * znear, 0};
|
||||
znear2 * rwidth, T{0}, T{0}, T{0},
|
||||
T{0}, znear2 * rheight, T{0}, T{0},
|
||||
(left + right) * rwidth, (top + bottom) * rheight, frange, -T{1},
|
||||
T{0}, T{0}, frange * znear, T{0}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> perspective_fov_lh(T fovy, T aspect, T znear, T zfar) {
|
||||
[[nodiscard]] constexpr mat<T, 4> perspective_fov_lh(T fovy, T aspect, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovlh
|
||||
|
||||
const T sy = rcp(tan(fovy * T(0.5)));
|
||||
const T sy = rcp(tan(fovy * T{0.5f}));
|
||||
const T sx = sy * rcp(aspect);
|
||||
const T sz = zfar * rcp(zfar - znear);
|
||||
const T tz = (znear * zfar) * rcp(znear - zfar);
|
||||
|
||||
return {
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, 1,
|
||||
0, 0, tz, 0};
|
||||
sx, T{0}, T{0}, T{0},
|
||||
T{0}, sy, T{0}, T{0},
|
||||
T{0}, T{0}, sz, T{1},
|
||||
T{0}, T{0}, tz, T{0}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> perspective_fov_rh(T fovy, T aspect, T znear, T zfar) {
|
||||
[[nodiscard]] constexpr mat<T, 4> perspective_fov_rh(T fovy, T aspect, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovrh
|
||||
|
||||
const T sy = rcp(tan(fovy * T(0.5)));
|
||||
const T sy = rcp(tan(fovy * T{0.5f}));
|
||||
const T sx = sy * rcp(aspect);
|
||||
const T sz = zfar * rcp(znear - zfar);
|
||||
const T tz = (znear * zfar) * rcp(znear - zfar);
|
||||
return {
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, -1,
|
||||
0, 0, tz, 0};
|
||||
sx, T{0}, T{0}, T{0},
|
||||
T{0}, sy, T{0}, T{0},
|
||||
T{0}, T{0}, sz, -T{1},
|
||||
T{0}, T{0}, tz, T{0}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -798,15 +833,15 @@ namespace vmath_hpp
|
||||
// angle
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] T angle(const vec<T, Size>& x, const vec<T, Size>& y) {
|
||||
[[nodiscard]] constexpr T angle(const vec<T, Size>& x, const vec<T, Size>& y) {
|
||||
const T rs = rsqrt(length2(x) * length2(y));
|
||||
return acos(clamp(dot(x, y) * rs, T(-1), T(1)));
|
||||
return acos(clamp(dot(x, y) * rs, -T{1}, T{1}));
|
||||
}
|
||||
|
||||
// rotate
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] vec<T, 2> rotate(const vec<T, 2>& v, T angle) {
|
||||
[[nodiscard]] constexpr vec<T, 2> rotate(const vec<T, 2>& v, T angle) {
|
||||
const auto [s, c] = sincos(angle);
|
||||
return {
|
||||
v.x * c - v.y * s,
|
||||
@@ -814,27 +849,27 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] vec<T, 3> rotate_x(const vec<T, 3>& v, T angle) {
|
||||
[[nodiscard]] constexpr vec<T, 3> rotate_x(const vec<T, 3>& v, T angle) {
|
||||
return v * qrotate(angle, unit3_x<T>);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] vec<T, 3> rotate_y(const vec<T, 3>& v, T angle) {
|
||||
[[nodiscard]] constexpr vec<T, 3> rotate_y(const vec<T, 3>& v, T angle) {
|
||||
return v * qrotate(angle, unit3_y<T>);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] vec<T, 3> rotate_z(const vec<T, 3>& v, T angle) {
|
||||
[[nodiscard]] constexpr vec<T, 3> rotate_z(const vec<T, 3>& v, T angle) {
|
||||
return v * qrotate(angle, unit3_z<T>);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] vec<T, 3> rotate(const vec<T, 3>& v, const qua<T>& q) {
|
||||
[[nodiscard]] constexpr vec<T, 3> rotate(const vec<T, 3>& v, const qua<T>& q) {
|
||||
return v * q;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] vec<T, 3> rotate(const vec<T, 3>& v, T angle, const vec<T, 3>& axis) {
|
||||
[[nodiscard]] constexpr vec<T, 3> rotate(const vec<T, 3>& v, T angle, const vec<T, 3>& axis) {
|
||||
return v * qrotate(angle, axis);
|
||||
}
|
||||
|
||||
@@ -842,7 +877,7 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> project(const vec<T, Size>& v, const vec<T, Size>& normal) {
|
||||
return dot(v, normal) * rcp(length2(normal)) * normal;
|
||||
return dot(v, normal) * rlength2(normal) * normal;
|
||||
}
|
||||
|
||||
// perpendicular
|
||||
@@ -862,115 +897,115 @@ namespace vmath_hpp
|
||||
// qrotate
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qrotate(const mat<T, 3>& m) {
|
||||
[[nodiscard]] constexpr qua<T> qrotate(const mat<T, 3>& m) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
|
||||
|
||||
auto xyzw = T(0.5) * sqrt(max(T(0), vec{
|
||||
T(1) + m[0][0] - m[1][1] - m[2][2],
|
||||
T(1) - m[0][0] + m[1][1] - m[2][2],
|
||||
T(1) - m[0][0] - m[1][1] + m[2][2],
|
||||
T(1) + m[0][0] + m[1][1] + m[2][2]}));
|
||||
auto xyzw = T{0.5f} * sqrt(max(T{0}, vec{
|
||||
T{1} + m[0][0] - m[1][1] - m[2][2],
|
||||
T{1} - m[0][0] + m[1][1] - m[2][2],
|
||||
T{1} - m[0][0] - m[1][1] + m[2][2],
|
||||
T{1} + m[0][0] + m[1][1] + m[2][2]}));
|
||||
|
||||
return qua(copysign(xyzw, {
|
||||
m[1][2] - m[2][1],
|
||||
m[2][0] - m[0][2],
|
||||
m[0][1] - m[1][0],
|
||||
T(1)}));
|
||||
T{1}}));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qrotate(const qua<T>& q, const mat<T, 3>& m) {
|
||||
[[nodiscard]] constexpr qua<T> qrotate(const qua<T>& q, const mat<T, 3>& m) {
|
||||
return q * qrotate(m);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qrotate(const vec<T, 3>& from, const vec<T, 3>& to) {
|
||||
[[nodiscard]] constexpr qua<T> qrotate(const vec<T, 3>& from, const vec<T, 3>& to) {
|
||||
/// REFERENCE:
|
||||
/// http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
|
||||
|
||||
const T n = sqrt(length2(from) * length2(to));
|
||||
const T s = dot(from, to) + n;
|
||||
|
||||
if ( s < T(0.000001) * n ) {
|
||||
return abs(from.x) > abs(from.z)
|
||||
? normalize(qua{vec{-from.y, from.x, T(0)}, T(0)})
|
||||
: normalize(qua{vec{T(0), -from.z, from.y}, T(0)});
|
||||
if ( s < T{0.000001f} * n ) {
|
||||
return abs(from.z) < abs(from.x)
|
||||
? normalize(qua{vec{-from.y, from.x, T{0}}, T{0}})
|
||||
: normalize(qua{vec{T{0}, -from.z, from.y}, T{0}});
|
||||
}
|
||||
|
||||
return normalize(qua{cross(from, to), s});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qrotate(const qua<T>& q, const vec<T, 3>& from, const vec<T, 3>& to) {
|
||||
[[nodiscard]] constexpr qua<T> qrotate(const qua<T>& q, const vec<T, 3>& from, const vec<T, 3>& to) {
|
||||
return q * qrotate(from, to);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qrotate(T angle, const vec<T, 3>& axis) {
|
||||
[[nodiscard]] constexpr qua<T> qrotate(T angle, const vec<T, 3>& axis) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/
|
||||
|
||||
const auto [s, c] = sincos(angle * T(0.5));
|
||||
const auto [s, c] = sincos(angle * T{0.5f});
|
||||
const auto [x, y, z] = normalize(axis);
|
||||
|
||||
return {vec{x,y,z} * s, c};
|
||||
return {vec{x, y, z} * s, c};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qrotate(const qua<T>& q, T angle, const vec<T, 3>& axis) {
|
||||
[[nodiscard]] constexpr qua<T> qrotate(const qua<T>& q, T angle, const vec<T, 3>& axis) {
|
||||
return q * qrotate(angle, axis);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qrotate_x(T angle) {
|
||||
[[nodiscard]] constexpr qua<T> qrotate_x(T angle) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/
|
||||
|
||||
const auto [s, c] = sincos(angle * T(0.5));
|
||||
const auto [s, c] = sincos(angle * T{0.5f});
|
||||
|
||||
return {s, T(0), T(0), c};
|
||||
return {vec{s, T{0}, T{0}}, c};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qrotate_x(const qua<T>& q, T angle) {
|
||||
[[nodiscard]] constexpr qua<T> qrotate_x(const qua<T>& q, T angle) {
|
||||
return qrotate(q, angle, unit3_x<T>);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qrotate_y(T angle) {
|
||||
[[nodiscard]] constexpr qua<T> qrotate_y(T angle) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/
|
||||
|
||||
const auto [s, c] = sincos(angle * T(0.5));
|
||||
const auto [s, c] = sincos(angle * T{0.5f});
|
||||
|
||||
return {T(0), s, T(0), c};
|
||||
return {vec{T{0}, s, T{0}}, c};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qrotate_y(const qua<T>& q, T angle) {
|
||||
[[nodiscard]] constexpr qua<T> qrotate_y(const qua<T>& q, T angle) {
|
||||
return qrotate(q, angle, unit3_y<T>);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qrotate_z(T angle) {
|
||||
[[nodiscard]] constexpr qua<T> qrotate_z(T angle) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/
|
||||
|
||||
const auto [s, c] = sincos(angle * T(0.5));
|
||||
const auto [s, c] = sincos(angle * T{0.5f});
|
||||
|
||||
return {T(0), T(0), s, c};
|
||||
return {vec{T{0}, T{0}, s}, c};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qrotate_z(const qua<T>& q, T angle) {
|
||||
[[nodiscard]] constexpr qua<T> qrotate_z(const qua<T>& q, T angle) {
|
||||
return qrotate(q, angle, unit3_z<T>);
|
||||
}
|
||||
|
||||
// look_at
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qlook_at_lh(const vec<T, 3>& dir, const vec<T, 3>& up) {
|
||||
[[nodiscard]] constexpr qua<T> qlook_at_lh(const vec<T, 3>& dir, const vec<T, 3>& up) {
|
||||
/// REFERENCE:
|
||||
/// https://www.euclideanspace.com/maths/algebra/vectors/lookat/
|
||||
|
||||
@@ -985,7 +1020,7 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qlook_at_rh(const vec<T, 3>& dir, const vec<T, 3>& up) {
|
||||
[[nodiscard]] constexpr qua<T> qlook_at_rh(const vec<T, 3>& dir, const vec<T, 3>& up) {
|
||||
/// REFERENCE:
|
||||
/// https://www.euclideanspace.com/maths/algebra/vectors/lookat/
|
||||
|
||||
|
||||
@@ -15,15 +15,13 @@
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_signed_v<T>, T>
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, T>
|
||||
constexpr abs(T x) noexcept {
|
||||
return x >= T(0) ? x : -x;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_unsigned_v<T>, T>
|
||||
constexpr abs(T x) noexcept {
|
||||
return x;
|
||||
if constexpr ( std::is_signed_v<T> ) {
|
||||
return x < T{0} ? -x : x;
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -35,13 +33,13 @@ namespace vmath_hpp
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, T>
|
||||
constexpr sign(T x) noexcept {
|
||||
return static_cast<T>((T(0) < x) - (x < T(0)));
|
||||
return static_cast<T>((T{0} < x) - (x < T{0}));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
constexpr rcp(T x) noexcept {
|
||||
return T(1) / x;
|
||||
return T{1} / x;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -113,13 +111,13 @@ namespace vmath_hpp
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, T>
|
||||
constexpr saturate(T x) noexcept {
|
||||
return clamp(x, T(0), T(1));
|
||||
return clamp(x, T{0}, T{1});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
constexpr lerp(T x, T y, T a) noexcept {
|
||||
return x * (T(1) - a) + y * a;
|
||||
return x * (T{1} - a) + y * a;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -131,50 +129,14 @@ namespace vmath_hpp
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
constexpr step(T edge, T x) noexcept {
|
||||
return x < edge ? T(0) : T(1);
|
||||
return x < edge ? T{0} : T{1};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
constexpr smoothstep(T edge0, T edge1, T x) noexcept {
|
||||
const T t = clamp((x - edge0) * rcp(edge1 - edge0), T(0), T(1));
|
||||
return t * t * (T(3) - T(2) * t);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
|
||||
isnan(T x) noexcept {
|
||||
return std::isnan(x);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
|
||||
isinf(T x) noexcept {
|
||||
return std::isinf(x);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
|
||||
isfinite(T x) noexcept {
|
||||
return std::isfinite(x);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
fma(T x, T y, T z) noexcept {
|
||||
return std::fma(x, y, z);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
frexp(T x, int* exp) noexcept {
|
||||
return std::frexp(x, exp);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
ldexp(T x, int exp) noexcept {
|
||||
return std::ldexp(x, exp);
|
||||
const T t = clamp((x - edge0) * rcp(edge1 - edge0), T{0}, T{1});
|
||||
return t * t * (T{3} - T{2} * t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,12 +317,24 @@ namespace vmath_hpp
|
||||
return abs(x);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, T>
|
||||
constexpr rlength(T x) noexcept {
|
||||
return rcp(abs(x));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, T>
|
||||
constexpr length2(T x) noexcept {
|
||||
return dot(x, x);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, T>
|
||||
constexpr rlength2(T x) noexcept {
|
||||
return rcp(dot(x, x));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, T>
|
||||
constexpr distance(T x, T y) noexcept {
|
||||
@@ -375,28 +349,28 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
normalize(T x) noexcept {
|
||||
return x * rsqrt(length2(x));
|
||||
constexpr normalize(T x) noexcept {
|
||||
return x * rlength(x);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
constexpr faceforward(T n, T i, T nref) noexcept {
|
||||
return dot(nref, i) < T(0) ? n : -n;
|
||||
return dot(nref, i) < T{0} ? n : -n;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
constexpr reflect(T i, T n) noexcept {
|
||||
return i - n * dot(n, i) * T(2);
|
||||
return i - T{2} * dot(n, i) * n;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
refract(T i, T n, T eta) noexcept {
|
||||
const T d = dot(n, i);
|
||||
const T k = T(1) - eta * eta * (T(1) - d * d);
|
||||
return T(k >= T(0)) * (eta * i - (eta * d + sqrt(k)) * n);
|
||||
const T k = T{1} - sqr(eta) * (T{1} - sqr(d));
|
||||
return k < T{0} ? T{0} : (eta * i - (eta * d + sqrt(k)) * n);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,7 +399,7 @@ namespace vmath_hpp
|
||||
/// REFERENCE:
|
||||
/// http://www.realtimecollisiondetection.net/pubs/Tolerances
|
||||
const T epsilon = std::numeric_limits<T>::epsilon();
|
||||
return abs(x - y) <= epsilon * max(max(T(1), abs(x)), abs(y));
|
||||
return abs(x - y) <= epsilon * max(max(T{1}, abs(x)), abs(y));
|
||||
} else {
|
||||
return x == y;
|
||||
}
|
||||
@@ -437,7 +411,7 @@ namespace vmath_hpp
|
||||
if constexpr ( std::is_floating_point_v<T> ) {
|
||||
/// REFERENCE:
|
||||
/// http://www.realtimecollisiondetection.net/pubs/Tolerances
|
||||
return abs(x - y) <= epsilon * max(max(T(1), abs(x)), abs(y));
|
||||
return abs(x - y) <= epsilon * max(max(T{1}, abs(x)), abs(y));
|
||||
} else {
|
||||
return abs(x - y) <= epsilon;
|
||||
}
|
||||
|
||||
@@ -20,21 +20,22 @@ namespace vmath_hpp::detail
|
||||
class mat_base<T, 2> {
|
||||
public:
|
||||
using row_type = vec<T, 2>;
|
||||
|
||||
row_type rows[2] = {
|
||||
{1, 0},
|
||||
{0, 1}};
|
||||
row_type{T{1}, T{0}},
|
||||
row_type{T{0}, T{1}}};
|
||||
public:
|
||||
constexpr mat_base() = default;
|
||||
|
||||
constexpr explicit mat_base(T d)
|
||||
: rows{
|
||||
row_type{d, 0},
|
||||
row_type{0, d}} {}
|
||||
row_type{d, T{0}},
|
||||
row_type{T{0}, d}} {}
|
||||
|
||||
constexpr explicit mat_base(const row_type& d)
|
||||
: rows{
|
||||
row_type{d[0], 0},
|
||||
row_type{0, d[1]}} {}
|
||||
row_type{d[0], T{0}},
|
||||
row_type{T{0}, d[1]}} {}
|
||||
|
||||
constexpr mat_base(
|
||||
T m11, T m12,
|
||||
@@ -47,42 +48,31 @@ namespace vmath_hpp::detail
|
||||
const row_type& row0,
|
||||
const row_type& row1)
|
||||
: rows{row0, row1} {}
|
||||
|
||||
constexpr explicit mat_base(
|
||||
const mat_base<T, 3>& other)
|
||||
: rows{
|
||||
row_type{other.rows[0]},
|
||||
row_type{other.rows[1]}} {}
|
||||
|
||||
constexpr explicit mat_base(
|
||||
const mat_base<T, 4>& other)
|
||||
: rows{
|
||||
row_type{other.rows[0]},
|
||||
row_type{other.rows[1]}} {}
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
class mat_base<T, 3> {
|
||||
public:
|
||||
using row_type = vec<T, 3>;
|
||||
|
||||
row_type rows[3] = {
|
||||
{1, 0, 0},
|
||||
{0, 1, 0},
|
||||
{0, 0, 1}};
|
||||
row_type{T{1}, T{0}, T{0}},
|
||||
row_type{T{0}, T{1}, T{0}},
|
||||
row_type{T{0}, T{0}, T{1}}};
|
||||
public:
|
||||
constexpr mat_base() = default;
|
||||
|
||||
constexpr explicit mat_base(T d)
|
||||
: rows{
|
||||
row_type{d, 0, 0},
|
||||
row_type{0, d, 0},
|
||||
row_type{0, 0, d}} {}
|
||||
row_type{d, T{0}, T{0}},
|
||||
row_type{T{0}, d, T{0}},
|
||||
row_type{T{0}, T{0}, d}} {}
|
||||
|
||||
constexpr explicit mat_base(const row_type& d)
|
||||
: rows{
|
||||
row_type{d[0], 0, 0},
|
||||
row_type{0, d[1], 0},
|
||||
row_type{0, 0, d[2]}} {}
|
||||
row_type{d[0], T{0}, T{0}},
|
||||
row_type{T{0}, d[1], T{0}},
|
||||
row_type{T{0}, T{0}, d[2]}} {}
|
||||
|
||||
constexpr mat_base(
|
||||
T m11, T m12, T m13,
|
||||
@@ -103,50 +93,50 @@ namespace vmath_hpp::detail
|
||||
const mat_base<T, 2>& m,
|
||||
const vec_base<T, 2>& v)
|
||||
: rows{
|
||||
row_type{m.rows[0], 0},
|
||||
row_type{m.rows[1], 0},
|
||||
row_type{v, 1}} {}
|
||||
row_type{m.rows[0], T{0}},
|
||||
row_type{m.rows[1], T{0}},
|
||||
row_type{v, T{1}}} {}
|
||||
|
||||
constexpr explicit mat_base(
|
||||
const mat_base<T, 2>& other)
|
||||
: rows{
|
||||
row_type{other.rows[0], 0},
|
||||
row_type{other.rows[1], 0},
|
||||
row_type{0, 0, 1}} {}
|
||||
row_type{other.rows[0], T{0}},
|
||||
row_type{other.rows[1], T{0}},
|
||||
row_type{T{0}, T{0}, T{1}}} {}
|
||||
|
||||
constexpr explicit mat_base(
|
||||
const mat_base<T, 4>& other)
|
||||
: rows{
|
||||
row_type{other.rows[0]},
|
||||
row_type{other.rows[1]},
|
||||
row_type{other.rows[2]}} {}
|
||||
constexpr explicit operator mat<T, 2>() const {
|
||||
return {
|
||||
vec<T, 2>{rows[0]},
|
||||
vec<T, 2>{rows[1]}};
|
||||
}
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
class mat_base<T, 4> {
|
||||
public:
|
||||
using row_type = vec<T, 4>;
|
||||
|
||||
row_type rows[4] = {
|
||||
{1, 0, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
{0, 0, 0, 1}};
|
||||
row_type{T{1}, T{0}, T{0}, T{0}},
|
||||
row_type{T{0}, T{1}, T{0}, T{0}},
|
||||
row_type{T{0}, T{0}, T{1}, T{0}},
|
||||
row_type{T{0}, T{0}, T{0}, T{1}}};
|
||||
public:
|
||||
constexpr mat_base() = default;
|
||||
|
||||
constexpr explicit mat_base(T d)
|
||||
: rows{
|
||||
row_type{d, 0, 0, 0},
|
||||
row_type{0, d, 0, 0},
|
||||
row_type{0, 0, d, 0},
|
||||
row_type{0, 0, 0, d}} {}
|
||||
row_type{d, T{0}, T{0}, T{0}},
|
||||
row_type{T{0}, d, T{0}, T{0}},
|
||||
row_type{T{0}, T{0}, d, T{0}},
|
||||
row_type{T{0}, T{0}, T{0}, d}} {}
|
||||
|
||||
constexpr explicit mat_base(const row_type& d)
|
||||
: rows{
|
||||
row_type{d[0], 0, 0, 0},
|
||||
row_type{0, d[1], 0, 0},
|
||||
row_type{0, 0, d[2], 0},
|
||||
row_type{0, 0, 0, d[3]}} {}
|
||||
row_type{d[0], T{0}, T{0}, T{0}},
|
||||
row_type{T{0}, d[1], T{0}, T{0}},
|
||||
row_type{T{0}, T{0}, d[2], T{0}},
|
||||
row_type{T{0}, T{0}, T{0}, d[3]}} {}
|
||||
|
||||
constexpr mat_base(
|
||||
T m11, T m12, T m13, T m14,
|
||||
@@ -170,26 +160,39 @@ namespace vmath_hpp::detail
|
||||
const mat_base<T, 3>& m,
|
||||
const vec_base<T, 3>& v)
|
||||
: rows{
|
||||
row_type{m.rows[0], 0},
|
||||
row_type{m.rows[1], 0},
|
||||
row_type{m.rows[2], 0},
|
||||
row_type{v, 1}} {}
|
||||
row_type{m.rows[0], T{0}},
|
||||
row_type{m.rows[1], T{0}},
|
||||
row_type{m.rows[2], T{0}},
|
||||
row_type{v, T{1}}} {}
|
||||
|
||||
constexpr explicit mat_base(
|
||||
const mat_base<T, 2>& other)
|
||||
: rows{
|
||||
row_type{other.rows[0], 0, 0},
|
||||
row_type{other.rows[1], 0, 0},
|
||||
row_type{0, 0, 1, 0},
|
||||
row_type{0, 0, 0, 1}} {}
|
||||
row_type{other.rows[0], T{0}, T{0}},
|
||||
row_type{other.rows[1], T{0}, T{0}},
|
||||
row_type{T{0}, T{0}, T{1}, T{0}},
|
||||
row_type{T{0}, T{0}, T{0}, T{1}}} {}
|
||||
|
||||
constexpr explicit mat_base(
|
||||
const mat_base<T, 3>& other)
|
||||
: rows{
|
||||
row_type{other.rows[0], 0},
|
||||
row_type{other.rows[1], 0},
|
||||
row_type{other.rows[2], 0},
|
||||
row_type{0, 0, 0, 1}} {}
|
||||
row_type{other.rows[0], T{0}},
|
||||
row_type{other.rows[1], T{0}},
|
||||
row_type{other.rows[2], T{0}},
|
||||
row_type{T{0}, T{0}, T{0}, T{1}}} {}
|
||||
|
||||
constexpr explicit operator mat<T, 2>() const {
|
||||
return {
|
||||
vec<T, 2>{rows[0]},
|
||||
vec<T, 2>{rows[1]}};
|
||||
}
|
||||
|
||||
constexpr explicit operator mat<T, 3>() const {
|
||||
return {
|
||||
vec<T, 3>{rows[0]},
|
||||
vec<T, 3>{rows[1]},
|
||||
vec<T, 3>{rows[2]}};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -200,7 +203,8 @@ namespace vmath_hpp
|
||||
public:
|
||||
using self_type = mat;
|
||||
using base_type = detail::mat_base<T, Size>;
|
||||
public:
|
||||
using component_type = T;
|
||||
|
||||
using row_type = vec<T, Size>;
|
||||
|
||||
using pointer = row_type*;
|
||||
@@ -214,7 +218,7 @@ namespace vmath_hpp
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
static constexpr std::size_t size = Size;
|
||||
static inline constexpr std::size_t size = Size;
|
||||
public:
|
||||
using base_type::mat_base;
|
||||
using base_type::rows;
|
||||
@@ -253,14 +257,6 @@ namespace vmath_hpp
|
||||
return &rows[0];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr reference operator[](std::size_t index) noexcept {
|
||||
return rows[index];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const_reference operator[](std::size_t index) const noexcept {
|
||||
return rows[index];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr reference at(std::size_t index) {
|
||||
VMATH_HPP_THROW_IF(index >= size, std::out_of_range("mat::at"));
|
||||
return rows[index];
|
||||
@@ -270,6 +266,14 @@ namespace vmath_hpp
|
||||
VMATH_HPP_THROW_IF(index >= size, std::out_of_range("mat::at"));
|
||||
return rows[index];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr reference operator[](std::size_t index) noexcept {
|
||||
return rows[index];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const_reference operator[](std::size_t index) const noexcept {
|
||||
return rows[index];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+128
-131
@@ -18,88 +18,94 @@ namespace vmath_hpp::detail::impl
|
||||
{
|
||||
template < typename A, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
mat<typename std::invoke_result_t<
|
||||
F,
|
||||
vec<A, Size>
|
||||
>::component_type, Size>
|
||||
map_join_impl(
|
||||
F&& f,
|
||||
const mat<A, Size>& a,
|
||||
std::index_sequence<Is...>
|
||||
) -> mat<typename decltype(f(
|
||||
std::declval<vec<A, Size>>()))::component_type, Size>
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
return { f(a[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
mat<typename std::invoke_result_t<
|
||||
F,
|
||||
vec<A, Size>,
|
||||
vec<B, Size>
|
||||
>::component_type, Size>
|
||||
map_join_impl(
|
||||
F&& f,
|
||||
const mat<A, Size>& a,
|
||||
const mat<B, Size>& b,
|
||||
std::index_sequence<Is...>
|
||||
) -> mat<typename decltype(f(
|
||||
std::declval<vec<A, Size>>(),
|
||||
std::declval<vec<B, Size>>()))::component_type, Size>
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
return { f(a[Is], b[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
mat<typename std::invoke_result_t<
|
||||
F,
|
||||
vec<A, Size>,
|
||||
vec<B, Size>,
|
||||
vec<C, Size>
|
||||
>::component_type, Size>
|
||||
map_join_impl(
|
||||
F&& f,
|
||||
const mat<A, Size>& a,
|
||||
const mat<B, Size>& b,
|
||||
const mat<C, Size>& c,
|
||||
std::index_sequence<Is...>
|
||||
) -> mat<typename decltype(f(
|
||||
std::declval<vec<A, Size>>(),
|
||||
std::declval<vec<B, Size>>(),
|
||||
std::declval<vec<C, Size>>()))::component_type, Size>
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
return { f(a[Is], b[Is], c[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join_impl(
|
||||
A fold_join_impl(
|
||||
F&& f,
|
||||
A init,
|
||||
const mat<B, Size>& b,
|
||||
std::index_sequence<Is...>
|
||||
) -> A {
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
return ((init = f(std::move(init), b[Is])), ...);
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join_impl(
|
||||
A fold_join_impl(
|
||||
F&& f,
|
||||
A init,
|
||||
const vec<B, Size>& b,
|
||||
const mat<C, Size>& c,
|
||||
std::index_sequence<Is...>
|
||||
) -> A {
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
return ((init = f(std::move(init), b[Is], c[Is])), ...);
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join_impl(
|
||||
A fold_join_impl(
|
||||
F&& f,
|
||||
A init,
|
||||
const mat<B, Size>& b,
|
||||
const mat<C, Size>& c,
|
||||
std::index_sequence<Is...>
|
||||
) -> A {
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
return ((init = f(std::move(init), b[Is], c[Is])), ...);
|
||||
}
|
||||
|
||||
template < typename A, std::size_t Size, typename F, std::size_t I, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold1_join_impl(
|
||||
vec<A, Size> fold1_join_impl(
|
||||
F&& f,
|
||||
const mat<A, Size>& a,
|
||||
std::index_sequence<I, Is...>
|
||||
) -> vec<A, Size> {
|
||||
std::index_sequence<I, Is...>)
|
||||
{
|
||||
vec<A, Size> init = a[I];
|
||||
return ((init = f(std::move(init), a[Is])), ...);
|
||||
}
|
||||
@@ -109,80 +115,44 @@ namespace vmath_hpp::detail
|
||||
{
|
||||
template < typename A, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const mat<A, Size>& a
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
auto map_join(F&& f, const mat<A, Size>& a) {
|
||||
return impl::map_join_impl(std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const mat<A, Size>& a,
|
||||
const mat<B, Size>& b
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, b, std::make_index_sequence<Size>{});
|
||||
auto map_join(F&& f, const mat<A, Size>& a, const mat<B, Size>& b) {
|
||||
return impl::map_join_impl(std::forward<F>(f), a, b, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const mat<A, Size>& a,
|
||||
const mat<B, Size>& b,
|
||||
const mat<C, Size>& c
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, b, c, std::make_index_sequence<Size>{});
|
||||
auto map_join(F&& f, const mat<A, Size>& a, const mat<B, Size>& b, const mat<C, Size>& c) {
|
||||
return impl::map_join_impl(std::forward<F>(f), a, b, c, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join(
|
||||
F&& f,
|
||||
A init,
|
||||
const mat<B, Size>& b
|
||||
) {
|
||||
return impl::fold_join_impl(
|
||||
std::forward<F>(f), std::move(init), b, std::make_index_sequence<Size>{});
|
||||
auto fold_join(F&& f, A init, const mat<B, Size>& b) {
|
||||
return impl::fold_join_impl(std::forward<F>(f), std::move(init), b, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join(
|
||||
F&& f,
|
||||
A init,
|
||||
const vec<B, Size>& b,
|
||||
const mat<C, Size>& c
|
||||
) {
|
||||
return impl::fold_join_impl(
|
||||
std::forward<F>(f), std::move(init), b, c, std::make_index_sequence<Size>{});
|
||||
auto fold_join(F&& f, A init, const vec<B, Size>& b, const mat<C, Size>& c) {
|
||||
return impl::fold_join_impl(std::forward<F>(f), std::move(init), b, c, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join(
|
||||
F&& f,
|
||||
A init,
|
||||
const mat<B, Size>& b,
|
||||
const mat<C, Size>& c
|
||||
) {
|
||||
return impl::fold_join_impl(
|
||||
std::forward<F>(f), std::move(init), b, c, std::make_index_sequence<Size>{});
|
||||
auto fold_join(F&& f, A init, const mat<B, Size>& b, const mat<C, Size>& c) {
|
||||
return impl::fold_join_impl(std::forward<F>(f), std::move(init), b, c, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold1_join(
|
||||
F&& f,
|
||||
const mat<A, Size>& a
|
||||
) {
|
||||
return impl::fold1_join_impl(
|
||||
std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
auto fold1_join(F&& f, const mat<A, Size>& a) {
|
||||
return impl::fold1_join_impl(std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,45 +165,45 @@ namespace vmath_hpp
|
||||
// +operator
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator+(const mat<T, Size>& xs) {
|
||||
return xs;
|
||||
[[nodiscard]] constexpr auto 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<T, Size> operator-(const mat<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr auto 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<T, Size> operator~(const mat<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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<T, Size> operator+(const mat<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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);
|
||||
}
|
||||
|
||||
@@ -252,17 +222,17 @@ namespace vmath_hpp
|
||||
// operator-
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator-(const mat<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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);
|
||||
}
|
||||
|
||||
@@ -281,24 +251,24 @@ namespace vmath_hpp
|
||||
// operator*
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator*(const mat<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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 vec<T, Size> operator*(const vec<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
[[nodiscard]] constexpr auto operator*(const vec<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return fold_join([](const vec<T, Size>& acc, T x, const vec<T, Size>& y){
|
||||
return acc + x * y;
|
||||
}, vec<T, Size>{}, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator*(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
[[nodiscard]] constexpr auto operator*(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return map_join([&ys](const vec<T, Size>& x){
|
||||
return x * ys;
|
||||
}, xs);
|
||||
@@ -324,12 +294,12 @@ namespace vmath_hpp
|
||||
// operator/
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator/(const mat<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto operator/(T x, const mat<T, Size>& ys) {
|
||||
return map_join([x](const vec<T, Size>& y){ return x / y; }, ys);
|
||||
}
|
||||
|
||||
@@ -343,17 +313,17 @@ namespace vmath_hpp
|
||||
// operator&
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator&(const mat<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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);
|
||||
}
|
||||
|
||||
@@ -372,17 +342,17 @@ namespace vmath_hpp
|
||||
// operator|
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator|(const mat<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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);
|
||||
}
|
||||
|
||||
@@ -401,17 +371,17 @@ namespace vmath_hpp
|
||||
// operator^
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator^(const mat<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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);
|
||||
}
|
||||
|
||||
@@ -430,34 +400,34 @@ namespace vmath_hpp
|
||||
// operator&&
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> operator&&(const mat<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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);
|
||||
}
|
||||
|
||||
@@ -501,53 +471,80 @@ namespace vmath_hpp
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
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);
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = decltype(any(std::declval<vec<T, Size>>())) >
|
||||
[[nodiscard]] constexpr U any(const mat<T, Size>& xs) {
|
||||
return fold_join([](U acc, const vec<T, Size>& x){ return acc || any(x); }, U{false}, xs);
|
||||
}
|
||||
|
||||
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);
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = decltype(all(std::declval<vec<T, Size>>())) >
|
||||
[[nodiscard]] constexpr U all(const mat<T, Size>& xs) {
|
||||
return fold_join([](U acc, const vec<T, Size>& x){ return acc && all(x); }, U{true}, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> approx(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = typename decltype(approx(
|
||||
std::declval<vec<T, Size>>(),
|
||||
std::declval<vec<T, Size>>()))::component_type >
|
||||
[[nodiscard]] constexpr mat<U, 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, const mat<T, Size>& ys, T epsilon) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = typename decltype(approx(
|
||||
std::declval<vec<T, Size>>(),
|
||||
std::declval<vec<T, Size>>(),
|
||||
std::declval<T>()))::component_type >
|
||||
[[nodiscard]] constexpr mat<U, 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);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> less(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = typename decltype(less(
|
||||
std::declval<vec<T, Size>>(),
|
||||
std::declval<vec<T, Size>>()))::component_type >
|
||||
[[nodiscard]] constexpr mat<U, 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);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> less_equal(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = typename decltype(less_equal(
|
||||
std::declval<vec<T, Size>>(),
|
||||
std::declval<vec<T, Size>>()))::component_type >
|
||||
[[nodiscard]] constexpr mat<U, 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);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> greater(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = typename decltype(greater(
|
||||
std::declval<vec<T, Size>>(),
|
||||
std::declval<vec<T, Size>>()))::component_type >
|
||||
[[nodiscard]] constexpr mat<U, 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);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> greater_equal(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = typename decltype(greater_equal(
|
||||
std::declval<vec<T, Size>>(),
|
||||
std::declval<vec<T, Size>>()))::component_type >
|
||||
[[nodiscard]] constexpr mat<U, 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);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> equal_to(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = typename decltype(equal_to(
|
||||
std::declval<vec<T, Size>>(),
|
||||
std::declval<vec<T, Size>>()))::component_type >
|
||||
[[nodiscard]] constexpr mat<U, 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);
|
||||
}
|
||||
|
||||
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) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = typename decltype(not_equal_to(
|
||||
std::declval<vec<T, Size>>(),
|
||||
std::declval<vec<T, Size>>()))::component_type >
|
||||
[[nodiscard]] constexpr mat<U, 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,63 @@
|
||||
#include "vmath_vec.hpp"
|
||||
#include "vmath_vec_fun.hpp"
|
||||
|
||||
namespace vmath_hpp::detail
|
||||
{
|
||||
template < typename T >
|
||||
class qua_base {
|
||||
public:
|
||||
vec<T, 3> v = vec<T, 3>{T{0}};
|
||||
T s = T{1};
|
||||
public:
|
||||
constexpr qua_base() = default;
|
||||
|
||||
constexpr qua_base(T vx, T vy, T vz, T s)
|
||||
: v{vx, vy, vz}, s{s} {}
|
||||
|
||||
constexpr qua_base(const vec<T, 3>& v, T s)
|
||||
: v{v}, s{s} {}
|
||||
|
||||
constexpr explicit qua_base(const vec<T, 4>& vs)
|
||||
: v{vs[0], vs[1], vs[2]}, s{vs[3]} {}
|
||||
|
||||
constexpr explicit operator vec<T, 4>() const {
|
||||
return {v, s};
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T& operator[](std::size_t index) noexcept {
|
||||
switch ( index ) {
|
||||
default:
|
||||
case 0: return v.x;
|
||||
case 1: return v.y;
|
||||
case 2: return v.z;
|
||||
case 3: return s;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const T& operator[](std::size_t index) const noexcept {
|
||||
switch ( index ) {
|
||||
default:
|
||||
case 0: return v.x;
|
||||
case 1: return v.y;
|
||||
case 2: return v.z;
|
||||
case 3: return s;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T >
|
||||
class qua final {
|
||||
public:
|
||||
vec<T, 3> v{0};
|
||||
T s{1};
|
||||
class qua final : public detail::qua_base<T> {
|
||||
public:
|
||||
using self_type = qua;
|
||||
using base_type = detail::qua_base<T>;
|
||||
using component_type = T;
|
||||
|
||||
using imag_type = vec<T, 3>;
|
||||
using real_type = T;
|
||||
|
||||
using pointer = component_type*;
|
||||
using const_pointer = const component_type*;
|
||||
|
||||
@@ -33,28 +79,15 @@ namespace vmath_hpp
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
static constexpr std::size_t size = 4;
|
||||
static inline constexpr std::size_t size = 4;
|
||||
public:
|
||||
using base_type::qua_base;
|
||||
using base_type::operator[];
|
||||
|
||||
constexpr qua() = default;
|
||||
constexpr qua(const qua&) = default;
|
||||
constexpr qua& operator=(const qua&) = default;
|
||||
|
||||
constexpr qua(T vx, T vy, T vz, T s)
|
||||
: v{vx, vy, vz}
|
||||
, s{s} {}
|
||||
|
||||
constexpr qua(const vec<T, 3>& v, T s)
|
||||
: v{v}
|
||||
, s{s} {}
|
||||
|
||||
constexpr explicit qua(const vec<T, 4>& vs)
|
||||
: v{vs[0], vs[1], vs[2]}
|
||||
, s{vs[3]} {}
|
||||
|
||||
constexpr explicit operator vec<T, 4>() const {
|
||||
return {(*this).v, (*this).s};
|
||||
}
|
||||
|
||||
void swap(qua& other) noexcept(std::is_nothrow_swappable_v<T>) {
|
||||
for ( std::size_t i = 0; i < size; ++i ) {
|
||||
using std::swap;
|
||||
@@ -85,26 +118,6 @@ namespace vmath_hpp
|
||||
return &(*this)[0];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr reference operator[](std::size_t index) noexcept {
|
||||
switch ( index ) {
|
||||
default:
|
||||
case 0: return v.x;
|
||||
case 1: return v.y;
|
||||
case 2: return v.z;
|
||||
case 3: return s;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const_reference operator[](std::size_t index) const noexcept {
|
||||
switch ( index ) {
|
||||
default:
|
||||
case 0: return v.x;
|
||||
case 1: return v.y;
|
||||
case 2: return v.z;
|
||||
case 3: return s;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr reference at(std::size_t index) {
|
||||
VMATH_HPP_THROW_IF(index >= size, std::out_of_range("qua::at"));
|
||||
return (*this)[index];
|
||||
|
||||
@@ -14,6 +14,51 @@
|
||||
#include "vmath_vec.hpp"
|
||||
#include "vmath_vec_fun.hpp"
|
||||
|
||||
namespace vmath_hpp::detail
|
||||
{
|
||||
template < typename A, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join(F&& f, const qua<A>& a) {
|
||||
return qua(map_join(std::forward<F>(f), vec{a}));
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join(F&& f, const qua<A>& a, const qua<B>& b) {
|
||||
return qua(map_join(std::forward<F>(f), vec{a}, vec{b}));
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join(F&& f, const qua<A>& a, const qua<B>& b, const qua<C>& c) {
|
||||
return qua(map_join(std::forward<F>(f), vec{a}, vec{b}, vec{c}));
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, typename D, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join(F&& f, const qua<A>& a, const qua<B>& b, const qua<C>& c, const qua<D>& d) {
|
||||
return qua(map_join(std::forward<F>(f), vec{a}, vec{b}, vec{c}, vec{d}));
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join(F&& f, A init, const qua<B>& b) {
|
||||
return fold_join(std::forward<F>(f), std::move(init), vec{b});
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join(F&& f, A init, const qua<B>& b, const qua<C>& c) {
|
||||
return fold_join(std::forward<F>(f), std::move(init), vec{b}, vec{c});
|
||||
}
|
||||
|
||||
template < typename A, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold1_join(F&& f, const qua<A>& a) {
|
||||
return fold1_join(std::forward<F>(f), vec{a});
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Operators
|
||||
//
|
||||
@@ -23,21 +68,21 @@ namespace vmath_hpp
|
||||
// +operator
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> operator+(const qua<T>& xs) {
|
||||
return xs;
|
||||
[[nodiscard]] constexpr auto operator+(const qua<T>& xs) {
|
||||
return qua(+vec<T, 4>{xs});
|
||||
}
|
||||
|
||||
// -operator
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> operator-(const qua<T>& xs) {
|
||||
[[nodiscard]] constexpr auto operator-(const qua<T>& xs) {
|
||||
return qua(-vec<T, 4>{xs});
|
||||
}
|
||||
|
||||
// operator+
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> operator+(const qua<T>& xs, const qua<T>& ys) {
|
||||
[[nodiscard]] constexpr auto operator+(const qua<T>& xs, const qua<T>& ys) {
|
||||
return qua(vec{xs} + vec{ys});
|
||||
}
|
||||
|
||||
@@ -51,7 +96,7 @@ namespace vmath_hpp
|
||||
// operator-
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> operator-(const qua<T>& xs, const qua<T>& ys) {
|
||||
[[nodiscard]] constexpr auto operator-(const qua<T>& xs, const qua<T>& ys) {
|
||||
return qua(vec{xs} - vec{ys});
|
||||
}
|
||||
|
||||
@@ -65,30 +110,30 @@ namespace vmath_hpp
|
||||
// operator*
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> operator*(const qua<T>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto operator*(const qua<T>& xs, T y) {
|
||||
return qua(vec{xs} * y);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> operator*(T x, const qua<T>& ys) {
|
||||
[[nodiscard]] constexpr auto operator*(T x, const qua<T>& ys) {
|
||||
return qua(x * vec{ys});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<T, 3> operator*(const vec<T, 3>& xs, const qua<T>& ys) {
|
||||
[[nodiscard]] constexpr auto operator*(const vec<T, 3>& xs, const qua<T>& ys) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/
|
||||
|
||||
const vec qv2 = cross(ys.v, xs) * T(2);
|
||||
const vec qv2 = cross(ys.v, xs) * T{2};
|
||||
return xs + qv2 * ys.s + cross(ys.v, qv2);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> operator*(const qua<T>& xs, const qua<T>& ys) {
|
||||
[[nodiscard]] constexpr auto operator*(const qua<T>& xs, const qua<T>& ys) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/arithmetic/
|
||||
|
||||
return {
|
||||
return qua{
|
||||
cross(ys.v, xs.v) + ys.s * xs.v + xs.s * ys.v,
|
||||
ys.s * xs.s - dot(ys.v, xs.v)};
|
||||
}
|
||||
@@ -113,12 +158,12 @@ namespace vmath_hpp
|
||||
// operator/
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> operator/(const qua<T>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto operator/(const qua<T>& xs, T y) {
|
||||
return qua(vec{xs} / y);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> operator/(T x, const qua<T>& ys) {
|
||||
[[nodiscard]] constexpr auto operator/(T x, const qua<T>& ys) {
|
||||
return qua(x / vec{ys});
|
||||
}
|
||||
|
||||
@@ -158,24 +203,24 @@ namespace vmath_hpp
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> lerp(const qua<T>& xs, const qua<T>& ys, T a) {
|
||||
[[nodiscard]] constexpr qua<T> lerp(const qua<T>& xs, const qua<T>& ys, T a) {
|
||||
return qua(lerp(vec{xs}, vec{ys}, a));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> lerp(const qua<T>& xs, const qua<T>& ys, T xs_a, T ys_a) {
|
||||
return qua(lerp(vec{xs}, vec{ys}, xs_a, ys_a));
|
||||
[[nodiscard]] constexpr qua<T> lerp(const qua<T>& xs, const qua<T>& ys, T x_a, T y_a) {
|
||||
return qua(lerp(vec{xs}, vec{ys}, x_a, y_a));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> nlerp(const qua<T>& unit_xs, const qua<T>& unit_ys, T a) {
|
||||
const T xs_scale = T(1) - a;
|
||||
[[nodiscard]] constexpr qua<T> nlerp(const qua<T>& unit_xs, const qua<T>& unit_ys, T a) {
|
||||
const T xs_scale = T{1} - a;
|
||||
const T ys_scale = a * sign(dot(unit_xs, unit_ys));
|
||||
return normalize(lerp(unit_xs, unit_ys, xs_scale, ys_scale));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> slerp(const qua<T>& unit_xs, const qua<T>& unit_ys, T a) {
|
||||
[[nodiscard]] constexpr qua<T> slerp(const qua<T>& unit_xs, const qua<T>& unit_ys, T a) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
|
||||
|
||||
@@ -183,34 +228,19 @@ namespace vmath_hpp
|
||||
const T raw_cos_theta_sign = sign(raw_cos_theta);
|
||||
|
||||
// half degree linear threshold: cos((pi / 180) * 0.25)
|
||||
if ( const T cos_theta = raw_cos_theta * raw_cos_theta_sign; cos_theta < T(0.99999) ) {
|
||||
if ( const T cos_theta = raw_cos_theta * raw_cos_theta_sign; cos_theta < T{0.99999f} ) {
|
||||
const T theta = acos(cos_theta);
|
||||
const T rsin_theta = rsqrt(T(1) - sqr(cos_theta));
|
||||
const T xs_scale = sin((T(1) - a) * theta) * rsin_theta;
|
||||
const T rsin_theta = rsqrt(T{1} - sqr(cos_theta));
|
||||
const T xs_scale = sin((T{1} - a) * theta) * rsin_theta;
|
||||
const T ys_scale = sin(a * theta) * raw_cos_theta_sign * rsin_theta;
|
||||
return lerp(unit_xs, unit_ys, xs_scale, ys_scale);
|
||||
} else {
|
||||
// use linear interpolation for small angles
|
||||
const T xs_scale = T(1) - a;
|
||||
const T xs_scale = T{1} - a;
|
||||
const T ys_scale = a * raw_cos_theta_sign;
|
||||
return normalize(lerp(unit_xs, unit_ys, xs_scale, ys_scale));
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] vec<bool, 4> isnan(const qua<T>& xs) {
|
||||
return isnan(vec{xs});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] vec<bool, 4> isinf(const qua<T>& xs) {
|
||||
return isinf(vec{xs});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] vec<bool, 4> isfinite(const qua<T>& xs) {
|
||||
return isfinite(vec{xs});
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -225,23 +255,33 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] T length(const qua<T>& xs) {
|
||||
[[nodiscard]] constexpr T length(const qua<T>& xs) {
|
||||
return length(vec{xs});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr T rlength(const qua<T>& xs) {
|
||||
return rlength(vec{xs});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr T length2(const qua<T>& xs) {
|
||||
return length2(vec{xs});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] T distance(const qua<T>& xs, const qua<T>& ys) {
|
||||
const qua zs = xs * conjugate(ys);
|
||||
return T(2) * atan2(length(zs.v), abs(zs.s));
|
||||
[[nodiscard]] constexpr T rlength2(const qua<T>& xs) {
|
||||
return rlength2(vec{xs});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> normalize(const qua<T>& xs) {
|
||||
[[nodiscard]] constexpr T distance(const qua<T>& xs, const qua<T>& ys) {
|
||||
const qua zs = xs * conjugate(ys);
|
||||
return T{2} * atan2(length(zs.v), abs(zs.s));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> normalize(const qua<T>& xs) {
|
||||
return qua(normalize(vec{xs}));
|
||||
}
|
||||
}
|
||||
@@ -252,43 +292,80 @@ namespace vmath_hpp
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<bool, 4> approx(const qua<T>& xs, const qua<T>& ys) {
|
||||
template < typename T
|
||||
, typename U = decltype(any(std::declval<vec<T, 4>>())) >
|
||||
[[nodiscard]] constexpr U any(const qua<T>& xs) {
|
||||
return any(vec{xs});
|
||||
}
|
||||
|
||||
template < typename T
|
||||
, typename U = decltype(all(std::declval<vec<T, 4>>())) >
|
||||
[[nodiscard]] constexpr U all(const qua<T>& xs) {
|
||||
return all(vec{xs});
|
||||
}
|
||||
|
||||
template < typename T
|
||||
, typename U = typename decltype(approx(
|
||||
std::declval<vec<T, 4>>(),
|
||||
std::declval<vec<T, 4>>()))::component_type >
|
||||
[[nodiscard]] constexpr vec<U, 4> approx(const qua<T>& xs, const qua<T>& ys) {
|
||||
return approx(vec{xs}, vec{ys});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<bool, 4> approx(const qua<T>& xs, const qua<T>& ys, T epsilon) {
|
||||
template < typename T
|
||||
, typename U = typename decltype(approx(
|
||||
std::declval<vec<T, 4>>(),
|
||||
std::declval<vec<T, 4>>(),
|
||||
std::declval<T>()))::component_type >
|
||||
[[nodiscard]] constexpr vec<U, 4> approx(const qua<T>& xs, const qua<T>& ys, T epsilon) {
|
||||
return approx(vec{xs}, vec{ys}, epsilon);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<bool, 4> less(const qua<T>& xs, const qua<T>& ys) {
|
||||
template < typename T
|
||||
, typename U = typename decltype(less(
|
||||
std::declval<vec<T, 4>>(),
|
||||
std::declval<vec<T, 4>>()))::component_type >
|
||||
[[nodiscard]] constexpr vec<U, 4> less(const qua<T>& xs, const qua<T>& ys) {
|
||||
return less(vec{xs}, vec{ys});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<bool, 4> less_equal(const qua<T>& xs, const qua<T>& ys) {
|
||||
template < typename T
|
||||
, typename U = typename decltype(less_equal(
|
||||
std::declval<vec<T, 4>>(),
|
||||
std::declval<vec<T, 4>>()))::component_type >
|
||||
[[nodiscard]] constexpr vec<U, 4> less_equal(const qua<T>& xs, const qua<T>& ys) {
|
||||
return less_equal(vec{xs}, vec{ys});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<bool, 4> greater(const qua<T>& xs, const qua<T>& ys) {
|
||||
template < typename T
|
||||
, typename U = typename decltype(greater(
|
||||
std::declval<vec<T, 4>>(),
|
||||
std::declval<vec<T, 4>>()))::component_type >
|
||||
[[nodiscard]] constexpr vec<U, 4> greater(const qua<T>& xs, const qua<T>& ys) {
|
||||
return greater(vec{xs}, vec{ys});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<bool, 4> greater_equal(const qua<T>& xs, const qua<T>& ys) {
|
||||
template < typename T
|
||||
, typename U = typename decltype(greater_equal(
|
||||
std::declval<vec<T, 4>>(),
|
||||
std::declval<vec<T, 4>>()))::component_type >
|
||||
[[nodiscard]] constexpr vec<U, 4> greater_equal(const qua<T>& xs, const qua<T>& ys) {
|
||||
return greater_equal(vec{xs}, vec{ys});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<bool, 4> equal_to(const qua<T>& xs, const qua<T>& ys) {
|
||||
template < typename T
|
||||
, typename U = typename decltype(equal_to(
|
||||
std::declval<vec<T, 4>>(),
|
||||
std::declval<vec<T, 4>>()))::component_type >
|
||||
[[nodiscard]] constexpr vec<U, 4> equal_to(const qua<T>& xs, const qua<T>& ys) {
|
||||
return equal_to(vec{xs}, vec{ys});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<bool, 4> not_equal_to(const qua<T>& xs, const qua<T>& ys) {
|
||||
template < typename T
|
||||
, typename U = typename decltype(not_equal_to(
|
||||
std::declval<vec<T, 4>>(),
|
||||
std::declval<vec<T, 4>>()))::component_type >
|
||||
[[nodiscard]] constexpr vec<U, 4> not_equal_to(const qua<T>& xs, const qua<T>& ys) {
|
||||
return not_equal_to(vec{xs}, vec{ys});
|
||||
}
|
||||
}
|
||||
@@ -310,6 +387,6 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> inverse(const qua<T>& q) {
|
||||
return conjugate(q) * rcp(length2(q));
|
||||
return conjugate(q) * rlength2(q);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ namespace vmath_hpp::detail
|
||||
template < typename T >
|
||||
class vec_base<T, 2> {
|
||||
public:
|
||||
T x{}, y{};
|
||||
T x = T{0};
|
||||
T y = T{0};
|
||||
public:
|
||||
constexpr vec_base() = default;
|
||||
|
||||
@@ -26,12 +27,6 @@ namespace vmath_hpp::detail
|
||||
constexpr vec_base(T x, T y)
|
||||
: x{x}, y{y} {}
|
||||
|
||||
constexpr explicit vec_base(const vec_base<T, 3>& xy)
|
||||
: x{xy[0]}, y{xy[1]} {}
|
||||
|
||||
constexpr explicit vec_base(const vec_base<T, 4>& xy)
|
||||
: x{xy[0]}, y{xy[1]} {}
|
||||
|
||||
[[nodiscard]] constexpr T& operator[](std::size_t index) noexcept {
|
||||
switch ( index ) {
|
||||
default:
|
||||
@@ -52,7 +47,9 @@ namespace vmath_hpp::detail
|
||||
template < typename T >
|
||||
class vec_base<T, 3> {
|
||||
public:
|
||||
T x{}, y{}, z{};
|
||||
T x = T{0};
|
||||
T y = T{0};
|
||||
T z = T{0};
|
||||
public:
|
||||
constexpr vec_base() = default;
|
||||
|
||||
@@ -68,8 +65,9 @@ namespace vmath_hpp::detail
|
||||
constexpr vec_base(T x, const vec_base<T, 2>& yz)
|
||||
: x{x}, y{yz[0]}, z{yz[1]} {}
|
||||
|
||||
constexpr explicit vec_base(const vec_base<T, 4>& xyz)
|
||||
: x{xyz[0]}, y{xyz[1]}, z{xyz[2]} {}
|
||||
constexpr explicit operator vec<T, 2>() const {
|
||||
return {x, y};
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T& operator[](std::size_t index) noexcept {
|
||||
switch ( index ) {
|
||||
@@ -93,7 +91,10 @@ namespace vmath_hpp::detail
|
||||
template < typename T >
|
||||
class vec_base<T, 4> {
|
||||
public:
|
||||
T x{}, y{}, z{}, w{};
|
||||
T x = T{0};
|
||||
T y = T{0};
|
||||
T z = T{0};
|
||||
T w = T{0};
|
||||
public:
|
||||
constexpr vec_base() = default;
|
||||
|
||||
@@ -121,6 +122,14 @@ namespace vmath_hpp::detail
|
||||
constexpr vec_base(T x, const vec_base<T, 3>& yzw)
|
||||
: x{x}, y{yzw[0]}, z{yzw[1]}, w{yzw[2]} {}
|
||||
|
||||
constexpr explicit operator vec<T, 2>() const {
|
||||
return {x, y};
|
||||
}
|
||||
|
||||
constexpr explicit operator vec<T, 3>() const {
|
||||
return {x, y, z};
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T& operator[](std::size_t index) noexcept {
|
||||
switch ( index ) {
|
||||
default:
|
||||
@@ -150,7 +159,6 @@ namespace vmath_hpp
|
||||
public:
|
||||
using self_type = vec;
|
||||
using base_type = detail::vec_base<T, Size>;
|
||||
public:
|
||||
using component_type = T;
|
||||
|
||||
using pointer = component_type*;
|
||||
@@ -164,7 +172,7 @@ namespace vmath_hpp
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
static constexpr std::size_t size = Size;
|
||||
static inline constexpr std::size_t size = Size;
|
||||
public:
|
||||
using base_type::vec_base;
|
||||
using base_type::operator[];
|
||||
|
||||
+165
-218
@@ -15,94 +15,80 @@ namespace vmath_hpp::detail::impl
|
||||
{
|
||||
template < typename A, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
vec<std::invoke_result_t<F, A>, Size> map_join_impl(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
std::index_sequence<Is...>
|
||||
) -> vec<decltype(f(
|
||||
std::declval<A>())), Size>
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
return { f(a[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
vec<std::invoke_result_t<F, A, B>, Size> map_join_impl(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
const vec<B, Size>& b,
|
||||
std::index_sequence<Is...>
|
||||
) -> vec<decltype(f(
|
||||
std::declval<A>(),
|
||||
std::declval<B>())), Size>
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
return { f(a[Is], b[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
vec<std::invoke_result_t<F, A, B, C>, Size> map_join_impl(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
const vec<B, Size>& b,
|
||||
const vec<C, Size>& c,
|
||||
std::index_sequence<Is...>
|
||||
) -> vec<decltype(f(
|
||||
std::declval<A>(),
|
||||
std::declval<B>(),
|
||||
std::declval<C>())), Size>
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
return { f(a[Is], b[Is], c[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, typename D, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
vec<std::invoke_result_t<F, A, B, C, D>, Size> map_join_impl(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
const vec<B, Size>& b,
|
||||
const vec<C, Size>& c,
|
||||
const vec<D, Size>& d,
|
||||
std::index_sequence<Is...>
|
||||
) -> vec<decltype(f(
|
||||
std::declval<A>(),
|
||||
std::declval<B>(),
|
||||
std::declval<C>(),
|
||||
std::declval<D>())), Size>
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
return { f(a[Is], b[Is], c[Is], d[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join_impl(
|
||||
A fold_join_impl(
|
||||
F&& f,
|
||||
A init,
|
||||
const vec<B, Size>& b,
|
||||
std::index_sequence<Is...>
|
||||
) -> A {
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
return ((init = f(std::move(init), b[Is])), ...);
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join_impl(
|
||||
A fold_join_impl(
|
||||
F&& f,
|
||||
A init,
|
||||
const vec<B, Size>& b,
|
||||
const vec<C, Size>& c,
|
||||
std::index_sequence<Is...>
|
||||
) -> A {
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
return ((init = f(std::move(init), b[Is], c[Is])), ...);
|
||||
}
|
||||
|
||||
template < typename A, std::size_t Size, typename F, std::size_t I, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold1_join_impl(
|
||||
A fold1_join_impl(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
std::index_sequence<I, Is...>
|
||||
) -> A {
|
||||
std::index_sequence<I, Is...>)
|
||||
{
|
||||
A init = a[I];
|
||||
return ((init = f(std::move(init), a[Is])), ...);
|
||||
}
|
||||
@@ -112,81 +98,44 @@ namespace vmath_hpp::detail
|
||||
{
|
||||
template < typename A, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const vec<A, Size>& a
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
auto map_join(F&& f, const vec<A, Size>& a) {
|
||||
return impl::map_join_impl(std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
const vec<B, Size>& b
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, b, std::make_index_sequence<Size>{});
|
||||
auto map_join(F&& f, const vec<A, Size>& a, const vec<B, Size>& b) {
|
||||
return impl::map_join_impl(std::forward<F>(f), a, b, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
const vec<B, Size>& b,
|
||||
const vec<C, Size>& c
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, b, c, std::make_index_sequence<Size>{});
|
||||
auto map_join(F&& f, const vec<A, Size>& a, const vec<B, Size>& b, const vec<C, Size>& c) {
|
||||
return impl::map_join_impl(std::forward<F>(f), a, b, c, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, typename D, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
const vec<B, Size>& b,
|
||||
const vec<C, Size>& c,
|
||||
const vec<D, Size>& d
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, b, c, d, std::make_index_sequence<Size>{});
|
||||
auto map_join(F&& f, const vec<A, Size>& a, const vec<B, Size>& b, const vec<C, Size>& c, const vec<D, Size>& d) {
|
||||
return impl::map_join_impl(std::forward<F>(f), a, b, c, d, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join(
|
||||
F&& f,
|
||||
A init,
|
||||
const vec<B, Size>& b
|
||||
) {
|
||||
return impl::fold_join_impl(
|
||||
std::forward<F>(f), std::move(init), b, std::make_index_sequence<Size>{});
|
||||
auto fold_join(F&& f, A init, const vec<B, Size>& b) {
|
||||
return impl::fold_join_impl(std::forward<F>(f), std::move(init), b, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join(
|
||||
F&& f,
|
||||
A init,
|
||||
const vec<B, Size>& b,
|
||||
const vec<C, Size>& c
|
||||
) {
|
||||
return impl::fold_join_impl(
|
||||
std::forward<F>(f), std::move(init), b, c, std::make_index_sequence<Size>{});
|
||||
auto fold_join(F&& f, A init, const vec<B, Size>& b, const vec<C, Size>& c) {
|
||||
return impl::fold_join_impl(std::forward<F>(f), std::move(init), b, c, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold1_join(
|
||||
F&& f,
|
||||
const vec<A, Size>& a
|
||||
) {
|
||||
return impl::fold1_join_impl(
|
||||
std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
auto fold1_join(F&& f, const vec<A, Size>& a) {
|
||||
return impl::fold1_join_impl(std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,45 +148,45 @@ namespace vmath_hpp
|
||||
// +operator
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator+(const vec<T, Size>& xs) {
|
||||
return xs;
|
||||
[[nodiscard]] constexpr auto 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<T, Size> operator-(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr auto 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<T, Size> operator~(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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<T, Size> operator+(const vec<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto operator+(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return x + y; }, xs, ys);
|
||||
}
|
||||
|
||||
@@ -256,17 +205,17 @@ namespace vmath_hpp
|
||||
// operator-
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator-(const vec<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto operator-(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return x - y; }, xs, ys);
|
||||
}
|
||||
|
||||
@@ -285,17 +234,17 @@ namespace vmath_hpp
|
||||
// operator*
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator*(const vec<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto operator*(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return x * y; }, xs, ys);
|
||||
}
|
||||
|
||||
@@ -314,17 +263,17 @@ namespace vmath_hpp
|
||||
// operator/
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator/(const vec<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto operator/(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return x / y; }, xs, ys);
|
||||
}
|
||||
|
||||
@@ -343,17 +292,17 @@ namespace vmath_hpp
|
||||
// operator&
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator&(const vec<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto operator&(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return x & y; }, xs, ys);
|
||||
}
|
||||
|
||||
@@ -372,17 +321,17 @@ namespace vmath_hpp
|
||||
// operator|
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator|(const vec<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto operator|(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return x | y; }, xs, ys);
|
||||
}
|
||||
|
||||
@@ -401,17 +350,17 @@ namespace vmath_hpp
|
||||
// operator^
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator^(const vec<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto operator^(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return x ^ y; }, xs, ys);
|
||||
}
|
||||
|
||||
@@ -430,34 +379,34 @@ namespace vmath_hpp
|
||||
// operator&&
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> operator&&(const vec<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto 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) {
|
||||
[[nodiscard]] constexpr auto operator||(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return x || y; }, xs, ys);
|
||||
}
|
||||
|
||||
@@ -522,61 +471,61 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> floor(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> floor(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return floor(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> trunc(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> trunc(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return trunc(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> round(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> round(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return round(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> ceil(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> ceil(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return ceil(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> fract(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> fract(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return fract(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> fmod(const vec<T, Size>& xs, T y) {
|
||||
[[nodiscard]] constexpr vec<T, Size> fmod(const vec<T, Size>& xs, T y) {
|
||||
return map_join([y](T x) { return fmod(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> fmod(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
[[nodiscard]] constexpr vec<T, Size> fmod(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y) { return fmod(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template < typename T, std::size_t Size, std::size_t... Is >
|
||||
VMATH_HPP_FORCE_INLINE
|
||||
constexpr VMATH_HPP_FORCE_INLINE
|
||||
vec<T, Size> modf_impl(const vec<T, Size>& xs, vec<T, Size>* is, std::index_sequence<Is...>) {
|
||||
return { modf(xs[Is], &(*is)[Is])... };
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
vec<T, Size> modf(const vec<T, Size>& xs, vec<T, Size>* is) {
|
||||
constexpr vec<T, Size> modf(const vec<T, Size>& xs, vec<T, Size>* is) {
|
||||
return impl::modf_impl(xs, is, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> copysign(const vec<T, Size>& xs, T s) {
|
||||
[[nodiscard]] constexpr vec<T, Size> copysign(const vec<T, Size>& xs, T s) {
|
||||
return map_join([s](T x) { return copysign(x, s); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> copysign(const vec<T, Size>& xs, const vec<T, Size>& ss) {
|
||||
[[nodiscard]] constexpr vec<T, Size> copysign(const vec<T, Size>& xs, const vec<T, Size>& ss) {
|
||||
return map_join([](T x, T s) { return copysign(x, s); }, xs, ss);
|
||||
}
|
||||
|
||||
@@ -683,45 +632,6 @@ namespace vmath_hpp
|
||||
[[nodiscard]] constexpr vec<T, Size> smoothstep(const vec<T, Size>& edges0, const vec<T, Size>& edges1, const vec<T, Size>& xs) {
|
||||
return map_join([](T edge0, T edge1, T x) { return smoothstep(edge0, edge1, x); }, edges0, edges1, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<bool, Size> isnan(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return isnan(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<bool, Size> isinf(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return isinf(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<bool, Size> isfinite(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return isfinite(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> fma(const vec<T, Size>& as, const vec<T, Size>& bs, const vec<T, Size>& cs) {
|
||||
return map_join([](T a, T b, T c) { return fma(a, b, c); }, as, bs, cs);
|
||||
}
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template < typename T, std::size_t Size, std::size_t... Is >
|
||||
VMATH_HPP_FORCE_INLINE
|
||||
vec<T, Size> frexp_impl(const vec<T, Size>& xs, vec<int, Size>* exps, std::index_sequence<Is...>) {
|
||||
return { frexp(xs[Is], &(*exps)[Is])... };
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
vec<T, Size> frexp(const vec<T, Size>& xs, vec<int, Size>* exps) {
|
||||
return impl::frexp_impl(xs, exps, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> ldexp(const vec<T, Size>& xs, const vec<int, Size>& exps) {
|
||||
return map_join([](T x, int exp) { return ldexp(x, exp); }, xs, exps);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -741,77 +651,77 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> sin(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> sin(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return sin(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> cos(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> cos(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return cos(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> tan(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> tan(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return tan(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> asin(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> asin(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return asin(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> acos(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> acos(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return acos(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> atan(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> atan(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return atan(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> atan2(const vec<T, Size>& ys, const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> atan2(const vec<T, Size>& ys, const vec<T, Size>& xs) {
|
||||
return map_join([](T y, T x) { return atan2(y, x); }, ys, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> sinh(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> sinh(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return sinh(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> cosh(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> cosh(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return cosh(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> tanh(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> tanh(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return tanh(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> asinh(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> asinh(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return asinh(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> acosh(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> acosh(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return acosh(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> atanh(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> atanh(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return atanh(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] std::pair<vec<T, Size>, vec<T, Size>> sincos(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr std::pair<vec<T, Size>, vec<T, Size>> sincos(const vec<T, Size>& xs) {
|
||||
return { sin(xs), cos(xs) };
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
void sincos(const vec<T, Size>& xs, vec<T, Size>* ss, vec<T, Size>* cs) {
|
||||
constexpr void sincos(const vec<T, Size>& xs, vec<T, Size>* ss, vec<T, Size>* cs) {
|
||||
*ss = sin(xs);
|
||||
*cs = cos(xs);
|
||||
}
|
||||
@@ -824,37 +734,37 @@ namespace vmath_hpp
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> pow(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
[[nodiscard]] constexpr vec<T, Size> pow(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y) { return pow(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> exp(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> exp(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return exp(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> log(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> log(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return log(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> exp2(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> exp2(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return exp2(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> log2(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> log2(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return log2(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> sqrt(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> sqrt(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return sqrt(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> rsqrt(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr vec<T, Size> rsqrt(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return rsqrt(x); }, xs);
|
||||
}
|
||||
}
|
||||
@@ -869,21 +779,31 @@ namespace vmath_hpp
|
||||
[[nodiscard]] constexpr T dot(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return fold_join([](T acc, T x, T y){
|
||||
return acc + (x * y);
|
||||
}, T(0), xs, ys);
|
||||
}, T{0}, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] T length(const vec<T, Size>& xs) {
|
||||
[[nodiscard]] constexpr T length(const vec<T, Size>& xs) {
|
||||
return sqrt(dot(xs, xs));
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr T rlength(const vec<T, Size>& xs) {
|
||||
return rsqrt(dot(xs, xs));
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr T length2(const vec<T, Size>& xs) {
|
||||
return dot(xs, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] T distance(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
[[nodiscard]] constexpr T rlength2(const vec<T, Size>& xs) {
|
||||
return rcp(dot(xs, xs));
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr T distance(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return length(ys - xs);
|
||||
}
|
||||
|
||||
@@ -906,25 +826,25 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> normalize(const vec<T, Size>& xs) {
|
||||
return xs * rsqrt(length2(xs));
|
||||
[[nodiscard]] constexpr vec<T, Size> normalize(const vec<T, Size>& xs) {
|
||||
return xs * rlength(xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> faceforward(const vec<T, Size>& n, const vec<T, Size>& i, const vec<T, Size>& nref) {
|
||||
return dot(nref, i) < T(0) ? n : -n;
|
||||
return dot(nref, i) < T{0} ? n : -n;
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> reflect(const vec<T, Size>& i, const vec<T, Size>& n) {
|
||||
return i - n * dot(n, i) * T(2);
|
||||
return i - T{2} * dot(n, i) * n;
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> refract(const vec<T, Size>& i, const vec<T, Size>& n, T eta) {
|
||||
[[nodiscard]] constexpr vec<T, Size> refract(const vec<T, Size>& i, const vec<T, Size>& n, T eta) {
|
||||
const T d = dot(n, i);
|
||||
const T k = T(1) - eta * eta * (T(1) - d * d);
|
||||
return T(k >= T(0)) * (eta * i - (eta * d + sqrt(k)) * n);
|
||||
const T k = T{1} - sqr(eta) * (T{1} - sqr(d));
|
||||
return k < T{0} ? vec<T, Size>{T{0}} : (eta * i - (eta * d + sqrt(k)) * n);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -934,53 +854,80 @@ namespace vmath_hpp
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
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
|
||||
, typename U = decltype(any(std::declval<T>())) >
|
||||
[[nodiscard]] constexpr U any(const vec<T, Size>& xs) {
|
||||
return fold_join([](U acc, T x){ return acc || any(x); }, U{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);
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = decltype(all(std::declval<T>())) >
|
||||
[[nodiscard]] constexpr U all(const vec<T, Size>& xs) {
|
||||
return fold_join([](U acc, T x){ return acc && all(x); }, U{true}, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> approx(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = decltype(approx(
|
||||
std::declval<T>(),
|
||||
std::declval<T>())) >
|
||||
[[nodiscard]] constexpr vec<U, 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, const vec<T, Size>& ys, T epsilon) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = decltype(approx(
|
||||
std::declval<T>(),
|
||||
std::declval<T>(),
|
||||
std::declval<T>())) >
|
||||
[[nodiscard]] constexpr vec<U, 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);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> less(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = decltype(less(
|
||||
std::declval<T>(),
|
||||
std::declval<T>())) >
|
||||
[[nodiscard]] constexpr vec<U, 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);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> less_equal(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = decltype(less_equal(
|
||||
std::declval<T>(),
|
||||
std::declval<T>())) >
|
||||
[[nodiscard]] constexpr vec<U, 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);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> greater(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = decltype(greater(
|
||||
std::declval<T>(),
|
||||
std::declval<T>())) >
|
||||
[[nodiscard]] constexpr vec<U, 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);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> greater_equal(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = decltype(greater_equal(
|
||||
std::declval<T>(),
|
||||
std::declval<T>())) >
|
||||
[[nodiscard]] constexpr vec<U, 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);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = decltype(equal_to(
|
||||
std::declval<T>(),
|
||||
std::declval<T>())) >
|
||||
[[nodiscard]] constexpr vec<U, 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);
|
||||
}
|
||||
|
||||
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) {
|
||||
template < typename T, std::size_t Size
|
||||
, typename U = decltype(not_equal_to(
|
||||
std::declval<T>(),
|
||||
std::declval<T>())) >
|
||||
[[nodiscard]] constexpr vec<U, 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ TEST_CASE("vmath/ext/units") {
|
||||
STATIC_CHECK(identity2x2<int> == int2x2());
|
||||
STATIC_CHECK(identity3x3<int> == int3x3());
|
||||
STATIC_CHECK(identity4x4<int> == int4x4());
|
||||
|
||||
STATIC_CHECK(qidentity<float> == qfloat());
|
||||
}
|
||||
|
||||
TEST_CASE("vmath/ext/hash") {
|
||||
|
||||
@@ -0,0 +1,956 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/vmath.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2020-2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "vmath_tests.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
template < typename T >
|
||||
class fix {
|
||||
public:
|
||||
fix() = default;
|
||||
|
||||
fix(fix&&) = default;
|
||||
fix& operator=(fix&&) = default;
|
||||
|
||||
fix(const fix&) = default;
|
||||
fix& operator=(const fix&) = default;
|
||||
|
||||
constexpr explicit fix(T underlying): underlying_(underlying) {}
|
||||
constexpr T underlying() const noexcept { return underlying_; }
|
||||
|
||||
constexpr friend fix abs(const fix& l) { using vmath_hpp::abs; return { fix{abs(l.underlying())} }; }
|
||||
constexpr friend fix sqr(const fix& l) { using vmath_hpp::sqr; return { fix{sqr(l.underlying())} }; }
|
||||
constexpr friend fix sign(const fix& l) { using vmath_hpp::sign; return { fix{sign(l.underlying())} }; }
|
||||
|
||||
constexpr friend fix rcp(const fix& l) { using vmath_hpp::rcp; return { fix{rcp(l.underlying())} }; }
|
||||
constexpr friend fix floor(const fix& l) { using vmath_hpp::floor; return { fix{floor(l.underlying())} }; }
|
||||
constexpr friend fix trunc(const fix& l) { using vmath_hpp::trunc; return { fix{trunc(l.underlying())} }; }
|
||||
constexpr friend fix round(const fix& l) { using vmath_hpp::round; return { fix{round(l.underlying())} }; }
|
||||
constexpr friend fix ceil(const fix& l) { using vmath_hpp::ceil; return { fix{ceil(l.underlying())} }; }
|
||||
constexpr friend fix fract(const fix& l) { using vmath_hpp::fract; return { fix{fract(l.underlying())} }; }
|
||||
|
||||
constexpr friend fix fmod(const fix& l, const fix& r) { using vmath_hpp::fmod; return { fix{fmod(l.underlying(), r.underlying())} }; }
|
||||
constexpr friend fix modf(const fix& l, fix* r) { using vmath_hpp::modf; return { fix{modf(l.underlying(), &r->underlying_)} }; }
|
||||
constexpr friend fix copysign(const fix& l, const fix& r) { using vmath_hpp::copysign; return { fix{copysign(l.underlying(), r.underlying())} }; }
|
||||
|
||||
constexpr friend fix min(const fix& l, const fix& r) { using vmath_hpp::min; return fix{min(l.underlying(), r.underlying())}; }
|
||||
constexpr friend fix max(const fix& l, const fix& r) { using vmath_hpp::max; return fix{max(l.underlying(), r.underlying())}; }
|
||||
constexpr friend fix clamp(const fix& l, const fix& min_l, const fix& max_l) { using vmath_hpp::clamp; return fix{clamp(l.underlying(), min_l.underlying(), max_l.underlying())}; }
|
||||
constexpr friend fix saturate(const fix& l) { using vmath_hpp::saturate; return fix{saturate(l.underlying())}; }
|
||||
constexpr friend fix lerp(const fix& l, const fix& r, const fix& a) { using vmath_hpp::lerp; return fix{lerp(l.underlying(), r.underlying(), a.underlying())}; }
|
||||
constexpr friend fix lerp(const fix& l, const fix& r, const fix& a, const fix& b) { using vmath_hpp::lerp; return fix{lerp(l.underlying(), r.underlying(), a.underlying(), b.underlying())}; }
|
||||
|
||||
constexpr friend fix step(const fix& e, const fix& l) { using vmath_hpp::step; return fix{step(e.underlying(), l.underlying())}; }
|
||||
constexpr friend fix smoothstep(const fix& e0, const fix& e1, const fix& l) { using vmath_hpp::smoothstep; return fix{smoothstep(e0.underlying(), e1.underlying(), l.underlying())}; }
|
||||
|
||||
//
|
||||
|
||||
constexpr friend fix<bool> any(const fix& l) { using vmath_hpp::any; return fix<bool>{any(l.underlying())}; }
|
||||
constexpr friend fix<bool> all(const fix& l) { using vmath_hpp::all; return fix<bool>{all(l.underlying())}; }
|
||||
|
||||
constexpr friend fix<bool> approx(const fix& l, const fix& r) { using vmath_hpp::approx; return fix<bool>{approx(l.underlying(), r.underlying())}; }
|
||||
constexpr friend fix<bool> approx(const fix& l, const fix& r, const fix& e) { using vmath_hpp::approx; return fix<bool>{approx(l.underlying(), r.underlying(), e.underlying())}; }
|
||||
|
||||
constexpr friend fix<bool> less(const fix& l, const fix& r) { using vmath_hpp::less; return fix<bool>{less(l.underlying(), r.underlying())}; }
|
||||
constexpr friend fix<bool> less_equal(const fix& l, const fix& r) { using vmath_hpp::less_equal; return fix<bool>{less_equal(l.underlying(), r.underlying())}; }
|
||||
constexpr friend fix<bool> greater(const fix& l, const fix& r) { using vmath_hpp::greater; return fix<bool>{greater(l.underlying(), r.underlying())}; }
|
||||
constexpr friend fix<bool> greater_equal(const fix& l, const fix& r) { using vmath_hpp::greater_equal; return fix<bool>{greater_equal(l.underlying(), r.underlying())}; }
|
||||
constexpr friend fix<bool> equal_to(const fix& l, const fix& r) { using vmath_hpp::equal_to; return fix<bool>{equal_to(l.underlying(), r.underlying())}; }
|
||||
constexpr friend fix<bool> not_equal_to(const fix& l, const fix& r) { using vmath_hpp::not_equal_to; return fix<bool>{not_equal_to(l.underlying(), r.underlying())}; }
|
||||
|
||||
//
|
||||
|
||||
constexpr friend fix radians(const fix& l) { using vmath_hpp::radians; return fix{radians(l.underlying())}; }
|
||||
constexpr friend fix degrees(const fix& l) { using vmath_hpp::degrees; return fix{degrees(l.underlying())}; }
|
||||
constexpr friend fix sin(const fix& l) { using vmath_hpp::sin; return fix{sin(l.underlying())}; }
|
||||
constexpr friend fix cos(const fix& l) { using vmath_hpp::cos; return fix{cos(l.underlying())}; }
|
||||
constexpr friend fix tan(const fix& l) { using vmath_hpp::tan; return fix{tan(l.underlying())}; }
|
||||
constexpr friend fix asin(const fix& l) { using vmath_hpp::asin; return fix{asin(l.underlying())}; }
|
||||
constexpr friend fix acos(const fix& l) { using vmath_hpp::acos; return fix{acos(l.underlying())}; }
|
||||
constexpr friend fix atan(const fix& l) { using vmath_hpp::atan; return fix{atan(l.underlying())}; }
|
||||
constexpr friend fix atan2(const fix& l, const fix& r) { using vmath_hpp::atan2; return fix{atan2(l.underlying(), r.underlying())}; }
|
||||
constexpr friend fix sinh(const fix& l) { using vmath_hpp::sinh; return fix{sinh(l.underlying())}; }
|
||||
constexpr friend fix cosh(const fix& l) { using vmath_hpp::cosh; return fix{cosh(l.underlying())}; }
|
||||
constexpr friend fix tanh(const fix& l) { using vmath_hpp::tanh; return fix{tanh(l.underlying())}; }
|
||||
constexpr friend fix asinh(const fix& l) { using vmath_hpp::asinh; return fix{asinh(l.underlying())}; }
|
||||
constexpr friend fix acosh(const fix& l) { using vmath_hpp::acosh; return fix{acosh(l.underlying())}; }
|
||||
constexpr friend fix atanh(const fix& l) { using vmath_hpp::atanh; return fix{atanh(l.underlying())}; }
|
||||
constexpr friend std::pair<fix,fix> sincos(const fix& l) { return { sin(l), cos(l) }; }
|
||||
constexpr friend void sincos(const fix& l, fix* s, fix* c) { *s = sin(l); *c = cos(l); }
|
||||
|
||||
//
|
||||
|
||||
constexpr friend fix pow(const fix& l, const fix& r) { using vmath_hpp::pow; return fix{pow(l.underlying(), r.underlying())}; }
|
||||
constexpr friend fix exp(const fix& l) { using vmath_hpp::exp; return fix{exp(l.underlying())}; }
|
||||
constexpr friend fix log(const fix& l) { using vmath_hpp::log; return fix{log(l.underlying())}; }
|
||||
constexpr friend fix exp2(const fix& l) { using vmath_hpp::exp2; return fix{exp2(l.underlying())}; }
|
||||
constexpr friend fix log2(const fix& l) { using vmath_hpp::log2; return fix{log2(l.underlying())}; }
|
||||
constexpr friend fix sqrt(const fix& l) { using vmath_hpp::sqrt; return fix{sqrt(l.underlying())}; }
|
||||
constexpr friend fix rsqrt(const fix& l) { using vmath_hpp::rsqrt; return fix{rsqrt(l.underlying())}; }
|
||||
|
||||
//
|
||||
|
||||
constexpr friend fix operator+(const fix& l) { return { fix{+l.underlying()} }; }
|
||||
constexpr friend fix operator-(const fix& l) { return { fix{-l.underlying()} }; }
|
||||
constexpr friend fix operator~(const fix& l) { return { fix{~l.underlying()} }; }
|
||||
constexpr friend fix<bool> operator!(const fix& l) { return { fix<bool>{!l.underlying()} }; }
|
||||
|
||||
constexpr friend fix operator+(const fix& l, const fix& r) { return fix{l.underlying() + r.underlying()}; }
|
||||
constexpr friend fix operator-(const fix& l, const fix& r) { return fix{l.underlying() - r.underlying()}; }
|
||||
constexpr friend fix operator*(const fix& l, const fix& r) { return fix{l.underlying() * r.underlying()}; }
|
||||
constexpr friend fix operator/(const fix& l, const fix& r) { return fix{l.underlying() / r.underlying()}; }
|
||||
|
||||
constexpr friend fix operator&(const fix& l, const fix& r) { return fix{l.underlying() & r.underlying()}; }
|
||||
constexpr friend fix operator|(const fix& l, const fix& r) { return fix{l.underlying() | r.underlying()}; }
|
||||
constexpr friend fix operator^(const fix& l, const fix& r) { return fix{l.underlying() ^ r.underlying()}; }
|
||||
|
||||
constexpr friend fix<bool> operator&&(const fix& l, const fix& r) { return fix<bool>{l.underlying() && r.underlying()}; }
|
||||
constexpr friend fix<bool> operator||(const fix& l, const fix& r) { return fix<bool>{l.underlying() || r.underlying()}; }
|
||||
|
||||
constexpr friend bool operator<(const fix& l, const fix& r) { return l.underlying() < r.underlying(); }
|
||||
constexpr friend bool operator==(const fix& l, const fix& r) { return l.underlying() == r.underlying(); }
|
||||
constexpr friend bool operator!=(const fix& l, const fix& r) { return l.underlying() != r.underlying(); }
|
||||
private:
|
||||
T underlying_{};
|
||||
};
|
||||
|
||||
using namespace vmath_hpp;
|
||||
using namespace vmath_tests;
|
||||
|
||||
using qfix = qua<fix<float>>;
|
||||
|
||||
using fix2b = vec<fix<bool>, 2>;
|
||||
using fix3b = vec<fix<bool>, 3>;
|
||||
using fix4b = vec<fix<bool>, 4>;
|
||||
|
||||
using fix2i = vec<fix<int>, 2>;
|
||||
using fix3i = vec<fix<int>, 3>;
|
||||
using fix4i = vec<fix<int>, 4>;
|
||||
|
||||
using fix2f = vec<fix<float>, 2>;
|
||||
using fix3f = vec<fix<float>, 3>;
|
||||
using fix4f = vec<fix<float>, 4>;
|
||||
|
||||
using fix2x2b = mat<fix<bool>, 2>;
|
||||
using fix3x3b = mat<fix<bool>, 3>;
|
||||
using fix4x4b = mat<fix<bool>, 4>;
|
||||
|
||||
using fix2x2i = mat<fix<int>, 2>;
|
||||
using fix3x3i = mat<fix<int>, 3>;
|
||||
using fix4x4i = mat<fix<int>, 4>;
|
||||
|
||||
using fix2x2f = mat<fix<float>, 2>;
|
||||
using fix3x3f = mat<fix<float>, 3>;
|
||||
using fix4x4f = mat<fix<float>, 4>;
|
||||
}
|
||||
|
||||
//
|
||||
// Common Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix2f abs(const fix2f&);
|
||||
template fix2f sqr(const fix2f&);
|
||||
template fix2f sign(const fix2f&);
|
||||
|
||||
template fix2f rcp(const fix2f&);
|
||||
template fix2f floor(const fix2f&);
|
||||
template fix2f trunc(const fix2f&);
|
||||
template fix2f round(const fix2f&);
|
||||
template fix2f ceil(const fix2f&);
|
||||
template fix2f fract(const fix2f&);
|
||||
|
||||
template fix2f fmod(const fix2f&, fix<float>);
|
||||
template fix2f fmod(const fix2f&, const fix2f&);
|
||||
|
||||
template fix2f modf(const fix2f&, fix2f*);
|
||||
|
||||
template fix2f copysign(const fix2f&, fix<float>);
|
||||
template fix2f copysign(const fix2f&, const fix2f&);
|
||||
|
||||
template fix<float> min(const fix2f&);
|
||||
template fix2f min(const fix2f&, fix<float>);
|
||||
template fix2f min(fix<float>, const fix2f&);
|
||||
template fix2f min(const fix2f&, const fix2f&);
|
||||
|
||||
template fix<float> max(const fix2f&);
|
||||
template fix2f max(const fix2f&, fix<float>);
|
||||
template fix2f max(fix<float>, const fix2f&);
|
||||
template fix2f max(const fix2f&, const fix2f&);
|
||||
|
||||
template fix2f clamp(const fix2f&, fix<float>, fix<float>);
|
||||
template fix2f clamp(const fix2f&, const fix2f&, const fix2f&);
|
||||
|
||||
template fix2f saturate(const fix2f&);
|
||||
|
||||
template fix2f lerp(const fix2f&, const fix2f&, fix<float>);
|
||||
template fix2f lerp(const fix2f&, const fix2f&, fix<float>, fix<float>);
|
||||
template fix2f lerp(const fix2f&, const fix2f&, const fix2f&);
|
||||
template fix2f lerp(const fix2f&, const fix2f&, const fix2f&, const fix2f&);
|
||||
|
||||
template fix2f step(fix<float>, const fix2f&);
|
||||
template fix2f step(const fix2f&, const fix2f&);
|
||||
template fix2f smoothstep(fix<float>, fix<float>, const fix2f&);
|
||||
template fix2f smoothstep(const fix2f&, const fix2f&, const fix2f&);
|
||||
}
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template qfix lerp(const qfix&, const qfix&, fix<float>);
|
||||
template qfix lerp(const qfix&, const qfix&, fix<float>, fix<float>);
|
||||
template qfix nlerp(const qfix&, const qfix&, fix<float>);
|
||||
template qfix slerp(const qfix&, const qfix&, fix<float>);
|
||||
}
|
||||
|
||||
//
|
||||
// Angle and Trigonometric Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix2f radians(const fix2f&);
|
||||
template fix2f degrees(const fix2f&);
|
||||
template fix2f sin(const fix2f&);
|
||||
template fix2f cos(const fix2f&);
|
||||
template fix2f tan(const fix2f&);
|
||||
template fix2f asin(const fix2f&);
|
||||
template fix2f acos(const fix2f&);
|
||||
template fix2f atan(const fix2f&);
|
||||
template fix2f atan2(const fix2f&, const fix2f&);
|
||||
template fix2f sinh(const fix2f&);
|
||||
template fix2f cosh(const fix2f&);
|
||||
template fix2f tanh(const fix2f&);
|
||||
template fix2f asinh(const fix2f&);
|
||||
template fix2f acosh(const fix2f&);
|
||||
template fix2f atanh(const fix2f&);
|
||||
template std::pair<fix2f, fix2f> sincos(const fix2f&);
|
||||
template void sincos(const fix2f&, fix2f*, fix2f*);
|
||||
}
|
||||
|
||||
//
|
||||
// Exponential Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix2f pow(const fix2f&, const fix2f&);
|
||||
template fix2f exp(const fix2f&);
|
||||
template fix2f log(const fix2f&);
|
||||
template fix2f exp2(const fix2f&);
|
||||
template fix2f log2(const fix2f&);
|
||||
template fix2f sqrt(const fix2f&);
|
||||
template fix2f rsqrt(const fix2f&);
|
||||
}
|
||||
|
||||
//
|
||||
// Geometric Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix<float> dot(const fix2f&, const fix2f&);
|
||||
template fix<float> length(const fix2f&);
|
||||
template fix<float> rlength(const fix2f&);
|
||||
template fix<float> length2(const fix2f&);
|
||||
template fix<float> rlength2(const fix2f&);
|
||||
template fix<float> distance(const fix2f&, const fix2f&);
|
||||
template fix<float> distance2(const fix2f&, const fix2f&);
|
||||
template fix<float> cross(const fix2f&, const fix2f&);
|
||||
template fix3f cross(const fix3f&, const fix3f&);
|
||||
template fix2f normalize(const fix2f&);
|
||||
template fix3f faceforward(const fix3f&, const fix3f&, const fix3f&);
|
||||
template fix3f reflect(const fix3f&, const fix3f&);
|
||||
template fix3f refract(const fix3f&, const fix3f&, fix<float>);
|
||||
}
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix<float> dot(const qfix&, const qfix&);
|
||||
template fix<float> length(const qfix&);
|
||||
template fix<float> rlength(const qfix&);
|
||||
template fix<float> length2(const qfix&);
|
||||
template fix<float> rlength2(const qfix&);
|
||||
template fix<float> distance(const qfix&, const qfix&);
|
||||
template qfix normalize(const qfix&);
|
||||
}
|
||||
|
||||
//
|
||||
// Relational Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix<bool> any(const fix2f&);
|
||||
template fix<bool> all(const fix2f&);
|
||||
template fix2b approx(const fix2f&, const fix2f&);
|
||||
template fix2b approx(const fix2f&, const fix2f&, fix<float>);
|
||||
template fix2b less(const fix2f&, const fix2f&);
|
||||
template fix2b less_equal(const fix2f&, const fix2f&);
|
||||
template fix2b greater(const fix2f&, const fix2f&);
|
||||
template fix2b greater_equal(const fix2f&, const fix2f&);
|
||||
template fix2b equal_to(const fix2f&, const fix2f&);
|
||||
template fix2b not_equal_to(const fix2f&, const fix2f&);
|
||||
}
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix<bool> any(const fix2x2f&);
|
||||
template fix<bool> all(const fix2x2f&);
|
||||
template fix2x2b approx(const fix2x2f&, const fix2x2f&);
|
||||
template fix2x2b approx(const fix2x2f&, const fix2x2f&, fix<float>);
|
||||
template fix2x2b less(const fix2x2f&, const fix2x2f&);
|
||||
template fix2x2b less_equal(const fix2x2f&, const fix2x2f&);
|
||||
template fix2x2b greater(const fix2x2f&, const fix2x2f&);
|
||||
template fix2x2b greater_equal(const fix2x2f&, const fix2x2f&);
|
||||
template fix2x2b equal_to(const fix2x2f&, const fix2x2f&);
|
||||
template fix2x2b not_equal_to(const fix2x2f&, const fix2x2f&);
|
||||
}
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix<bool> any(const qfix&);
|
||||
template fix<bool> all(const qfix&);
|
||||
template fix4b approx(const qfix&, const qfix&);
|
||||
template fix4b approx(const qfix&, const qfix&, fix<float>);
|
||||
template fix4b less(const qfix&, const qfix&);
|
||||
template fix4b less_equal(const qfix&, const qfix&);
|
||||
template fix4b greater(const qfix&, const qfix&);
|
||||
template fix4b greater_equal(const qfix&, const qfix&);
|
||||
template fix4b equal_to(const qfix&, const qfix&);
|
||||
template fix4b not_equal_to(const qfix&, const qfix&);
|
||||
}
|
||||
|
||||
//
|
||||
// Matrix Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix2x2f transpose(const fix2x2f&);
|
||||
template fix3x3f transpose(const fix3x3f&);
|
||||
template fix4x4f transpose(const fix4x4f&);
|
||||
|
||||
template fix<float> determinant(const fix2x2f&);
|
||||
template fix<float> determinant(const fix3x3f&);
|
||||
template fix<float> determinant(const fix4x4f&);
|
||||
|
||||
template fix2x2f inverse(const fix2x2f&);
|
||||
template fix3x3f inverse(const fix3x3f&);
|
||||
template fix4x4f inverse(const fix4x4f&);
|
||||
}
|
||||
|
||||
//
|
||||
// Quaternion Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template qfix conjugate(const qfix&);
|
||||
template qfix inverse(const qfix&);
|
||||
}
|
||||
|
||||
//
|
||||
// Access
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix<float> component(const fix2f&, std::size_t);
|
||||
template fix2f component(fix2f, std::size_t, fix<float>);
|
||||
|
||||
template fix2f row(const fix2x2f&, std::size_t);
|
||||
template fix2x2f row(fix2x2f, std::size_t, const fix2f&);
|
||||
|
||||
template fix2f column(const fix2x2f&, std::size_t);
|
||||
template fix2x2f column(const fix2x2f&, std::size_t, const fix2f&);
|
||||
|
||||
template fix<float> real(const qfix&);
|
||||
template qfix real(qfix, fix<float>);
|
||||
|
||||
template fix3f imag(const qfix&);
|
||||
template qfix imag(qfix, const fix3f&);
|
||||
}
|
||||
|
||||
//
|
||||
// Matrix Transform 3D
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix4x4f translate(fix<float> x, fix<float> y, fix<float> z);
|
||||
template fix4x4f translate(const fix4x4f&, fix<float>, fix<float>, fix<float>);
|
||||
template fix4x4f translate(const fix3f&);
|
||||
template fix4x4f translate(const fix4x4f&, const fix3f&);
|
||||
|
||||
template fix4x4f rotate(const qfix&);
|
||||
template fix4x4f rotate(const fix4x4f&, const qfix&);
|
||||
template fix4x4f rotate(fix<float>, const fix3f&);
|
||||
template fix4x4f rotate(const fix4x4f&, fix<float>, const fix3f&);
|
||||
|
||||
template fix4x4f rotate_x(fix<float>);
|
||||
template fix4x4f rotate_x(const fix4x4f&, fix<float>);
|
||||
|
||||
template fix4x4f rotate_y(fix<float>);
|
||||
template fix4x4f rotate_y(const fix4x4f&, fix<float>);
|
||||
|
||||
template fix4x4f rotate_z(fix<float>);
|
||||
template fix4x4f rotate_z(const fix4x4f&, fix<float>);
|
||||
|
||||
template fix4x4f scale(fix<float>, fix<float>, fix<float>);
|
||||
template fix4x4f scale(const fix4x4f&, fix<float>, fix<float>, fix<float>);
|
||||
template fix4x4f scale(const fix3f&);
|
||||
template fix4x4f scale(const fix4x4f&, const fix3f&);
|
||||
|
||||
template fix4x4f look_at_lh(const fix3f&, const fix3f&, const fix3f&);
|
||||
template fix4x4f look_at_rh(const fix3f&, const fix3f&, const fix3f&);
|
||||
}
|
||||
|
||||
//
|
||||
// Matrix Transform 2D
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix3x3f translate(fix<float>, fix<float>);
|
||||
template fix3x3f translate(const fix3x3f&, fix<float>, fix<float>);
|
||||
template fix3x3f translate(const fix2f&);
|
||||
template fix3x3f translate(const fix3x3f&, const fix2f&);
|
||||
|
||||
template fix3x3f rotate(fix<float>);
|
||||
template fix3x3f rotate(const fix3x3f&, fix<float>);
|
||||
|
||||
template fix3x3f scale(fix<float>, fix<float>);
|
||||
template fix3x3f scale(const fix3x3f&, fix<float>, fix<float>);
|
||||
template fix3x3f scale(const fix2f&);
|
||||
template fix3x3f scale(const fix3x3f&, const fix2f&);
|
||||
|
||||
template fix3x3f shear(fix<float>, fix<float>);
|
||||
template fix3x3f shear(const fix3x3f&, fix<float>, fix<float>);
|
||||
template fix3x3f shear(const fix2f&);
|
||||
template fix3x3f shear(const fix3x3f&, const fix2f&);
|
||||
|
||||
template fix3x3f shear_x(fix<float>);
|
||||
template fix3x3f shear_x(const fix3x3f&, fix<float>);
|
||||
|
||||
template fix3x3f shear_y(fix<float>);
|
||||
template fix3x3f shear_y(const fix3x3f&, fix<float>);
|
||||
}
|
||||
|
||||
//
|
||||
// Matrix Projections
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix4x4f orthographic_lh(fix<float>, fix<float>, fix<float>, fix<float>);
|
||||
template fix4x4f orthographic_rh(fix<float>, fix<float>, fix<float>, fix<float>);
|
||||
|
||||
template fix4x4f orthographic_lh(fix<float>, fix<float>, fix<float>, fix<float>, fix<float>, fix<float>);
|
||||
template fix4x4f orthographic_rh(fix<float>, fix<float>, fix<float>, fix<float>, fix<float>, fix<float>);
|
||||
|
||||
template fix4x4f perspective_lh(fix<float>, fix<float>, fix<float>, fix<float>);
|
||||
template fix4x4f perspective_rh(fix<float>, fix<float>, fix<float>, fix<float>);
|
||||
|
||||
template fix4x4f perspective_lh(fix<float>, fix<float>, fix<float>, fix<float>, fix<float>, fix<float>);
|
||||
template fix4x4f perspective_rh(fix<float>, fix<float>, fix<float>, fix<float>, fix<float>, fix<float>);
|
||||
|
||||
template fix4x4f perspective_fov_lh(fix<float>, fix<float>, fix<float>, fix<float>);
|
||||
template fix4x4f perspective_fov_rh(fix<float>, fix<float>, fix<float>, fix<float>);
|
||||
}
|
||||
|
||||
//
|
||||
// Vector Transform
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template fix<float> angle(const fix3f&, const fix3f&);
|
||||
template fix2f rotate(const fix2f&, fix<float>);
|
||||
template fix3f rotate_x(const fix3f&, fix<float>);
|
||||
template fix3f rotate_y(const fix3f&, fix<float>);
|
||||
template fix3f rotate_z(const fix3f&, fix<float>);
|
||||
template fix3f rotate(const fix3f&, const qfix&);
|
||||
template fix3f rotate(const fix3f&, fix<float>, const fix3f&);
|
||||
template fix3f project(const fix3f&, const fix3f&);
|
||||
template fix3f perpendicular(const fix3f&, const fix3f&);
|
||||
}
|
||||
|
||||
//
|
||||
// Quaternion Transform
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template qfix qrotate(const fix3x3f&);
|
||||
template qfix qrotate(const qfix&, const fix3x3f&);
|
||||
|
||||
template qfix qrotate(const fix3f&, const fix3f&);
|
||||
template qfix qrotate(const qfix&, const fix3f&, const fix3f&);
|
||||
|
||||
template qfix qrotate(fix<float>, const fix3f&);
|
||||
template qfix qrotate(const qfix&, fix<float>, const fix3f&);
|
||||
|
||||
template qfix qrotate_x(fix<float>);
|
||||
template qfix qrotate_x(const qfix&, fix<float>);
|
||||
|
||||
template qfix qrotate_y(fix<float>);
|
||||
template qfix qrotate_y(const qfix&, fix<float>);
|
||||
|
||||
template qfix qrotate_z(fix<float>);
|
||||
template qfix qrotate_z(const qfix&, fix<float>);
|
||||
|
||||
template qfix qlook_at_lh(const fix3f&, const fix3f&);
|
||||
template qfix qlook_at_rh(const fix3f&, const fix3f&);
|
||||
}
|
||||
|
||||
//
|
||||
// fix_vec
|
||||
//
|
||||
|
||||
TEST_CASE("vmath/fix_vec") {
|
||||
SUBCASE("fix2 ctors") {
|
||||
constexpr fix2i v0{};
|
||||
constexpr fix2i v1{fix(1)};
|
||||
constexpr fix2i v2{fix(1), fix(2)};
|
||||
constexpr fix2i v3{fix3i{fix(1), fix(2), fix(3)}};
|
||||
constexpr fix2i v4{fix4i{fix(1), fix(2), fix(3), fix(4)}};
|
||||
|
||||
STATIC_CHECK((v0[0] == fix(0)));
|
||||
STATIC_CHECK((v1[0] == fix(1) && v1[1] == fix(1)));
|
||||
STATIC_CHECK((v2[0] == fix(1) && v2[1] == fix(2)));
|
||||
STATIC_CHECK((v3[0] == fix(1) && v3[1] == fix(2)));
|
||||
STATIC_CHECK((v4[0] == fix(1) && v4[1] == fix(2)));
|
||||
}
|
||||
|
||||
SUBCASE("fix3 ctors") {
|
||||
constexpr fix3i v0{};
|
||||
constexpr fix3i v1{fix(1)};
|
||||
constexpr fix3i v2{fix(1), fix(2), fix(3)};
|
||||
constexpr fix3i v3{fix2i{fix(1), fix(2)}, fix(3)};
|
||||
constexpr fix3i v4{fix(1), fix2i{fix(2), fix(3)}};
|
||||
constexpr fix3i v5{fix4i{fix(1), fix(2), fix(3), fix(4)}};
|
||||
|
||||
STATIC_CHECK((v0[0] == fix(0)));
|
||||
STATIC_CHECK((v1[0] == fix(1) && v1[1] == fix(1) && v1[2] == fix(1)));
|
||||
STATIC_CHECK((v2[0] == fix(1) && v2[1] == fix(2) && v2[2] == fix(3)));
|
||||
STATIC_CHECK((v3[0] == fix(1) && v3[1] == fix(2) && v3[2] == fix(3)));
|
||||
STATIC_CHECK((v4[0] == fix(1) && v4[1] == fix(2) && v4[2] == fix(3)));
|
||||
STATIC_CHECK((v5[0] == fix(1) && v5[1] == fix(2) && v5[2] == fix(3)));
|
||||
}
|
||||
|
||||
SUBCASE("fix4 ctors") {
|
||||
constexpr fix4i v0{};
|
||||
constexpr fix4i v1{fix(1)};
|
||||
constexpr fix4i v2{fix(1), fix(2), fix(3), fix(4)};
|
||||
constexpr fix4i v3{fix2i{fix(1), fix(2)}, fix(3), fix(4)};
|
||||
constexpr fix4i v4{fix(1), fix2i{fix(2), fix(3)}, fix(4)};
|
||||
constexpr fix4i v5{fix(1), fix(2), fix2i{fix(3), fix(4)}};
|
||||
constexpr fix4i v6{fix2i{fix(1), fix(2)}, fix2i{fix(3), fix(4)}};
|
||||
constexpr fix4i v7{fix3i{fix(1), fix(2), fix(3)}, fix(4)};
|
||||
constexpr fix4i v8{fix(1), fix3i{fix(2), fix(3), fix(4)}};
|
||||
|
||||
STATIC_CHECK((v0.at(0) == fix(0)));
|
||||
STATIC_CHECK((v1.at(0) == fix(1) && v1.at(1) == fix(1) && v1.at(2) == fix(1) && v1.at(3) == fix(1)));
|
||||
STATIC_CHECK((v2.at(0) == fix(1) && v2.at(1) == fix(2) && v2.at(2) == fix(3) && v2.at(3) == fix(4)));
|
||||
STATIC_CHECK((v3.at(0) == fix(1) && v3.at(1) == fix(2) && v3.at(2) == fix(3) && v3.at(3) == fix(4)));
|
||||
STATIC_CHECK((v4.at(0) == fix(1) && v4.at(1) == fix(2) && v4.at(2) == fix(3) && v4.at(3) == fix(4)));
|
||||
STATIC_CHECK((v5.at(0) == fix(1) && v5.at(1) == fix(2) && v5.at(2) == fix(3) && v5.at(3) == fix(4)));
|
||||
STATIC_CHECK((v6.at(0) == fix(1) && v6.at(1) == fix(2) && v6.at(2) == fix(3) && v6.at(3) == fix(4)));
|
||||
STATIC_CHECK((v7.at(0) == fix(1) && v7.at(1) == fix(2) && v7.at(2) == fix(3) && v7.at(3) == fix(4)));
|
||||
STATIC_CHECK((v8.at(0) == fix(1) && v8.at(1) == fix(2) && v8.at(2) == fix(3) && v8.at(3) == fix(4)));
|
||||
}
|
||||
|
||||
SUBCASE("swap") {
|
||||
{
|
||||
vec v0{fix(1), fix(2)};
|
||||
vec v1{fix(3), fix(4)};
|
||||
swap(v0, v1);
|
||||
CHECK(v0 == fix2i(fix(3),fix(4)));
|
||||
CHECK(v1 == fix2i(fix(1),fix(2)));
|
||||
}
|
||||
{
|
||||
vec v0{fix{1},fix{2},fix{3}};
|
||||
vec v1{fix2i{fix(3),fix(4)}, fix{5}};
|
||||
swap(v0, v1);
|
||||
CHECK(v0 == fix3i(fix(3),fix(4),fix(5)));
|
||||
CHECK(v1 == fix3i(fix(1),fix(2),fix(3)));
|
||||
}
|
||||
{
|
||||
vec v0{fix{1},fix{2},fix{3},fix{4}};
|
||||
vec v1{fix{3},fix3i{fix(4),fix(5),fix(6)}};
|
||||
swap(v0, v1);
|
||||
CHECK(v0 == fix4i(fix(3),fix(4),fix(5),fix(6)));
|
||||
CHECK(v1 == fix4i(fix(1),fix(2),fix(3),fix(4)));
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("operators") {
|
||||
fix2b vb{};
|
||||
fix2i vi{};
|
||||
bool b{};
|
||||
|
||||
vi = {+fix2i{fix(1),fix(2)}};
|
||||
vi = {-fix2i{fix(1),fix(2)}};
|
||||
vi = {~fix2i{fix(1),fix(2)}};
|
||||
vb = {!fix2i{fix(1),fix(2)}};
|
||||
|
||||
vi = {fix2i{fix(1),fix(2)} + fix{3}};
|
||||
vi = {fix{3} + fix2i{fix(1),fix(2)}};
|
||||
vi = {fix2i{fix(1),fix(2)} + fix2i{fix(1),fix(2)}};
|
||||
|
||||
vi = {fix2i{fix(1),fix(2)} - fix{3}};
|
||||
vi = {fix{3} - fix2i{fix(1),fix(2)}};
|
||||
vi = {fix2i{fix(1),fix(2)} - fix2i{fix(1),fix(2)}};
|
||||
|
||||
vi = {fix2i{fix(1),fix(2)} * fix{3}};
|
||||
vi = {fix{3} * fix2i{fix(1),fix(2)}};
|
||||
vi = {fix2i{fix(1),fix(2)} * fix2i{fix(1),fix(2)}};
|
||||
|
||||
vi = {fix2i{fix(1),fix(2)} / fix{3}};
|
||||
vi = {fix{3} / fix2i{fix(1),fix(2)}};
|
||||
vi = {fix2i{fix(1),fix(2)} / fix2i{fix(1),fix(2)}};
|
||||
|
||||
vi = {fix2i{fix(1),fix(2)} & fix{3}};
|
||||
vi = {fix{3} & fix2i{fix(1),fix(2)}};
|
||||
vi = {fix2i{fix(1),fix(2)} & fix2i{fix(1),fix(2)}};
|
||||
|
||||
vi = {fix2i{fix(1),fix(2)} | fix{3}};
|
||||
vi = {fix{3} | fix2i{fix(1),fix(2)}};
|
||||
vi = {fix2i{fix(1),fix(2)} | fix2i{fix(1),fix(2)}};
|
||||
|
||||
vi = {fix2i{fix(1),fix(2)} ^ fix{3}};
|
||||
vi = {fix{3} ^ fix2i{fix(1),fix(2)}};
|
||||
vi = {fix2i{fix(1),fix(2)} ^ fix2i{fix(1),fix(2)}};
|
||||
|
||||
vb = {fix2i{fix(1),fix(2)} && fix{3}};
|
||||
vb = {fix{3} && fix2i{fix(1),fix(2)}};
|
||||
vb = {fix2i{fix(1),fix(2)} && fix2i{fix(1),fix(2)}};
|
||||
|
||||
vb = {fix2i{fix(1),fix(2)} || fix{3}};
|
||||
vb = {fix{3} || fix2i{fix(1),fix(2)}};
|
||||
vb = {fix2i{fix(1),fix(2)} || fix2i{fix(1),fix(2)}};
|
||||
|
||||
b = {fix2i{fix(1),fix(2)} == fix2i{fix(1),fix(2)}};
|
||||
b = {fix2i{fix(1),fix(2)} != fix2i{fix(1),fix(2)}};
|
||||
b = {fix2i{fix(1),fix(2)} < fix2i{fix(1),fix(2)}};
|
||||
|
||||
CHECK_FALSE(b);
|
||||
|
||||
{
|
||||
vi = {vi += fix{3}};
|
||||
vi = {vi += fix2i{fix(4),fix(5)}};
|
||||
vi = {vi -= fix{3}};
|
||||
vi = {vi -= fix2i{fix(4),fix(5)}};
|
||||
vi = {vi *= fix{3}};
|
||||
vi = {vi *= fix2i{fix(4),fix(5)}};
|
||||
vi = {vi /= fix{3}};
|
||||
vi = {vi /= fix2i{fix(4),fix(5)}};
|
||||
vi = {vi &= fix{3}};
|
||||
vi = {vi &= fix2i{fix(4),fix(5)}};
|
||||
vi = {vi |= fix{3}};
|
||||
vi = {vi |= fix2i{fix(4),fix(5)}};
|
||||
vi = {vi ^= fix{3}};
|
||||
vi = {vi ^= fix2i{fix(4),fix(5)}};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// fix_mat
|
||||
//
|
||||
|
||||
TEST_CASE("vmath/fix_mat") {
|
||||
SUBCASE("fix2x2 ctors") {
|
||||
constexpr fix2x2i v0{};
|
||||
constexpr fix2x2i v1{fix(2)};
|
||||
constexpr fix2x2i v2{fix2i{fix(1), fix(2)}};
|
||||
constexpr fix2x2i v3{fix(1), fix(2), fix(3), fix(4)};
|
||||
constexpr fix2x2i v4{{fix(1), fix(2)}, {fix(3), fix(4)}};
|
||||
constexpr fix2x2i v5{fix3x3i{fix(1)}};
|
||||
constexpr fix2x2i v6{fix4x4i{fix(1)}};
|
||||
|
||||
STATIC_CHECK((v0[0] == fix2i(fix(1),fix(0)) && v0[1] == fix2i(fix(0),fix(1))));
|
||||
STATIC_CHECK((v1[0] == fix2i(fix(2),fix(0)) && v1[1] == fix2i(fix(0),fix(2))));
|
||||
STATIC_CHECK((v2[0] == fix2i(fix(1),fix(0)) && v2[1] == fix2i(fix(0),fix(2))));
|
||||
STATIC_CHECK((v3[0] == fix2i(fix(1),fix(2)) && v3[1] == fix2i(fix(3),fix(4))));
|
||||
STATIC_CHECK((v4[0] == fix2i(fix(1),fix(2)) && v4[1] == fix2i(fix(3),fix(4))));
|
||||
STATIC_CHECK((v5[0] == fix2i(fix(1),fix(0)) && v5[1] == fix2i(fix(0),fix(1))));
|
||||
STATIC_CHECK((v6[0] == fix2i(fix(1),fix(0)) && v6[1] == fix2i(fix(0),fix(1))));
|
||||
}
|
||||
|
||||
SUBCASE("fix3x3 ctors") {
|
||||
constexpr fix3x3i v0{};
|
||||
constexpr fix3x3i v1{fix(2)};
|
||||
constexpr fix3x3i v2{fix3i{fix(1), fix(2), fix(3)}};
|
||||
constexpr fix3x3i v3{fix(1),fix(2),fix(3),fix(4),fix(5),fix(6),fix(7),fix(8),fix(9)};
|
||||
constexpr fix3x3i v4{{fix(1),fix(2),fix(3)},{fix(4),fix(5),fix(6)},{fix(7),fix(8),fix(9)}};
|
||||
constexpr fix3x3i v5{fix2x2i{fix(1)},fix2i{fix(0)}};
|
||||
constexpr fix3x3i v6{fix2x2i{fix(1)}};
|
||||
constexpr fix3x3i v7{fix4x4i{fix(1)}};
|
||||
|
||||
STATIC_CHECK((v0[0] == fix3i(fix(1),fix(0),fix(0)) && v0[1] == fix3i(fix(0),fix(1),fix(0)) && v0[2] == fix3i(fix(0),fix(0),fix(1))));
|
||||
STATIC_CHECK((v1[0] == fix3i(fix(2),fix(0),fix(0)) && v1[1] == fix3i(fix(0),fix(2),fix(0)) && v1[2] == fix3i(fix(0),fix(0),fix(2))));
|
||||
STATIC_CHECK((v2[0] == fix3i(fix(1),fix(0),fix(0)) && v2[1] == fix3i(fix(0),fix(2),fix(0)) && v2[2] == fix3i(fix(0),fix(0),fix(3))));
|
||||
STATIC_CHECK((v3[0] == fix3i(fix(1),fix(2),fix(3)) && v3[1] == fix3i(fix(4),fix(5),fix(6)) && v3[2] == fix3i(fix(7),fix(8),fix(9))));
|
||||
STATIC_CHECK((v4[0] == fix3i(fix(1),fix(2),fix(3)) && v4[1] == fix3i(fix(4),fix(5),fix(6)) && v4[2] == fix3i(fix(7),fix(8),fix(9))));
|
||||
STATIC_CHECK((v5[0] == fix3i(fix(1),fix(0),fix(0)) && v5[1] == fix3i(fix(0),fix(1),fix(0)) && v5[2] == fix3i(fix(0),fix(0),fix(1))));
|
||||
STATIC_CHECK((v6[0] == fix3i(fix(1),fix(0),fix(0)) && v6[1] == fix3i(fix(0),fix(1),fix(0)) && v6[2] == fix3i(fix(0),fix(0),fix(1))));
|
||||
STATIC_CHECK((v7[0] == fix3i(fix(1),fix(0),fix(0)) && v7[1] == fix3i(fix(0),fix(1),fix(0)) && v7[2] == fix3i(fix(0),fix(0),fix(1))));
|
||||
}
|
||||
|
||||
SUBCASE("fix4x4 ctors") {
|
||||
constexpr fix4x4i v0{};
|
||||
constexpr fix4x4i v1{fix(2)};
|
||||
constexpr fix4x4i v2{fix4i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
constexpr fix4x4i v3{fix(1),fix(2),fix(3),fix(4),fix(5),fix(6),fix(7),fix(8),fix(9),fix(10),fix(11),fix(12),fix(13),fix(14),fix(15),fix(16)};
|
||||
constexpr fix4x4i v4{{fix(1),fix(2),fix(3),fix(4)},{fix(5),fix(6),fix(7),fix(8)},{fix(9),fix(10),fix(11),fix(12)},{fix(13),fix(14),fix(15),fix(16)}};
|
||||
constexpr fix4x4i v5{fix3x3i{fix(1)},fix3i{fix(0)}};
|
||||
constexpr fix4x4i v6{fix2x2i{fix(1)}};
|
||||
constexpr fix4x4i v7{fix3x3i{fix(1)}};
|
||||
|
||||
STATIC_CHECK((v0[0] == fix4i(fix(1),fix(0),fix(0),fix(0)) && v0[1] == fix4i(fix(0),fix(1),fix(0),fix(0)) && v0[2] == fix4i(fix(0),fix(0),fix(1),fix(0)) && v0[3] == fix4i(fix(0),fix(0),fix(0),fix(1))));
|
||||
STATIC_CHECK((v1[0] == fix4i(fix(2),fix(0),fix(0),fix(0)) && v1[1] == fix4i(fix(0),fix(2),fix(0),fix(0)) && v1[2] == fix4i(fix(0),fix(0),fix(2),fix(0)) && v1[3] == fix4i(fix(0),fix(0),fix(0),fix(2))));
|
||||
STATIC_CHECK((v2[0] == fix4i(fix(1),fix(0),fix(0),fix(0)) && v2[1] == fix4i(fix(0),fix(2),fix(0),fix(0)) && v2[2] == fix4i(fix(0),fix(0),fix(3),fix(0)) && v2[3] == fix4i(fix(0),fix(0),fix(0),fix(4))));
|
||||
STATIC_CHECK((v3[0] == fix4i(fix(1),fix(2),fix(3),fix(4)) && v3[1] == fix4i(fix(5),fix(6),fix(7),fix(8)) && v3[2] == fix4i(fix(9),fix(10),fix(11),fix(12)) && v3[3] == fix4i(fix(13),fix(14),fix(15),fix(16))));
|
||||
STATIC_CHECK((v4[0] == fix4i(fix(1),fix(2),fix(3),fix(4)) && v4[1] == fix4i(fix(5),fix(6),fix(7),fix(8)) && v4[2] == fix4i(fix(9),fix(10),fix(11),fix(12)) && v4[3] == fix4i(fix(13),fix(14),fix(15),fix(16))));
|
||||
STATIC_CHECK((v5[0] == fix4i(fix(1),fix(0),fix(0),fix(0)) && v5[1] == fix4i(fix(0),fix(1),fix(0),fix(0)) && v5[2] == fix4i(fix(0),fix(0),fix(1),fix(0)) && v5[3] == fix4i(fix(0),fix(0),fix(0),fix(1))));
|
||||
STATIC_CHECK((v6[0] == fix4i(fix(1),fix(0),fix(0),fix(0)) && v6[1] == fix4i(fix(0),fix(1),fix(0),fix(0)) && v6[2] == fix4i(fix(0),fix(0),fix(1),fix(0)) && v6[3] == fix4i(fix(0),fix(0),fix(0),fix(1))));
|
||||
STATIC_CHECK((v7[0] == fix4i(fix(1),fix(0),fix(0),fix(0)) && v7[1] == fix4i(fix(0),fix(1),fix(0),fix(0)) && v7[2] == fix4i(fix(0),fix(0),fix(1),fix(0)) && v7[3] == fix4i(fix(0),fix(0),fix(0),fix(1))));
|
||||
}
|
||||
|
||||
SUBCASE("swap") {
|
||||
{
|
||||
fix2x2i v0{fix(1)};
|
||||
fix2x2i v1{fix(2)};
|
||||
swap(v0, v1);
|
||||
CHECK(v0 == fix2x2i(fix(2)));
|
||||
CHECK(v1 == fix2x2i(fix(1)));
|
||||
}
|
||||
{
|
||||
fix3x3i v0{fix(1)};
|
||||
fix3x3i v1{fix(2)};
|
||||
swap(v0, v1);
|
||||
CHECK(v0 == fix3x3i(fix(2)));
|
||||
CHECK(v1 == fix3x3i(fix(1)));
|
||||
}
|
||||
{
|
||||
fix4x4i v0{fix(1)};
|
||||
fix4x4i v1{fix(2)};
|
||||
swap(v0, v1);
|
||||
CHECK(v0 == fix4x4i(fix(2)));
|
||||
CHECK(v1 == fix4x4i(fix(1)));
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("operators") {
|
||||
fix2x2b mb{};
|
||||
fix2x2i mi{};
|
||||
fix2i vi{};
|
||||
bool b{};
|
||||
|
||||
mi = {+fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
mi = {-fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
mi = {~fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
mb = {!fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} + fix{3}};
|
||||
mi = {fix{3} + fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} + fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} - fix{3}};
|
||||
mi = {fix{3} - fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} - fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} * fix{3}};
|
||||
mi = {fix{3} * fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
vi = {vi * mi};
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} * fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} / fix{3}};
|
||||
mi = {fix{3} / fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
// mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} / fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} & fix{3}};
|
||||
mi = {fix{3} & fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} & fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} | fix{3}};
|
||||
mi = {fix{3} | fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} | fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} ^ fix{3}};
|
||||
mi = {fix{3} ^ fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} ^ fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
|
||||
mb = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} && fix{3}};
|
||||
mb = {fix{3} && fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
mb = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} && fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
|
||||
mb = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} || fix{3}};
|
||||
mb = {fix{3} || fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
mb = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} || fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
|
||||
b = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} == fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
b = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} != fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
b = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} < fix2x2i{fix(1),fix(2),fix(3),fix(4)}};
|
||||
|
||||
CHECK_FALSE(b);
|
||||
|
||||
{
|
||||
mi = {mi += fix{3}};
|
||||
mi = {mi += fix2x2i{fix(4),fix(5),fix(6),fix(7)}};
|
||||
mi = {mi -= fix{3}};
|
||||
mi = {mi -= fix2x2i{fix(4),fix(5),fix(6),fix(7)}};
|
||||
mi = {mi *= fix{3}};
|
||||
vi = {vi *= fix2x2i{fix(4),fix(5),fix(6),fix(7)}};
|
||||
mi = {mi *= fix2x2i{fix(4),fix(5),fix(6),fix(7)}};
|
||||
mi = {mi /= fix{3}};
|
||||
//mi = {mi /= fix2x2i{fix(4),fix(5),fix(6),fix(7)}};
|
||||
mi = {mi &= fix{3}};
|
||||
mi = {mi &= fix2x2i{fix(4),fix(5),fix(6),fix(7)}};
|
||||
mi = {mi |= fix{3}};
|
||||
mi = {mi |= fix2x2i{fix(4),fix(5),fix(6),fix(7)}};
|
||||
mi = {mi ^= fix{3}};
|
||||
mi = {mi ^= fix2x2i{fix(4),fix(5),fix(6),fix(7)}};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// fix_qua
|
||||
//
|
||||
|
||||
TEST_CASE("vmath/fix_qua") {
|
||||
SUBCASE("ctors") {
|
||||
constexpr qfix v0{};
|
||||
constexpr qfix v1{fix(1.f), fix(2.f), fix(3.f), fix(4.f)};
|
||||
constexpr qfix v2{fix3f{fix(1.f), fix(2.f), fix(3.f)}, fix(4.f)};
|
||||
constexpr qfix v3{fix4f{fix(1.f), fix(2.f), fix(3.f), fix(4.f)}};
|
||||
|
||||
STATIC_CHECK((v0.at(0) == fix(0.f)));
|
||||
STATIC_CHECK((v1.at(0) == fix(1.f) && v1.at(1) == fix(2.f) && v1.at(2) == fix(3.f) && v1.at(3) == fix(4.f)));
|
||||
STATIC_CHECK((v2.at(0) == fix(1.f) && v2.at(1) == fix(2.f) && v2.at(2) == fix(3.f) && v2.at(3) == fix(4.f)));
|
||||
STATIC_CHECK((v3.at(0) == fix(1.f) && v3.at(1) == fix(2.f) && v3.at(2) == fix(3.f) && v3.at(3) == fix(4.f)));
|
||||
}
|
||||
|
||||
SUBCASE("swap") {
|
||||
qfix v0{fix(1.f),fix(2.f),fix(3.f),fix(4.f)};
|
||||
qfix v1{fix(4.f),fix(3.f),fix(2.f),fix(1.f)};
|
||||
swap(v0, v1);
|
||||
CHECK(v0 == qfix(fix(4.f),fix(3.f),fix(2.f),fix(1.f)));
|
||||
CHECK(v1 == qfix(fix(1.f),fix(2.f),fix(3.f),fix(4.f)));
|
||||
}
|
||||
|
||||
SUBCASE("operators") {
|
||||
qfix qf;
|
||||
fix3f vf;
|
||||
bool b{};
|
||||
|
||||
qf = {+qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
qf = {-qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
|
||||
qf = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} + qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
qf = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} - qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
qf = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} * fix{1.f}};
|
||||
qf = {fix{1.f} * qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
vf = {fix3f{fix(1.f),fix(2.f),fix(3.f)} * qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
qf = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} * qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
qf = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} / fix{1.f}};
|
||||
qf = {fix{1.f} / qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
|
||||
qf = {qf += qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
qf = {qf -= qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
qf = {qf *= fix{1.f}};
|
||||
vf = {vf *= qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
qf = {qf *= qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
qf = {qf /= fix{1.f}};
|
||||
|
||||
b = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} == qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
b = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} != qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
b = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} < qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}};
|
||||
|
||||
CHECK_FALSE(b);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Units
|
||||
//
|
||||
|
||||
TEST_CASE("vmath/fix_units") {
|
||||
{
|
||||
STATIC_CHECK(zero2<fix<float>> == fix2f{fix(0.f),fix(0.f)});
|
||||
STATIC_CHECK(zero3<fix<float>> == fix3f{fix(0.f),fix(0.f),fix(0.f)});
|
||||
STATIC_CHECK(zero4<fix<float>> == fix4f{fix(0.f),fix(0.f),fix(0.f),fix(0.f)});
|
||||
}
|
||||
{
|
||||
STATIC_CHECK(unit2<fix<float>> == fix2f{fix(1.f),fix(1.f)});
|
||||
STATIC_CHECK(unit3<fix<float>> == fix3f{fix(1.f),fix(1.f),fix(1.f)});
|
||||
STATIC_CHECK(unit4<fix<float>> == fix4f{fix(1.f),fix(1.f),fix(1.f),fix(1.f)});
|
||||
}
|
||||
{
|
||||
STATIC_CHECK(unit2_x<fix<float>> == fix2f{fix(1.f),fix(0.f)});
|
||||
STATIC_CHECK(unit2_y<fix<float>> == fix2f{fix(0.f),fix(1.f)});
|
||||
|
||||
STATIC_CHECK(unit3_x<fix<float>> == fix3f{fix(1.f),fix(0.f),fix(0.f)});
|
||||
STATIC_CHECK(unit3_y<fix<float>> == fix3f{fix(0.f),fix(1.f),fix(0.f)});
|
||||
STATIC_CHECK(unit3_z<fix<float>> == fix3f{fix(0.f),fix(0.f),fix(1.f)});
|
||||
|
||||
STATIC_CHECK(unit4_x<fix<float>> == fix4f{fix(1.f),fix(0.f),fix(0.f),fix(0.f)});
|
||||
STATIC_CHECK(unit4_y<fix<float>> == fix4f{fix(0.f),fix(1.f),fix(0.f),fix(0.f)});
|
||||
STATIC_CHECK(unit4_z<fix<float>> == fix4f{fix(0.f),fix(0.f),fix(1.f),fix(0.f)});
|
||||
STATIC_CHECK(unit4_w<fix<float>> == fix4f{fix(0.f),fix(0.f),fix(0.f),fix(1.f)});
|
||||
}
|
||||
{
|
||||
STATIC_CHECK(zero2x2<fix<float>> == fix2x2f{
|
||||
fix(0.f),fix(0.f),
|
||||
fix(0.f),fix(0.f)});
|
||||
STATIC_CHECK(zero3x3<fix<float>> == fix3x3f{
|
||||
fix(0.f),fix(0.f),fix(0.f),
|
||||
fix(0.f),fix(0.f),fix(0.f),
|
||||
fix(0.f),fix(0.f),fix(0.f)});
|
||||
STATIC_CHECK(zero4x4<fix<float>> == fix4x4f{
|
||||
fix(0.f),fix(0.f),fix(0.f),fix(0.f),
|
||||
fix(0.f),fix(0.f),fix(0.f),fix(0.f),
|
||||
fix(0.f),fix(0.f),fix(0.f),fix(0.f),
|
||||
fix(0.f),fix(0.f),fix(0.f),fix(0.f)});
|
||||
}
|
||||
{
|
||||
STATIC_CHECK(unit2x2<fix<float>> == fix2x2f{
|
||||
fix(1.f),fix(1.f),
|
||||
fix(1.f),fix(1.f)});
|
||||
STATIC_CHECK(unit3x3<fix<float>> == fix3x3f{
|
||||
fix(1.f),fix(1.f),fix(1.f),
|
||||
fix(1.f),fix(1.f),fix(1.f),
|
||||
fix(1.f),fix(1.f),fix(1.f)});
|
||||
STATIC_CHECK(unit4x4<fix<float>> == fix4x4f{
|
||||
fix(1.f),fix(1.f),fix(1.f),fix(1.f),
|
||||
fix(1.f),fix(1.f),fix(1.f),fix(1.f),
|
||||
fix(1.f),fix(1.f),fix(1.f),fix(1.f),
|
||||
fix(1.f),fix(1.f),fix(1.f),fix(1.f)});
|
||||
}
|
||||
{
|
||||
STATIC_CHECK(identity2x2<fix<float>> == fix2x2f{
|
||||
fix(1.f),fix(0.f),
|
||||
fix(0.f),fix(1.f)});
|
||||
STATIC_CHECK(identity3x3<fix<float>> == fix3x3f{
|
||||
fix(1.f),fix(0.f),fix(0.f),
|
||||
fix(0.f),fix(1.f),fix(0.f),
|
||||
fix(0.f),fix(0.f),fix(1.f)});
|
||||
STATIC_CHECK(identity4x4<fix<float>> == fix4x4f{
|
||||
fix(1.f),fix(0.f),fix(0.f),fix(0.f),
|
||||
fix(0.f),fix(1.f),fix(0.f),fix(0.f),
|
||||
fix(0.f),fix(0.f),fix(1.f),fix(0.f),
|
||||
fix(0.f),fix(0.f),fix(0.f),fix(1.f)});
|
||||
}
|
||||
{
|
||||
STATIC_CHECK(qidentity<fix<float>> == qfix{
|
||||
fix(0.f),fix(0.f),fix(0.f),
|
||||
fix(1.f)});
|
||||
}
|
||||
}
|
||||
@@ -105,29 +105,21 @@ TEST_CASE("vmath/fun") {
|
||||
STATIC_CHECK(step(0.5f, 0.4f) == uapprox(0.f));
|
||||
STATIC_CHECK(step(0.5f, 0.6f) == uapprox(1.f));
|
||||
STATIC_CHECK(smoothstep(0.f, 1.f, 0.1f) == uapprox(0.028f));
|
||||
|
||||
CHECK_FALSE(vmath_hpp::isnan(1.f));
|
||||
CHECK_FALSE(vmath_hpp::isinf(1.f));
|
||||
CHECK(vmath_hpp::isfinite(1.f));
|
||||
|
||||
CHECK(fma(2.f, 3.f, 4.f) == uapprox(10.f));
|
||||
|
||||
{
|
||||
int out_exp{};
|
||||
CHECK(frexp(1.7f, &out_exp) == uapprox(0.85f));
|
||||
CHECK(out_exp == 1);
|
||||
}
|
||||
|
||||
CHECK(ldexp(0.85f, 1) == uapprox(1.7f));
|
||||
}
|
||||
|
||||
SUBCASE("Geometric Functions") {
|
||||
STATIC_CHECK(length(10.f) == uapprox(10.f));
|
||||
STATIC_CHECK(length(-10.f) == uapprox(10.f));
|
||||
|
||||
STATIC_CHECK(rlength(10.f) == uapprox(0.1f));
|
||||
STATIC_CHECK(rlength(-10.f) == uapprox(0.1f));
|
||||
|
||||
STATIC_CHECK(length2(10.f) == uapprox(100.f));
|
||||
STATIC_CHECK(length2(-10.f) == uapprox(100.f));
|
||||
|
||||
STATIC_CHECK(rlength2(10.f) == uapprox(0.01f));
|
||||
STATIC_CHECK(rlength2(-10.f) == uapprox(0.01f));
|
||||
|
||||
STATIC_CHECK(distance(5.f, 10.f) == uapprox(5.f));
|
||||
STATIC_CHECK(distance(-5.f, -10.f) == uapprox(5.f));
|
||||
|
||||
@@ -135,7 +127,7 @@ TEST_CASE("vmath/fun") {
|
||||
STATIC_CHECK(distance2(-5.f, -10.f) == uapprox(25.f));
|
||||
|
||||
STATIC_CHECK(dot(2.f, 5.f) == uapprox(10.f));
|
||||
CHECK(normalize(0.5f) == uapprox(1.f));
|
||||
STATIC_CHECK(normalize(0.5f) == uapprox(1.f));
|
||||
|
||||
STATIC_CHECK(faceforward(1.f, 2.f, 3.f) == uapprox(-1.f));
|
||||
STATIC_CHECK(reflect(1.f, 2.f) == uapprox(-7.f));
|
||||
|
||||
@@ -128,12 +128,6 @@ TEST_CASE("vmath/qua_fun") {
|
||||
qrotate_z(radians(290.f)),
|
||||
slerp(qrotate_z(radians(220.f)), qrotate_z(radians(0.f)), 0.5f))));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK_FALSE(any(isnan(qfloat(1,1,1,1))));
|
||||
CHECK_FALSE(any(isinf(qfloat(1,1,1,1))));
|
||||
CHECK(all(isfinite(qfloat(1,1,1,1))));
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("Geometric Functions") {
|
||||
@@ -142,9 +136,15 @@ TEST_CASE("vmath/qua_fun") {
|
||||
CHECK(length(qfloat(10.f,0.f,0.f,0.f)) == uapprox(10.f));
|
||||
CHECK(length(qfloat(-10.f,0.f,0.f,0.f)) == uapprox(10.f));
|
||||
|
||||
CHECK(rlength(qfloat(10.f,0.f,0.f,0.f)) == uapprox(0.1f));
|
||||
CHECK(rlength(qfloat(-10.f,0.f,0.f,0.f)) == uapprox(0.1f));
|
||||
|
||||
STATIC_CHECK(length2(qfloat(10.f,0.f,0.f,0.f)) == uapprox(100.f));
|
||||
STATIC_CHECK(length2(qfloat(-10.f,0.f,0.f,0.f)) == uapprox(100.f));
|
||||
|
||||
STATIC_CHECK(rlength2(qfloat(10.f,0.f,0.f,0.f)) == uapprox(0.01f));
|
||||
STATIC_CHECK(rlength2(qfloat(-10.f,0.f,0.f,0.f)) == uapprox(0.01f));
|
||||
|
||||
CHECK(distance(qrotate_z(radians(0.f)) * 2.f, qrotate_z(radians(0.f)) * 1.5f) == uapprox(radians(0.f)));
|
||||
CHECK(distance(qrotate_z(radians(0.f)) * 3.f, qrotate_z(radians(360.f)) * 2.5f) == uapprox(radians(0.f)));
|
||||
CHECK(distance(qrotate_z(radians(0.f)) * 4.f, qrotate_z(radians(180.f)) * 3.5f) == uapprox(radians(180.f)));
|
||||
@@ -156,6 +156,19 @@ TEST_CASE("vmath/qua_fun") {
|
||||
}
|
||||
|
||||
SUBCASE("Relational Functions") {
|
||||
STATIC_CHECK(any(qua(1,0,0,0)));
|
||||
STATIC_CHECK(any(qua(0,1,0,0)));
|
||||
STATIC_CHECK(any(qua(0,0,1,0)));
|
||||
STATIC_CHECK(any(qua(0,0,0,1)));
|
||||
STATIC_CHECK(any(qua(1,1,1,1)));
|
||||
STATIC_CHECK_FALSE(any(qua(0,0,0,0)));
|
||||
|
||||
STATIC_CHECK_FALSE(all(qua(1,0,0,0)));
|
||||
STATIC_CHECK_FALSE(all(qua(0,1,0,0)));
|
||||
STATIC_CHECK_FALSE(all(qua(0,0,1,0)));
|
||||
STATIC_CHECK(all(qua(1,1,1,1)));
|
||||
STATIC_CHECK_FALSE(all(qua(0,0,0,0)));
|
||||
|
||||
STATIC_CHECK(approx(qua(1,1,1,1), qua(0,1,2,3)) == bool4(false, true, false, false));
|
||||
STATIC_CHECK(approx(qua(1,1,1,1), qua(0,1,2,3), 0) == bool4(false, true, false, false));
|
||||
STATIC_CHECK(approx(qua(1,1,1,1), qua(0,1,2,3), 1) == bool4(true, true, true, false));
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace vmath_tests
|
||||
|
||||
template < typename T >
|
||||
struct uapprox_base {
|
||||
T epsilon = T(10) * std::numeric_limits<T>::epsilon();
|
||||
T epsilon = T{10} * std::numeric_limits<T>::epsilon();
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
@@ -57,7 +57,7 @@ namespace vmath_tests
|
||||
|
||||
template < typename T >
|
||||
constexpr bool operator==(const vec<T, 2>& l, const uapprox2<T>& r) {
|
||||
return all(approx(l, r.value,r.epsilon));
|
||||
return all(approx(l, r.value, r.epsilon));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
|
||||
@@ -16,27 +16,31 @@ TEST_CASE("vmath/vec_fun") {
|
||||
SUBCASE("Detail") {
|
||||
STATIC_CHECK(map_join([](const int& x){
|
||||
return x * 2;
|
||||
}, int2{1}) == int2{2});
|
||||
}, vec{1,2,3,4}) == vec{2,4,6,8});
|
||||
|
||||
STATIC_CHECK(map_join([](const int& x, const int& y){
|
||||
return x + y;
|
||||
}, int2{1}, int2{1}) == int2{2});
|
||||
}, vec{1,2,3,4}, vec{2,3,4,5}) == vec{3,5,7,9});
|
||||
|
||||
STATIC_CHECK(map_join([](const int& x, const int& y, const int& z){
|
||||
return x + y + z;
|
||||
}, int2{1}, int2{1}, int2{1}) == int2(3));
|
||||
}, vec{1,2,3,4}, vec{2,3,4,5}, vec{3,4,5,6}) == vec{6,9,12,15});
|
||||
|
||||
STATIC_CHECK(map_join([](const int& x, const int& y, const int& z, const int& w){
|
||||
return x + y + z + w;
|
||||
}, vec{1,2,3,4}, vec{2,3,4,5}, vec{3,4,5,6}, vec{4,5,6,7}) == vec{10,14,18,22});
|
||||
|
||||
STATIC_CHECK(fold_join([](int acc, const int& x){
|
||||
return acc + x;
|
||||
}, 0, int2{1}) == 2);
|
||||
return acc - x;
|
||||
}, 0, vec{1,2,3,4}) == -10);
|
||||
|
||||
STATIC_CHECK(fold_join([](int acc, const int& x, const int& y){
|
||||
return acc + x + y;
|
||||
}, 0, int2{1}, int2{1}) == 4);
|
||||
return acc - x - y;
|
||||
}, 0, vec{1,2,3,4}, vec{2,3,4,5}) == -24);
|
||||
|
||||
STATIC_CHECK(fold1_join([](const int& acc, const int& x){
|
||||
return acc + x;
|
||||
}, int2{1}) == 2);
|
||||
return acc - x;
|
||||
}, vec{1,2,3,4}) == -8);
|
||||
}
|
||||
|
||||
SUBCASE("Operators") {
|
||||
@@ -245,29 +249,21 @@ TEST_CASE("vmath/vec_fun") {
|
||||
|
||||
STATIC_CHECK(smoothstep(0.f, 1.f, float2(0.1f)) == uapprox2(0.028f));
|
||||
STATIC_CHECK(smoothstep(float2(0.f), float2(1.f), float2(0.1f)) == uapprox2(0.028f));
|
||||
|
||||
CHECK_FALSE(isnan(float2(1.f)).x);
|
||||
CHECK_FALSE(isinf(float2(1.f)).x);
|
||||
CHECK(isfinite(float2(1.f)).x);
|
||||
|
||||
CHECK_FALSE(fma(float2(2.f), float2(3.f), float2(4.f)).x == uapprox(12.f));
|
||||
|
||||
{
|
||||
int2 out_exp{};
|
||||
CHECK(frexp(float2(1.7f), &out_exp).x == uapprox(0.85f));
|
||||
CHECK(out_exp == int2(1));
|
||||
}
|
||||
|
||||
CHECK(ldexp(float2(0.85f), int2(1)).x == uapprox(1.7f));
|
||||
}
|
||||
|
||||
SUBCASE("Geometric Functions") {
|
||||
CHECK(length(float2(10.f,0.f)) == uapprox(10.f));
|
||||
CHECK(length(float2(-10.f,0.f)) == uapprox(10.f));
|
||||
|
||||
CHECK(rlength(float2(10.f,0.f)) == uapprox(0.1f));
|
||||
CHECK(rlength(float2(-10.f,0.f)) == uapprox(0.1f));
|
||||
|
||||
STATIC_CHECK(length2(float2(10.f,0.f)) == uapprox(100.f));
|
||||
STATIC_CHECK(length2(float2(-10.f,0.f)) == uapprox(100.f));
|
||||
|
||||
STATIC_CHECK(rlength2(float2(10.f,0.f)) == uapprox(0.01f));
|
||||
STATIC_CHECK(rlength2(float2(-10.f,0.f)) == uapprox(0.01f));
|
||||
|
||||
CHECK(distance(float2(5.f,0.f), float2(10.f,0.f)) == uapprox(5.f));
|
||||
CHECK(distance(float2(-5.f,0.f), float2(-10.f,0.f)) == uapprox(5.f));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user