mirror of
https://github.com/BlackMATov/vmath.hpp.git
synced 2025-12-15 12:39:47 +07:00
@@ -1,28 +0,0 @@
|
||||
image:
|
||||
- Visual Studio 2017
|
||||
- Visual Studio 2019
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
||||
for:
|
||||
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- platform: x86
|
||||
configuration: Release
|
||||
build_script:
|
||||
- .ci\build_windows_x86.bat
|
||||
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- platform: x64
|
||||
configuration: Release
|
||||
build_script:
|
||||
- .ci\build_windows_x64.bat
|
||||
14
.github/workflows/coverage.yml
vendored
Normal file
14
.github/workflows/coverage.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: coverage
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-10.15
|
||||
name: "coverage"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install lcov by Homebrew
|
||||
run: brew install lcov
|
||||
- name: Build && Test && Upload
|
||||
run: .ci/build_coverage.sh
|
||||
22
.github/workflows/darwin.yml
vendored
Normal file
22
.github/workflows/darwin.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: darwin
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{matrix.config.os}}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
# https://github.com/actions/virtual-environments/tree/main/images/macos
|
||||
- { os: "macos-10.15", xcode: "10.3" }
|
||||
- { os: "macos-10.15", xcode: "11.7" }
|
||||
- { os: "macos-10.15", xcode: "12.4" }
|
||||
name: "xcode-${{matrix.config.xcode}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Select Xcode
|
||||
run: sudo xcode-select --switch "/Applications/Xcode_${{matrix.config.xcode}}.app"
|
||||
- name: Build && Test
|
||||
run: .ci/build_darwin.sh
|
||||
25
.github/workflows/linux.yml
vendored
Normal file
25
.github/workflows/linux.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: linux
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{matrix.config.os}}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
# https://github.com/actions/virtual-environments/tree/main/images/linux
|
||||
- { os: "ubuntu-20.04", cc: "gcc-7", cxx: "g++-7" }
|
||||
- { os: "ubuntu-20.04", cc: "gcc-8", cxx: "g++-8" }
|
||||
- { os: "ubuntu-20.04", cc: "gcc-9", cxx: "g++-9" }
|
||||
- { os: "ubuntu-20.04", cc: "gcc-10", cxx: "g++-10" }
|
||||
- { os: "ubuntu-20.04", cc: "clang-8", cxx: "clang++-8" }
|
||||
- { os: "ubuntu-20.04", cc: "clang-9", cxx: "clang++-9" }
|
||||
- { os: "ubuntu-20.04", cc: "clang-10", cxx: "clang++-10" }
|
||||
name: "${{matrix.config.cxx}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build && Test
|
||||
run: .ci/build_linux.sh
|
||||
env: { CC: "${{matrix.config.cc}}", CXX: "${{matrix.config.cxx}}" }
|
||||
21
.github/workflows/windows.yml
vendored
Normal file
21
.github/workflows/windows.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: windows
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{matrix.config.os}}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
# https://github.com/actions/virtual-environments/tree/main/images/win
|
||||
- { os: "windows-2016", vs: "Visual Studio 2017", arch: "x86" }
|
||||
- { 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}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build && Test
|
||||
run: .ci\build_windows_${{matrix.config.arch}}.bat
|
||||
89
.travis.yml
89
.travis.yml
@@ -1,89 +0,0 @@
|
||||
git:
|
||||
depth: false
|
||||
quiet: true
|
||||
|
||||
language: cpp
|
||||
|
||||
jobs:
|
||||
include:
|
||||
|
||||
#
|
||||
# linux (g++)
|
||||
#
|
||||
|
||||
- os: linux
|
||||
dist: bionic
|
||||
stage: linux
|
||||
name: g++-7
|
||||
addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-7"] } }
|
||||
env: CC=gcc-7 CXX=g++-7
|
||||
script: .ci/build_linux.sh
|
||||
|
||||
- os: linux
|
||||
dist: bionic
|
||||
stage: linux
|
||||
name: g++-8
|
||||
addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-8"] } }
|
||||
env: CC=gcc-8 CXX=g++-8
|
||||
script: .ci/build_linux.sh
|
||||
|
||||
#
|
||||
# linux (clang++)
|
||||
#
|
||||
|
||||
- os: linux
|
||||
dist: bionic
|
||||
stage: linux
|
||||
name: clang++-5.0
|
||||
addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["clang-5.0"] } }
|
||||
env: CC=clang-5.0 CXX=clang++-5.0
|
||||
script: .ci/build_linux.sh
|
||||
|
||||
- os: linux
|
||||
dist: bionic
|
||||
stage: linux
|
||||
name: clang++-6.0
|
||||
addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["clang-6.0"] } }
|
||||
env: CC=clang-6.0 CXX=clang++-6.0
|
||||
script: .ci/build_linux.sh
|
||||
|
||||
#
|
||||
# darwin
|
||||
#
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode10
|
||||
stage: darwin
|
||||
name: xcode10
|
||||
script: .ci/build_darwin.sh
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode11
|
||||
stage: darwin
|
||||
name: xcode11
|
||||
script: .ci/build_darwin.sh
|
||||
|
||||
#
|
||||
# windows
|
||||
#
|
||||
|
||||
- os: windows
|
||||
stage: windows
|
||||
name: x86
|
||||
script: .ci/build_windows_x86.bat
|
||||
|
||||
- os: windows
|
||||
stage: windows
|
||||
name: x64
|
||||
script: .ci/build_windows_x64.bat
|
||||
|
||||
#
|
||||
# coverage
|
||||
#
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode10
|
||||
stage: coverage
|
||||
name: coverage
|
||||
addons: { homebrew: { packages: ["lcov"], update: true } }
|
||||
script: .ci/build_coverage.sh
|
||||
@@ -14,5 +14,8 @@
|
||||
#include "vmath_mat.hpp"
|
||||
#include "vmath_mat_fun.hpp"
|
||||
|
||||
#include "vmath_qua.hpp"
|
||||
#include "vmath_qua_fun.hpp"
|
||||
|
||||
#include "vmath_vec.hpp"
|
||||
#include "vmath_vec_fun.hpp"
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "vmath_fun.hpp"
|
||||
#include "vmath_vec_fun.hpp"
|
||||
#include "vmath_mat_fun.hpp"
|
||||
#include "vmath_qua_fun.hpp"
|
||||
|
||||
//
|
||||
// Units
|
||||
@@ -73,6 +74,11 @@ namespace vmath_hpp::detail
|
||||
[[nodiscard]] std::size_t hash(const mat<T, Size>& m) noexcept {
|
||||
return fold_join(hash_combiner{}, std::size_t{}, m);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::size_t hash(const qua<T>& q) noexcept {
|
||||
return hash(vec{q});
|
||||
}
|
||||
}
|
||||
|
||||
namespace std
|
||||
@@ -90,6 +96,13 @@ namespace std
|
||||
return vmath_hpp::detail::hash(m);
|
||||
}
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
struct hash<vmath_hpp::qua<T>> {
|
||||
size_t operator()(const vmath_hpp::qua<T>& q) const noexcept {
|
||||
return vmath_hpp::detail::hash(q);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
@@ -115,6 +128,11 @@ namespace vmath_hpp
|
||||
[[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);
|
||||
}
|
||||
|
||||
template < typename To, typename From >
|
||||
[[nodiscard]] constexpr qua<To> cast_to(const qua<From>& q) {
|
||||
return qua(cast_to<To>(vec{q}));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -131,8 +149,8 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> component(vec<T, Size> v, std::size_t index, T x) {
|
||||
v[index] = x;
|
||||
[[nodiscard]] constexpr vec<T, Size> component(vec<T, Size> v, std::size_t index, T component) {
|
||||
v[index] = component;
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -144,8 +162,8 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> row(mat<T, Size> m, std::size_t index, const vec<T, Size>& v) {
|
||||
m.rows[index] = v;
|
||||
[[nodiscard]] constexpr mat<T, Size> row(mat<T, Size> m, std::size_t index, const vec<T, Size>& row) {
|
||||
m.rows[index] = row;
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -161,8 +179,8 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
mat<T, Size> column_impl(const mat<T, Size>& m, std::size_t index, const vec<T, Size>& v, std::index_sequence<Is...>) {
|
||||
return { component(m[Is], index, v[Is])... };
|
||||
mat<T, Size> column_impl(const mat<T, Size>& m, std::size_t index, const vec<T, Size>& column, std::index_sequence<Is...>) {
|
||||
return { component(m[Is], index, column[Is])... };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,8 +190,34 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> column(const mat<T, Size>& m, std::size_t index, const vec<T, Size>& v) {
|
||||
return impl::column_impl(m, index, v, std::make_index_sequence<Size>{});
|
||||
[[nodiscard]] constexpr mat<T, Size> column(const mat<T, Size>& m, std::size_t index, const vec<T, Size>& column) {
|
||||
return impl::column_impl(m, index, column, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
// real
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr T real(const qua<T>& q) {
|
||||
return q.s;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> real(qua<T> q, T real) {
|
||||
q.s = real;
|
||||
return q;
|
||||
}
|
||||
|
||||
// imag
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<T, 3> imag(const qua<T>& q) {
|
||||
return q.v;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> imag(qua<T> q, const vec<T, 3>& imag) {
|
||||
q.v = imag;
|
||||
return q;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +231,9 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 4> translate(T x, T y, T z) {
|
||||
/// REFERENCE:
|
||||
/// https://en.wikipedia.org/wiki/Translation_(geometry)
|
||||
|
||||
return {
|
||||
{1, 0, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
@@ -195,13 +242,13 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 4> translate(const vec<T, 3>& v) {
|
||||
return translate(v.x, v.y, v.z);
|
||||
[[nodiscard]] constexpr mat<T, 4> translate(const mat<T, 4>& m, T x, T y, T z) {
|
||||
return m * translate(x, y, z);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 4> translate(const mat<T, 4>& m, T x, T y, T z) {
|
||||
return m * translate(x, y, z);
|
||||
[[nodiscard]] constexpr mat<T, 4> translate(const vec<T, 3>& v) {
|
||||
return translate(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -211,8 +258,46 @@ namespace vmath_hpp
|
||||
|
||||
// rotate
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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 sx2 = qs * x2;
|
||||
const T sy2 = qs * y2;
|
||||
const T sz2 = qs * z2;
|
||||
|
||||
const T xx2 = qv.x * x2;
|
||||
const T xy2 = qv.x * y2;
|
||||
const T xz2 = qv.x * z2;
|
||||
|
||||
const T yy2 = qv.y * y2;
|
||||
const T yz2 = qv.y * z2;
|
||||
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};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/
|
||||
|
||||
const auto [s, c] = sincos(angle);
|
||||
const auto [x, y, z] = normalize(axis);
|
||||
|
||||
@@ -225,15 +310,20 @@ namespace vmath_hpp
|
||||
const T zs = z * s;
|
||||
|
||||
const T ic = T(1) - c;
|
||||
|
||||
const T xxm = xx * ic;
|
||||
const T yym = yy * ic;
|
||||
const T zzm = zz * ic;
|
||||
|
||||
const T xym = x * y * ic;
|
||||
const T xzm = x * z * ic;
|
||||
const T yzm = y * z * ic;
|
||||
|
||||
return {
|
||||
xx * ic + c, xym + zs, xzm - ys, 0,
|
||||
xym - zs, yy * ic + c, yzm + xs, 0,
|
||||
xzm + ys, yzm - xs, zz * ic + c, 0,
|
||||
0, 0, 0, 1};
|
||||
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};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -243,7 +333,11 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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,
|
||||
@@ -258,7 +352,11 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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,
|
||||
@@ -273,7 +371,11 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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,
|
||||
@@ -290,6 +392,9 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 4> scale(T x, T y, T z) {
|
||||
/// REFERENCE:
|
||||
/// https://en.wikipedia.org/wiki/Scaling_(geometry)
|
||||
|
||||
return {
|
||||
{x, 0, 0, 0},
|
||||
{0, y, 0, 0},
|
||||
@@ -298,13 +403,13 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 4> scale(const vec<T, 3>& v) {
|
||||
return scale(v.x, v.y, v.z);
|
||||
[[nodiscard]] constexpr mat<T, 4> scale(const mat<T, 4>& m, T x, T y, T z) {
|
||||
return m * scale(x, y, z);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 4> scale(const mat<T, 4>& m, T x, T y, T z) {
|
||||
return m * scale(x, y, z);
|
||||
[[nodiscard]] constexpr mat<T, 4> scale(const vec<T, 3>& v) {
|
||||
return scale(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -316,9 +421,12 @@ namespace vmath_hpp
|
||||
|
||||
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) {
|
||||
const vec<T, 3> az = normalize(at - eye);
|
||||
const vec<T, 3> ax = normalize(cross(up, az));
|
||||
const vec<T, 3> ay = cross(az, ax);
|
||||
/// REFERENCE:
|
||||
/// https://www.euclideanspace.com/maths/algebra/vectors/lookat/
|
||||
|
||||
const vec az = normalize(at - eye);
|
||||
const vec ax = normalize(cross(up, az));
|
||||
const vec ay = cross(az, ax);
|
||||
|
||||
const T dx = dot(ax, eye);
|
||||
const T dy = dot(ay, eye);
|
||||
@@ -333,9 +441,12 @@ namespace vmath_hpp
|
||||
|
||||
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) {
|
||||
const vec<T, 3> az = normalize(eye - at);
|
||||
const vec<T, 3> ax = normalize(cross(up, az));
|
||||
const vec<T, 3> ay = cross(az, ax);
|
||||
/// REFERENCE:
|
||||
/// https://www.euclideanspace.com/maths/algebra/vectors/lookat/
|
||||
|
||||
const vec az = normalize(eye - at);
|
||||
const vec ax = normalize(cross(up, az));
|
||||
const vec ay = cross(az, ax);
|
||||
|
||||
const T dx = dot(ax, eye);
|
||||
const T dy = dot(ay, eye);
|
||||
@@ -359,6 +470,9 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> translate(T x, T y) {
|
||||
/// REFERENCE:
|
||||
/// https://en.wikipedia.org/wiki/Translation_(geometry)
|
||||
|
||||
return {
|
||||
{1, 0, 0},
|
||||
{0, 1, 0},
|
||||
@@ -366,13 +480,13 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> translate(const vec<T, 2>& v) {
|
||||
return translate(v.x, v.y);
|
||||
[[nodiscard]] constexpr mat<T, 3> translate(const mat<T, 3>& m, T x, T y) {
|
||||
return m * translate(x, y);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> translate(const mat<T, 3>& m, T x, T y) {
|
||||
return m * translate(x, y);
|
||||
[[nodiscard]] constexpr mat<T, 3> translate(const vec<T, 2>& v) {
|
||||
return translate(v.x, v.y);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -384,7 +498,11 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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,
|
||||
@@ -400,6 +518,9 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> scale(T x, T y) {
|
||||
/// REFERENCE:
|
||||
/// https://en.wikipedia.org/wiki/Scaling_(geometry)
|
||||
|
||||
return {
|
||||
{x, 0, 0},
|
||||
{0, y, 0},
|
||||
@@ -407,13 +528,13 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> scale(const vec<T, 2>& v) {
|
||||
return scale(v.x, v.y);
|
||||
[[nodiscard]] constexpr mat<T, 3> scale(const mat<T, 3>& m, T x, T y) {
|
||||
return m * scale(x, y);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> scale(const mat<T, 3>& m, T x, T y) {
|
||||
return m * scale(x, y);
|
||||
[[nodiscard]] constexpr mat<T, 3> scale(const vec<T, 2>& v) {
|
||||
return scale(v.x, v.y);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -425,51 +546,60 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> shear(T x, T y) {
|
||||
/// REFERENCE:
|
||||
/// https://en.wikipedia.org/wiki/Shear_matrix
|
||||
|
||||
return {
|
||||
{1, y, 0},
|
||||
{x, 1, 0},
|
||||
{0, 0, 1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> shear(const vec<T, 2>& v) {
|
||||
return shear(v.x, v.y);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> shear(const mat<T, 3>& m, T x, T y) {
|
||||
return m * shear(x, y);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> shear(const vec<T, 2>& v) {
|
||||
return shear(v.x, v.y);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> shear(const mat<T, 3>& m, const vec<T, 2>& v) {
|
||||
return m * shear(v);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> shear_x(T y) {
|
||||
[[nodiscard]] constexpr mat<T, 3> shear_x(T x) {
|
||||
/// REFERENCE:
|
||||
/// https://en.wikipedia.org/wiki/Shear_matrix
|
||||
|
||||
return {
|
||||
{1, 0, 0},
|
||||
{y, 1, 0},
|
||||
{x, 1, 0},
|
||||
{0, 0, 1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> shear_x(const mat<T, 3>& m, T y) {
|
||||
return m * shear_x(y);
|
||||
[[nodiscard]] constexpr mat<T, 3> shear_x(const mat<T, 3>& m, T x) {
|
||||
return m * shear_x(x);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> shear_y(T x) {
|
||||
[[nodiscard]] constexpr mat<T, 3> shear_y(T y) {
|
||||
/// REFERENCE:
|
||||
/// https://en.wikipedia.org/wiki/Shear_matrix
|
||||
|
||||
return {
|
||||
{1, x, 0},
|
||||
{1, y, 0},
|
||||
{0, 1, 0},
|
||||
{0, 0, 1}};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 3> shear_y(const mat<T, 3>& m, T x) {
|
||||
return m * shear_y(x);
|
||||
[[nodiscard]] constexpr mat<T, 3> shear_y(const mat<T, 3>& m, T y) {
|
||||
return m * shear_y(y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,81 +612,91 @@ namespace vmath_hpp
|
||||
// orthographic
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> orthographic_lh_zo(T left, T right, T bottom, T top, T znear, T zfar) {
|
||||
const T sx = T(2) * rcp(right - left);
|
||||
const T sy = T(2) * rcp(top - bottom);
|
||||
const T sz = T(1) * rcp(zfar - znear);
|
||||
[[nodiscard]] mat<T, 4> orthographic_lh(T width, T height, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixortholh
|
||||
|
||||
const T tx = - (right + left) / (right - left);
|
||||
const T ty = - (top + bottom) / (top - bottom);
|
||||
const T tz = - znear / (zfar - znear);
|
||||
const T rwidth = rcp(width);
|
||||
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 sz = frange;
|
||||
const T tz = -frange * znear;
|
||||
|
||||
return {
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, 0,
|
||||
tx, ty, tz, 1};
|
||||
0, 0, tz, 1};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> orthographic_lh_no(T left, T right, T bottom, T top, T znear, T zfar) {
|
||||
const T sx = T(2) * rcp(right - left);
|
||||
const T sy = T(2) * rcp(top - bottom);
|
||||
const T sz = T(2) * rcp(zfar - znear);
|
||||
[[nodiscard]] mat<T, 4> orthographic_rh(T width, T height, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthorh
|
||||
|
||||
const T tx = - (right + left) / (right - left);
|
||||
const T ty = - (top + bottom) / (top - bottom);
|
||||
const T tz = - (zfar + znear) / (zfar - znear);
|
||||
const T rwidth = rcp(width);
|
||||
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 sz = frange;
|
||||
const T tz = frange * znear;
|
||||
|
||||
return {
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, 0,
|
||||
tx, ty, tz, 1};
|
||||
0, 0, tz, 1};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> orthographic_rh_zo(T left, T right, T bottom, T top, T znear, T zfar) {
|
||||
const T sx = T(2) * rcp(right - left);
|
||||
const T sy = T(2) * rcp(top - bottom);
|
||||
const T sz = -T(1) * rcp(zfar - znear);
|
||||
[[nodiscard]] 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
|
||||
|
||||
const T tx = - (right + left) / (right - left);
|
||||
const T ty = - (top + bottom) / (top - bottom);
|
||||
const T tz = - znear / (zfar - znear);
|
||||
const T rwidth = rcp(right - left);
|
||||
const T rheight = rcp(top - bottom);
|
||||
const T frange = rcp(zfar - znear);
|
||||
|
||||
return {
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, 0,
|
||||
tx, ty, tz, 1};
|
||||
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};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> orthographic_rh_no(T left, T right, T bottom, T top, T znear, T zfar) {
|
||||
const T sx = T(2) * rcp(right - left);
|
||||
const T sy = T(2) * rcp(top - bottom);
|
||||
const T sz = -T(2) * rcp(zfar - znear);
|
||||
[[nodiscard]] 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
|
||||
|
||||
const T tx = - (right + left) / (right - left);
|
||||
const T ty = - (top + bottom) / (top - bottom);
|
||||
const T tz = - (zfar + znear) / (zfar - znear);
|
||||
const T rwidth = rcp(right - left);
|
||||
const T rheight = rcp(top - bottom);
|
||||
const T frange = rcp(znear - zfar);
|
||||
|
||||
return {
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, 0,
|
||||
tx, ty, tz, 1};
|
||||
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};
|
||||
}
|
||||
|
||||
// perspective
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> perspective_lh_zo(T fov, T aspect, T znear, T zfar) {
|
||||
const T sy = rcp(tan(fov * T(0.5)));
|
||||
const T sx = sy / aspect;
|
||||
const T sz = zfar / (zfar - znear);
|
||||
const T tz = (znear * zfar) / (znear - zfar);
|
||||
[[nodiscard]] 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 sz = zfar * rcp(zfar - znear);
|
||||
const T tz = (znear * zfar) * rcp(znear - zfar);
|
||||
|
||||
return {
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
@@ -565,25 +705,16 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> perspective_lh_no(T fov, T aspect, T znear, T zfar) {
|
||||
const T sy = rcp(tan(fov * T(0.5)));
|
||||
const T sx = sy / aspect;
|
||||
const T sz = (zfar + znear) / (zfar - znear);
|
||||
const T tz = (T(2) * znear * zfar) / (znear - zfar);
|
||||
return {
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, 1,
|
||||
0, 0, tz, 0};
|
||||
}
|
||||
[[nodiscard]] mat<T, 4> perspective_rh(T width, T height, T znear, T zfar) {
|
||||
/// REFERENCE:
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectiverh
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> perspective_rh_zo(T fov, T aspect, T znear, T zfar) {
|
||||
const T sy = rcp(tan(fov * T(0.5)));
|
||||
const T sx = sy / aspect;
|
||||
const T sz = zfar / (znear - zfar);
|
||||
const T tz = (znear * zfar) / (znear - zfar);
|
||||
return {
|
||||
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,
|
||||
@@ -591,11 +722,65 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] mat<T, 4> perspective_rh_no(T fov, T aspect, T znear, T zfar) {
|
||||
const T sy = rcp(tan(fov * T(0.5)));
|
||||
const T sx = sy / aspect;
|
||||
const T sz = (zfar + znear) / (znear - zfar);
|
||||
const T tz = (T(2) * znear * zfar) / (znear - zfar);
|
||||
[[nodiscard]] 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 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};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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 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};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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 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};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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 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,
|
||||
@@ -614,7 +799,8 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] T angle(const vec<T, Size>& x, const vec<T, Size>& y) {
|
||||
return acos(dot(x, y) * rsqrt(length2(x) * length2(y)));
|
||||
const T rs = rsqrt(length2(x) * length2(y));
|
||||
return acos(clamp(dot(x, y) * rs, T(-1), T(1)));
|
||||
}
|
||||
|
||||
// rotate
|
||||
@@ -628,19 +814,188 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] vec<T, 3> rotate(const vec<T, 3>& v, T angle, const vec<T, 3>& normal) {
|
||||
return v * mat<T, 3>(rotate(angle, normal));
|
||||
[[nodiscard]] 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, 4> rotate(const vec<T, 4>& v, T angle, const vec<T, 3>& normal) {
|
||||
return v * rotate(angle, normal);
|
||||
[[nodiscard]] 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) {
|
||||
return v * qrotate(angle, unit3_z<T>);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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) {
|
||||
return v * qrotate(angle, axis);
|
||||
}
|
||||
|
||||
// project
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> project(const vec<T, Size>& v, const vec<T, Size>& normal) {
|
||||
return dot(v, normal) / length2(normal) * normal;
|
||||
[[nodiscard]] constexpr vec<T, Size> project(const vec<T, Size>& v, const vec<T, Size>& normal) {
|
||||
return dot(v, normal) * rcp(length2(normal)) * normal;
|
||||
}
|
||||
|
||||
// perpendicular
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> perpendicular(const vec<T, Size>& v, const vec<T, Size>& normal) {
|
||||
return v - project(v, normal);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Quaternion Transform
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
// qrotate
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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]}));
|
||||
|
||||
return qua(copysign(xyzw, {
|
||||
m[1][2] - m[2][1],
|
||||
m[2][0] - m[0][2],
|
||||
m[0][1] - m[1][0],
|
||||
T(1)}));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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) {
|
||||
/// 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)});
|
||||
}
|
||||
|
||||
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) {
|
||||
return q * qrotate(from, to);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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 [x, y, z] = normalize(axis);
|
||||
|
||||
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) {
|
||||
return q * qrotate(angle, axis);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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));
|
||||
|
||||
return {s, T(0), T(0), c};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/
|
||||
|
||||
const auto [s, c] = sincos(angle * T(0.5));
|
||||
|
||||
return {T(0), s, T(0), c};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/
|
||||
|
||||
const auto [s, c] = sincos(angle * T(0.5));
|
||||
|
||||
return {T(0), T(0), s, c};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] 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) {
|
||||
/// REFERENCE:
|
||||
/// https://www.euclideanspace.com/maths/algebra/vectors/lookat/
|
||||
|
||||
const vec az = normalize(dir);
|
||||
const vec ax = normalize(cross(up, az));
|
||||
const vec ay = cross(az, ax);
|
||||
|
||||
return qrotate(mat{
|
||||
ax.x, ay.x, az.x,
|
||||
ax.y, ay.y, az.y,
|
||||
ax.z, ay.z, az.z});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> qlook_at_rh(const vec<T, 3>& dir, const vec<T, 3>& up) {
|
||||
/// REFERENCE:
|
||||
/// https://www.euclideanspace.com/maths/algebra/vectors/lookat/
|
||||
|
||||
const vec az = normalize(-dir);
|
||||
const vec ax = normalize(cross(up, az));
|
||||
const vec ay = cross(az, ax);
|
||||
|
||||
return qrotate(mat{
|
||||
ax.x, ay.x, az.x,
|
||||
ax.y, ay.y, az.y,
|
||||
ax.z, ay.z, az.z});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_signed_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 {
|
||||
@@ -21,9 +27,9 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_signed_v<T>, T>
|
||||
constexpr abs(T x) noexcept {
|
||||
return x >= T(0) ? x : -x;
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, T>
|
||||
constexpr sqr(T x) noexcept {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -80,34 +86,24 @@ namespace vmath_hpp
|
||||
return std::modf(x, y);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
copysign(T x, T s) noexcept {
|
||||
return std::copysign(x, s);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, T>
|
||||
constexpr min(T x, T y) noexcept {
|
||||
return x < y ? x : y;
|
||||
}
|
||||
|
||||
template < typename T, typename... Ts >
|
||||
[[nodiscard]] std::enable_if_t<
|
||||
std::is_arithmetic_v<T>,
|
||||
std::common_type_t<T, Ts...>>
|
||||
constexpr min(T x, T y, Ts... ts) noexcept {
|
||||
return min(min(x, y), ts...);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, T>
|
||||
constexpr max(T x, T y) noexcept {
|
||||
return x < y ? y : x;
|
||||
}
|
||||
|
||||
template < typename T, typename... Ts >
|
||||
[[nodiscard]] std::enable_if_t<
|
||||
std::is_arithmetic_v<T>,
|
||||
std::common_type_t<T, Ts...>>
|
||||
constexpr max(T x, T y, Ts... ts) noexcept {
|
||||
return max(max(x, y), ts...);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, T>
|
||||
constexpr clamp(T x, T min_x, T max_x) noexcept {
|
||||
@@ -126,6 +122,12 @@ namespace vmath_hpp
|
||||
return x * (T(1) - a) + y * a;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
constexpr lerp(T x, T y, T x_a, T y_a) noexcept {
|
||||
return x * x_a + y * y_a;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, T>
|
||||
constexpr step(T edge, T x) noexcept {
|
||||
@@ -135,7 +137,7 @@ namespace vmath_hpp
|
||||
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) / (edge1 - edge0), T(0), T(1));
|
||||
const T t = clamp((x - edge0) * rcp(edge1 - edge0), T(0), T(1));
|
||||
return t * t * (T(3) - T(2) * t);
|
||||
}
|
||||
|
||||
@@ -177,7 +179,7 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
//
|
||||
// Angle and Trigonometry Functions
|
||||
// Angle and Trigonometric Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
@@ -275,11 +277,11 @@ namespace vmath_hpp
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, std::pair<T, T>>
|
||||
sincos(T x) noexcept {
|
||||
return {sin(x), cos(x)};
|
||||
return { sin(x), cos(x) };
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::enable_if_t<std::is_floating_point_v<T>, void>
|
||||
std::enable_if_t<std::is_floating_point_v<T>, void>
|
||||
sincos(T x, T* s, T* c) noexcept {
|
||||
*s = sin(x);
|
||||
*c = cos(x);
|
||||
@@ -374,7 +376,7 @@ 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(dot(x, x));
|
||||
return x * rsqrt(length2(x));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -420,9 +422,10 @@ namespace vmath_hpp
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
|
||||
constexpr approx(T x, T y) noexcept {
|
||||
if constexpr ( std::is_floating_point_v<T> ) {
|
||||
// http://www.realtimecollisiondetection.net/pubs/Tolerances
|
||||
/// REFERENCE:
|
||||
/// http://www.realtimecollisiondetection.net/pubs/Tolerances
|
||||
const T epsilon = std::numeric_limits<T>::epsilon();
|
||||
return abs(x - y) <= epsilon * max(T(1), abs(x), abs(y));
|
||||
return abs(x - y) <= epsilon * max(max(T(1), abs(x)), abs(y));
|
||||
} else {
|
||||
return x == y;
|
||||
}
|
||||
@@ -432,8 +435,9 @@ namespace vmath_hpp
|
||||
[[nodiscard]] std::enable_if_t<std::is_arithmetic_v<T>, bool>
|
||||
constexpr approx(T x, T y, T epsilon) noexcept {
|
||||
if constexpr ( std::is_floating_point_v<T> ) {
|
||||
// http://www.realtimecollisiondetection.net/pubs/Tolerances
|
||||
return abs(x - y) <= epsilon * max(T(1), abs(x), abs(y));
|
||||
/// REFERENCE:
|
||||
/// http://www.realtimecollisiondetection.net/pubs/Tolerances
|
||||
return abs(x - y) <= epsilon * max(max(T(1), abs(x)), abs(y));
|
||||
} else {
|
||||
return abs(x - y) <= epsilon;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
@@ -24,6 +25,19 @@
|
||||
# define VMATH_HPP_FORCE_INLINE inline
|
||||
#endif
|
||||
|
||||
#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND)
|
||||
# define VMATH_HPP_NO_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
#ifdef VMATH_HPP_NO_EXCEPTIONS
|
||||
# define VMATH_HPP_THROW(...) std::abort()
|
||||
#else
|
||||
# define VMATH_HPP_THROW(...) throw __VA_ARGS__
|
||||
#endif
|
||||
|
||||
#define VMATH_HPP_THROW_IF(pred, ...)\
|
||||
( (pred) ? VMATH_HPP_THROW(__VA_ARGS__) : (void)0 )
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T, std::size_t Size >
|
||||
@@ -49,13 +63,13 @@ namespace vmath_hpp
|
||||
using double3 = vec<double, 3>;
|
||||
using double4 = vec<double, 4>;
|
||||
|
||||
using size2 = vec<std::size_t, 2>;
|
||||
using size3 = vec<std::size_t, 3>;
|
||||
using size4 = vec<std::size_t, 4>;
|
||||
using size2_t = vec<std::size_t, 2>;
|
||||
using size3_t = vec<std::size_t, 3>;
|
||||
using size4_t = vec<std::size_t, 4>;
|
||||
|
||||
using ptrdiff2 = vec<std::ptrdiff_t, 2>;
|
||||
using ptrdiff3 = vec<std::ptrdiff_t, 3>;
|
||||
using ptrdiff4 = vec<std::ptrdiff_t, 4>;
|
||||
using ptrdiff2_t = vec<std::ptrdiff_t, 2>;
|
||||
using ptrdiff3_t = vec<std::ptrdiff_t, 3>;
|
||||
using ptrdiff4_t = vec<std::ptrdiff_t, 4>;
|
||||
}
|
||||
|
||||
namespace vmath_hpp
|
||||
@@ -83,11 +97,20 @@ namespace vmath_hpp
|
||||
using double3x3 = mat<double, 3>;
|
||||
using double4x4 = mat<double, 4>;
|
||||
|
||||
using size2x2 = mat<std::size_t, 2>;
|
||||
using size3x3 = mat<std::size_t, 3>;
|
||||
using size4x4 = mat<std::size_t, 4>;
|
||||
using size2x2_t = mat<std::size_t, 2>;
|
||||
using size3x3_t = mat<std::size_t, 3>;
|
||||
using size4x4_t = mat<std::size_t, 4>;
|
||||
|
||||
using ptrdiff2x2 = mat<std::ptrdiff_t, 2>;
|
||||
using ptrdiff3x3 = mat<std::ptrdiff_t, 3>;
|
||||
using ptrdiff4x4 = mat<std::ptrdiff_t, 4>;
|
||||
using ptrdiff2x2_t = mat<std::ptrdiff_t, 2>;
|
||||
using ptrdiff3x3_t = mat<std::ptrdiff_t, 3>;
|
||||
using ptrdiff4x4_t = mat<std::ptrdiff_t, 4>;
|
||||
}
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T >
|
||||
class qua;
|
||||
|
||||
using qfloat = qua<float>;
|
||||
using qdouble = qua<double>;
|
||||
}
|
||||
|
||||
@@ -262,16 +262,12 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr reference at(std::size_t index) {
|
||||
if ( index >= Size ) {
|
||||
throw std::out_of_range("mat::at");
|
||||
}
|
||||
VMATH_HPP_THROW_IF(index >= size, std::out_of_range("mat::at"));
|
||||
return rows[index];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const_reference at(std::size_t index) const {
|
||||
if ( index >= Size ) {
|
||||
throw std::out_of_range("mat::at");
|
||||
}
|
||||
VMATH_HPP_THROW_IF(index >= size, std::out_of_range("mat::at"));
|
||||
return rows[index];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -192,6 +192,13 @@ namespace vmath_hpp::detail
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
// +operator
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator+(const mat<T, Size>& xs) {
|
||||
return xs;
|
||||
}
|
||||
|
||||
// -operator
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
@@ -494,149 +501,51 @@ namespace vmath_hpp
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
// any
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr bool any(const mat<T, Size>& xs) {
|
||||
return fold_join([](bool acc, const vec<T, Size>& x){ return acc || any(x); }, false, xs);
|
||||
}
|
||||
|
||||
// all
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr bool all(const mat<T, Size>& xs) {
|
||||
return fold_join([](bool acc, const vec<T, Size>& x){ return acc && all(x); }, true, xs);
|
||||
}
|
||||
|
||||
// approx
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> approx(const mat<T, Size>& xs, T y) {
|
||||
return map_join([y](const vec<T, Size>& x){ return approx(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> approx(T x, const mat<T, Size>& ys) {
|
||||
return map_join([x](const vec<T, Size>& y){ return approx(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> approx(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return approx(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> approx(const mat<T, Size>& xs, T y, T epsilon) {
|
||||
return map_join([y, epsilon](const vec<T, Size>& x){ return approx(x, y, epsilon); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> approx(T x, const mat<T, Size>& ys, T epsilon) {
|
||||
return map_join([x, epsilon](const vec<T, Size>& y){ return approx(x, y, epsilon); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> approx(const mat<T, Size>& xs, const mat<T, Size>& ys, T epsilon) {
|
||||
return map_join([epsilon](const vec<T, Size>& x, const vec<T, Size>& y){ return approx(x, y, epsilon); }, xs, ys);
|
||||
}
|
||||
|
||||
// less
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> less(const mat<T, Size>& xs, T y) {
|
||||
return map_join([y](const vec<T, Size>& x){ return less(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> less(T x, const mat<T, Size>& ys) {
|
||||
return map_join([x](const vec<T, Size>& y){ return less(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> less(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return less(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
// less_equal
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> less_equal(const mat<T, Size>& xs, T y) {
|
||||
return map_join([y](const vec<T, Size>& x){ return less_equal(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> less_equal(T x, const mat<T, Size>& ys) {
|
||||
return map_join([x](const vec<T, Size>& y){ return less_equal(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> less_equal(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return less_equal(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
// greater
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> greater(const mat<T, Size>& xs, T y) {
|
||||
return map_join([y](const vec<T, Size>& x){ return greater(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> greater(T x, const mat<T, Size>& ys) {
|
||||
return map_join([x](const vec<T, Size>& y){ return greater(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> greater(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return greater(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
// greater_equal
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> greater_equal(const mat<T, Size>& xs, T y) {
|
||||
return map_join([y](const vec<T, Size>& x){ return greater_equal(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> greater_equal(T x, const mat<T, Size>& ys) {
|
||||
return map_join([x](const vec<T, Size>& y){ return greater_equal(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> greater_equal(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return greater_equal(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
// equal_to
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> equal_to(const mat<T, Size>& xs, T y) {
|
||||
return map_join([y](const vec<T, Size>& x){ return equal_to(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> equal_to(T x, const mat<T, Size>& ys) {
|
||||
return map_join([x](const vec<T, Size>& y){ return equal_to(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> equal_to(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return equal_to(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
// not_equal_to
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> not_equal_to(const mat<T, Size>& xs, T y) {
|
||||
return map_join([y](const vec<T, Size>& x){ return not_equal_to(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> not_equal_to(T x, const mat<T, Size>& ys) {
|
||||
return map_join([x](const vec<T, Size>& y){ return not_equal_to(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<bool, Size> not_equal_to(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return not_equal_to(x, y); }, xs, ys);
|
||||
@@ -723,6 +632,9 @@ namespace vmath_hpp
|
||||
T a, T b,
|
||||
T c, T d)
|
||||
{
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/twoD/
|
||||
|
||||
return
|
||||
+ a * d
|
||||
- b * c;
|
||||
@@ -735,6 +647,9 @@ namespace vmath_hpp
|
||||
T d, T e, T f,
|
||||
T g, T h, T i)
|
||||
{
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/threeD/
|
||||
|
||||
return
|
||||
+ a * determinant_2x2_impl(e, f, h, i)
|
||||
- b * determinant_2x2_impl(d, f, g, i)
|
||||
@@ -750,6 +665,9 @@ namespace vmath_hpp
|
||||
T i, T j, T k, T l,
|
||||
T m, T n, T o, T p)
|
||||
{
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/fourD/
|
||||
|
||||
return
|
||||
+ a * determinant_3x3_impl(f, g, h, j, k, l, n, o, p)
|
||||
- b * determinant_3x3_impl(e, g, h, i, k, l, m, o, p)
|
||||
@@ -790,13 +708,16 @@ namespace vmath_hpp
|
||||
T a, T b,
|
||||
T c, T d)
|
||||
{
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/twoD/
|
||||
|
||||
const T inv_det = rcp(determinant_2x2_impl(
|
||||
a, b,
|
||||
c, d));
|
||||
|
||||
const mat<T, 2> inv_m(
|
||||
const mat inv_m{
|
||||
d, -b,
|
||||
-c, a);
|
||||
-c, a};
|
||||
|
||||
return inv_m * inv_det;
|
||||
}
|
||||
@@ -808,12 +729,15 @@ namespace vmath_hpp
|
||||
T d, T e, T f,
|
||||
T g, T h, T i)
|
||||
{
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/threeD/
|
||||
|
||||
const T inv_det = rcp(determinant_3x3_impl(
|
||||
a, b, c,
|
||||
d, e, f,
|
||||
g, h, i));
|
||||
|
||||
const mat<T, 3> inv_m(
|
||||
const mat inv_m{
|
||||
e * i - f * h,
|
||||
c * h - b * i,
|
||||
b * f - c * e,
|
||||
@@ -822,7 +746,7 @@ namespace vmath_hpp
|
||||
c * d - a * f,
|
||||
d * h - e * g,
|
||||
b * g - a * h,
|
||||
a * e - b * d);
|
||||
a * e - b * d};
|
||||
|
||||
return inv_m * inv_det;
|
||||
}
|
||||
@@ -835,13 +759,16 @@ namespace vmath_hpp
|
||||
T i, T j, T k, T l,
|
||||
T m, T n, T o, T p)
|
||||
{
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/
|
||||
|
||||
const T inv_det = rcp(determinant_4x4_impl(
|
||||
a, b, c, d,
|
||||
e, f, g, h,
|
||||
i, j, k, l,
|
||||
m, n, o, p));
|
||||
|
||||
const mat<T, 4> inv_m(
|
||||
const mat inv_m{
|
||||
(f * (k * p - l * o) + g * (l * n - j * p) + h * (j * o - k * n)),
|
||||
(j * (c * p - d * o) + k * (d * n - b * p) + l * (b * o - c * n)),
|
||||
(n * (c * h - d * g) + o * (d * f - b * h) + p * (b * g - c * f)),
|
||||
@@ -857,7 +784,7 @@ namespace vmath_hpp
|
||||
(e * (k * n - j * o) + f * (i * o - k * m) + g * (j * m - i * n)),
|
||||
(i * (c * n - b * o) + j * (a * o - c * m) + k * (b * m - a * n)),
|
||||
(m * (c * f - b * g) + n * (a * g - c * e) + o * (b * e - a * f)),
|
||||
(a * (f * k - g * j) + b * (g * i - e * k) + c * (e * j - f * i)));
|
||||
(a * (f * k - g * j) + b * (g * i - e * k) + c * (e * j - f * i))};
|
||||
|
||||
return inv_m * inv_det;
|
||||
}
|
||||
|
||||
147
headers/vmath.hpp/vmath_qua.hpp
Normal file
147
headers/vmath.hpp/vmath_qua.hpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/*******************************************************************************
|
||||
* 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)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vmath_fwd.hpp"
|
||||
|
||||
#include "vmath_vec.hpp"
|
||||
#include "vmath_vec_fun.hpp"
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T >
|
||||
class qua final {
|
||||
public:
|
||||
vec<T, 3> v{0};
|
||||
T s{1};
|
||||
public:
|
||||
using self_type = qua;
|
||||
using component_type = T;
|
||||
|
||||
using pointer = component_type*;
|
||||
using const_pointer = const component_type*;
|
||||
|
||||
using reference = component_type&;
|
||||
using const_reference = const component_type&;
|
||||
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
static constexpr std::size_t size = 4;
|
||||
public:
|
||||
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;
|
||||
swap((*this)[i], other[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] iterator begin() noexcept { return iterator(data()); }
|
||||
[[nodiscard]] const_iterator begin() const noexcept { return const_iterator(data()); }
|
||||
[[nodiscard]] iterator end() noexcept { return iterator(data() + size); }
|
||||
[[nodiscard]] const_iterator end() const noexcept { return const_iterator(data() + size); }
|
||||
|
||||
[[nodiscard]] reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
|
||||
[[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
|
||||
[[nodiscard]] reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
|
||||
[[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
|
||||
|
||||
[[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
|
||||
[[nodiscard]] const_iterator cend() const noexcept { return end(); }
|
||||
[[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); }
|
||||
[[nodiscard]] const_reverse_iterator crend() const noexcept { return rend(); }
|
||||
|
||||
[[nodiscard]] pointer data() noexcept {
|
||||
return &(*this)[0];
|
||||
}
|
||||
|
||||
[[nodiscard]] const_pointer data() const noexcept {
|
||||
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];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const_reference at(std::size_t index) const {
|
||||
VMATH_HPP_THROW_IF(index >= size, std::out_of_range("qua::at"));
|
||||
return (*this)[index];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
// vec
|
||||
|
||||
template < typename T >
|
||||
vec(const qua<T>&) -> vec<T, 4>;
|
||||
|
||||
// qua
|
||||
|
||||
template < typename T >
|
||||
qua(T, T, T, T) -> qua<T>;
|
||||
|
||||
template < typename T >
|
||||
qua(const vec<T, 3>&, T) -> qua<T>;
|
||||
|
||||
template < typename T >
|
||||
qua(const vec<T, 4>&) -> qua<T>;
|
||||
|
||||
template < typename T >
|
||||
qua(std::initializer_list<T>) -> qua<T>;
|
||||
|
||||
// swap
|
||||
|
||||
template < typename T >
|
||||
void swap(qua<T>& l, qua<T>& r) noexcept(noexcept(l.swap(r))) {
|
||||
l.swap(r);
|
||||
}
|
||||
}
|
||||
315
headers/vmath.hpp/vmath_qua_fun.hpp
Normal file
315
headers/vmath.hpp/vmath_qua_fun.hpp
Normal file
@@ -0,0 +1,315 @@
|
||||
/*******************************************************************************
|
||||
* 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)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vmath_fwd.hpp"
|
||||
|
||||
#include "vmath_fun.hpp"
|
||||
#include "vmath_qua.hpp"
|
||||
|
||||
#include "vmath_vec.hpp"
|
||||
#include "vmath_vec_fun.hpp"
|
||||
|
||||
//
|
||||
// Operators
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
// +operator
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> operator+(const qua<T>& xs) {
|
||||
return xs;
|
||||
}
|
||||
|
||||
// -operator
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> 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) {
|
||||
return qua(vec{xs} + vec{ys});
|
||||
}
|
||||
|
||||
// operator+=
|
||||
|
||||
template < typename T >
|
||||
constexpr qua<T>& operator+=(qua<T>& xs, const qua<T>& ys) {
|
||||
return (xs = (xs + ys));
|
||||
}
|
||||
|
||||
// operator-
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> operator-(const qua<T>& xs, const qua<T>& ys) {
|
||||
return qua(vec{xs} - vec{ys});
|
||||
}
|
||||
|
||||
// operator-=
|
||||
|
||||
template < typename T >
|
||||
constexpr qua<T>& operator-=(qua<T>& xs, const qua<T>& ys) {
|
||||
return (xs = (xs - ys));
|
||||
}
|
||||
|
||||
// operator*
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> 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) {
|
||||
return qua(x * vec{ys});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<T, 3> 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);
|
||||
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) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/arithmetic/
|
||||
|
||||
return {
|
||||
cross(ys.v, xs.v) + ys.s * xs.v + xs.s * ys.v,
|
||||
ys.s * xs.s - dot(ys.v, xs.v)};
|
||||
}
|
||||
|
||||
// operator*=
|
||||
|
||||
template < typename T >
|
||||
constexpr qua<T>& operator*=(qua<T>& xs, T y) {
|
||||
return (xs = (xs * y));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
constexpr vec<T, 3>& operator*=(vec<T, 3>& xs, const qua<T>& ys) {
|
||||
return (xs = (xs * ys));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
constexpr qua<T>& operator*=(qua<T>& xs, const qua<T>& ys) {
|
||||
return (xs = (xs * ys));
|
||||
}
|
||||
|
||||
// operator/
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> 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) {
|
||||
return qua(x / vec{ys});
|
||||
}
|
||||
|
||||
// operator/=
|
||||
|
||||
template < typename T >
|
||||
constexpr qua<T>& operator/=(qua<T>& xs, T y) {
|
||||
return (xs = (xs / y));
|
||||
}
|
||||
|
||||
// operator==
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr bool operator==(const qua<T>& xs, const qua<T>& ys) {
|
||||
return vec{xs} == vec{ys};
|
||||
}
|
||||
|
||||
// operator!=
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr bool operator!=(const qua<T>& xs, const qua<T>& ys) {
|
||||
return vec{xs} != vec{ys};
|
||||
}
|
||||
|
||||
// operator<
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr bool operator<(const qua<T>& xs, const qua<T>& ys) {
|
||||
return vec{xs} < vec{ys};
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Common Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T >
|
||||
[[nodiscard]] 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));
|
||||
}
|
||||
|
||||
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;
|
||||
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) {
|
||||
/// REFERENCE:
|
||||
/// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
|
||||
|
||||
const T raw_cos_theta = dot(unit_xs, unit_ys);
|
||||
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) ) {
|
||||
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 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 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});
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Geometric Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr T dot(const qua<T>& xs, const qua<T>& ys) {
|
||||
return dot(vec{xs}, vec{ys});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] T length(const qua<T>& xs) {
|
||||
return length(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));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] qua<T> normalize(const qua<T>& xs) {
|
||||
return qua(normalize(vec{xs}));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Relational Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<bool, 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) {
|
||||
return approx(vec{xs}, vec{ys}, epsilon);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<bool, 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) {
|
||||
return less_equal(vec{xs}, vec{ys});
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<bool, 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) {
|
||||
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) {
|
||||
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) {
|
||||
return not_equal_to(vec{xs}, vec{ys});
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Quaternion Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
// conjugate
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> conjugate(const qua<T>& q) {
|
||||
return {-q.v, q.s};
|
||||
}
|
||||
|
||||
// inverse
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr qua<T> inverse(const qua<T>& q) {
|
||||
return conjugate(q) * rcp(length2(q));
|
||||
}
|
||||
}
|
||||
@@ -204,16 +204,12 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr reference at(std::size_t index) {
|
||||
if ( index >= Size ) {
|
||||
throw std::out_of_range("vec::at");
|
||||
}
|
||||
VMATH_HPP_THROW_IF(index >= size, std::out_of_range("vec::at"));
|
||||
return (*this)[index];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const_reference at(std::size_t index) const {
|
||||
if ( index >= Size ) {
|
||||
throw std::out_of_range("vec::at");
|
||||
}
|
||||
VMATH_HPP_THROW_IF(index >= size, std::out_of_range("vec::at"));
|
||||
return (*this)[index];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -55,6 +55,24 @@ namespace vmath_hpp::detail::impl
|
||||
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(
|
||||
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>
|
||||
{
|
||||
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(
|
||||
@@ -125,6 +143,19 @@ namespace vmath_hpp::detail
|
||||
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>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join(
|
||||
@@ -165,6 +196,13 @@ namespace vmath_hpp::detail
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
// +operator
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator+(const vec<T, Size>& xs) {
|
||||
return xs;
|
||||
}
|
||||
|
||||
// -operator
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
@@ -458,7 +496,236 @@ namespace vmath_hpp
|
||||
}
|
||||
|
||||
//
|
||||
// Angle and Trigonometry Functions
|
||||
// Common Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> abs(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return abs(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> sqr(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return sqr(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> sign(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return sign(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> rcp(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return rcp(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] 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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
return map_join([](T x, T s) { return copysign(x, s); }, xs, ss);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr T min(const vec<T, Size>& xs) {
|
||||
return fold1_join([](T acc, T x){ return min(acc, x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> min(const vec<T, Size>& xs, T y) {
|
||||
return map_join([y](T x) { return min(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> min(T x, const vec<T, Size>& ys) {
|
||||
return map_join([x](T y) { return min(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> min(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y) { return min(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr T max(const vec<T, Size>& xs) {
|
||||
return fold1_join([](T acc, T x){ return max(acc, x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> max(const vec<T, Size>& xs, T y) {
|
||||
return map_join([y](T x) { return max(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> max(T x, const vec<T, Size>& ys) {
|
||||
return map_join([x](T y) { return max(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> max(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y) { return max(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> clamp(const vec<T, Size>& xs, T min_x, T max_x) {
|
||||
return map_join([min_x, max_x](T x) { return clamp(x, min_x, max_x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> clamp(const vec<T, Size>& xs, const vec<T, Size>& min_xs, const vec<T, Size>& max_xs) {
|
||||
return map_join([](T x, T min_x, T max_x) { return clamp(x, min_x, max_x); }, xs, min_xs, max_xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> saturate(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return saturate(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> lerp(const vec<T, Size>& xs, const vec<T, Size>& ys, T a) {
|
||||
return map_join([a](T x, T y) { return lerp(x, y, a); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> lerp(const vec<T, Size>& xs, const vec<T, Size>& ys, T x_a, T y_a) {
|
||||
return map_join([x_a, y_a](T x, T y) { return lerp(x, y, x_a, y_a); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> lerp(
|
||||
const vec<T, Size>& xs,
|
||||
const vec<T, Size>& ys,
|
||||
const vec<T, Size>& as)
|
||||
{
|
||||
return map_join([](T x, T y, T a) { return lerp(x, y, a); }, xs, ys, as);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> lerp(
|
||||
const vec<T, Size>& xs,
|
||||
const vec<T, Size>& ys,
|
||||
const vec<T, Size>& xs_a,
|
||||
const vec<T, Size>& ys_a)
|
||||
{
|
||||
return map_join([](T x, T y, T x_a, T y_a) { return lerp(x, y, x_a, y_a); }, xs, ys, xs_a, ys_a);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> step(T edge, const vec<T, Size>& xs) {
|
||||
return map_join([edge](T x) { return step(edge, x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> step(const vec<T, Size>& edges, const vec<T, Size>& xs) {
|
||||
return map_join([](T edge, T x) { return step(edge, x); }, edges, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> smoothstep(T edge0, T edge1, const vec<T, Size>& xs) {
|
||||
return map_join([edge0, edge1](T x) { return smoothstep(edge0, edge1, x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[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);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Angle and Trigonometric Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
@@ -538,10 +805,15 @@ namespace vmath_hpp
|
||||
return map_join([](T x) { return atanh(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, size_t Size >
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] 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) {
|
||||
*ss = map_join([](T x){ return sin(x); }, xs);
|
||||
*cs = map_join([](T x){ return cos(x); }, xs);
|
||||
*ss = sin(xs);
|
||||
*cs = cos(xs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -587,191 +859,6 @@ namespace vmath_hpp
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Common Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> abs(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return abs(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> sign(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return sign(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> rcp(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return rcp(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] 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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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
|
||||
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) {
|
||||
return impl::modf_impl(xs, is, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr T min(const vec<T, Size>& xs) {
|
||||
return fold1_join([](T acc, T x){ return min(acc, x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> min(const vec<T, Size>& xs, T y) {
|
||||
return map_join([y](T x) { return min(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> min(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y) { return min(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr T max(const vec<T, Size>& xs) {
|
||||
return fold1_join([](T acc, T x){ return max(acc, x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> max(const vec<T, Size>& xs, T y) {
|
||||
return map_join([y](T x) { return max(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> max(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y) { return max(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> clamp(const vec<T, Size>& xs, T min_x, T max_x) {
|
||||
return map_join([min_x, max_x](T x) { return clamp(x, min_x, max_x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> clamp(const vec<T, Size>& xs, const vec<T, Size>& min_xs, const vec<T, Size>& max_xs) {
|
||||
return map_join([](T x, T min_x, T max_x) { return clamp(x, min_x, max_x); }, xs, min_xs, max_xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> saturate(const vec<T, Size>& xs) {
|
||||
return map_join([](T x) { return saturate(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> lerp(const vec<T, Size>& xs, const vec<T, Size>& ys, T a) {
|
||||
return map_join([a](T x, T y) { return lerp(x, y, a); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> lerp(const vec<T, Size>& xs, const vec<T, Size>& ys, const vec<T, Size>& as) {
|
||||
return map_join([](T x, T y, T a) { return lerp(x, y, a); }, xs, ys, as);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> step(T edge, const vec<T, Size>& xs) {
|
||||
return map_join([edge](T x) { return step(edge, x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> step(const vec<T, Size>& edges, const vec<T, Size>& xs) {
|
||||
return map_join([](T edge, T x) { return step(edge, x); }, edges, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> smoothstep(T edge0, T edge1, const vec<T, Size>& xs) {
|
||||
return map_join([edge0, edge1](T x) { return smoothstep(edge0, edge1, x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[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);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Geometric Functions
|
||||
//
|
||||
@@ -820,7 +907,7 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> normalize(const vec<T, Size>& xs) {
|
||||
return xs * rsqrt(dot(xs, xs));
|
||||
return xs * rsqrt(length2(xs));
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
@@ -847,149 +934,51 @@ namespace vmath_hpp
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
// any
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr bool any(const vec<T, Size>& xs) {
|
||||
return fold_join([](bool acc, T x){ return acc || any(x); }, false, xs);
|
||||
}
|
||||
|
||||
// all
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr bool all(const vec<T, Size>& xs) {
|
||||
return fold_join([](bool acc, T x){ return acc && all(x); }, true, xs);
|
||||
}
|
||||
|
||||
// approx
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> approx(const vec<T, Size>& xs, T y) {
|
||||
return map_join([y](T x){ return approx(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> approx(T x, const vec<T, Size>& ys) {
|
||||
return map_join([x](T y){ return approx(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> approx(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return approx(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> approx(const vec<T, Size>& xs, T y, T epsilon) {
|
||||
return map_join([y, epsilon](T x){ return approx(x, y, epsilon); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> approx(T x, const vec<T, Size>& ys, T epsilon) {
|
||||
return map_join([x, epsilon](T y){ return approx(x, y, epsilon); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> approx(const vec<T, Size>& xs, const vec<T, Size>& ys, T epsilon) {
|
||||
return map_join([epsilon](T x, T y){ return approx(x, y, epsilon); }, xs, ys);
|
||||
}
|
||||
|
||||
// less
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> less(const vec<T, Size>& xs, T y) {
|
||||
return map_join([y](T x){ return less(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> less(T x, const vec<T, Size>& ys) {
|
||||
return map_join([x](T y){ return less(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> less(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return less(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
// less_equal
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> less_equal(const vec<T, Size>& xs, T y) {
|
||||
return map_join([y](T x){ return less_equal(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> less_equal(T x, const vec<T, Size>& ys) {
|
||||
return map_join([x](T y){ return less_equal(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> less_equal(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return less_equal(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
// greater
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> greater(const vec<T, Size>& xs, T y) {
|
||||
return map_join([y](T x){ return greater(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> greater(T x, const vec<T, Size>& ys) {
|
||||
return map_join([x](T y){ return greater(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> greater(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return greater(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
// greater_equal
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> greater_equal(const vec<T, Size>& xs, T y) {
|
||||
return map_join([y](T x){ return greater_equal(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> greater_equal(T x, const vec<T, Size>& ys) {
|
||||
return map_join([x](T y){ return greater_equal(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> greater_equal(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return greater_equal(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
// equal_to
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> equal_to(const vec<T, Size>& xs, T y) {
|
||||
return map_join([y](T x){ return equal_to(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> equal_to(T x, const vec<T, Size>& ys) {
|
||||
return map_join([x](T y){ return equal_to(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return equal_to(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
// not_equal_to
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> not_equal_to(const vec<T, Size>& xs, T y) {
|
||||
return map_join([y](T x){ return not_equal_to(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> not_equal_to(T x, const vec<T, Size>& ys) {
|
||||
return map_join([x](T y){ return not_equal_to(x, y); }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> not_equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return map_join([](T x, T y){ return not_equal_to(x, y); }, xs, ys);
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
#include "doctest.h"
|
||||
|
||||
#define STATIC_REQUIRE(...)\
|
||||
#define STATIC_CHECK(...)\
|
||||
static_assert(__VA_ARGS__, #__VA_ARGS__);\
|
||||
REQUIRE(__VA_ARGS__);
|
||||
CHECK(__VA_ARGS__);
|
||||
|
||||
#define STATIC_REQUIRE_FALSE(...)\
|
||||
#define STATIC_CHECK_FALSE(...)\
|
||||
static_assert(!(__VA_ARGS__), "!(" #__VA_ARGS__ ")");\
|
||||
REQUIRE(!(__VA_ARGS__));
|
||||
CHECK(!(__VA_ARGS__));
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "vmath_tests.hpp"
|
||||
#include "doctest/doctest.hpp"
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
@@ -16,214 +15,400 @@ namespace
|
||||
{
|
||||
using namespace vmath_hpp;
|
||||
using namespace vmath_tests;
|
||||
|
||||
constexpr float pi = radians(180.f);
|
||||
constexpr float pi_2 = radians(90.f);
|
||||
constexpr float pi_4 = radians(45.f);
|
||||
}
|
||||
|
||||
TEST_CASE("vmath/ext") {
|
||||
SUBCASE("units") {
|
||||
STATIC_REQUIRE(zero2<int> == int2(0,0));
|
||||
STATIC_REQUIRE(zero3<int> == int3(0,0,0));
|
||||
STATIC_REQUIRE(zero4<int> == int4(0,0,0,0));
|
||||
TEST_CASE("vmath/ext/units") {
|
||||
STATIC_CHECK(zero2<int> == int2(0,0));
|
||||
STATIC_CHECK(zero3<int> == int3(0,0,0));
|
||||
STATIC_CHECK(zero4<int> == int4(0,0,0,0));
|
||||
|
||||
STATIC_REQUIRE(unit2<int> == int2(1,1));
|
||||
STATIC_REQUIRE(unit2_x<int> == int2(1,0));
|
||||
STATIC_REQUIRE(unit2_y<int> == int2(0,1));
|
||||
STATIC_CHECK(unit2<int> == int2(1,1));
|
||||
STATIC_CHECK(unit2_x<int> == int2(1,0));
|
||||
STATIC_CHECK(unit2_y<int> == int2(0,1));
|
||||
|
||||
STATIC_REQUIRE(unit3<int> == int3(1,1,1));
|
||||
STATIC_REQUIRE(unit3_x<int> == int3(1,0,0));
|
||||
STATIC_REQUIRE(unit3_y<int> == int3(0,1,0));
|
||||
STATIC_REQUIRE(unit3_z<int> == int3(0,0,1));
|
||||
STATIC_CHECK(unit3<int> == int3(1,1,1));
|
||||
STATIC_CHECK(unit3_x<int> == int3(1,0,0));
|
||||
STATIC_CHECK(unit3_y<int> == int3(0,1,0));
|
||||
STATIC_CHECK(unit3_z<int> == int3(0,0,1));
|
||||
|
||||
STATIC_REQUIRE(unit4<int> == int4(1,1,1,1));
|
||||
STATIC_REQUIRE(unit4_x<int> == int4(1,0,0,0));
|
||||
STATIC_REQUIRE(unit4_y<int> == int4(0,1,0,0));
|
||||
STATIC_REQUIRE(unit4_z<int> == int4(0,0,1,0));
|
||||
STATIC_REQUIRE(unit4_w<int> == int4(0,0,0,1));
|
||||
STATIC_CHECK(unit4<int> == int4(1,1,1,1));
|
||||
STATIC_CHECK(unit4_x<int> == int4(1,0,0,0));
|
||||
STATIC_CHECK(unit4_y<int> == int4(0,1,0,0));
|
||||
STATIC_CHECK(unit4_z<int> == int4(0,0,1,0));
|
||||
STATIC_CHECK(unit4_w<int> == int4(0,0,0,1));
|
||||
|
||||
STATIC_REQUIRE(zero2x2<int> == int2x2(0,0,0,0));
|
||||
STATIC_REQUIRE(zero3x3<int> == int3x3(0,0,0,0,0,0,0,0,0));
|
||||
STATIC_REQUIRE(zero4x4<int> == int4x4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0));
|
||||
STATIC_CHECK(zero2x2<int> == int2x2(0,0,0,0));
|
||||
STATIC_CHECK(zero3x3<int> == int3x3(0,0,0,0,0,0,0,0,0));
|
||||
STATIC_CHECK(zero4x4<int> == int4x4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0));
|
||||
|
||||
STATIC_REQUIRE(unit2x2<int> == int2x2(1,1,1,1));
|
||||
STATIC_REQUIRE(unit3x3<int> == int3x3(1,1,1,1,1,1,1,1,1));
|
||||
STATIC_REQUIRE(unit4x4<int> == int4x4(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1));
|
||||
STATIC_CHECK(unit2x2<int> == int2x2(1,1,1,1));
|
||||
STATIC_CHECK(unit3x3<int> == int3x3(1,1,1,1,1,1,1,1,1));
|
||||
STATIC_CHECK(unit4x4<int> == int4x4(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1));
|
||||
|
||||
STATIC_REQUIRE(identity2x2<int> == int2x2());
|
||||
STATIC_REQUIRE(identity3x3<int> == int3x3());
|
||||
STATIC_REQUIRE(identity4x4<int> == int4x4());
|
||||
}
|
||||
STATIC_CHECK(identity2x2<int> == int2x2());
|
||||
STATIC_CHECK(identity3x3<int> == int3x3());
|
||||
STATIC_CHECK(identity4x4<int> == int4x4());
|
||||
}
|
||||
|
||||
SUBCASE("hash") {
|
||||
REQUIRE(std::hash<int2>{}({1,2}) == std::hash<int2>{}({1,2}));
|
||||
REQUIRE_FALSE(std::hash<int2>{}({1,2}) == std::hash<int2>{}({2,1}));
|
||||
TEST_CASE("vmath/ext/hash") {
|
||||
SUBCASE("vector") {
|
||||
CHECK(std::hash<int2>{}({1,2}) == std::hash<int2>{}({1,2}));
|
||||
CHECK_FALSE(std::hash<int2>{}({1,2}) == std::hash<int2>{}({2,1}));
|
||||
|
||||
REQUIRE(std::hash<int3>{}({1,2,3}) == std::hash<int3>{}({1,2,3}));
|
||||
REQUIRE_FALSE(std::hash<int3>{}({1,2,3}) == std::hash<int3>{}({3,2,1}));
|
||||
CHECK(std::hash<int3>{}({1,2,3}) == std::hash<int3>{}({1,2,3}));
|
||||
CHECK_FALSE(std::hash<int3>{}({1,2,3}) == std::hash<int3>{}({3,2,1}));
|
||||
|
||||
REQUIRE(std::hash<int4>{}({1,2,3,4}) == std::hash<int4>{}({1,2,3,4}));
|
||||
REQUIRE_FALSE(std::hash<int4>{}({1,2,3,4}) == std::hash<int4>{}({3,2,1,4}));
|
||||
CHECK(std::hash<int4>{}({1,2,3,4}) == std::hash<int4>{}({1,2,3,4}));
|
||||
CHECK_FALSE(std::hash<int4>{}({1,2,3,4}) == std::hash<int4>{}({3,2,1,4}));
|
||||
|
||||
REQUIRE(std::hash<int2x2>{}({1,2,3,4}) == std::hash<int2x2>{}({1,2,3,4}));
|
||||
REQUIRE_FALSE(std::hash<int2x2>{}({1,2,3,4}) == std::hash<int2x2>{}({1,2,4,3}));
|
||||
{
|
||||
std::set<int2> s;
|
||||
s.insert(int2(1,2));
|
||||
REQUIRE(s.count(int2(1,2)) > 0);
|
||||
REQUIRE_FALSE(s.count(int2(1,1)) > 0);
|
||||
CHECK(s.count(int2(1,2)) > 0);
|
||||
CHECK_FALSE(s.count(int2(1,1)) > 0);
|
||||
}
|
||||
{
|
||||
std::map<int2, int> s;
|
||||
s.emplace(int2(1,2),3);
|
||||
s.emplace(int2(2,3),5);
|
||||
REQUIRE(s[int2(1,2)] == 3);
|
||||
REQUIRE(s[int2(2,3)] == 5);
|
||||
CHECK(s[int2(1,2)] == 3);
|
||||
CHECK(s[int2(2,3)] == 5);
|
||||
}
|
||||
{
|
||||
std::unordered_set<int2> s;
|
||||
s.insert(int2(1,2));
|
||||
REQUIRE(s.count(int2(1,2)) > 0);
|
||||
REQUIRE_FALSE(s.count(int2(1,1)) > 0);
|
||||
CHECK(s.count(int2(1,2)) > 0);
|
||||
CHECK_FALSE(s.count(int2(1,1)) > 0);
|
||||
}
|
||||
{
|
||||
std::unordered_map<int2, int> s;
|
||||
s.emplace(int2(1,2),3);
|
||||
s.emplace(int2(2,3),5);
|
||||
REQUIRE(s[int2(1,2)] == 3);
|
||||
REQUIRE(s[int2(2,3)] == 5);
|
||||
CHECK(s[int2(1,2)] == 3);
|
||||
CHECK(s[int2(2,3)] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("matrix") {
|
||||
CHECK(std::hash<int2x2>{}({1,2,3,4}) == std::hash<int2x2>{}({1,2,3,4}));
|
||||
CHECK_FALSE(std::hash<int2x2>{}({1,2,3,4}) == std::hash<int2x2>{}({1,2,4,3}));
|
||||
|
||||
{
|
||||
std::set<int2x2> s;
|
||||
s.insert(int2x2(1,2,3,4));
|
||||
CHECK(s.count(int2x2(1,2,3,4)) > 0);
|
||||
CHECK_FALSE(s.count(int2x2(1,1,1,1)) > 0);
|
||||
}
|
||||
{
|
||||
std::map<int2x2, int> s;
|
||||
s.emplace(int2x2(1,2,3,4),3);
|
||||
s.emplace(int2x2(2,3,4,5),5);
|
||||
CHECK(s[int2x2(1,2,3,4)] == 3);
|
||||
CHECK(s[int2x2(2,3,4,5)] == 5);
|
||||
}
|
||||
{
|
||||
std::unordered_set<int2x2> s;
|
||||
s.insert(int2x2(1,2,3,4));
|
||||
CHECK(s.count(int2x2(1,2,3,4)) > 0);
|
||||
CHECK_FALSE(s.count(int2x2(1,1,1,1)) > 0);
|
||||
}
|
||||
{
|
||||
std::unordered_map<int2x2, int> s;
|
||||
s.emplace(int2x2(1,2,3,4),3);
|
||||
s.emplace(int2x2(2,3,4,5),5);
|
||||
CHECK(s[int2x2(1,2,3,4)] == 3);
|
||||
CHECK(s[int2x2(2,3,4,5)] == 5);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("quaternion") {
|
||||
CHECK(std::hash<qfloat>{}({1,2,3,4}) == std::hash<qfloat>{}({1,2,3,4}));
|
||||
CHECK_FALSE(std::hash<qfloat>{}({1,2,3,4}) == std::hash<qfloat>{}({3,2,1,4}));
|
||||
|
||||
{
|
||||
std::set<qua<int>> s;
|
||||
s.insert(qua(1,2,3,4));
|
||||
CHECK(s.count(qua(1,2,3,4)) > 0);
|
||||
CHECK_FALSE(s.count(qua(1,1,1,1)) > 0);
|
||||
}
|
||||
{
|
||||
std::map<qua<int>, int> s;
|
||||
s.emplace(qua(1,2,3,4),3);
|
||||
s.emplace(qua(2,3,4,5),5);
|
||||
CHECK(s[qua(1,2,3,4)] == 3);
|
||||
CHECK(s[qua(2,3,4,5)] == 5);
|
||||
}
|
||||
{
|
||||
std::unordered_set<qua<int>> s;
|
||||
s.insert(qua(1,2,3,4));
|
||||
CHECK(s.count(qua(1,2,3,4)) > 0);
|
||||
CHECK_FALSE(s.count(qua(1,1,1,1)) > 0);
|
||||
}
|
||||
{
|
||||
std::unordered_map<qua<int>, int> s;
|
||||
s.emplace(qua(1,2,3,4),3);
|
||||
s.emplace(qua(2,3,4,5),5);
|
||||
CHECK(s[qua(1,2,3,4)] == 3);
|
||||
CHECK(s[qua(2,3,4,5)] == 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("vmath/ext/cast") {
|
||||
SUBCASE("cast_to") {
|
||||
{
|
||||
constexpr auto i = cast_to<int>(1.5f);
|
||||
STATIC_REQUIRE(i == 1);
|
||||
STATIC_REQUIRE(std::is_same_v<decltype(i), const int>);
|
||||
}
|
||||
{
|
||||
constexpr auto v = cast_to<int>(float2{1.5f});
|
||||
STATIC_REQUIRE(v == int2(1));
|
||||
STATIC_REQUIRE(std::is_same_v<decltype(v)::component_type, int>);
|
||||
}
|
||||
{
|
||||
constexpr auto m = cast_to<int>(float2x2{1.5f});
|
||||
STATIC_REQUIRE(m == int2x2(1));
|
||||
STATIC_REQUIRE(std::is_same_v<decltype(m)::row_type, int2>);
|
||||
}
|
||||
constexpr auto i = cast_to<int>(1.5f);
|
||||
STATIC_CHECK(i == 1);
|
||||
STATIC_CHECK(std::is_same_v<decltype(i), const int>);
|
||||
|
||||
constexpr auto v = cast_to<int>(float2(1.5f));
|
||||
STATIC_CHECK(v == int2(1));
|
||||
STATIC_CHECK(std::is_same_v<decltype(v)::component_type, int>);
|
||||
|
||||
constexpr auto m = cast_to<int>(float2x2(1.5f));
|
||||
STATIC_CHECK(m == int2x2(1));
|
||||
STATIC_CHECK(std::is_same_v<decltype(m)::row_type, int2>);
|
||||
|
||||
constexpr auto q = cast_to<int>(qfloat(1.5f, 2.2f, 3.6f, 4.5f));
|
||||
STATIC_CHECK(q == qua(1,2,3,4));
|
||||
STATIC_CHECK(std::is_same_v<decltype(q)::component_type, int>);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("vmath/ext/access") {
|
||||
SUBCASE("component") {
|
||||
STATIC_REQUIRE(component(int2{1,2}, 0) == 1);
|
||||
STATIC_REQUIRE(component(int2{1,2}, 1) == 2);
|
||||
STATIC_CHECK(component(int2{1,2}, 0) == 1);
|
||||
STATIC_CHECK(component(int2{1,2}, 1) == 2);
|
||||
|
||||
STATIC_REQUIRE(component(int2{0,0}, 0, 1) == int2{1,0});
|
||||
STATIC_REQUIRE(component(int2{0,0}, 1, 2) == int2{0,2});
|
||||
STATIC_CHECK(component(int2{0,0}, 0, 1) == int2{1,0});
|
||||
STATIC_CHECK(component(int2{0,0}, 1, 2) == int2{0,2});
|
||||
}
|
||||
|
||||
SUBCASE("row") {
|
||||
STATIC_REQUIRE(row(int2x2(1,2,3,4), 0) == int2(1,2));
|
||||
STATIC_REQUIRE(row(int2x2(1,2,3,4), 1) == int2(3,4));
|
||||
STATIC_CHECK(row(int2x2(1,2,3,4), 0) == int2(1,2));
|
||||
STATIC_CHECK(row(int2x2(1,2,3,4), 1) == int2(3,4));
|
||||
|
||||
STATIC_REQUIRE(row(int2x2(), 0, {1,2}) == int2x2(1,2,0,1));
|
||||
STATIC_REQUIRE(row(int2x2(), 1, {3,4}) == int2x2(1,0,3,4));
|
||||
STATIC_CHECK(row(int2x2(), 0, {1,2}) == int2x2(1,2,0,1));
|
||||
STATIC_CHECK(row(int2x2(), 1, {3,4}) == int2x2(1,0,3,4));
|
||||
}
|
||||
|
||||
SUBCASE("column") {
|
||||
STATIC_REQUIRE(column(int2x2(1,2,3,4), 0) == int2(1,3));
|
||||
STATIC_REQUIRE(column(int2x2(1,2,3,4), 1) == int2(2,4));
|
||||
STATIC_CHECK(column(int2x2(1,2,3,4), 0) == int2(1,3));
|
||||
STATIC_CHECK(column(int2x2(1,2,3,4), 1) == int2(2,4));
|
||||
|
||||
STATIC_REQUIRE(column(int2x2(), 0, {2,3}) == int2x2(2,0,3,1));
|
||||
STATIC_REQUIRE(column(int2x2(), 1, {3,4}) == int2x2(1,3,0,4));
|
||||
STATIC_CHECK(column(int2x2(), 0, {2,3}) == int2x2(2,0,3,1));
|
||||
STATIC_CHECK(column(int2x2(), 1, {3,4}) == int2x2(1,3,0,4));
|
||||
}
|
||||
|
||||
SUBCASE("matrix translate") {
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * translate(float2{1.f,2.f}) == uapprox3(3.f,5.f,1.f));
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * translate(translate(float2{1.f,2.f}), float2{1.f,2.f}) == uapprox3(4.f,7.f,1.f));
|
||||
|
||||
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(float3{1.f,2.f,3.f}) == uapprox4(3.f,5.f,7.f,1.f));
|
||||
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(float3{1.f,2.f,3.f}), float3{1.f,2.f,3.f}) == uapprox4(4.f,7.f,10.f,1.f));
|
||||
SUBCASE("real") {
|
||||
STATIC_CHECK(real(qua{1,2,3,4}) == 4);
|
||||
STATIC_CHECK(real(qua{1,2,3,4}, 5) == qua{1,2,3,5});
|
||||
}
|
||||
|
||||
SUBCASE("matrix rotate") {
|
||||
constexpr float pi = radians(180.f);
|
||||
constexpr float pi_2 = radians(90.f);
|
||||
constexpr float pi_4 = radians(45.f);
|
||||
SUBCASE("imag") {
|
||||
STATIC_CHECK(imag(qua{1,2,3,4}) == vec{1,2,3});
|
||||
STATIC_CHECK(imag(qua{1,2,3,4}, {4,3,2}) == qua{4,3,2,4});
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(float4(0.f,1.f,0.f,1.f) * rotate_x(pi_2) == uapprox4(0.f,0.f,1.f,1.f));
|
||||
REQUIRE(float4(0.f,0.f,1.f,1.f) * rotate_y(pi_2) == uapprox4(1.f,0.f,0.f,1.f));
|
||||
REQUIRE(float4(1.f,0.f,0.f,1.f) * rotate_z(pi_2) == uapprox4(0.f,1.f,0.f,1.f));
|
||||
TEST_CASE("vmath/ext/matrix_transform") {
|
||||
SUBCASE("translate") {
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * translate(float2{1.f,2.f}) == uapprox3(3.f,5.f,1.f));
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * translate(translate(float2{1.f,2.f}), float2{1.f,2.f}) == uapprox3(4.f,7.f,1.f));
|
||||
|
||||
REQUIRE(float4(0.f,1.f,0.f,1.f) * rotate_x(rotate_x(pi_4),pi_4) == uapprox4(0.f,0.f,1.f,1.f));
|
||||
REQUIRE(float4(0.f,0.f,1.f,1.f) * rotate_y(rotate_y(pi_4),pi_4) == uapprox4(1.f,0.f,0.f,1.f));
|
||||
REQUIRE(float4(1.f,0.f,0.f,1.f) * rotate_z(rotate_z(pi_4),pi_4) == uapprox4(0.f,1.f,0.f,1.f));
|
||||
|
||||
REQUIRE(float3(2.f,3.f,1.f) * rotate(pi) == uapprox3(-2.f,-3.f,1.f));
|
||||
REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f));
|
||||
REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,float3{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f));
|
||||
|
||||
REQUIRE(float3(2.f,3.f,1.f) * rotate(rotate(pi_2),pi_2) == uapprox3(-2.f,-3.f,1.f));
|
||||
REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,{0.f,0.f,1.f}),pi_2,{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f));
|
||||
REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,float3{0.f,0.f,1.f}),pi_2,float3{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f));
|
||||
STATIC_CHECK(float4(2.f,3.f,4.f,1.f) * translate(float3{1.f,2.f,3.f}) == uapprox4(3.f,5.f,7.f,1.f));
|
||||
STATIC_CHECK(float4(2.f,3.f,4.f,1.f) * translate(translate(float3{1.f,2.f,3.f}), float3{1.f,2.f,3.f}) == uapprox4(4.f,7.f,10.f,1.f));
|
||||
}
|
||||
|
||||
SUBCASE("matrix scale") {
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * scale(float2{2.f,3.f}) == uapprox3(4.f,9.f,1.f));
|
||||
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == uapprox4(4.f,9.f,16.f,1.f));
|
||||
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == uapprox4(4.f,9.f,16.f,1.f));
|
||||
SUBCASE("rotate") {
|
||||
CHECK(float4(0.f,1.f,0.f,1.f) * rotate_x(pi_2) == uapprox4(0.f,0.f,1.f,1.f));
|
||||
CHECK(float4(0.f,0.f,1.f,1.f) * rotate_y(pi_2) == uapprox4(1.f,0.f,0.f,1.f));
|
||||
CHECK(float4(1.f,0.f,0.f,1.f) * rotate_z(pi_2) == uapprox4(0.f,1.f,0.f,1.f));
|
||||
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * scale(scale(float2{2.f,2.f}), {2.f,3.f}) == uapprox3(8.f,18.f,1.f));
|
||||
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), {2.f,3.f,4.f}) == uapprox4(8.f,18.f,32.f,1.f));
|
||||
STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), float3{2.f,3.f,4.f}) == uapprox4(8.f,18.f,32.f,1.f));
|
||||
CHECK(float4(0.f,1.f,0.f,1.f) * rotate_x(rotate_x(pi_4),pi_4) == uapprox4(0.f,0.f,1.f,1.f));
|
||||
CHECK(float4(0.f,0.f,1.f,1.f) * rotate_y(rotate_y(pi_4),pi_4) == uapprox4(1.f,0.f,0.f,1.f));
|
||||
CHECK(float4(1.f,0.f,0.f,1.f) * rotate_z(rotate_z(pi_4),pi_4) == uapprox4(0.f,1.f,0.f,1.f));
|
||||
|
||||
CHECK(float3(2.f,3.f,1.f) * rotate(pi) == uapprox3(-2.f,-3.f,1.f));
|
||||
CHECK(float4(2.f,3.f,4.f,1.f) * rotate(pi,{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f));
|
||||
CHECK(float4(2.f,3.f,4.f,1.f) * rotate(pi,float3{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f));
|
||||
CHECK(float4(2.f,3.f,4.f,1.f) * rotate(qrotate(pi,float3{0.f,0.f,1.f})) == uapprox4(-2.f,-3.f,4.f,1.f));
|
||||
|
||||
CHECK(float3(2.f,3.f,1.f) * rotate(rotate(pi_2),pi_2) == uapprox3(-2.f,-3.f,1.f));
|
||||
CHECK(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,{0.f,0.f,1.f}),pi_2,{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f));
|
||||
CHECK(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,float3{0.f,0.f,1.f}),pi_2,float3{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f));
|
||||
CHECK(float4(2.f,3.f,4.f,1.f) * rotate(rotate(qrotate(pi_2,float3{0.f,0.f,1.f})),qrotate(pi_2,float3{0.f,0.f,1.f})) == uapprox4(-2.f,-3.f,4.f,1.f));
|
||||
}
|
||||
|
||||
SUBCASE("matrix shear") {
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_x(0.f) == uapprox3(2.f,3.f,1.f));
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_x(1.f) == uapprox3(5.f,3.f,1.f));
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_x(shear_x(1.f),1.f) == uapprox3(8.f,3.f,1.f));
|
||||
SUBCASE("scale") {
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * scale(float2{2.f,3.f}) == uapprox3(4.f,9.f,1.f));
|
||||
STATIC_CHECK(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == uapprox4(4.f,9.f,16.f,1.f));
|
||||
STATIC_CHECK(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == uapprox4(4.f,9.f,16.f,1.f));
|
||||
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_y(0.f) == uapprox3(2.f,3.f,1.f));
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_y(1.f) == uapprox3(2.f,5.f,1.f));
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_y(shear_y(1.f),1.f) == uapprox3(2.f,7.f,1.f));
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * scale(scale(float2{2.f,2.f}), {2.f,3.f}) == uapprox3(8.f,18.f,1.f));
|
||||
STATIC_CHECK(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), {2.f,3.f,4.f}) == uapprox4(8.f,18.f,32.f,1.f));
|
||||
STATIC_CHECK(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), float3{2.f,3.f,4.f}) == uapprox4(8.f,18.f,32.f,1.f));
|
||||
}
|
||||
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(float2(0.f,0.f)) == uapprox3(2.f,3.f,1.f));
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(float2(1.f,0.f)) == uapprox3(5.f,3.f,1.f));
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(float2(0.f,1.f)) == uapprox3(2.f,5.f,1.f));
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(shear(float2(1.f,0.f)),float2(1.f,0.f)) == uapprox3(8.f,3.f,1.f));
|
||||
STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(shear(float2(0.f,1.f)),float2(0.f,1.f)) == uapprox3(2.f,7.f,1.f));
|
||||
SUBCASE("shear") {
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear_x(0.f) == uapprox3(2.f,3.f,1.f));
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear_x(1.f) == uapprox3(5.f,3.f,1.f));
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear_x(2.f) == uapprox3(8.f,3.f,1.f));
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear_x(shear_x(1.f),1.f) == uapprox3(8.f,3.f,1.f));
|
||||
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear_y(0.f) == uapprox3(2.f,3.f,1.f));
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear_y(1.f) == uapprox3(2.f,5.f,1.f));
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear_y(2.f) == uapprox3(2.f,7.f,1.f));
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear_y(shear_y(1.f),1.f) == uapprox3(2.f,7.f,1.f));
|
||||
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear(float2(0.f,0.f)) == uapprox3(2.f,3.f,1.f));
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear(float2(2.f,0.f)) == uapprox3(8.f,3.f,1.f));
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear(float2(0.f,2.f)) == uapprox3(2.f,7.f,1.f));
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear(shear(float2(1.f,0.f)),float2(1.f,0.f)) == uapprox3(8.f,3.f,1.f));
|
||||
STATIC_CHECK(float3(2.f,3.f,1.f) * shear(shear(float2(0.f,1.f)),float2(0.f,1.f)) == uapprox3(2.f,7.f,1.f));
|
||||
}
|
||||
|
||||
SUBCASE("matrix look_at") {
|
||||
(void)look_at_lh(float3(-10.f), float3(0.f), float3(0,-1,0));
|
||||
(void)look_at_rh(float3(-10.f), float3(0.f), float3(0,-1,0));
|
||||
|
||||
(void)orthographic_lh_zo(0.f, 800.f, 0.f, 640.f, 0.f, 10.f);
|
||||
(void)orthographic_lh_no(0.f, 800.f, 0.f, 640.f, 0.f, 10.f);
|
||||
(void)orthographic_rh_zo(0.f, 800.f, 0.f, 640.f, 0.f, 10.f);
|
||||
(void)orthographic_rh_no(0.f, 800.f, 0.f, 640.f, 0.f, 10.f);
|
||||
|
||||
(void)perspective_lh_zo(1.f, 1.3f, 0.f, 10.f);
|
||||
(void)perspective_lh_no(1.f, 1.3f, 0.f, 10.f);
|
||||
(void)perspective_rh_zo(1.f, 1.3f, 0.f, 10.f);
|
||||
(void)perspective_rh_no(1.f, 1.3f, 0.f, 10.f);
|
||||
}
|
||||
|
||||
SUBCASE("vector angle") {
|
||||
REQUIRE(angle(float2(2.f,0.f), float2(0.f,1.f)) == uapprox(radians(90.f)));
|
||||
REQUIRE(angle(float2(0.f,3.f), float2(1.f,0.f)) == uapprox(radians(90.f)));
|
||||
REQUIRE(angle(float2(0.5f,0.f), float2(-1.f,0.f)) == uapprox(radians(180.f)));
|
||||
REQUIRE(angle(float2(-0.2f,0.f), float2(1.f,0.f)) == uapprox(radians(180.f)));
|
||||
REQUIRE(angle(float3(0.f,2.f,0.f), float3(0.f,0.f,1.f)) == uapprox(radians(90.f)));
|
||||
REQUIRE(angle(float3(0.f,0.f,3.f), float3(0.f,1.f,0.f)) == uapprox(radians(90.f)));
|
||||
}
|
||||
|
||||
SUBCASE("vector rotate") {
|
||||
REQUIRE(rotate(float2(2.f,0.f), radians(90.f)) == uapprox2(0.f,2.f));
|
||||
REQUIRE(rotate(float2(1.5f,0.f), radians(-90.f)) == uapprox2(0.f,-1.5f));
|
||||
|
||||
REQUIRE(rotate(float3(1.5f,0.f,0.f), radians(90.f), float3(0,0,1)) == uapprox3(0.f,1.5f,0.f));
|
||||
REQUIRE(rotate(float4(1.5f,0.f,0.f,1.f), radians(90.f), float3(0,0,1)) == uapprox4(0.f,1.5f,0.f,1.f));
|
||||
}
|
||||
|
||||
SUBCASE("vector project") {
|
||||
REQUIRE(project(float2(2.f, 2.f), float2(0.f, 1.f)) == uapprox2(0.f, 2.f));
|
||||
REQUIRE(project(float3(2.f, 2.f, 2.f), float3(0.f, 0.f, 1.f)) == uapprox3(0.f, 0.f, 2.f));
|
||||
(void)look_at_lh(float3(1,2,3), float3(0,0,0), float3(0,2,0));
|
||||
(void)look_at_rh(float3(1,2,3), float3(0,0,0), float3(0,2,0));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("vmath/ext/matrix_projections") {
|
||||
SUBCASE("orthographic") {
|
||||
CHECK(all(approx(
|
||||
orthographic_lh(800.f, 600.f, 5.f, 10.f),
|
||||
scale(1.f,1.f,-1.f) * orthographic_rh(800.f, 600.f, 5.f, 10.f))));
|
||||
|
||||
CHECK(all(approx(
|
||||
orthographic_lh(100.f, 800.f, 50.f, 640.f, 5.f, 10.f),
|
||||
scale(1.f,1.f,-1.f) * orthographic_rh(100.f, 800.f, 50.f, 640.f, 5.f, 10.f))));
|
||||
}
|
||||
|
||||
|
||||
SUBCASE("perspective") {
|
||||
CHECK(all(approx(
|
||||
perspective_lh(800.f, 600.f, 5.f, 10.f),
|
||||
scale(1.f,1.f,-1.f) * perspective_rh(800.f, 600.f, 5.f, 10.f))));
|
||||
|
||||
CHECK(all(approx(
|
||||
perspective_fov_lh(1.5f, 1.3f, 0.f, 10.f),
|
||||
scale(1.f,1.f,-1.f) * perspective_fov_rh(1.5f, 1.3f, 0.f, 10.f))));
|
||||
|
||||
CHECK(all(approx(
|
||||
perspective_lh(100.f, 800.f, 50.f, 600.f, 5.f, 10.f),
|
||||
scale(1.f,1.f,-1.f) * perspective_rh(100.f, 800.f, 50.f, 600.f, 5.f, 10.f))));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("vmath/ext/vector_transform") {
|
||||
SUBCASE("angle") {
|
||||
CHECK(angle(float2(2.f,0.f), float2(0.f,1.f)) == uapprox(radians(90.f)));
|
||||
CHECK(angle(float2(0.f,3.f), float2(1.f,0.f)) == uapprox(radians(90.f)));
|
||||
CHECK(angle(float2(0.5f,0.f), float2(-1.f,0.f)) == uapprox(radians(180.f)));
|
||||
CHECK(angle(float2(-0.2f,0.f), float2(1.f,0.f)) == uapprox(radians(180.f)));
|
||||
CHECK(angle(float3(0.f,2.f,0.f), float3(0.f,0.f,1.f)) == uapprox(radians(90.f)));
|
||||
CHECK(angle(float3(0.f,0.f,3.f), float3(0.f,1.f,0.f)) == uapprox(radians(90.f)));
|
||||
}
|
||||
|
||||
SUBCASE("rotate") {
|
||||
CHECK(rotate(float2(2.f,0.f), radians(90.f)) == uapprox2(0.f,2.f));
|
||||
CHECK(rotate(float2(1.5f,0.f), radians(-90.f)) == uapprox2(0.f,-1.5f));
|
||||
|
||||
CHECK(rotate_x(float3(0.f,1.5f,0.f), radians(90.f)) == uapprox3(0.f,0.f,1.5f));
|
||||
CHECK(rotate_y(float3(0.f,0.f,1.5f), radians(90.f)) == uapprox3(1.5f,0.f,0.f));
|
||||
CHECK(rotate_z(float3(1.5f,0.f,0.f), radians(90.f)) == uapprox3(0.f,1.5f,0.f));
|
||||
|
||||
CHECK(rotate(float3(1.5f,0.f,0.f), qrotate_z(radians(90.f))) == uapprox3(0.f,1.5f,0.f));
|
||||
CHECK(rotate(float3(1.5f,0.f,0.f), radians(90.f), float3(0,0,1)) == uapprox3(0.f,1.5f,0.f));
|
||||
}
|
||||
|
||||
SUBCASE("project") {
|
||||
STATIC_CHECK(project(float2(2.f, 2.f), float2(0.f, 1.f)) == uapprox2(0.f, 2.f));
|
||||
STATIC_CHECK(project(float3(2.f, 2.f, 2.f), float3(0.f, 0.f, 1.f)) == uapprox3(0.f, 0.f, 2.f));
|
||||
}
|
||||
|
||||
SUBCASE("perpendicular") {
|
||||
STATIC_CHECK(perpendicular(float2(2.f, 2.f), float2(0.f, 1.f)) == uapprox2(2.f, 0.f));
|
||||
STATIC_CHECK(perpendicular(float3(2.f, 2.f, 2.f), float3(0.f, 0.f, 1.f)) == uapprox3(2.f, 2.f, 0.f));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("vmath/ext/quaternion_transform") {
|
||||
SUBCASE("qrotate(m)") {
|
||||
CHECK(all(approx(
|
||||
vec{4.f,3.f,2.f,1.f} * rotate(qrotate(float3x3(rotate(0.f, vec{1.f,2.f,3.f})))),
|
||||
vec{4.f,3.f,2.f,1.f} * rotate(0.f, vec{1.f,2.f,3.f}), 0.001f)));
|
||||
CHECK(all(approx(
|
||||
vec{4.f,3.f,2.f,1.f} * rotate(qrotate(float3x3(rotate(radians(12.5f), vec{1.f,2.f,3.f})))),
|
||||
vec{4.f,3.f,2.f,1.f} * rotate(radians(12.5f), vec{1.f,2.f,3.f}), 0.001f)));
|
||||
CHECK(all(approx(
|
||||
vec{4.f,3.f,2.f,1.f} * rotate(qrotate(float3x3(rotate(radians(-190.5f), vec{1.f,2.f,3.f})))),
|
||||
vec{4.f,3.f,2.f,1.f} * rotate(radians(-190.5f), vec{1.f,2.f,3.f}), 0.001f)));
|
||||
}
|
||||
|
||||
SUBCASE("qrotate(q, m)") {
|
||||
CHECK(all(approx(
|
||||
vec{4.f,3.f,2.f} * qrotate(
|
||||
qrotate(float3x3(rotate(0.f, vec{1.f,2.f,3.f}))),
|
||||
float3x3(rotate(0.f, vec{3.f,2.f,1.f}))),
|
||||
vec{4.f,3.f,2.f} *
|
||||
float3x3(rotate(0.f, vec{1.f,2.f,3.f})) *
|
||||
float3x3(rotate(0.f, vec{3.f,2.f,1.f})))));
|
||||
}
|
||||
|
||||
SUBCASE("qrotate(from, to)") {
|
||||
CHECK(+unit3_x<float> * qrotate(-unit3_x<float>, +unit3_x<float>) == uapprox3(-unit3_x<float>));
|
||||
CHECK(-unit3_y<float> * qrotate(+unit3_y<float>, -unit3_y<float>) == uapprox3(+unit3_y<float>));
|
||||
CHECK(+unit3_z<float> * qrotate(-unit3_z<float>, +unit3_z<float>) == uapprox3(-unit3_z<float>));
|
||||
CHECK(vec{1.f,2.f,3.f} * qrotate(vec{1.f,2.f,3.f}, vec{-2.f,1.f,3.f}) == uapprox3(-2.f,1.f,3.f));
|
||||
CHECK(vec{-2.f,1.f,3.f} * qrotate(vec{-2.f,1.f,3.f}, vec{1.f,2.f,3.f}) == uapprox3(1.f,2.f,3.f));
|
||||
}
|
||||
|
||||
SUBCASE("qrotate(q, from, to)") {
|
||||
CHECK(vec{1.f,2.f,3.f} *
|
||||
inverse(qrotate(float3x3(rotate(radians(12.f), {2.f,2.f,2.f})))) *
|
||||
qrotate(
|
||||
qrotate(float3x3(rotate(radians(12.f), {2.f,2.f,2.f}))),
|
||||
vec{1.f,2.f,3.f},
|
||||
vec{-2.f,1.f,3.f}) == uapprox3(vec{-2.f,1.f,3.f}));
|
||||
}
|
||||
|
||||
SUBCASE("qrotate(angle, axis)") {
|
||||
CHECK(all(approx(
|
||||
rotate(12.3f, float3(1.f,2.f,3.f)),
|
||||
rotate(qrotate(12.3f, float3(1.f,2.f,3.f)) * 2.f))));
|
||||
|
||||
CHECK(float3(0.f,1.f,0.f) * qrotate_x(pi_2) == uapprox3(0.f,0.f,1.f));
|
||||
CHECK(float3(0.f,0.f,1.f) * qrotate_y(pi_2) == uapprox3(1.f,0.f,0.f));
|
||||
CHECK(float3(1.f,0.f,0.f) * qrotate_z(pi_2) == uapprox3(0.f,1.f,0.f));
|
||||
|
||||
CHECK(float3(2.f,3.f,4.f) * qrotate(pi,{0.f,0.f,1.f}) == uapprox3(-2.f,-3.f,4.f));
|
||||
CHECK(float3(2.f,3.f,4.f) * qrotate(pi,float3{0.f,0.f,1.f}) == uapprox3(-2.f,-3.f,4.f));
|
||||
|
||||
CHECK(qrotate_x(12.3f) == qrotate(12.3f, unit3_x<float> * 2.f));
|
||||
CHECK(qrotate_y(12.3f) == qrotate(12.3f, unit3_y<float> * 2.f));
|
||||
CHECK(qrotate_z(12.3f) == qrotate(12.3f, unit3_z<float> * 2.f));
|
||||
}
|
||||
|
||||
SUBCASE("qrotate(q, angle, axis)") {
|
||||
CHECK(float3(0.f,1.f,0.f) * qrotate_x(qrotate_x(pi_4),pi_4) == uapprox3(0.f,0.f,1.f));
|
||||
CHECK(float3(0.f,0.f,1.f) * qrotate_y(qrotate_y(pi_4),pi_4) == uapprox3(1.f,0.f,0.f));
|
||||
CHECK(float3(1.f,0.f,0.f) * qrotate_z(qrotate_z(pi_4),pi_4) == uapprox3(0.f,1.f,0.f));
|
||||
|
||||
CHECK(float3(2.f,3.f,4.f) * qrotate(qrotate(pi_2,{0.f,0.f,1.f}),pi_2,{0.f,0.f,1.f}) == uapprox3(-2.f,-3.f,4.f));
|
||||
CHECK(float3(2.f,3.f,4.f) * qrotate(qrotate(pi_2,float3{0.f,0.f,1.f}),pi_2,float3{0.f,0.f,1.f}) == uapprox3(-2.f,-3.f,4.f));
|
||||
}
|
||||
|
||||
SUBCASE("qlook_at") {
|
||||
CHECK(all(approx(
|
||||
qlook_at_lh(float3(1.f,2.f,3.f), float3(0,1,0)),
|
||||
qrotate(float3x3(look_at_lh(float3(), float3(1.f,2.f,3.f), float3(0,1,0)))))));
|
||||
CHECK(all(approx(
|
||||
qlook_at_rh(float3(1.f,2.f,3.f), float3(0,1,0)),
|
||||
qrotate(float3x3(look_at_rh(float3(), float3(1.f,2.f,3.f), float3(0,1,0)))))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "vmath_tests.hpp"
|
||||
#include "doctest/doctest.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -14,32 +13,28 @@ namespace
|
||||
}
|
||||
|
||||
TEST_CASE("vmath/fun") {
|
||||
SUBCASE("Angle and Trigonometry Functions") {
|
||||
STATIC_REQUIRE(radians(degrees(12.13f)) == uapprox(12.13f));
|
||||
STATIC_REQUIRE(degrees(radians(12.13f)) == uapprox(12.13f));
|
||||
SUBCASE("Angle and Trigonometric Functions") {
|
||||
STATIC_CHECK(radians(degrees(12.13f)) == uapprox(12.13f));
|
||||
STATIC_CHECK(degrees(radians(12.13f)) == uapprox(12.13f));
|
||||
|
||||
(void)sin(0.f);
|
||||
(void)cos(0.f);
|
||||
(void)tan(0.f);
|
||||
{
|
||||
CHECK(asin(sin(1.23f)) == uapprox(1.23f));
|
||||
CHECK(acos(cos(1.23f)) == uapprox(1.23f));
|
||||
CHECK(atan(tan(1.23f)) == uapprox(1.23f));
|
||||
|
||||
(void)asin(0.f);
|
||||
(void)acos(0.f);
|
||||
(void)atan(0.f);
|
||||
(void)atan2(0.f, 0.f);
|
||||
|
||||
(void)sinh(0.f);
|
||||
(void)cosh(0.f);
|
||||
(void)tanh(0.f);
|
||||
|
||||
(void)asinh(0.f);
|
||||
(void)acosh(0.f);
|
||||
(void)atanh(0.f);
|
||||
CHECK(asinh(sinh(1.23f)) == uapprox(1.23f));
|
||||
CHECK(acosh(cosh(1.23f)) == uapprox(1.23f));
|
||||
CHECK(atanh(tanh(1.23f)) == uapprox(1.23f));
|
||||
}
|
||||
|
||||
{
|
||||
float out_s{}, out_c{};
|
||||
sincos(15.f, &out_s, &out_c);
|
||||
REQUIRE(out_s == uapprox(sin(15.f)));
|
||||
REQUIRE(out_c == uapprox(cos(15.f)));
|
||||
CHECK(out_s == uapprox(sin(15.f)));
|
||||
CHECK(out_c == uapprox(cos(15.f)));
|
||||
const auto [out_s2, out_c2] = sincos(15.f);
|
||||
CHECK(out_s2 == uapprox(sin(15.f)));
|
||||
CHECK(out_c2 == uapprox(cos(15.f)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,113 +49,118 @@ TEST_CASE("vmath/fun") {
|
||||
}
|
||||
|
||||
SUBCASE("Common Functions") {
|
||||
STATIC_REQUIRE(vmath_hpp::abs(1) == 1);
|
||||
STATIC_REQUIRE(vmath_hpp::abs(-1) == 1);
|
||||
STATIC_REQUIRE(vmath_hpp::abs(1.f) == uapprox(1.f));
|
||||
STATIC_REQUIRE(vmath_hpp::abs(-1.f) == uapprox(1.f));
|
||||
STATIC_CHECK(vmath_hpp::abs(1) == 1);
|
||||
STATIC_CHECK(vmath_hpp::abs(-1) == 1);
|
||||
STATIC_CHECK(vmath_hpp::abs(1.f) == uapprox(1.f));
|
||||
STATIC_CHECK(vmath_hpp::abs(-1.f) == uapprox(1.f));
|
||||
|
||||
STATIC_REQUIRE(sign(2) == 1);
|
||||
STATIC_REQUIRE(sign(-2) == -1);
|
||||
STATIC_REQUIRE(sign(0) == 0);
|
||||
STATIC_REQUIRE(sign(2.f) == uapprox(1.f));
|
||||
STATIC_REQUIRE(sign(-2.f) == uapprox(-1.f));
|
||||
STATIC_REQUIRE(sign(0.f) == uapprox(0.f));
|
||||
STATIC_CHECK(sqr(2) == 4);
|
||||
STATIC_CHECK(sqr(-4.f) == uapprox(16.f));
|
||||
|
||||
STATIC_REQUIRE(rcp(2.f) == uapprox(0.5f));
|
||||
STATIC_REQUIRE(rcp(4.f) == uapprox(0.25f));
|
||||
STATIC_CHECK(sign(2) == 1);
|
||||
STATIC_CHECK(sign(-2) == -1);
|
||||
STATIC_CHECK(sign(0) == 0);
|
||||
STATIC_CHECK(sign(2.f) == uapprox(1.f));
|
||||
STATIC_CHECK(sign(-2.f) == uapprox(-1.f));
|
||||
STATIC_CHECK(sign(0.f) == uapprox(0.f));
|
||||
|
||||
REQUIRE(floor(1.7f) == uapprox(1.f));
|
||||
REQUIRE(trunc(1.7f) == uapprox(1.f));
|
||||
REQUIRE(round(1.7f) == uapprox(2.f));
|
||||
REQUIRE(ceil(1.7f) == uapprox(2.f));
|
||||
STATIC_CHECK(rcp(2.f) == uapprox(0.5f));
|
||||
STATIC_CHECK(rcp(4.f) == uapprox(0.25f));
|
||||
|
||||
REQUIRE(fract(1.7f) == uapprox(0.7f));
|
||||
REQUIRE(fract(-2.3f) == uapprox(0.7f));
|
||||
CHECK(floor(1.7f) == uapprox(1.f));
|
||||
CHECK(trunc(1.7f) == uapprox(1.f));
|
||||
CHECK(round(1.7f) == uapprox(2.f));
|
||||
CHECK(ceil(1.7f) == uapprox(2.f));
|
||||
|
||||
REQUIRE(fmod(1.7f, 1.2f) == uapprox(0.5f));
|
||||
CHECK(fract(1.7f) == uapprox(0.7f));
|
||||
CHECK(fract(-2.3f) == uapprox(0.7f));
|
||||
|
||||
CHECK(fmod(1.7f, 1.2f) == uapprox(0.5f));
|
||||
|
||||
{
|
||||
float out_i{};
|
||||
REQUIRE(modf(1.7f, &out_i) == uapprox(0.7f));
|
||||
REQUIRE(out_i == uapprox(1.f));
|
||||
CHECK(modf(1.7f, &out_i) == uapprox(0.7f));
|
||||
CHECK(out_i == uapprox(1.f));
|
||||
}
|
||||
|
||||
STATIC_REQUIRE(min(0.f, 1.f) == uapprox(0.f));
|
||||
STATIC_REQUIRE(min(3.f, 2.f, 1.f) == uapprox(1.f));
|
||||
STATIC_REQUIRE(min(4.f, 3.f, 2.f, 1.f) == uapprox(1.f));
|
||||
STATIC_CHECK(min(0.f, 1.f) == uapprox(0.f));
|
||||
STATIC_CHECK(max(0.f, 1.f) == uapprox(1.f));
|
||||
|
||||
STATIC_REQUIRE(max(0.f, 1.f) == uapprox(1.f));
|
||||
STATIC_REQUIRE(max(3.f, 2.f, 1.f) == uapprox(3.f));
|
||||
STATIC_REQUIRE(max(4.f, 3.f, 2.f, 1.f) == uapprox(4.f));
|
||||
STATIC_CHECK(clamp(1.0f, 2.f, 3.f) == uapprox(2.0f));
|
||||
STATIC_CHECK(clamp(2.5f, 2.f, 3.f) == uapprox(2.5f));
|
||||
STATIC_CHECK(clamp(3.5f, 2.f, 3.f) == uapprox(3.0f));
|
||||
|
||||
STATIC_REQUIRE(clamp(1.0f, 2.f, 3.f) == uapprox(2.0f));
|
||||
STATIC_REQUIRE(clamp(2.5f, 2.f, 3.f) == uapprox(2.5f));
|
||||
STATIC_REQUIRE(clamp(3.5f, 2.f, 3.f) == uapprox(3.0f));
|
||||
STATIC_CHECK(saturate(-0.5f) == uapprox(0.f));
|
||||
STATIC_CHECK(saturate(0.5f) == uapprox(0.5f));
|
||||
STATIC_CHECK(saturate(1.5f) == uapprox(1.f));
|
||||
|
||||
STATIC_REQUIRE(saturate(-0.5f) == uapprox(0.f));
|
||||
STATIC_REQUIRE(saturate(0.5f) == uapprox(0.5f));
|
||||
STATIC_REQUIRE(saturate(1.5f) == uapprox(1.f));
|
||||
STATIC_CHECK(lerp(2.f, 10.f, 0.f) == uapprox(2.f));
|
||||
STATIC_CHECK(lerp(2.f, 10.f, 0.5f) == uapprox(6.f));
|
||||
STATIC_CHECK(lerp(2.f, 10.f, 1.f) == uapprox(10.f));
|
||||
|
||||
STATIC_REQUIRE(lerp(0.f, 10.f, 0.5f) == uapprox(5.f));
|
||||
STATIC_REQUIRE(step(0.5f, 0.4f) == uapprox(0.f));
|
||||
STATIC_REQUIRE(step(0.5f, 0.6f) == uapprox(1.f));
|
||||
STATIC_REQUIRE(smoothstep(0.f, 1.f, 0.1f) == uapprox(0.028f));
|
||||
STATIC_CHECK(lerp(2.f, 10.f, 0.f, 1.f) == uapprox(10.f));
|
||||
STATIC_CHECK(lerp(2.f, 10.f, 1.f, 0.f) == uapprox(2.f));
|
||||
STATIC_CHECK(lerp(2.f, 10.f, 0.5f, 0.2f) == uapprox(3.f));
|
||||
|
||||
REQUIRE_FALSE(vmath_hpp::isnan(1.f));
|
||||
REQUIRE_FALSE(vmath_hpp::isinf(1.f));
|
||||
REQUIRE(vmath_hpp::isfinite(1.f));
|
||||
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));
|
||||
|
||||
REQUIRE(fma(2.f, 3.f, 4.f) == uapprox(10.f));
|
||||
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{};
|
||||
REQUIRE(frexp(1.7f, &out_exp) == uapprox(0.85f));
|
||||
REQUIRE(out_exp == 1);
|
||||
CHECK(frexp(1.7f, &out_exp) == uapprox(0.85f));
|
||||
CHECK(out_exp == 1);
|
||||
}
|
||||
|
||||
REQUIRE(ldexp(0.85f, 1) == uapprox(1.7f));
|
||||
CHECK(ldexp(0.85f, 1) == uapprox(1.7f));
|
||||
}
|
||||
|
||||
SUBCASE("Geometric Functions") {
|
||||
STATIC_REQUIRE(length(10.f) == uapprox(10.f));
|
||||
STATIC_REQUIRE(length(-10.f) == uapprox(10.f));
|
||||
STATIC_CHECK(length(10.f) == uapprox(10.f));
|
||||
STATIC_CHECK(length(-10.f) == uapprox(10.f));
|
||||
|
||||
STATIC_REQUIRE(length2(10.f) == uapprox(100.f));
|
||||
STATIC_REQUIRE(length2(-10.f) == uapprox(100.f));
|
||||
STATIC_CHECK(length2(10.f) == uapprox(100.f));
|
||||
STATIC_CHECK(length2(-10.f) == uapprox(100.f));
|
||||
|
||||
STATIC_REQUIRE(distance(5.f, 10.f) == uapprox(5.f));
|
||||
STATIC_REQUIRE(distance(-5.f, -10.f) == uapprox(5.f));
|
||||
STATIC_CHECK(distance(5.f, 10.f) == uapprox(5.f));
|
||||
STATIC_CHECK(distance(-5.f, -10.f) == uapprox(5.f));
|
||||
|
||||
STATIC_REQUIRE(distance2(5.f, 10.f) == uapprox(25.f));
|
||||
STATIC_REQUIRE(distance2(-5.f, -10.f) == uapprox(25.f));
|
||||
STATIC_CHECK(distance2(5.f, 10.f) == uapprox(25.f));
|
||||
STATIC_CHECK(distance2(-5.f, -10.f) == uapprox(25.f));
|
||||
|
||||
STATIC_REQUIRE(dot(2.f, 5.f) == uapprox(10.f));
|
||||
REQUIRE(normalize(0.5f) == uapprox(1.f));
|
||||
STATIC_CHECK(dot(2.f, 5.f) == uapprox(10.f));
|
||||
CHECK(normalize(0.5f) == uapprox(1.f));
|
||||
|
||||
STATIC_REQUIRE(faceforward(1.f, 2.f, 3.f) == uapprox(-1.f));
|
||||
STATIC_REQUIRE(reflect(1.f, 2.f) == uapprox(-7.f));
|
||||
REQUIRE(refract(1.f, 2.f, 1.f) == uapprox(-7.f));
|
||||
STATIC_CHECK(faceforward(1.f, 2.f, 3.f) == uapprox(-1.f));
|
||||
STATIC_CHECK(reflect(1.f, 2.f) == uapprox(-7.f));
|
||||
CHECK(refract(1.f, 2.f, 1.f) == uapprox(-7.f));
|
||||
}
|
||||
|
||||
SUBCASE("Relational Functions") {
|
||||
STATIC_REQUIRE_FALSE(any(false));
|
||||
STATIC_REQUIRE_FALSE(any(0));
|
||||
STATIC_REQUIRE(any(true));
|
||||
STATIC_REQUIRE(any(1));
|
||||
STATIC_CHECK_FALSE(any(false));
|
||||
STATIC_CHECK_FALSE(any(0));
|
||||
STATIC_CHECK(any(true));
|
||||
STATIC_CHECK(any(1));
|
||||
|
||||
STATIC_REQUIRE_FALSE(all(false));
|
||||
STATIC_REQUIRE_FALSE(all(0));
|
||||
STATIC_REQUIRE(all(true));
|
||||
STATIC_REQUIRE(all(1));
|
||||
STATIC_CHECK_FALSE(all(false));
|
||||
STATIC_CHECK_FALSE(all(0));
|
||||
STATIC_CHECK(all(true));
|
||||
STATIC_CHECK(all(1));
|
||||
|
||||
STATIC_REQUIRE(approx(1, 1));
|
||||
STATIC_REQUIRE_FALSE(approx(0, 1));
|
||||
STATIC_REQUIRE_FALSE(approx(0, 1, 0));
|
||||
STATIC_REQUIRE(approx(0, 1, 1));
|
||||
STATIC_CHECK(approx(1, 1));
|
||||
STATIC_CHECK_FALSE(approx(0, 1));
|
||||
STATIC_CHECK_FALSE(approx(0, 1, 0));
|
||||
STATIC_CHECK(approx(0, 1, 1));
|
||||
|
||||
STATIC_REQUIRE(approx(1.f, 1.f + std::numeric_limits<float>::epsilon() * 0.5f));
|
||||
STATIC_REQUIRE_FALSE(approx(1.f, 1.f + std::numeric_limits<float>::epsilon() * 1.5f));
|
||||
STATIC_REQUIRE(approx(100.f, 100.f + std::numeric_limits<float>::epsilon() * 90.f));
|
||||
STATIC_REQUIRE_FALSE(approx(100.f, 100.f + std::numeric_limits<float>::epsilon() * 110.f));
|
||||
STATIC_CHECK(approx(1.f, 1.f + std::numeric_limits<float>::epsilon() * 0.5f));
|
||||
STATIC_CHECK_FALSE(approx(1.f, 1.f + std::numeric_limits<float>::epsilon() * 1.5f));
|
||||
STATIC_CHECK(approx(100.f, 100.f + std::numeric_limits<float>::epsilon() * 90.f));
|
||||
STATIC_CHECK_FALSE(approx(100.f, 100.f + std::numeric_limits<float>::epsilon() * 110.f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "vmath_tests.hpp"
|
||||
#include "doctest/doctest.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -32,201 +31,175 @@ namespace
|
||||
|
||||
TEST_CASE("vmath/mat_fun") {
|
||||
SUBCASE("detail") {
|
||||
STATIC_REQUIRE(map_join([](const int2& x){
|
||||
STATIC_CHECK(map_join([](const int2& x){
|
||||
return x * 2;
|
||||
}, int2x2{}) == int2x2(2,0,0,2));
|
||||
|
||||
STATIC_REQUIRE(map_join([](const int2& x, const int2& y){
|
||||
STATIC_CHECK(map_join([](const int2& x, const int2& y){
|
||||
return x + y;
|
||||
}, int2x2{}, int2x2{}) == int2x2(2,0,0,2));
|
||||
|
||||
STATIC_REQUIRE(map_join([](const int2& x, const int2& y, const int2& z){
|
||||
STATIC_CHECK(map_join([](const int2& x, const int2& y, const int2& z){
|
||||
return x + y + z;
|
||||
}, int2x2{}, int2x2{}, int2x2{}) == int2x2(3,0,0,3));
|
||||
|
||||
STATIC_REQUIRE(fold_join([](int acc, const int2& x){
|
||||
STATIC_CHECK(fold_join([](int acc, const int2& x){
|
||||
return acc + x.x;
|
||||
}, 0, int2x2{}) == 1);
|
||||
|
||||
STATIC_REQUIRE(fold_join([](int acc, const int2& x, const int2& y){
|
||||
STATIC_CHECK(fold_join([](int acc, const int2& x, const int2& y){
|
||||
return acc + x.x + y.x;
|
||||
}, 0, int2x2{}, int2x2{}) == 2);
|
||||
|
||||
STATIC_REQUIRE(fold1_join([](const int2& acc, const int2& x){
|
||||
STATIC_CHECK(fold1_join([](const int2& acc, const int2& x){
|
||||
return acc + x;
|
||||
}, int2x2{}) == int2(1,1));
|
||||
}
|
||||
|
||||
SUBCASE("operators") {
|
||||
STATIC_REQUIRE(-int2x2(1,2,3,4) == int2x2(-1,-2,-3,-4));
|
||||
STATIC_REQUIRE(~uint2x2(0xF0F0F0F0,0x0F0F0F0F,0xF0F0F0F0,0x0F0F0F0F) == uint2x2(0x0F0F0F0F,0xF0F0F0F0,0x0F0F0F0F,0xF0F0F0F0));
|
||||
STATIC_REQUIRE(!int2x2(-1,0,1,2) == bool2x2(false,true,false,false));
|
||||
STATIC_CHECK(+int2x2(1,-2,3,-4) == int2x2(1,-2,3,-4));
|
||||
STATIC_CHECK(-int2x2(1,-2,3,-4) == int2x2(-1,2,-3,4));
|
||||
STATIC_CHECK(~uint2x2(0xF0F0F0F0,0x0F0F0F0F,0xF0F0F0F0,0x0F0F0F0F) == uint2x2(0x0F0F0F0F,0xF0F0F0F0,0x0F0F0F0F,0xF0F0F0F0));
|
||||
STATIC_CHECK((!int2x2(-1,0,1,2)) == bool2x2(false,true,false,false));
|
||||
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4) + 2 == int2x2(3,4,5,6));
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4) - 2 == int2x2(-1,0,1,2));
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4) * 2 == int2x2(2,4,6,8));
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4) / 2 == int2x2(0,1,1,2));
|
||||
STATIC_REQUIRE((int2x2(11,12,11,12) & 6) == int2x2(2,4,2,4));
|
||||
STATIC_REQUIRE((int2x2(11,12,11,12) | 6) == int2x2(15,14,15,14));
|
||||
STATIC_REQUIRE((int2x2(11,12,11,12) ^ 6) == int2x2(13,10,13,10));
|
||||
STATIC_REQUIRE((int2x2(1,0,1,0) && 1) == bool2x2(1,0,1,0));
|
||||
STATIC_REQUIRE((int2x2(1,0,1,0) || 1) == bool2x2(1,1,1,1));
|
||||
STATIC_CHECK(int2x2(1,2,3,4) + 2 == int2x2(3,4,5,6));
|
||||
STATIC_CHECK(int2x2(1,2,3,4) - 2 == int2x2(-1,0,1,2));
|
||||
STATIC_CHECK(int2x2(1,2,3,4) * 2 == int2x2(2,4,6,8));
|
||||
STATIC_CHECK(int2x2(1,2,3,4) / 2 == int2x2(0,1,1,2));
|
||||
STATIC_CHECK((int2x2(11,12,11,12) & 6) == int2x2(2,4,2,4));
|
||||
STATIC_CHECK((int2x2(11,12,11,12) | 6) == int2x2(15,14,15,14));
|
||||
STATIC_CHECK((int2x2(11,12,11,12) ^ 6) == int2x2(13,10,13,10));
|
||||
STATIC_CHECK((int2x2(1,0,1,0) && 1) == bool2x2(1,0,1,0));
|
||||
STATIC_CHECK((int2x2(1,0,1,0) || 1) == bool2x2(1,1,1,1));
|
||||
|
||||
STATIC_REQUIRE(4 + int2x2(1,2,3,4) == int2x2(5,6,7,8));
|
||||
STATIC_REQUIRE(4 - int2x2(1,2,3,4) == int2x2(3,2,1,0));
|
||||
STATIC_REQUIRE(4 * int2x2(1,2,3,4) == int2x2(4,8,12,16));
|
||||
STATIC_REQUIRE(4 / int2x2(1,2,3,4) == int2x2(4,2,1,1));
|
||||
STATIC_REQUIRE((6 &int2x2(11,12,11,12)) == int2x2(2,4,2,4));
|
||||
STATIC_REQUIRE((6 |int2x2(11,12,11,12)) == int2x2(15,14,15,14));
|
||||
STATIC_REQUIRE((6 ^ int2x2(11,12,11,12)) == int2x2(13,10,13,10));
|
||||
STATIC_REQUIRE((1 && int2x2(1,0,1,0)) == bool2x2(1,0,1,0));
|
||||
STATIC_REQUIRE((1 || int2x2(1,0,1,0)) == bool2x2(1,1,1,1));
|
||||
STATIC_CHECK(4 + int2x2(1,2,3,4) == int2x2(5,6,7,8));
|
||||
STATIC_CHECK(4 - int2x2(1,2,3,4) == int2x2(3,2,1,0));
|
||||
STATIC_CHECK(4 * int2x2(1,2,3,4) == int2x2(4,8,12,16));
|
||||
STATIC_CHECK(4 / int2x2(1,2,3,4) == int2x2(4,2,1,1));
|
||||
STATIC_CHECK((6 &int2x2(11,12,11,12)) == int2x2(2,4,2,4));
|
||||
STATIC_CHECK((6 |int2x2(11,12,11,12)) == int2x2(15,14,15,14));
|
||||
STATIC_CHECK((6 ^ int2x2(11,12,11,12)) == int2x2(13,10,13,10));
|
||||
STATIC_CHECK((1 && int2x2(1,0,1,0)) == bool2x2(1,0,1,0));
|
||||
STATIC_CHECK((1 || int2x2(1,0,1,0)) == bool2x2(1,1,1,1));
|
||||
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4) + int2x2(5,6,7,8) == int2x2(6,8,10,12));
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4) - int2x2(5,6,7,8) == int2x2(-4,-4,-4,-4));
|
||||
STATIC_CHECK(int2x2(1,2,3,4) + int2x2(5,6,7,8) == int2x2(6,8,10,12));
|
||||
STATIC_CHECK(int2x2(1,2,3,4) - int2x2(5,6,7,8) == int2x2(-4,-4,-4,-4));
|
||||
|
||||
STATIC_REQUIRE(int2x2() * int2x2() == int2x2());
|
||||
STATIC_REQUIRE(int3x3() * int3x3() == int3x3());
|
||||
STATIC_CHECK(int2x2() * int2x2() == int2x2());
|
||||
STATIC_CHECK(int3x3() * int3x3() == int3x3());
|
||||
|
||||
STATIC_REQUIRE(int2(1,2) * int2x2() == int2(1,2));
|
||||
STATIC_REQUIRE(int3(1,2,3) * int3x3() == int3(1,2,3));
|
||||
STATIC_REQUIRE(int4(1,2,3,4) * int4x4() == int4(1,2,3,4));
|
||||
STATIC_CHECK(int2(1,2) * int2x2() == int2(1,2));
|
||||
STATIC_CHECK(int3(1,2,3) * int3x3() == int3(1,2,3));
|
||||
STATIC_CHECK(int4(1,2,3,4) * int4x4() == int4(1,2,3,4));
|
||||
|
||||
STATIC_REQUIRE((int2x2(6,7,6,7) & int2x2(11,12,11,12)) == int2x2(2,4,2,4));
|
||||
STATIC_REQUIRE((int2x2(6,7,6,7) | int2x2(11,12,11,12)) == int2x2(15,15,15,15));
|
||||
STATIC_REQUIRE((int2x2(6,7,6,7) ^ int2x2(11,12,11,12)) == int2x2(13,11,13,11));
|
||||
STATIC_REQUIRE((int2x2(0,1,0,1) && int2x2(1,0,1,0)) == bool2x2(0,0,0,0));
|
||||
STATIC_REQUIRE((int2x2(0,1,0,1) || int2x2(1,0,1,0)) == bool2x2(1,1,1,1));
|
||||
STATIC_CHECK((int2x2(6,7,6,7) & int2x2(11,12,11,12)) == int2x2(2,4,2,4));
|
||||
STATIC_CHECK((int2x2(6,7,6,7) | int2x2(11,12,11,12)) == int2x2(15,15,15,15));
|
||||
STATIC_CHECK((int2x2(6,7,6,7) ^ int2x2(11,12,11,12)) == int2x2(13,11,13,11));
|
||||
STATIC_CHECK((int2x2(0,1,0,1) && int2x2(1,0,1,0)) == bool2x2(0,0,0,0));
|
||||
STATIC_CHECK((int2x2(0,1,0,1) || int2x2(1,0,1,0)) == bool2x2(1,1,1,1));
|
||||
|
||||
{
|
||||
int2x2 v{1,2,3,4};
|
||||
REQUIRE(&v == &(v += 3));
|
||||
REQUIRE(v == int2x2{4,5,6,7});
|
||||
REQUIRE(&v == &(v += int2x2{1,2,3,4}));
|
||||
REQUIRE(v == int2x2{5,7,9,11});
|
||||
CHECK(&v == &(v += 3));
|
||||
CHECK(v == int2x2{4,5,6,7});
|
||||
CHECK(&v == &(v += int2x2{1,2,3,4}));
|
||||
CHECK(v == int2x2{5,7,9,11});
|
||||
}
|
||||
{
|
||||
int2x2 v{4,5,6,7};
|
||||
REQUIRE(&v == &(v -= 3));
|
||||
REQUIRE(v == int2x2{1,2,3,4});
|
||||
REQUIRE(&v == &(v -= int2x2{2,4,6,8}));
|
||||
REQUIRE(v == int2x2{-1,-2,-3,-4});
|
||||
CHECK(&v == &(v -= 3));
|
||||
CHECK(v == int2x2{1,2,3,4});
|
||||
CHECK(&v == &(v -= int2x2{2,4,6,8}));
|
||||
CHECK(v == int2x2{-1,-2,-3,-4});
|
||||
}
|
||||
{
|
||||
int2x2 v{1,2,3,4};
|
||||
REQUIRE(&v == &(v *= 3));
|
||||
REQUIRE(v == int2x2{3,6,9,12});
|
||||
CHECK(&v == &(v *= 3));
|
||||
CHECK(v == int2x2{3,6,9,12});
|
||||
}
|
||||
{
|
||||
int4 v{0, 0, 0, 1};
|
||||
REQUIRE(&v == &(v *= translate(int3{1,2,3})));
|
||||
REQUIRE(v == uapprox4(1,2,3,1));
|
||||
CHECK(&v == &(v *= translate(int3{1,2,3})));
|
||||
CHECK(v == uapprox4(1,2,3,1));
|
||||
}
|
||||
{
|
||||
int3 v{1, 2, 3};
|
||||
REQUIRE(&v == &(v *= int3x3(scale(int3{2,3,4}))));
|
||||
REQUIRE(v == int3(2,6,12));
|
||||
CHECK(&v == &(v *= int3x3(scale(int3{2,3,4}))));
|
||||
CHECK(v == int3(2,6,12));
|
||||
}
|
||||
{
|
||||
int4x4 v = translate(int3{1, 2, 3});
|
||||
REQUIRE(&v == &(v *= translate(int3{1,2,3})));
|
||||
REQUIRE(v == translate(int3{2,4,6}));
|
||||
CHECK(&v == &(v *= translate(int3{1,2,3})));
|
||||
CHECK(v == translate(int3{2,4,6}));
|
||||
}
|
||||
{
|
||||
int3x3 v = int3x3(scale(int3{1, 2, 3}));
|
||||
REQUIRE(&v == &(v *= int3x3(scale(int3{2,3,4}))));
|
||||
REQUIRE(v == int3x3(scale(int3{2,6,12})));
|
||||
CHECK(&v == &(v *= int3x3(scale(int3{2,3,4}))));
|
||||
CHECK(v == int3x3(scale(int3{2,6,12})));
|
||||
}
|
||||
{
|
||||
int2x2 v1{11,12,11,12};
|
||||
REQUIRE(&v1 == &(v1 &= 6));
|
||||
REQUIRE(v1 == int2x2(2,4,2,4));
|
||||
CHECK(&v1 == &(v1 &= 6));
|
||||
CHECK(v1 == int2x2(2,4,2,4));
|
||||
int2x2 v2{6,7,6,7};
|
||||
REQUIRE(&v2 == &(v2 &= int2x2(11,12,11,12)));
|
||||
REQUIRE(v2 == int2x2(2,4,2,4));
|
||||
CHECK(&v2 == &(v2 &= int2x2(11,12,11,12)));
|
||||
CHECK(v2 == int2x2(2,4,2,4));
|
||||
}
|
||||
{
|
||||
int2x2 v1{11,12,11,12};
|
||||
REQUIRE(&v1 == &(v1 |= 6));
|
||||
REQUIRE(v1 == int2x2(15,14,15,14));
|
||||
CHECK(&v1 == &(v1 |= 6));
|
||||
CHECK(v1 == int2x2(15,14,15,14));
|
||||
int2x2 v2{6,7,6,7};
|
||||
REQUIRE(&v2 == &(v2 |= int2x2(11,12,11,12)));
|
||||
REQUIRE(v2 == int2x2(15,15,15,15));
|
||||
CHECK(&v2 == &(v2 |= int2x2(11,12,11,12)));
|
||||
CHECK(v2 == int2x2(15,15,15,15));
|
||||
}
|
||||
{
|
||||
int2x2 v1{11,12,11,12};
|
||||
REQUIRE(&v1 == &(v1 ^= 6));
|
||||
REQUIRE(v1 == int2x2(13,10,13,10));
|
||||
CHECK(&v1 == &(v1 ^= 6));
|
||||
CHECK(v1 == int2x2(13,10,13,10));
|
||||
int2x2 v2{6,7,6,7};
|
||||
REQUIRE(&v2 == &(v2 ^= int2x2(11,12,11,12)));
|
||||
REQUIRE(v2 == int2x2(13,11,13,11));
|
||||
CHECK(&v2 == &(v2 ^= int2x2(11,12,11,12)));
|
||||
CHECK(v2 == int2x2(13,11,13,11));
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("relational functions") {
|
||||
STATIC_REQUIRE_FALSE(any(bool2x2(false, false, false, false)));
|
||||
STATIC_REQUIRE(any(bool2x2(true, false, true, false)));
|
||||
STATIC_REQUIRE(any(bool2x2(false, true, false, true)));
|
||||
STATIC_REQUIRE(any(bool2x2(true, true, true, true)));
|
||||
STATIC_CHECK_FALSE(any(bool2x2(false, false, false, false)));
|
||||
STATIC_CHECK(any(bool2x2(true, false, true, false)));
|
||||
STATIC_CHECK(any(bool2x2(false, true, false, true)));
|
||||
STATIC_CHECK(any(bool2x2(true, true, true, true)));
|
||||
|
||||
STATIC_REQUIRE_FALSE(any(int2x2(0, 0, 0, 0)));
|
||||
STATIC_REQUIRE(any(int2x2(1, 0, 1, 0)));
|
||||
STATIC_REQUIRE(any(int2x2(0, 1, 0, 1)));
|
||||
STATIC_REQUIRE(any(int2x2(1, 1, 1, 1)));
|
||||
STATIC_CHECK_FALSE(any(int2x2(0, 0, 0, 0)));
|
||||
STATIC_CHECK(any(int2x2(1, 0, 1, 0)));
|
||||
STATIC_CHECK(any(int2x2(0, 1, 0, 1)));
|
||||
STATIC_CHECK(any(int2x2(1, 1, 1, 1)));
|
||||
|
||||
STATIC_REQUIRE_FALSE(all(bool2x2(false, false, false, false)));
|
||||
STATIC_REQUIRE_FALSE(all(bool2x2(true, false, true, false)));
|
||||
STATIC_REQUIRE_FALSE(all(bool2x2(false, true, false, true)));
|
||||
STATIC_REQUIRE(all(bool2x2(true, true, true, true)));
|
||||
STATIC_CHECK_FALSE(all(bool2x2(false, false, false, false)));
|
||||
STATIC_CHECK_FALSE(all(bool2x2(true, false, true, false)));
|
||||
STATIC_CHECK_FALSE(all(bool2x2(false, true, false, true)));
|
||||
STATIC_CHECK(all(bool2x2(true, true, true, true)));
|
||||
|
||||
STATIC_REQUIRE_FALSE(all(int2x2(0, 0, 0, 0)));
|
||||
STATIC_REQUIRE_FALSE(all(int2x2(1, 0, 1, 0)));
|
||||
STATIC_REQUIRE_FALSE(all(int2x2(0, 1, 0, 1)));
|
||||
STATIC_REQUIRE(all(int2x2(1, 1, 1, 1)));
|
||||
STATIC_CHECK_FALSE(all(int2x2(0, 0, 0, 0)));
|
||||
STATIC_CHECK_FALSE(all(int2x2(1, 0, 1, 0)));
|
||||
STATIC_CHECK_FALSE(all(int2x2(0, 1, 0, 1)));
|
||||
STATIC_CHECK(all(int2x2(1, 1, 1, 1)));
|
||||
|
||||
STATIC_REQUIRE(approx(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(false, true, false, false));
|
||||
STATIC_REQUIRE(approx(int2x2(0,1,2,3),1) == bool2x2(false, true, false, false));
|
||||
STATIC_REQUIRE(approx(1,int2x2(0,1,2,3)) == bool2x2(false, true, false, false));
|
||||
STATIC_CHECK(approx(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(false, true, false, false));
|
||||
STATIC_CHECK(approx(int2x2(1,1,1,1), int2x2(0,1,2,3), 0) == bool2x2(false, true, false, false));
|
||||
STATIC_CHECK(approx(int2x2(1,1,1,1), int2x2(0,1,2,3), 1) == bool2x2(true, true, true, false));
|
||||
STATIC_CHECK(approx(int2x2(1,1,1,1), int2x2(0,1,2,3), 2) == bool2x2(true, true, true, true));
|
||||
|
||||
STATIC_REQUIRE(approx(int2x2(1,1,1,1), int2x2(0,1,2,3), 0) == bool2x2(false, true, false, false));
|
||||
STATIC_REQUIRE(approx(int2x2(0,1,2,3), 1, 0) == bool2x2(false, true, false, false));
|
||||
STATIC_REQUIRE(approx(1, int2x2(0,1,2,3), 0) == bool2x2(false, true, false, false));
|
||||
STATIC_CHECK(less(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(false, false, true, true));
|
||||
STATIC_CHECK(less_equal(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(false, true, true, true));
|
||||
STATIC_CHECK(greater(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(true, false, false, false));
|
||||
STATIC_CHECK(greater_equal(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(true, true, false, false));
|
||||
|
||||
STATIC_REQUIRE(approx(int2x2(1,1,1,1), int2x2(0,1,2,3), 1) == bool2x2(true, true, true, false));
|
||||
STATIC_REQUIRE(approx(int2x2(0,1,2,3), 1, 1) == bool2x2(true, true, true, false));
|
||||
STATIC_REQUIRE(approx(1, int2x2(0,1,2,3), 1) == bool2x2(true, true, true, false));
|
||||
|
||||
STATIC_REQUIRE(approx(int2x2(1,1,1,1), int2x2(0,1,2,3), 2) == bool2x2(true, true, true, true));
|
||||
STATIC_REQUIRE(approx(int2x2(0,1,2,3), 1, 2) == bool2x2(true, true, true, true));
|
||||
STATIC_REQUIRE(approx(1, int2x2(0,1,2,3), 2) == bool2x2(true, true, true, true));
|
||||
|
||||
STATIC_REQUIRE(less(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(false, false, true, true));
|
||||
STATIC_REQUIRE(less(int2x2(0,1,2,3), 1) == bool2x2(true, false, false, false));
|
||||
STATIC_REQUIRE(less(1, int2x2(0,1,2,3)) == bool2x2(false, false, true, true));
|
||||
|
||||
STATIC_REQUIRE(less_equal(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(false, true, true, true));
|
||||
STATIC_REQUIRE(less_equal(int2x2(0,1,2,3), 1) == bool2x2(true, true, false, false));
|
||||
STATIC_REQUIRE(less_equal(1, int2x2(0,1,2,3)) == bool2x2(false, true, true, true));
|
||||
|
||||
STATIC_REQUIRE(greater(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(true, false, false, false));
|
||||
STATIC_REQUIRE(greater(int2x2(0,1,2,3), 1) == bool2x2(false, false, true, true));
|
||||
STATIC_REQUIRE(greater(1, int2x2(0,1,2,3)) == bool2x2(true, false, false, false));
|
||||
|
||||
STATIC_REQUIRE(greater_equal(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(true, true, false, false));
|
||||
STATIC_REQUIRE(greater_equal(int2x2(0,1,2,3), 1) == bool2x2(false, true, true, true));
|
||||
STATIC_REQUIRE(greater_equal(1, int2x2(0,1,2,3)) == bool2x2(true, true, false, false));
|
||||
|
||||
STATIC_REQUIRE(equal_to(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(false, true, false, false));
|
||||
STATIC_REQUIRE(equal_to(int2x2(0,1,2,3),1) == bool2x2(false, true, false, false));
|
||||
STATIC_REQUIRE(equal_to(1,int2x2(0,1,2,3)) == bool2x2(false, true, false, false));
|
||||
|
||||
STATIC_REQUIRE(not_equal_to(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(true, false, true, true));
|
||||
STATIC_REQUIRE(not_equal_to(int2x2(0,1,2,3),1) == bool2x2(true, false, true, true));
|
||||
STATIC_REQUIRE(not_equal_to(1,int2x2(0,1,2,3)) == bool2x2(true, false, true, true));
|
||||
STATIC_CHECK(equal_to(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(false, true, false, false));
|
||||
STATIC_CHECK(not_equal_to(int2x2(1,1,1,1), int2x2(0,1,2,3)) == bool2x2(true, false, true, true));
|
||||
}
|
||||
|
||||
SUBCASE("transpose") {
|
||||
STATIC_REQUIRE(transpose(int2x2(
|
||||
STATIC_CHECK(transpose(int2x2(
|
||||
1, 2,
|
||||
3, 4
|
||||
)) == int2x2(
|
||||
@@ -234,7 +207,7 @@ TEST_CASE("vmath/mat_fun") {
|
||||
2, 4
|
||||
));
|
||||
|
||||
STATIC_REQUIRE(transpose(int3x3(
|
||||
STATIC_CHECK(transpose(int3x3(
|
||||
1, 2, 3,
|
||||
4, 5, 6,
|
||||
7, 8, 9
|
||||
@@ -244,7 +217,7 @@ TEST_CASE("vmath/mat_fun") {
|
||||
3, 6, 9
|
||||
));
|
||||
|
||||
STATIC_REQUIRE(transpose(int4x4(
|
||||
STATIC_CHECK(transpose(int4x4(
|
||||
1, 2, 3, 4,
|
||||
5, 6, 7, 8,
|
||||
9, 10, 11, 12,
|
||||
@@ -261,65 +234,61 @@ TEST_CASE("vmath/mat_fun") {
|
||||
constexpr int2x2 m2{1,2,3,4};
|
||||
constexpr int3x3 m3{1,2,3,4,5,6,7,8,9};
|
||||
constexpr int4x4 m4{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
|
||||
STATIC_REQUIRE(determinant(m2) == determinant(transpose(m2)));
|
||||
STATIC_REQUIRE(determinant(m3) == determinant(transpose(m3)));
|
||||
STATIC_REQUIRE(determinant(m4) == determinant(transpose(m4)));
|
||||
STATIC_CHECK(determinant(m2) == determinant(transpose(m2)));
|
||||
STATIC_CHECK(determinant(m3) == determinant(transpose(m3)));
|
||||
STATIC_CHECK(determinant(m4) == determinant(transpose(m4)));
|
||||
|
||||
STATIC_REQUIRE(determinant(generate_frank_matrix<int, 2>()) == 1);
|
||||
STATIC_REQUIRE(determinant(generate_frank_matrix<int, 3>()) == 1);
|
||||
STATIC_REQUIRE(determinant(generate_frank_matrix<int, 4>()) == 1);
|
||||
STATIC_CHECK(determinant(generate_frank_matrix<int, 2>()) == 1);
|
||||
STATIC_CHECK(determinant(generate_frank_matrix<int, 3>()) == 1);
|
||||
STATIC_CHECK(determinant(generate_frank_matrix<int, 4>()) == 1);
|
||||
|
||||
STATIC_REQUIRE(determinant(transpose(generate_frank_matrix<int, 2>())) == 1);
|
||||
STATIC_REQUIRE(determinant(transpose(generate_frank_matrix<int, 3>())) == 1);
|
||||
STATIC_REQUIRE(determinant(transpose(generate_frank_matrix<int, 4>())) == 1);
|
||||
STATIC_CHECK(determinant(transpose(generate_frank_matrix<int, 2>())) == 1);
|
||||
STATIC_CHECK(determinant(transpose(generate_frank_matrix<int, 3>())) == 1);
|
||||
STATIC_CHECK(determinant(transpose(generate_frank_matrix<int, 4>())) == 1);
|
||||
}
|
||||
|
||||
SUBCASE("inverse") {
|
||||
STATIC_REQUIRE(inverse(float2x2()) == float2x2());
|
||||
STATIC_REQUIRE(inverse(float3x3()) == float3x3());
|
||||
STATIC_REQUIRE(inverse(float4x4()) == float4x4());
|
||||
STATIC_CHECK(inverse(float2x2()) == float2x2());
|
||||
STATIC_CHECK(inverse(float3x3()) == float3x3());
|
||||
STATIC_CHECK(inverse(float4x4()) == float4x4());
|
||||
|
||||
STATIC_REQUIRE(inverse(float2x2(0.5)) == float2x2(2.f));
|
||||
STATIC_REQUIRE(inverse(float3x3(0.5)) == float3x3(2.f));
|
||||
STATIC_REQUIRE(inverse(float4x4(0.5)) == float4x4(2.f));
|
||||
STATIC_CHECK(inverse(float2x2(0.5)) == float2x2(2.f));
|
||||
STATIC_CHECK(inverse(float3x3(0.5)) == float3x3(2.f));
|
||||
STATIC_CHECK(inverse(float4x4(0.5)) == float4x4(2.f));
|
||||
|
||||
{
|
||||
constexpr float4x4 m1 = translate(float3(1.f, 2.f, 3.f));
|
||||
constexpr float4x4 rm1 = inverse(m1);
|
||||
STATIC_REQUIRE(all(approx(
|
||||
STATIC_CHECK(all(approx(
|
||||
unit4_z<float> * m1 * rm1,
|
||||
unit4_z<float>,
|
||||
uapprox_epsilon_v<float>)));
|
||||
unit4_z<float>)));
|
||||
}
|
||||
|
||||
{
|
||||
const float3 axis2 = normalize(float3(1.f, 2.f, 3.f));
|
||||
const float4x4 m2 = rotate(0.5f,axis2);
|
||||
const float4x4 rm2 = inverse(m2);
|
||||
REQUIRE(all(approx(
|
||||
CHECK(all(approx(
|
||||
unit4_z<float> * m2 * rm2,
|
||||
unit4_z<float>,
|
||||
uapprox_epsilon_v<float>)));
|
||||
unit4_z<float>)));
|
||||
}
|
||||
|
||||
{
|
||||
const float3 axis3 = normalize(float3(1.f, 2.f, 3.f));
|
||||
const float3x3 m3 = float3x3(rotate(0.5f,axis3));
|
||||
const float3x3 rm3 = inverse(m3);
|
||||
REQUIRE(all(approx(
|
||||
CHECK(all(approx(
|
||||
unit3_z<float> * m3 * rm3,
|
||||
unit3_z<float>,
|
||||
uapprox_epsilon_v<float>)));
|
||||
unit3_z<float>)));
|
||||
}
|
||||
|
||||
{
|
||||
const float3 axis4 = normalize(float3(0.f, 0.f, 3.f));
|
||||
const float2x2 m4 = float2x2(rotate(0.5f,axis4));
|
||||
const float2x2 rm4 = inverse(m4);
|
||||
REQUIRE(all(approx(
|
||||
CHECK(all(approx(
|
||||
unit2_y<float> * m4 * rm4,
|
||||
unit2_y<float>,
|
||||
uapprox_epsilon_v<float>)));
|
||||
unit2_y<float>)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "vmath_tests.hpp"
|
||||
#include "doctest/doctest.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -15,81 +14,81 @@ namespace
|
||||
|
||||
TEST_CASE("vmath/mat") {
|
||||
SUBCASE("size/sizeof") {
|
||||
STATIC_REQUIRE(int2x2{}.size == 2);
|
||||
STATIC_REQUIRE(int3x3{}.size == 3);
|
||||
STATIC_REQUIRE(int4x4{}.size == 4);
|
||||
STATIC_CHECK(int2x2{}.size == 2);
|
||||
STATIC_CHECK(int3x3{}.size == 3);
|
||||
STATIC_CHECK(int4x4{}.size == 4);
|
||||
|
||||
STATIC_REQUIRE(sizeof(int2x2{}) == sizeof(int) * 2 * 2);
|
||||
STATIC_REQUIRE(sizeof(int3x3{}) == sizeof(int) * 3 * 3);
|
||||
STATIC_REQUIRE(sizeof(int4x4{}) == sizeof(int) * 4 * 4);
|
||||
STATIC_CHECK(sizeof(int2x2{}) == sizeof(int) * 2 * 2);
|
||||
STATIC_CHECK(sizeof(int3x3{}) == sizeof(int) * 3 * 3);
|
||||
STATIC_CHECK(sizeof(int4x4{}) == sizeof(int) * 4 * 4);
|
||||
}
|
||||
|
||||
SUBCASE("guides") {
|
||||
STATIC_REQUIRE(mat{1,2,3,4}.size == 2);
|
||||
STATIC_REQUIRE(mat{{1,2},{3,4}}.size == 2);
|
||||
STATIC_REQUIRE(mat{vec{1,2},vec{3,4}}.size == 2);
|
||||
STATIC_CHECK(mat{1,2,3,4}.size == 2);
|
||||
STATIC_CHECK(mat{{1,2},{3,4}}.size == 2);
|
||||
STATIC_CHECK(mat{vec{1,2},vec{3,4}}.size == 2);
|
||||
|
||||
STATIC_REQUIRE(mat{1,2,3,4,5,6,7,8,9}.size == 3);
|
||||
STATIC_REQUIRE(mat{{1,2,3},{4,5,6},{7,8,9}}.size == 3);
|
||||
STATIC_REQUIRE(mat{vec{1,2,3},vec{4,5,6},vec{7,8,9}}.size == 3);
|
||||
STATIC_REQUIRE(mat{mat{1,2,3,4},vec{5,6}}.size == 3);
|
||||
STATIC_CHECK(mat{1,2,3,4,5,6,7,8,9}.size == 3);
|
||||
STATIC_CHECK(mat{{1,2,3},{4,5,6},{7,8,9}}.size == 3);
|
||||
STATIC_CHECK(mat{vec{1,2,3},vec{4,5,6},vec{7,8,9}}.size == 3);
|
||||
STATIC_CHECK(mat{mat{1,2,3,4},vec{5,6}}.size == 3);
|
||||
|
||||
STATIC_REQUIRE(mat{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}.size == 4);
|
||||
STATIC_REQUIRE(mat{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}}.size == 4);
|
||||
STATIC_REQUIRE(mat{vec{1,2,3,4},vec{5,6,7,8},vec{9,10,11,12},vec{13,14,15,16}}.size == 4);
|
||||
STATIC_REQUIRE(mat{mat{1,2,3,4,5,6,7,8,9},vec{5,6,7}}.size == 4);
|
||||
STATIC_CHECK(mat{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}.size == 4);
|
||||
STATIC_CHECK(mat{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}}.size == 4);
|
||||
STATIC_CHECK(mat{vec{1,2,3,4},vec{5,6,7,8},vec{9,10,11,12},vec{13,14,15,16}}.size == 4);
|
||||
STATIC_CHECK(mat{mat{1,2,3,4,5,6,7,8,9},vec{5,6,7}}.size == 4);
|
||||
}
|
||||
|
||||
SUBCASE("ctors") {
|
||||
{
|
||||
STATIC_REQUIRE(int2x2()[0] == int2(1,0));
|
||||
STATIC_REQUIRE(int2x2()[1] == int2(0,1));
|
||||
STATIC_CHECK(int2x2()[0] == int2(1,0));
|
||||
STATIC_CHECK(int2x2()[1] == int2(0,1));
|
||||
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4)[0] == int2(1,2));
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4)[1] == int2(3,4));
|
||||
STATIC_CHECK(int2x2(1,2,3,4)[0] == int2(1,2));
|
||||
STATIC_CHECK(int2x2(1,2,3,4)[1] == int2(3,4));
|
||||
|
||||
STATIC_REQUIRE(int2x2({1,2},{3,4})[0] == int2(1,2));
|
||||
STATIC_REQUIRE(int2x2({1,2},{3,4})[1] == int2(3,4));
|
||||
STATIC_CHECK(int2x2({1,2},{3,4})[0] == int2(1,2));
|
||||
STATIC_CHECK(int2x2({1,2},{3,4})[1] == int2(3,4));
|
||||
}
|
||||
{
|
||||
constexpr int2x2 v(1,2,3,4);
|
||||
constexpr int2x2 v2 = v;
|
||||
STATIC_REQUIRE(v2 == int2x2(1,2,3,4));
|
||||
STATIC_CHECK(v2 == int2x2(1,2,3,4));
|
||||
}
|
||||
{
|
||||
constexpr int2x2 v(1,2,3,4);
|
||||
constexpr int2x2 v2 = std::move(v);
|
||||
STATIC_REQUIRE(v2 == int2x2(1,2,3,4));
|
||||
STATIC_CHECK(v2 == int2x2(1,2,3,4));
|
||||
}
|
||||
{
|
||||
STATIC_REQUIRE(int2x2() == int2x2(1,0,0,1));
|
||||
STATIC_REQUIRE(int2x2(2) == int2x2(2,0,0,2));
|
||||
STATIC_REQUIRE(int2x2(int2{2,3}) == int2x2(2,0,0,3));
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4) == int2x2(1,2,3,4));
|
||||
STATIC_REQUIRE(int2x2({1,2},{3,4}) == int2x2(1,2,3,4));
|
||||
STATIC_REQUIRE(int2x2(int2x2({1,2},{3,4})) == int2x2(1,2,3,4));
|
||||
STATIC_REQUIRE(int2x2(int3x3({1,2,3},{4,5,6},{7,8,9})) == int2x2(1,2,4,5));
|
||||
STATIC_REQUIRE(int2x2(int4x4({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == int2x2(1,2,5,6));
|
||||
STATIC_CHECK(int2x2() == int2x2(1,0,0,1));
|
||||
STATIC_CHECK(int2x2(2) == int2x2(2,0,0,2));
|
||||
STATIC_CHECK(int2x2(int2{2,3}) == int2x2(2,0,0,3));
|
||||
STATIC_CHECK(int2x2(1,2,3,4) == int2x2(1,2,3,4));
|
||||
STATIC_CHECK(int2x2({1,2},{3,4}) == int2x2(1,2,3,4));
|
||||
STATIC_CHECK(int2x2(int2x2({1,2},{3,4})) == int2x2(1,2,3,4));
|
||||
STATIC_CHECK(int2x2(int3x3({1,2,3},{4,5,6},{7,8,9})) == int2x2(1,2,4,5));
|
||||
STATIC_CHECK(int2x2(int4x4({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == int2x2(1,2,5,6));
|
||||
|
||||
STATIC_REQUIRE(int3x3() == int3x3(1,0,0,0,1,0,0,0,1));
|
||||
STATIC_REQUIRE(int3x3(2) == int3x3(2,0,0,0,2,0,0,0,2));
|
||||
STATIC_REQUIRE(int3x3(int3{2,3,4}) == int3x3(2,0,0,0,3,0,0,0,4));
|
||||
STATIC_REQUIRE(int3x3(1,2,3,4,5,6,7,8,9) == int3x3(1,2,3,4,5,6,7,8,9));
|
||||
STATIC_REQUIRE(int3x3({1,2,3},{4,5,6},{7,8,9}) == int3x3(1,2,3,4,5,6,7,8,9));
|
||||
STATIC_REQUIRE(int3x3(int2x2({1,2},{3,4}),int2{5,6}) == int3x3(1,2,0,3,4,0,5,6,1));
|
||||
STATIC_REQUIRE(int3x3(int3x3({1,2,3},{4,5,6},{7,8,9})) == int3x3(1,2,3,4,5,6,7,8,9));
|
||||
STATIC_REQUIRE(int3x3(int2x2({1,2},{3,4})) == int3x3(1,2,0,3,4,0,0,0,1));
|
||||
STATIC_REQUIRE(int3x3(int4x4({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == int3x3(1,2,3,5,6,7,9,10,11));
|
||||
STATIC_CHECK(int3x3() == int3x3(1,0,0,0,1,0,0,0,1));
|
||||
STATIC_CHECK(int3x3(2) == int3x3(2,0,0,0,2,0,0,0,2));
|
||||
STATIC_CHECK(int3x3(int3{2,3,4}) == int3x3(2,0,0,0,3,0,0,0,4));
|
||||
STATIC_CHECK(int3x3(1,2,3,4,5,6,7,8,9) == int3x3(1,2,3,4,5,6,7,8,9));
|
||||
STATIC_CHECK(int3x3({1,2,3},{4,5,6},{7,8,9}) == int3x3(1,2,3,4,5,6,7,8,9));
|
||||
STATIC_CHECK(int3x3(int2x2({1,2},{3,4}),int2{5,6}) == int3x3(1,2,0,3,4,0,5,6,1));
|
||||
STATIC_CHECK(int3x3(int3x3({1,2,3},{4,5,6},{7,8,9})) == int3x3(1,2,3,4,5,6,7,8,9));
|
||||
STATIC_CHECK(int3x3(int2x2({1,2},{3,4})) == int3x3(1,2,0,3,4,0,0,0,1));
|
||||
STATIC_CHECK(int3x3(int4x4({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == int3x3(1,2,3,5,6,7,9,10,11));
|
||||
|
||||
STATIC_REQUIRE(int4x4() == int4x4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1));
|
||||
STATIC_REQUIRE(int4x4(2) == int4x4(2,0,0,0,0,2,0,0,0,0,2,0,0,0,0,2));
|
||||
STATIC_REQUIRE(int4x4(int4{2,3,4,5}) == int4x4(2,0,0,0,0,3,0,0,0,0,4,0,0,0,0,5));
|
||||
STATIC_REQUIRE(int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) == int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
|
||||
STATIC_REQUIRE(int4x4({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}) == int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
|
||||
STATIC_REQUIRE(int4x4(int3x3({1,2,3},{4,5,6},{7,8,9}),int3{10,11,12}) == int4x4(1,2,3,0,4,5,6,0,7,8,9,0,10,11,12,1));
|
||||
STATIC_REQUIRE(int4x4(int4x4({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
|
||||
STATIC_REQUIRE(int4x4(int2x2({1,2},{3,4})) == int4x4(1,2,0,0,3,4,0,0,0,0,1,0,0,0,0,1));
|
||||
STATIC_REQUIRE(int4x4(int3x3({1,2,3},{4,5,6},{7,8,9})) == int4x4(1,2,3,0,4,5,6,0,7,8,9,0,0,0,0,1));
|
||||
STATIC_CHECK(int4x4() == int4x4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1));
|
||||
STATIC_CHECK(int4x4(2) == int4x4(2,0,0,0,0,2,0,0,0,0,2,0,0,0,0,2));
|
||||
STATIC_CHECK(int4x4(int4{2,3,4,5}) == int4x4(2,0,0,0,0,3,0,0,0,0,4,0,0,0,0,5));
|
||||
STATIC_CHECK(int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) == int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
|
||||
STATIC_CHECK(int4x4({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}) == int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
|
||||
STATIC_CHECK(int4x4(int3x3({1,2,3},{4,5,6},{7,8,9}),int3{10,11,12}) == int4x4(1,2,3,0,4,5,6,0,7,8,9,0,10,11,12,1));
|
||||
STATIC_CHECK(int4x4(int4x4({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
|
||||
STATIC_CHECK(int4x4(int2x2({1,2},{3,4})) == int4x4(1,2,0,0,3,4,0,0,0,0,1,0,0,0,0,1));
|
||||
STATIC_CHECK(int4x4(int3x3({1,2,3},{4,5,6},{7,8,9})) == int4x4(1,2,3,0,4,5,6,0,7,8,9,0,0,0,0,1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,13 +97,13 @@ TEST_CASE("vmath/mat") {
|
||||
int2x2 v(1,2,3,4);
|
||||
int2x2 v2;
|
||||
v2 = v;
|
||||
REQUIRE(v2 == int2x2(1,2,3,4));
|
||||
CHECK(v2 == int2x2(1,2,3,4));
|
||||
}
|
||||
{
|
||||
int2x2 v(1,2,3,4);
|
||||
int2x2 v2;
|
||||
v2 = std::move(v);
|
||||
REQUIRE(v2 == int2x2(1,2,3,4));
|
||||
CHECK(v2 == int2x2(1,2,3,4));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,15 +112,15 @@ TEST_CASE("vmath/mat") {
|
||||
int2x2 v1(1,2,3,4);
|
||||
int2x2 v2(4,5,6,7);
|
||||
v1.swap(v2);
|
||||
REQUIRE(v1 == int2x2(4,5,6,7));
|
||||
REQUIRE(v2 == int2x2(1,2,3,4));
|
||||
CHECK(v1 == int2x2(4,5,6,7));
|
||||
CHECK(v2 == int2x2(1,2,3,4));
|
||||
}
|
||||
{
|
||||
int2x2 v1(1,2,3,4);
|
||||
int2x2 v2(4,5,6,7);
|
||||
swap(v1, v2);
|
||||
REQUIRE(v1 == int2x2(4,5,6,7));
|
||||
REQUIRE(v2 == int2x2(1,2,3,4));
|
||||
CHECK(v1 == int2x2(4,5,6,7));
|
||||
CHECK(v2 == int2x2(1,2,3,4));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,121 +128,126 @@ TEST_CASE("vmath/mat") {
|
||||
{
|
||||
int2x2 m{1,2,3,4};
|
||||
|
||||
REQUIRE(*m.begin() == vec{1,2});
|
||||
REQUIRE(*(m.begin() + 1) == vec{3,4});
|
||||
REQUIRE(*(m.end() - 1) == vec{3,4});
|
||||
REQUIRE(*(m.end() - 2) == vec{1,2});
|
||||
REQUIRE(m.begin() + 2 == m.end());
|
||||
REQUIRE(m.end() - 2 == m.begin());
|
||||
CHECK(*m.begin() == vec{1,2});
|
||||
CHECK(*(m.begin() + 1) == vec{3,4});
|
||||
CHECK(*(m.end() - 1) == vec{3,4});
|
||||
CHECK(*(m.end() - 2) == vec{1,2});
|
||||
CHECK(m.begin() + 2 == m.end());
|
||||
CHECK(m.end() - 2 == m.begin());
|
||||
|
||||
REQUIRE(*m.cbegin() == vec{1,2});
|
||||
REQUIRE(*(m.cbegin() + 1) == vec{3,4});
|
||||
REQUIRE(*(m.cend() - 1) == vec{3,4});
|
||||
REQUIRE(*(m.cend() - 2) == vec{1,2});
|
||||
REQUIRE(m.cbegin() + 2 == m.cend());
|
||||
REQUIRE(m.cend() - 2 == m.cbegin());
|
||||
CHECK(*m.cbegin() == vec{1,2});
|
||||
CHECK(*(m.cbegin() + 1) == vec{3,4});
|
||||
CHECK(*(m.cend() - 1) == vec{3,4});
|
||||
CHECK(*(m.cend() - 2) == vec{1,2});
|
||||
CHECK(m.cbegin() + 2 == m.cend());
|
||||
CHECK(m.cend() - 2 == m.cbegin());
|
||||
|
||||
REQUIRE(*m.rbegin() == vec{3,4});
|
||||
REQUIRE(*(m.rbegin() + 1) == vec{1,2});
|
||||
REQUIRE(*(m.rend() - 1) == vec{1,2});
|
||||
REQUIRE(*(m.rend() - 2) == vec{3,4});
|
||||
REQUIRE(m.rbegin() + 2 == m.rend());
|
||||
REQUIRE(m.rend() - 2 == m.rbegin());
|
||||
CHECK(*m.rbegin() == vec{3,4});
|
||||
CHECK(*(m.rbegin() + 1) == vec{1,2});
|
||||
CHECK(*(m.rend() - 1) == vec{1,2});
|
||||
CHECK(*(m.rend() - 2) == vec{3,4});
|
||||
CHECK(m.rbegin() + 2 == m.rend());
|
||||
CHECK(m.rend() - 2 == m.rbegin());
|
||||
|
||||
REQUIRE(*m.crbegin() == vec{3,4});
|
||||
REQUIRE(*(m.crbegin() + 1) == vec{1,2});
|
||||
REQUIRE(*(m.crend() - 1) == vec{1,2});
|
||||
REQUIRE(*(m.crend() - 2) == vec{3,4});
|
||||
REQUIRE(m.crbegin() + 2 == m.crend());
|
||||
REQUIRE(m.crend() - 2 == m.crbegin());
|
||||
CHECK(*m.crbegin() == vec{3,4});
|
||||
CHECK(*(m.crbegin() + 1) == vec{1,2});
|
||||
CHECK(*(m.crend() - 1) == vec{1,2});
|
||||
CHECK(*(m.crend() - 2) == vec{3,4});
|
||||
CHECK(m.crbegin() + 2 == m.crend());
|
||||
CHECK(m.crend() - 2 == m.crbegin());
|
||||
|
||||
*m.begin() = {5,6};
|
||||
REQUIRE(m == int2x2{5,6,3,4});
|
||||
CHECK(m == int2x2{5,6,3,4});
|
||||
*m.rbegin() = {7,8};
|
||||
REQUIRE(m == int2x2{5,6,7,8});
|
||||
CHECK(m == int2x2{5,6,7,8});
|
||||
}
|
||||
{
|
||||
const int2x2 m{1,2,3,4};
|
||||
|
||||
REQUIRE(*m.begin() == vec{1,2});
|
||||
REQUIRE(*(m.begin() + 1) == vec{3,4});
|
||||
REQUIRE(*(m.end() - 1) == vec{3,4});
|
||||
REQUIRE(*(m.end() - 2) == vec{1,2});
|
||||
REQUIRE(m.begin() + 2 == m.end());
|
||||
REQUIRE(m.end() - 2 == m.begin());
|
||||
CHECK(*m.begin() == vec{1,2});
|
||||
CHECK(*(m.begin() + 1) == vec{3,4});
|
||||
CHECK(*(m.end() - 1) == vec{3,4});
|
||||
CHECK(*(m.end() - 2) == vec{1,2});
|
||||
CHECK(m.begin() + 2 == m.end());
|
||||
CHECK(m.end() - 2 == m.begin());
|
||||
|
||||
REQUIRE(*m.cbegin() == vec{1,2});
|
||||
REQUIRE(*(m.cbegin() + 1) == vec{3,4});
|
||||
REQUIRE(*(m.cend() - 1) == vec{3,4});
|
||||
REQUIRE(*(m.cend() - 2) == vec{1,2});
|
||||
REQUIRE(m.cbegin() + 2 == m.cend());
|
||||
REQUIRE(m.cend() - 2 == m.cbegin());
|
||||
CHECK(*m.cbegin() == vec{1,2});
|
||||
CHECK(*(m.cbegin() + 1) == vec{3,4});
|
||||
CHECK(*(m.cend() - 1) == vec{3,4});
|
||||
CHECK(*(m.cend() - 2) == vec{1,2});
|
||||
CHECK(m.cbegin() + 2 == m.cend());
|
||||
CHECK(m.cend() - 2 == m.cbegin());
|
||||
|
||||
REQUIRE(*m.rbegin() == vec{3,4});
|
||||
REQUIRE(*(m.rbegin() + 1) == vec{1,2});
|
||||
REQUIRE(*(m.rend() - 1) == vec{1,2});
|
||||
REQUIRE(*(m.rend() - 2) == vec{3,4});
|
||||
REQUIRE(m.rbegin() + 2 == m.rend());
|
||||
REQUIRE(m.rend() - 2 == m.rbegin());
|
||||
CHECK(*m.rbegin() == vec{3,4});
|
||||
CHECK(*(m.rbegin() + 1) == vec{1,2});
|
||||
CHECK(*(m.rend() - 1) == vec{1,2});
|
||||
CHECK(*(m.rend() - 2) == vec{3,4});
|
||||
CHECK(m.rbegin() + 2 == m.rend());
|
||||
CHECK(m.rend() - 2 == m.rbegin());
|
||||
|
||||
REQUIRE(*m.crbegin() == vec{3,4});
|
||||
REQUIRE(*(m.crbegin() + 1) == vec{1,2});
|
||||
REQUIRE(*(m.crend() - 1) == vec{1,2});
|
||||
REQUIRE(*(m.crend() - 2) == vec{3,4});
|
||||
REQUIRE(m.crbegin() + 2 == m.crend());
|
||||
REQUIRE(m.crend() - 2 == m.crbegin());
|
||||
CHECK(*m.crbegin() == vec{3,4});
|
||||
CHECK(*(m.crbegin() + 1) == vec{1,2});
|
||||
CHECK(*(m.crend() - 1) == vec{1,2});
|
||||
CHECK(*(m.crend() - 2) == vec{3,4});
|
||||
CHECK(m.crbegin() + 2 == m.crend());
|
||||
CHECK(m.crend() - 2 == m.crbegin());
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("data") {
|
||||
{
|
||||
int2x2 m2;
|
||||
REQUIRE(m2.data() == &m2[0]);
|
||||
CHECK(m2.data() == &m2[0]);
|
||||
|
||||
int3x3 m3;
|
||||
REQUIRE(m3.data() == &m3[0]);
|
||||
CHECK(m3.data() == &m3[0]);
|
||||
|
||||
int4x4 m4;
|
||||
REQUIRE(m4.data() == &m4[0]);
|
||||
CHECK(m4.data() == &m4[0]);
|
||||
}
|
||||
{
|
||||
const int2x2 m2;
|
||||
REQUIRE(m2.data() == &m2[0]);
|
||||
CHECK(m2.data() == &m2[0]);
|
||||
|
||||
const int3x3 m3;
|
||||
REQUIRE(m3.data() == &m3[0]);
|
||||
CHECK(m3.data() == &m3[0]);
|
||||
|
||||
const int4x4 m4;
|
||||
REQUIRE(m4.data() == &m4[0]);
|
||||
CHECK(m4.data() == &m4[0]);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("operator[]") {
|
||||
{
|
||||
STATIC_REQUIRE(int2x2()[0] == int2(1,0));
|
||||
STATIC_REQUIRE(int2x2()[1] == int2(0,1));
|
||||
STATIC_CHECK(int2x2()[0] == int2(1,0));
|
||||
STATIC_CHECK(int2x2()[1] == int2(0,1));
|
||||
|
||||
STATIC_REQUIRE(int3x3()[0] == int3(1,0,0));
|
||||
STATIC_REQUIRE(int3x3()[1] == int3(0,1,0));
|
||||
STATIC_REQUIRE(int3x3()[2] == int3(0,0,1));
|
||||
STATIC_CHECK(int3x3()[0] == int3(1,0,0));
|
||||
STATIC_CHECK(int3x3()[1] == int3(0,1,0));
|
||||
STATIC_CHECK(int3x3()[2] == int3(0,0,1));
|
||||
|
||||
STATIC_REQUIRE(int4x4()[0] == int4(1,0,0,0));
|
||||
STATIC_REQUIRE(int4x4()[1] == int4(0,1,0,0));
|
||||
STATIC_REQUIRE(int4x4()[2] == int4(0,0,1,0));
|
||||
STATIC_REQUIRE(int4x4()[3] == int4(0,0,0,1));
|
||||
STATIC_CHECK(int4x4()[0] == int4(1,0,0,0));
|
||||
STATIC_CHECK(int4x4()[1] == int4(0,1,0,0));
|
||||
STATIC_CHECK(int4x4()[2] == int4(0,0,1,0));
|
||||
STATIC_CHECK(int4x4()[3] == int4(0,0,0,1));
|
||||
}
|
||||
{
|
||||
int2x2 v;
|
||||
v[0] = int2(1,2);
|
||||
v[1] = int2(3,4);
|
||||
REQUIRE(v == int2x2(1,2,3,4));
|
||||
CHECK(v == int2x2(1,2,3,4));
|
||||
CHECK(std::as_const(v).at(0) == int2(1,2));
|
||||
CHECK(std::as_const(v).at(1) == int2(3,4));
|
||||
}
|
||||
{
|
||||
int3x3 v;
|
||||
v[0] = int3(1,2,3);
|
||||
v[1] = int3(4,5,6);
|
||||
v[2] = int3(7,8,9);
|
||||
REQUIRE(v == int3x3(1,2,3,4,5,6,7,8,9));
|
||||
CHECK(v == int3x3(1,2,3,4,5,6,7,8,9));
|
||||
CHECK(std::as_const(v).at(0) == int3(1,2,3));
|
||||
CHECK(std::as_const(v).at(1) == int3(4,5,6));
|
||||
CHECK(std::as_const(v).at(2) == int3(7,8,9));
|
||||
}
|
||||
{
|
||||
int4x4 v;
|
||||
@@ -251,33 +255,39 @@ TEST_CASE("vmath/mat") {
|
||||
v[1] = int4(5,6,7,8);
|
||||
v[2] = int4(9,10,11,12);
|
||||
v[3] = int4(13,14,15,16);
|
||||
REQUIRE(v == int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
|
||||
CHECK(v == int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
|
||||
CHECK(std::as_const(v).at(0) == int4(1,2,3,4));
|
||||
CHECK(std::as_const(v).at(1) == int4(5,6,7,8));
|
||||
CHECK(std::as_const(v).at(2) == int4(9,10,11,12));
|
||||
CHECK(std::as_const(v).at(3) == int4(13,14,15,16));
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("at") {
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4).at(0) == int2(1,2));
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4).at(1) == int2(3,4));
|
||||
REQUIRE_THROWS_AS((void)int2x2(1,2,3,4).at(2), std::out_of_range);
|
||||
STATIC_CHECK(int2x2(1,2,3,4).at(0) == int2(1,2));
|
||||
STATIC_CHECK(int2x2(1,2,3,4).at(1) == int2(3,4));
|
||||
#ifndef VMATH_HPP_NO_EXCEPTIONS
|
||||
CHECK_THROWS_AS((void)int2x2(1,2,3,4).at(2), std::out_of_range);
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("operator==/operator!=") {
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4) == int2x2(1,2,3,4));
|
||||
STATIC_REQUIRE_FALSE(int2x2(1,2,3,4) == int2x2(2,2,3,4));
|
||||
STATIC_REQUIRE_FALSE(int2x2(1,2,3,4) == int2x2(1,3,3,4));
|
||||
STATIC_CHECK(int2x2(1,2,3,4) == int2x2(1,2,3,4));
|
||||
STATIC_CHECK_FALSE(int2x2(1,2,3,4) == int2x2(2,2,3,4));
|
||||
STATIC_CHECK_FALSE(int2x2(1,2,3,4) == int2x2(1,3,3,4));
|
||||
|
||||
STATIC_REQUIRE_FALSE(int2x2(1,2,3,4) != int2x2(1,2,3,4));
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4) != int2x2(2,2,3,4));
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4) != int2x2(1,3,3,4));
|
||||
STATIC_CHECK_FALSE(int2x2(1,2,3,4) != int2x2(1,2,3,4));
|
||||
STATIC_CHECK(int2x2(1,2,3,4) != int2x2(2,2,3,4));
|
||||
STATIC_CHECK(int2x2(1,2,3,4) != int2x2(1,3,3,4));
|
||||
}
|
||||
|
||||
SUBCASE("operator<") {
|
||||
STATIC_REQUIRE_FALSE(int2x2(1,2,3,4) < int2x2(1,2,3,4));
|
||||
STATIC_CHECK_FALSE(int2x2(1,2,3,4) < int2x2(1,2,3,4));
|
||||
|
||||
STATIC_REQUIRE(int2x2(1,1,3,4) < int2x2(1,2,3,4));
|
||||
STATIC_REQUIRE_FALSE(int2x2(1,2,3,4) < int2x2(1,1,3,4));
|
||||
STATIC_CHECK(int2x2(1,1,3,4) < int2x2(1,2,3,4));
|
||||
STATIC_CHECK_FALSE(int2x2(1,2,3,4) < int2x2(1,1,3,4));
|
||||
|
||||
STATIC_REQUIRE(int2x2(0,3,3,4) < int2x2(1,2,3,4));
|
||||
STATIC_REQUIRE_FALSE(int2x2(1,2,3,4) < int2x2(0,3,3,4));
|
||||
STATIC_CHECK(int2x2(0,3,3,4) < int2x2(1,2,3,4));
|
||||
STATIC_CHECK_FALSE(int2x2(1,2,3,4) < int2x2(0,3,3,4));
|
||||
}
|
||||
}
|
||||
|
||||
181
untests/vmath_qua_fun_tests.cpp
Normal file
181
untests/vmath_qua_fun_tests.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
{
|
||||
using namespace vmath_hpp;
|
||||
using namespace vmath_tests;
|
||||
}
|
||||
|
||||
TEST_CASE("vmath/qua_fun") {
|
||||
SUBCASE("Operators") {
|
||||
STATIC_CHECK(+qua(1,-2,3,-4) == qua(1,-2,3,-4));
|
||||
STATIC_CHECK(-qua(1,-2,3,-4) == qua(-1,2,-3,4));
|
||||
|
||||
STATIC_CHECK(qua(1,2,3,4) + qua(3,4,5,6) == qua(4,6,8,10));
|
||||
STATIC_CHECK(qua(1,2,3,4) - qua(3,5,7,9) == qua(-2,-3,-4,-5));
|
||||
|
||||
{
|
||||
qua v{1,2,3,4};
|
||||
CHECK(&v == &(v += qua{3,4,5,6}));
|
||||
CHECK(v == qua{4,6,8,10});
|
||||
}
|
||||
|
||||
{
|
||||
qua v{1,2,3,4};
|
||||
CHECK(&v == &(v -= qua{3,4,5,6}));
|
||||
CHECK(v == qua{-2,-2,-2,-2});
|
||||
}
|
||||
|
||||
STATIC_CHECK(qua(1,2,3,4) * 2 == qua(2,4,6,8));
|
||||
STATIC_CHECK(qua(2,4,6,8) / 2 == qua(1,2,3,4));
|
||||
|
||||
STATIC_CHECK(2 * qua(1,2,3,4) == qua(2,4,6,8));
|
||||
STATIC_CHECK(8 / qua(1,2,4,8) == qua(8,4,2,1));
|
||||
|
||||
{
|
||||
qua v{1,2,3,4};
|
||||
CHECK(&v == &(v *= 2));
|
||||
CHECK(v == qua{2,4,6,8});
|
||||
CHECK(&v == &(v *= qua<int>{}));
|
||||
CHECK(v == qua{2,4,6,8});
|
||||
}
|
||||
|
||||
{
|
||||
qua v{2,4,6,8};
|
||||
CHECK(&v == &(v /= 2));
|
||||
CHECK(v == qua{1,2,3,4});
|
||||
}
|
||||
|
||||
{
|
||||
float3 v{1,0,0};
|
||||
CHECK(&v == &(v *= qfloat{0,0,0.7071067812f,0.7071067812f}));
|
||||
CHECK(v == uapprox3(0.f,1.f,0.f));
|
||||
}
|
||||
|
||||
STATIC_CHECK(qfloat{} * qfloat{} == qfloat{});
|
||||
STATIC_CHECK(float3{1,2,3} * qfloat{} == uapprox3(1.f,2.f,3.f));
|
||||
STATIC_CHECK(float3{1,0,0} * qfloat{0,0,0.7071067812f,0.7071067812f} == uapprox3(0.f,1.f,0.f));
|
||||
}
|
||||
|
||||
SUBCASE("Common Functions") {
|
||||
{
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(5.f)),
|
||||
nlerp(qrotate_z(radians(5.f)), qrotate_z(radians(15.f)), 0.f),
|
||||
0.00001f)));
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(6.f)),
|
||||
nlerp(qrotate_z(radians(5.f)), qrotate_z(radians(15.f)), 0.1f),
|
||||
0.00001f)));
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(10.f)),
|
||||
nlerp(qrotate_z(radians(5.f)), qrotate_z(radians(15.f)), 0.5f),
|
||||
0.00001f)));
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(15.f)),
|
||||
nlerp(qrotate_z(radians(5.f)), qrotate_z(radians(15.f)), 1.f),
|
||||
0.00001f)));
|
||||
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(315.f)),
|
||||
nlerp(qrotate_z(radians(270.f)), qrotate_z(radians(0.f)), 0.5f))));
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(290.f)),
|
||||
nlerp(qrotate_z(radians(220.f)), qrotate_z(radians(0.f)), 0.5f))));
|
||||
}
|
||||
{
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(5.f)),
|
||||
slerp(qrotate_z(radians(5.f)), qrotate_z(radians(15.f)), 0.f),
|
||||
0.00001f)));
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(6.f)),
|
||||
slerp(qrotate_z(radians(5.f)), qrotate_z(radians(15.f)), 0.1f),
|
||||
0.00001f)));
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(10.f)),
|
||||
slerp(qrotate_z(radians(5.f)), qrotate_z(radians(15.f)), 0.5f),
|
||||
0.00001f)));
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(15.f)),
|
||||
slerp(qrotate_z(radians(5.f)), qrotate_z(radians(15.f)), 1.f),
|
||||
0.00001f)));
|
||||
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(0.f)),
|
||||
slerp(qrotate_z(radians(0.f)), qrotate_z(radians(0.f)), 0.5f))));
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(0.25f)),
|
||||
slerp(qrotate_z(radians(0.f)), qrotate_z(radians(0.5f)), 0.5f))));
|
||||
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(-45.f)),
|
||||
slerp(qrotate_z(radians(0.f)), qrotate_z(radians(270.f)), 0.5f))));
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(-70.f)),
|
||||
slerp(qrotate_z(radians(0.f)), qrotate_z(radians(220.f)), 0.5f))));
|
||||
|
||||
CHECK(all(approx(
|
||||
qrotate_z(radians(315.f)),
|
||||
slerp(qrotate_z(radians(270.f)), qrotate_z(radians(0.f)), 0.5f))));
|
||||
CHECK(all(approx(
|
||||
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") {
|
||||
STATIC_CHECK(dot(qua(1,2,3,4),qua(3,4,5,6)) == 50);
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
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)));
|
||||
CHECK(distance(qrotate_z(radians(180.f)) * 5.f, qrotate_z(radians(0.f)) * 4.5f) == uapprox(radians(180.f)));
|
||||
CHECK(distance(qrotate_z(radians(15.f)) * 6.f, qrotate_z(radians(350.f)) * 5.5f) == uapprox(radians(25.f)));
|
||||
CHECK(distance(qrotate_z(radians(350.f)) * 7.f, qrotate_z(radians(15.f)) * 6.5f) == uapprox(radians(25.f)));
|
||||
|
||||
CHECK(normalize(qfloat(0.5f,0.f,0.f,0.f)).v == uapprox3(1.f,0.f,0.f));
|
||||
}
|
||||
|
||||
SUBCASE("Relational Functions") {
|
||||
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));
|
||||
STATIC_CHECK(approx(qua(1,1,1,1), qua(0,1,2,3), 2) == bool4(true, true, true, true));
|
||||
|
||||
STATIC_CHECK(less(qua(1,1,1,1), qua(0,1,2,3)) == bool4(false, false, true, true));
|
||||
STATIC_CHECK(less_equal(qua(1,1,1,1), qua(0,1,2,3)) == bool4(false, true, true, true));
|
||||
STATIC_CHECK(greater(qua(1,1,1,1), qua(0,1,2,3)) == bool4(true, false, false, false));
|
||||
STATIC_CHECK(greater_equal(qua(1,1,1,1), qua(0,1,2,3)) == bool4(true, true, false, false));
|
||||
|
||||
STATIC_CHECK(equal_to(qua(1,1,1,1), qua(0,1,2,3)) == bool4(false, true, false, false));
|
||||
STATIC_CHECK(not_equal_to(qua(1,1,1,1), qua(0,1,2,3)) == bool4(true, false, true, true));
|
||||
}
|
||||
|
||||
SUBCASE("Quaternion Functions") {
|
||||
STATIC_CHECK(conjugate(qua(1,2,3,4)) == qua(-1,-2,-3,4));
|
||||
STATIC_CHECK(inverse(qua(0.f,0.f,0.7071067812f,0.7071067812f)).v == uapprox3(0.f,0.f,-0.7071067812f));
|
||||
STATIC_CHECK(inverse(qua(0.f,0.f,0.7071067812f,0.7071067812f)).s == uapprox(0.7071067812f));
|
||||
|
||||
CHECK(inverse(qrotate_x(10.f)) == qrotate_x(-10.f));
|
||||
CHECK(all(approx(inverse(qrotate_x(10.f) * qrotate_y(15.f)), qrotate_y(-15.f) * qrotate_x(-10.f))));
|
||||
}
|
||||
}
|
||||
258
untests/vmath_qua_tests.cpp
Normal file
258
untests/vmath_qua_tests.cpp
Normal file
@@ -0,0 +1,258 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
{
|
||||
using namespace vmath_hpp;
|
||||
using namespace vmath_tests;
|
||||
}
|
||||
|
||||
TEST_CASE("vmath/qua") {
|
||||
SUBCASE("size/sizeof") {
|
||||
STATIC_CHECK(qfloat{}.size == 4);
|
||||
STATIC_CHECK(qdouble{}.size == 4);
|
||||
|
||||
STATIC_CHECK(sizeof(qfloat{}) == sizeof(float) * 4);
|
||||
STATIC_CHECK(sizeof(qdouble{}) == sizeof(double) * 4);
|
||||
}
|
||||
|
||||
SUBCASE("guides") {
|
||||
STATIC_CHECK(qua{1,2,3,4}.size == 4);
|
||||
STATIC_CHECK(qua{{1,2,3},4}.size == 4);
|
||||
STATIC_CHECK(qua{vec{1,2,3},4}.size == 4);
|
||||
STATIC_CHECK(qua{{1,2,3,4}}.size == 4);
|
||||
STATIC_CHECK(qua(vec{1,2,3,4}).size == 4);
|
||||
}
|
||||
|
||||
SUBCASE("ctors") {
|
||||
{
|
||||
STATIC_CHECK(qfloat{}.v == uapprox3(0.f));
|
||||
STATIC_CHECK(qfloat{}.s == uapprox(1.f));
|
||||
|
||||
STATIC_CHECK(qfloat{1,2,3,4}.v == uapprox3(1.f,2.f,3.f));
|
||||
STATIC_CHECK(qfloat{1,2,3,4}.s == uapprox(4.f));
|
||||
|
||||
STATIC_CHECK(qfloat{{1,2,3},4}.v == uapprox3(1.f,2.f,3.f));
|
||||
STATIC_CHECK(qfloat{{1,2,3},4}.s == uapprox(4.f));
|
||||
|
||||
STATIC_CHECK(qfloat{{1,2,3,4}}.v == uapprox3(1.f,2.f,3.f));
|
||||
STATIC_CHECK(qfloat{{1,2,3,4}}.s == uapprox(4.f));
|
||||
}
|
||||
{
|
||||
constexpr qfloat q(1,2,3,4);
|
||||
constexpr qfloat q2 = q;
|
||||
STATIC_CHECK(q2 == qfloat(1,2,3,4));
|
||||
}
|
||||
{
|
||||
constexpr qfloat q(1,2,3,4);
|
||||
constexpr qfloat q2 = std::move(q);
|
||||
STATIC_CHECK(q2 == qfloat(1,2,3,4));
|
||||
}
|
||||
{
|
||||
STATIC_CHECK(qfloat(1,2,3,4) == qfloat(1,2,3,4));
|
||||
STATIC_CHECK(qfloat(float3(1,2,3),4) == qfloat(1,2,3,4));
|
||||
STATIC_CHECK(qfloat(float4(1,2,3,4)) == qfloat(1,2,3,4));
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("operator=") {
|
||||
{
|
||||
qfloat v(1,2,3,4);
|
||||
qfloat v2;
|
||||
v2 = v;
|
||||
CHECK(v2 == qfloat(1,2,3,4));
|
||||
}
|
||||
{
|
||||
qfloat v(1,2,3,4);
|
||||
qfloat v2;
|
||||
v2 = std::move(v);
|
||||
CHECK(v2 == qfloat(1,2,3,4));
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("swap") {
|
||||
{
|
||||
qfloat v1(1,2,3,4);
|
||||
qfloat v2(4,5,6,7);
|
||||
v1.swap(v2);
|
||||
CHECK(v1 == qfloat(4,5,6,7));
|
||||
CHECK(v2 == qfloat(1,2,3,4));
|
||||
}
|
||||
{
|
||||
qfloat v1(1,2,3,4);
|
||||
qfloat v2(4,5,6,7);
|
||||
swap(v1, v2);
|
||||
CHECK(v1 == qfloat(4,5,6,7));
|
||||
CHECK(v2 == qfloat(1,2,3,4));
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("iter") {
|
||||
{
|
||||
qfloat v{1,2,3,4};
|
||||
|
||||
CHECK(*v.begin() == 1);
|
||||
CHECK(*(v.begin() + 1) == 2);
|
||||
CHECK(*(v.end() - 1) == 4);
|
||||
CHECK(*(v.end() - 2) == 3);
|
||||
CHECK(v.begin() + 4 == v.end());
|
||||
CHECK(v.end() - 4 == v.begin());
|
||||
|
||||
CHECK(*v.cbegin() == 1);
|
||||
CHECK(*(v.cbegin() + 1) == 2);
|
||||
CHECK(*(v.cend() - 1) == 4);
|
||||
CHECK(*(v.cend() - 2) == 3);
|
||||
CHECK(v.cbegin() + 4 == v.cend());
|
||||
CHECK(v.cend() - 4 == v.cbegin());
|
||||
|
||||
CHECK(*v.rbegin() == 4);
|
||||
CHECK(*(v.rbegin() + 1) == 3);
|
||||
CHECK(*(v.rend() - 1) == 1);
|
||||
CHECK(*(v.rend() - 2) == 2);
|
||||
CHECK(v.rbegin() + 4 == v.rend());
|
||||
CHECK(v.rend() - 4 == v.rbegin());
|
||||
|
||||
CHECK(*v.crbegin() == 4);
|
||||
CHECK(*(v.crbegin() + 1) == 3);
|
||||
CHECK(*(v.crend() - 1) == 1);
|
||||
CHECK(*(v.crend() - 2) == 2);
|
||||
CHECK(v.crbegin() + 4 == v.crend());
|
||||
CHECK(v.crend() - 4 == v.crbegin());
|
||||
|
||||
*v.begin() = 3;
|
||||
CHECK(v == qfloat{3,2,3,4});
|
||||
*v.rbegin() = 5;
|
||||
CHECK(v == qfloat{3,2,3,5});
|
||||
}
|
||||
{
|
||||
const qfloat v{1,2,3,4};
|
||||
|
||||
CHECK(*v.begin() == 1);
|
||||
CHECK(*(v.begin() + 1) == 2);
|
||||
CHECK(*(v.end() - 1) == 4);
|
||||
CHECK(*(v.end() - 2) == 3);
|
||||
CHECK(v.begin() + 4 == v.end());
|
||||
CHECK(v.end() - 4 == v.begin());
|
||||
|
||||
CHECK(*v.cbegin() == 1);
|
||||
CHECK(*(v.cbegin() + 1) == 2);
|
||||
CHECK(*(v.cend() - 1) == 4);
|
||||
CHECK(*(v.cend() - 2) == 3);
|
||||
CHECK(v.cbegin() + 4 == v.cend());
|
||||
CHECK(v.cend() - 4 == v.cbegin());
|
||||
|
||||
CHECK(*v.rbegin() == 4);
|
||||
CHECK(*(v.rbegin() + 1) == 3);
|
||||
CHECK(*(v.rend() - 1) == 1);
|
||||
CHECK(*(v.rend() - 2) == 2);
|
||||
CHECK(v.rbegin() + 4 == v.rend());
|
||||
CHECK(v.rend() - 4 == v.rbegin());
|
||||
|
||||
CHECK(*v.crbegin() == 4);
|
||||
CHECK(*(v.crbegin() + 1) == 3);
|
||||
CHECK(*(v.crend() - 1) == 1);
|
||||
CHECK(*(v.crend() - 2) == 2);
|
||||
CHECK(v.crbegin() + 4 == v.crend());
|
||||
CHECK(v.crend() - 4 == v.crbegin());
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("data") {
|
||||
{
|
||||
qfloat i2;
|
||||
CHECK(i2.data() == &i2[0]);
|
||||
}
|
||||
{
|
||||
const qfloat i2;
|
||||
CHECK(i2.data() == &i2[0]);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("operator[]") {
|
||||
{
|
||||
STATIC_CHECK(qua(1,2,3,4).v == vec(1,2,3));
|
||||
STATIC_CHECK(qua(1,2,3,4).s == 4);
|
||||
}
|
||||
{
|
||||
STATIC_CHECK(qua(1,2,3,4)[0] == 1);
|
||||
STATIC_CHECK(qua(1,2,3,4)[1] == 2);
|
||||
STATIC_CHECK(qua(1,2,3,4)[2] == 3);
|
||||
STATIC_CHECK(qua(1,2,3,4)[3] == 4);
|
||||
}
|
||||
{
|
||||
qua<int> v;
|
||||
v.v = vec(1,2,3);
|
||||
v.s = 4;
|
||||
CHECK(v == qua(1,2,3,4));
|
||||
}
|
||||
{
|
||||
qua<int> v;
|
||||
v[0] = 1;
|
||||
v[1] = 2;
|
||||
v[2] = 3;
|
||||
v[3] = 4;
|
||||
CHECK(v == qua(1,2,3,4));
|
||||
}
|
||||
{
|
||||
qua<int> v;
|
||||
v.at(0) = 1;
|
||||
v.at(1) = 2;
|
||||
v.at(2) = 3;
|
||||
v.at(3) = 4;
|
||||
CHECK(v == qua(1,2,3,4));
|
||||
}
|
||||
{
|
||||
const qua v{1,2,3,4};
|
||||
CHECK(v[0] == 1);
|
||||
CHECK(v[1] == 2);
|
||||
CHECK(v[2] == 3);
|
||||
CHECK(v[3] == 4);
|
||||
CHECK(v.at(0) == 1);
|
||||
CHECK(v.at(1) == 2);
|
||||
CHECK(v.at(2) == 3);
|
||||
CHECK(v.at(3) == 4);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("at") {
|
||||
STATIC_CHECK(qfloat(1,2,3,4).at(0) == 1);
|
||||
STATIC_CHECK(qfloat(1,2,3,4).at(1) == 2);
|
||||
STATIC_CHECK(qfloat(1,2,3,4).at(2) == 3);
|
||||
STATIC_CHECK(qfloat(1,2,3,4).at(3) == 4);
|
||||
#ifndef VMATH_HPP_NO_EXCEPTIONS
|
||||
CHECK_THROWS_AS((void)qfloat(1,2,3,4).at(4), std::out_of_range);
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("operator==/operator!=") {
|
||||
STATIC_CHECK(qfloat(1,2,3,4) == qfloat(1,2,3,4));
|
||||
STATIC_CHECK_FALSE(qfloat(1,2,3,4) == qfloat(2,2,3,4));
|
||||
STATIC_CHECK_FALSE(qfloat(1,2,3,4) == qfloat(1,3,3,4));
|
||||
|
||||
STATIC_CHECK_FALSE(qfloat(1,2,3,4) != qfloat(1,2,3,4));
|
||||
STATIC_CHECK(qfloat(1,2,3,4) != qfloat(2,2,3,4));
|
||||
STATIC_CHECK(qfloat(1,2,3,4) != qfloat(1,3,3,4));
|
||||
}
|
||||
|
||||
SUBCASE("operator<") {
|
||||
STATIC_CHECK_FALSE(qfloat(1,2,3,4) < qfloat(1,2,3,4));
|
||||
|
||||
STATIC_CHECK(qfloat(0,2,3,4) < qfloat(1,2,3,4));
|
||||
STATIC_CHECK(qfloat(1,1,3,4) < qfloat(1,2,3,4));
|
||||
STATIC_CHECK(qfloat(1,2,2,4) < qfloat(1,2,3,4));
|
||||
STATIC_CHECK(qfloat(1,2,3,3) < qfloat(1,2,3,4));
|
||||
|
||||
STATIC_CHECK_FALSE(qfloat(1,2,3,4) < qfloat(0,2,3,4));
|
||||
STATIC_CHECK_FALSE(qfloat(1,2,3,4) < qfloat(1,1,3,4));
|
||||
STATIC_CHECK_FALSE(qfloat(1,2,3,4) < qfloat(1,2,2,4));
|
||||
STATIC_CHECK_FALSE(qfloat(1,2,3,4) < qfloat(1,2,3,3));
|
||||
|
||||
STATIC_CHECK(qfloat(0,3,3,4) < qfloat(1,2,3,4));
|
||||
STATIC_CHECK_FALSE(qfloat(1,2,3,4) < qfloat(0,3,3,4));
|
||||
}
|
||||
}
|
||||
@@ -5,46 +5,25 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include <vmath.hpp/vmath.hpp>
|
||||
|
||||
#include <cfloat>
|
||||
#include "doctest/doctest.hpp"
|
||||
|
||||
namespace vmath_tests
|
||||
{
|
||||
using namespace vmath_hpp;
|
||||
|
||||
template < typename T >
|
||||
struct uapprox_epsilon;
|
||||
|
||||
template <>
|
||||
struct uapprox_epsilon<int> {
|
||||
static constexpr int value = 0;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct uapprox_epsilon<float> {
|
||||
static constexpr float value = FLT_EPSILON * 100;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct uapprox_epsilon<double> {
|
||||
static constexpr float value = DBL_EPSILON * 100;
|
||||
struct uapprox_base {
|
||||
T epsilon = T(10) * std::numeric_limits<T>::epsilon();
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
inline constexpr T uapprox_epsilon_v = uapprox_epsilon<T>::value;
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
template < typename T >
|
||||
struct uapprox {
|
||||
struct uapprox : uapprox_base<T> {
|
||||
T value;
|
||||
explicit constexpr uapprox(T v) : value(v) {}
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
struct uapprox2 {
|
||||
struct uapprox2 : uapprox_base<T> {
|
||||
vec<T, 2> value;
|
||||
constexpr explicit uapprox2(T v) : value(v) {}
|
||||
constexpr explicit uapprox2(T x, T y) : value(x, y) {}
|
||||
@@ -52,7 +31,7 @@ namespace vmath_tests
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
struct uapprox3 {
|
||||
struct uapprox3 : uapprox_base<T> {
|
||||
vec<T, 3> value;
|
||||
constexpr explicit uapprox3(T v) : value(v) {}
|
||||
constexpr explicit uapprox3(T x, T y, T z) : value(x, y, z) {}
|
||||
@@ -60,7 +39,7 @@ namespace vmath_tests
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
struct uapprox4 {
|
||||
struct uapprox4 : uapprox_base<T> {
|
||||
vec<T, 4> value;
|
||||
constexpr explicit uapprox4(T v) : value(v) {}
|
||||
constexpr explicit uapprox4(T x, T y, T z, T w) : value(x, y, z, w) {}
|
||||
@@ -73,21 +52,21 @@ namespace vmath_tests
|
||||
|
||||
template < typename T >
|
||||
constexpr bool operator==(const T& l, const uapprox<T>& r) {
|
||||
return approx(l, r.value, uapprox_epsilon_v<T>);
|
||||
return approx(l, r.value, r.epsilon);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
constexpr bool operator==(const vec<T, 2>& l, const uapprox2<T>& r) {
|
||||
return all(approx(l, r.value, uapprox_epsilon_v<T>));
|
||||
return all(approx(l, r.value,r.epsilon));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
constexpr bool operator==(const vec<T, 3>& l, const uapprox3<T>& r) {
|
||||
return all(approx(l, r.value, uapprox_epsilon_v<T>));
|
||||
return all(approx(l, r.value, r.epsilon));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
constexpr bool operator==(const vec<T, 4>& l, const uapprox4<T>& r) {
|
||||
return all(approx(l, r.value, uapprox_epsilon_v<T>));
|
||||
return all(approx(l, r.value, r.epsilon));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "vmath_tests.hpp"
|
||||
#include "doctest/doctest.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -15,123 +14,124 @@ namespace
|
||||
|
||||
TEST_CASE("vmath/vec_fun") {
|
||||
SUBCASE("Detail") {
|
||||
STATIC_REQUIRE(map_join([](const int& x){
|
||||
STATIC_CHECK(map_join([](const int& x){
|
||||
return x * 2;
|
||||
}, int2{1}) == int2{2});
|
||||
|
||||
STATIC_REQUIRE(map_join([](const int& x, const int& y){
|
||||
STATIC_CHECK(map_join([](const int& x, const int& y){
|
||||
return x + y;
|
||||
}, int2{1}, int2{1}) == int2{2});
|
||||
|
||||
STATIC_REQUIRE(map_join([](const int& x, const int& y, const int& z){
|
||||
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));
|
||||
|
||||
STATIC_REQUIRE(fold_join([](int acc, const int& x){
|
||||
STATIC_CHECK(fold_join([](int acc, const int& x){
|
||||
return acc + x;
|
||||
}, 0, int2{1}) == 2);
|
||||
|
||||
STATIC_REQUIRE(fold_join([](int acc, const int& x, const int& y){
|
||||
STATIC_CHECK(fold_join([](int acc, const int& x, const int& y){
|
||||
return acc + x + y;
|
||||
}, 0, int2{1}, int2{1}) == 4);
|
||||
|
||||
STATIC_REQUIRE(fold1_join([](const int& acc, const int& x){
|
||||
STATIC_CHECK(fold1_join([](const int& acc, const int& x){
|
||||
return acc + x;
|
||||
}, int2{1}) == 2);
|
||||
}
|
||||
|
||||
SUBCASE("Operators") {
|
||||
STATIC_REQUIRE(-int2(1,-2) == int2(-1,2));
|
||||
STATIC_REQUIRE(~uint2(0xF0F0F0F0,0x0F0F0F0F) == uint2(0x0F0F0F0F,0xF0F0F0F0));
|
||||
STATIC_REQUIRE(!int3(-1,0,1) == bool3(false, true, false));
|
||||
STATIC_CHECK(+int2(1,-2) == int2(1,-2));
|
||||
STATIC_CHECK(-int2(1,-2) == int2(-1,2));
|
||||
STATIC_CHECK(~uint2(0xF0F0F0F0,0x0F0F0F0F) == uint2(0x0F0F0F0F,0xF0F0F0F0));
|
||||
STATIC_CHECK((!int3(-1,0,1)) == bool3(false, true, false));
|
||||
|
||||
STATIC_REQUIRE(int2(1,2) + 3 == int2(4,5));
|
||||
STATIC_REQUIRE(int2(1,2) - 3 == int2(-2,-1));
|
||||
STATIC_REQUIRE(int2(1,2) * 3 == int2(3,6));
|
||||
STATIC_REQUIRE(int2(2,4) / 2 == int2(1,2));
|
||||
STATIC_REQUIRE((int2(11,12) & 6) == int2(2,4));
|
||||
STATIC_REQUIRE((int2(11,12) | 6) == int2(15,14));
|
||||
STATIC_REQUIRE((int2(11,12) ^ 6) == int2(13,10));
|
||||
STATIC_REQUIRE((int2(1,0) && 1) == bool2(1,0));
|
||||
STATIC_REQUIRE((int2(1,0) || 1) == bool2(1,1));
|
||||
STATIC_CHECK(int2(1,2) + 3 == int2(4,5));
|
||||
STATIC_CHECK(int2(1,2) - 3 == int2(-2,-1));
|
||||
STATIC_CHECK(int2(1,2) * 3 == int2(3,6));
|
||||
STATIC_CHECK(int2(2,4) / 2 == int2(1,2));
|
||||
STATIC_CHECK((int2(11,12) & 6) == int2(2,4));
|
||||
STATIC_CHECK((int2(11,12) | 6) == int2(15,14));
|
||||
STATIC_CHECK((int2(11,12) ^ 6) == int2(13,10));
|
||||
STATIC_CHECK((int2(1,0) && 1) == bool2(1,0));
|
||||
STATIC_CHECK((int2(1,0) || 1) == bool2(1,1));
|
||||
|
||||
STATIC_REQUIRE(3 + int2(1,2) == int2(4,5));
|
||||
STATIC_REQUIRE(3 - int2(1,2) == int2(2,1));
|
||||
STATIC_REQUIRE(3 * int2(1,2) == int2(3,6));
|
||||
STATIC_REQUIRE(4 / int2(2,4) == int2(2,1));
|
||||
STATIC_REQUIRE((6 & int2(11,12)) == int2(2,4));
|
||||
STATIC_REQUIRE((6 | int2(11,12)) == int2(15,14));
|
||||
STATIC_REQUIRE((6 ^ int2(11,12)) == int2(13,10));
|
||||
STATIC_REQUIRE((1 && int2(1,0)) == bool2(1,0));
|
||||
STATIC_REQUIRE((1 || int2(1,0)) == bool2(1,1));
|
||||
STATIC_CHECK(3 + int2(1,2) == int2(4,5));
|
||||
STATIC_CHECK(3 - int2(1,2) == int2(2,1));
|
||||
STATIC_CHECK(3 * int2(1,2) == int2(3,6));
|
||||
STATIC_CHECK(4 / int2(2,4) == int2(2,1));
|
||||
STATIC_CHECK((6 & int2(11,12)) == int2(2,4));
|
||||
STATIC_CHECK((6 | int2(11,12)) == int2(15,14));
|
||||
STATIC_CHECK((6 ^ int2(11,12)) == int2(13,10));
|
||||
STATIC_CHECK((1 && int2(1,0)) == bool2(1,0));
|
||||
STATIC_CHECK((1 || int2(1,0)) == bool2(1,1));
|
||||
|
||||
STATIC_REQUIRE(int2(1,2) + int2(3,4) == int2(4,6));
|
||||
STATIC_REQUIRE(int2(1,2) - int2(3,4) == int2(-2,-2));
|
||||
STATIC_REQUIRE(int2(1,2) * int2(3,4) == int2(3,8));
|
||||
STATIC_REQUIRE(int2(3,4) / int2(1,2) == int2(3,2));
|
||||
STATIC_REQUIRE((int2(6,7) & int2(11,12)) == int2(2,4));
|
||||
STATIC_REQUIRE((int2(6,7) | int2(11,12)) == int2(15,15));
|
||||
STATIC_REQUIRE((int2(6,7) ^ int2(11,12)) == int2(13,11));
|
||||
STATIC_REQUIRE((int2(0,1) && int2(1,0)) == bool2(0,0));
|
||||
STATIC_REQUIRE((int2(0,1) || int2(1,0)) == bool2(1,1));
|
||||
STATIC_CHECK(int2(1,2) + int2(3,4) == int2(4,6));
|
||||
STATIC_CHECK(int2(1,2) - int2(3,4) == int2(-2,-2));
|
||||
STATIC_CHECK(int2(1,2) * int2(3,4) == int2(3,8));
|
||||
STATIC_CHECK(int2(3,4) / int2(1,2) == int2(3,2));
|
||||
STATIC_CHECK((int2(6,7) & int2(11,12)) == int2(2,4));
|
||||
STATIC_CHECK((int2(6,7) | int2(11,12)) == int2(15,15));
|
||||
STATIC_CHECK((int2(6,7) ^ int2(11,12)) == int2(13,11));
|
||||
STATIC_CHECK((int2(0,1) && int2(1,0)) == bool2(0,0));
|
||||
STATIC_CHECK((int2(0,1) || int2(1,0)) == bool2(1,1));
|
||||
|
||||
{
|
||||
int2 v{1,2};
|
||||
REQUIRE(&v == &(v += 3));
|
||||
REQUIRE(v == int2{4,5});
|
||||
REQUIRE(&v == &(v += int2{1,2}));
|
||||
REQUIRE(v == int2{5,7});
|
||||
CHECK(&v == &(v += 3));
|
||||
CHECK(v == int2{4,5});
|
||||
CHECK(&v == &(v += int2{1,2}));
|
||||
CHECK(v == int2{5,7});
|
||||
}
|
||||
{
|
||||
int2 v{4,5};
|
||||
REQUIRE(&v == &(v -= 3));
|
||||
REQUIRE(v == int2{1,2});
|
||||
REQUIRE(&v == &(v -= int2{2,4}));
|
||||
REQUIRE(v == int2{-1,-2});
|
||||
CHECK(&v == &(v -= 3));
|
||||
CHECK(v == int2{1,2});
|
||||
CHECK(&v == &(v -= int2{2,4}));
|
||||
CHECK(v == int2{-1,-2});
|
||||
}
|
||||
{
|
||||
int2 v{1,2};
|
||||
REQUIRE(&v == &(v *= 3));
|
||||
REQUIRE(v == int2{3,6});
|
||||
REQUIRE(&v == &(v *= int2{2,3}));
|
||||
REQUIRE(v == int2{6,18});
|
||||
CHECK(&v == &(v *= 3));
|
||||
CHECK(v == int2{3,6});
|
||||
CHECK(&v == &(v *= int2{2,3}));
|
||||
CHECK(v == int2{6,18});
|
||||
}
|
||||
{
|
||||
int2 v{6,18};
|
||||
REQUIRE(&v == &(v /= 2));
|
||||
REQUIRE(v == int2{3,9});
|
||||
REQUIRE(&v == &(v /= int2{3,4}));
|
||||
REQUIRE(v == int2{1,2});
|
||||
CHECK(&v == &(v /= 2));
|
||||
CHECK(v == int2{3,9});
|
||||
CHECK(&v == &(v /= int2{3,4}));
|
||||
CHECK(v == int2{1,2});
|
||||
}
|
||||
{
|
||||
int2 v1{11,12};
|
||||
REQUIRE(&v1 == &(v1 &= 6));
|
||||
REQUIRE(v1 == int2(2,4));
|
||||
CHECK(&v1 == &(v1 &= 6));
|
||||
CHECK(v1 == int2(2,4));
|
||||
int2 v2{6,7};
|
||||
REQUIRE(&v2 == &(v2 &= int2(11,12)));
|
||||
REQUIRE(v2 == int2(2,4));
|
||||
CHECK(&v2 == &(v2 &= int2(11,12)));
|
||||
CHECK(v2 == int2(2,4));
|
||||
}
|
||||
{
|
||||
int2 v1{11,12};
|
||||
REQUIRE(&v1 == &(v1 |= 6));
|
||||
REQUIRE(v1 == int2(15,14));
|
||||
CHECK(&v1 == &(v1 |= 6));
|
||||
CHECK(v1 == int2(15,14));
|
||||
int2 v2{6,7};
|
||||
REQUIRE(&v2 == &(v2 |= int2(11,12)));
|
||||
REQUIRE(v2 == int2(15,15));
|
||||
CHECK(&v2 == &(v2 |= int2(11,12)));
|
||||
CHECK(v2 == int2(15,15));
|
||||
}
|
||||
{
|
||||
int2 v1{11,12};
|
||||
REQUIRE(&v1 == &(v1 ^= 6));
|
||||
REQUIRE(v1 == int2(13,10));
|
||||
CHECK(&v1 == &(v1 ^= 6));
|
||||
CHECK(v1 == int2(13,10));
|
||||
int2 v2{6,7};
|
||||
REQUIRE(&v2 == &(v2 ^= int2(11,12)));
|
||||
REQUIRE(v2 == int2(13,11));
|
||||
CHECK(&v2 == &(v2 ^= int2(11,12)));
|
||||
CHECK(v2 == int2(13,11));
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("Angle and Trigonometry Functions") {
|
||||
STATIC_REQUIRE(radians(degrees(float2(12.13f))) == uapprox2(12.13f));
|
||||
STATIC_REQUIRE(degrees(radians(float2(12.13f))) == uapprox2(12.13f));
|
||||
SUBCASE("Angle and Trigonometric Functions") {
|
||||
STATIC_CHECK(radians(degrees(float2(12.13f))) == uapprox2(12.13f));
|
||||
STATIC_CHECK(degrees(radians(float2(12.13f))) == uapprox2(12.13f));
|
||||
|
||||
(void)sin(float2(1.f));
|
||||
(void)cos(float2(1.f));
|
||||
@@ -153,8 +153,11 @@ TEST_CASE("vmath/vec_fun") {
|
||||
{
|
||||
float2 out_ss{}, out_cs{};
|
||||
sincos(float2(10.f,15.f), &out_ss, &out_cs);
|
||||
REQUIRE(out_ss == uapprox2(sin(10.f), sin(15.f)));
|
||||
REQUIRE(out_cs == uapprox2(cos(10.f), cos(15.f)));
|
||||
CHECK(out_ss == uapprox2(sin(10.f), sin(15.f)));
|
||||
CHECK(out_cs == uapprox2(cos(10.f), cos(15.f)));
|
||||
const auto [out_ss2, out_cs2] = sincos(float2(10.f,15.f));
|
||||
CHECK(out_ss2 == uapprox2(sin(10.f), sin(15.f)));
|
||||
CHECK(out_cs2 == uapprox2(cos(10.f), cos(15.f)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,9 +172,25 @@ TEST_CASE("vmath/vec_fun") {
|
||||
}
|
||||
|
||||
SUBCASE("Common Functions") {
|
||||
STATIC_REQUIRE(abs(float2(1.f, -1.f)) == uapprox2(1.f,1.f));
|
||||
STATIC_REQUIRE(sign(float3(1.f, -1.f, 0.f)) == uapprox3(1.f,-1.f,0.f));
|
||||
STATIC_REQUIRE(rcp(float2(2.f, 4.f)) == uapprox2(0.5f,0.25f));
|
||||
STATIC_CHECK(abs(float2(1.f, -1.f)) == uapprox2(1.f,1.f));
|
||||
STATIC_CHECK(sqr(float2(2.f, -3.f)) == uapprox2(4.f,9.f));
|
||||
STATIC_CHECK(sign(float3(1.f, -1.f, 0.f)) == uapprox3(1.f,-1.f,0.f));
|
||||
STATIC_CHECK(rcp(float2(2.f, 4.f)) == uapprox2(0.5f,0.25f));
|
||||
|
||||
CHECK(copysign(
|
||||
float4(2.f, -4.f, 2.f, -4.f),
|
||||
5.f)
|
||||
== uapprox4(2.f, 4.f, 2.f, 4.f));
|
||||
|
||||
CHECK(copysign(
|
||||
float4(2.f, -4.f, 2.f, -4.f),
|
||||
-5.f)
|
||||
== uapprox4(-2.f, -4.f, -2.f, -4.f));
|
||||
|
||||
CHECK(copysign(
|
||||
float4(2.f, -4.f, 2.f, -4.f),
|
||||
float4(10.f, 5.f, -4.f, -0.4f))
|
||||
== uapprox4(2.f, 4.f, -2.f, -4.f));
|
||||
|
||||
(void)floor(float2(1.f, -1.f));
|
||||
(void)trunc(float2(1.f, -1.f));
|
||||
@@ -179,136 +198,124 @@ TEST_CASE("vmath/vec_fun") {
|
||||
(void)ceil(float2(1.f, -1.f));
|
||||
(void)fract(float2(1.f, -1.f));
|
||||
|
||||
REQUIRE(fmod(float2(1.7f), 1.2f) == uapprox2(0.5f));
|
||||
REQUIRE(fmod(float2(1.7f), float2(1.2f)) == uapprox2(0.5f));
|
||||
CHECK(fmod(float2(1.7f), 1.2f) == uapprox2(0.5f));
|
||||
CHECK(fmod(float2(1.7f), float2(1.2f)) == uapprox2(0.5f));
|
||||
|
||||
{
|
||||
float2 out_i{};
|
||||
REQUIRE(modf(float2(1.7f), &out_i) == uapprox2(0.7f));
|
||||
REQUIRE(out_i.x == uapprox(1.f));
|
||||
CHECK(modf(float2(1.7f), &out_i) == uapprox2(0.7f));
|
||||
CHECK(out_i.x == uapprox(1.f));
|
||||
}
|
||||
|
||||
STATIC_REQUIRE(min(int2(1,2)) == 1);
|
||||
STATIC_REQUIRE(min(int2(1,2), 1) == int2(1,1));
|
||||
STATIC_REQUIRE(min(int2(1,1), int2(0,2)) == int2(0,1));
|
||||
STATIC_CHECK(min(int2(1,2)) == 1);
|
||||
STATIC_CHECK(min(int2(1,2), 1) == int2(1,1));
|
||||
STATIC_CHECK(min(1, int2(1,2)) == int2(1,1));
|
||||
STATIC_CHECK(min(int2(1,1), int2(0,2)) == int2(0,1));
|
||||
|
||||
STATIC_REQUIRE(max(int2(1,2)) == 2);
|
||||
STATIC_REQUIRE(max(int2(1,2), 1) == int2(1,2));
|
||||
STATIC_REQUIRE(max(int2(1,1), int2(0,2)) == int2(1,2));
|
||||
STATIC_CHECK(max(int2(1,2)) == 2);
|
||||
STATIC_CHECK(max(int2(1,2), 1) == int2(1,2));
|
||||
STATIC_CHECK(max(1, int2(1,2)) == int2(1,2));
|
||||
STATIC_CHECK(max(int2(1,1), int2(0,2)) == int2(1,2));
|
||||
|
||||
STATIC_REQUIRE(clamp(int2(1,2), 0, 1) == int2(1,1));
|
||||
STATIC_REQUIRE(clamp(int2(1,2), int2(0), int2(1)) == int2(1,1));
|
||||
STATIC_CHECK(clamp(int2(1,2), 0, 1) == int2(1,1));
|
||||
STATIC_CHECK(clamp(int2(1,2), int2(0), int2(1)) == int2(1,1));
|
||||
|
||||
STATIC_REQUIRE(saturate(float3(-1.f,0.5,1.5f)) == uapprox3(0.f,0.5f,1.f));
|
||||
STATIC_CHECK(saturate(float3(-1.f,0.5,1.5f)) == uapprox3(0.f,0.5f,1.f));
|
||||
|
||||
STATIC_REQUIRE(lerp(float2(0.f), float2(10.f), 0.5f) == uapprox2(5.f));
|
||||
STATIC_REQUIRE(lerp(float2(0.f), float2(10.f), float2(0.5f)) == uapprox2(5.f));
|
||||
STATIC_CHECK(lerp(float2(2.f), float2(10.f), 0.f) == uapprox2(2.f));
|
||||
STATIC_CHECK(lerp(float2(2.f), float2(10.f), 0.5f) == uapprox2(6.f));
|
||||
STATIC_CHECK(lerp(float2(2.f), float2(10.f), 1.f) == uapprox2(10.f));
|
||||
|
||||
STATIC_REQUIRE(step(0.5f, float2(0.4f)) == uapprox2(0.f));
|
||||
STATIC_REQUIRE(step(0.5f, float2(0.6f)) == uapprox2(1.f));
|
||||
STATIC_REQUIRE(step(float2(0.5f), float2(0.4f)) == uapprox2(0.f));
|
||||
STATIC_REQUIRE(step(float2(0.5f), float2(0.6f)) == uapprox2(1.f));
|
||||
STATIC_CHECK(lerp(float2(2.f), float2(10.f), 0.f, 1.f) == uapprox2(10.f));
|
||||
STATIC_CHECK(lerp(float2(2.f), float2(10.f), 1.f, 0.f) == uapprox2(2.f));
|
||||
STATIC_CHECK(lerp(float2(2.f), float2(10.f), 0.5f, 0.2f) == uapprox2(3.f));
|
||||
|
||||
STATIC_REQUIRE(smoothstep(0.f, 1.f, float2(0.1f)) == uapprox2(0.028f));
|
||||
STATIC_REQUIRE(smoothstep(float2(0.f), float2(1.f), float2(0.1f)) == uapprox2(0.028f));
|
||||
STATIC_CHECK(lerp(float2(2.f), float2(10.f), float2(0.f)) == uapprox2(2.f));
|
||||
STATIC_CHECK(lerp(float2(2.f), float2(10.f), float2(0.5f)) == uapprox2(6.f));
|
||||
STATIC_CHECK(lerp(float2(2.f), float2(10.f), float2(1.f)) == uapprox2(10.f));
|
||||
|
||||
REQUIRE_FALSE(isnan(float2(1.f)).x);
|
||||
REQUIRE_FALSE(isinf(float2(1.f)).x);
|
||||
REQUIRE(isfinite(float2(1.f)).x);
|
||||
STATIC_CHECK(lerp(float2(2.f), float2(10.f), float2(0.f), float2(1.f)) == uapprox2(10.f));
|
||||
STATIC_CHECK(lerp(float2(2.f), float2(10.f), float2(1.f), float2(0.f)) == uapprox2(2.f));
|
||||
STATIC_CHECK(lerp(float2(2.f), float2(10.f), float2(0.5f), float2(0.2f)) == uapprox2(3.f));
|
||||
|
||||
REQUIRE_FALSE(fma(float2(2.f), float2(3.f), float2(4.f)).x == uapprox(12.f));
|
||||
STATIC_CHECK(step(0.5f, float2(0.4f)) == uapprox2(0.f));
|
||||
STATIC_CHECK(step(0.5f, float2(0.6f)) == uapprox2(1.f));
|
||||
STATIC_CHECK(step(float2(0.5f), float2(0.4f)) == uapprox2(0.f));
|
||||
STATIC_CHECK(step(float2(0.5f), float2(0.6f)) == uapprox2(1.f));
|
||||
|
||||
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{};
|
||||
REQUIRE(frexp(float2(1.7f), &out_exp).x == uapprox(0.85f));
|
||||
REQUIRE(out_exp == int2(1));
|
||||
CHECK(frexp(float2(1.7f), &out_exp).x == uapprox(0.85f));
|
||||
CHECK(out_exp == int2(1));
|
||||
}
|
||||
|
||||
REQUIRE(ldexp(float2(0.85f), int2(1)).x == uapprox(1.7f));
|
||||
CHECK(ldexp(float2(0.85f), int2(1)).x == uapprox(1.7f));
|
||||
}
|
||||
|
||||
SUBCASE("Geometric Functions") {
|
||||
REQUIRE(length(float2(10.f,0.f)) == uapprox(10.f));
|
||||
REQUIRE(length(float2(-10.f,0.f)) == uapprox(10.f));
|
||||
CHECK(length(float2(10.f,0.f)) == uapprox(10.f));
|
||||
CHECK(length(float2(-10.f,0.f)) == uapprox(10.f));
|
||||
|
||||
STATIC_REQUIRE(length2(float2(10.f,0.f)) == uapprox(100.f));
|
||||
STATIC_REQUIRE(length2(float2(-10.f,0.f)) == uapprox(100.f));
|
||||
STATIC_CHECK(length2(float2(10.f,0.f)) == uapprox(100.f));
|
||||
STATIC_CHECK(length2(float2(-10.f,0.f)) == uapprox(100.f));
|
||||
|
||||
REQUIRE(distance(float2(5.f,0.f), float2(10.f,0.f)) == uapprox(5.f));
|
||||
REQUIRE(distance(float2(-5.f,0.f), float2(-10.f,0.f)) == uapprox(5.f));
|
||||
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));
|
||||
|
||||
STATIC_REQUIRE(distance2(float2(5.f,0.f), float2(10.f,0.f)) == uapprox(25.f));
|
||||
STATIC_REQUIRE(distance2(float2(-5.f,0.f), float2(-10.f,0.f)) == uapprox(25.f));
|
||||
STATIC_CHECK(distance2(float2(5.f,0.f), float2(10.f,0.f)) == uapprox(25.f));
|
||||
STATIC_CHECK(distance2(float2(-5.f,0.f), float2(-10.f,0.f)) == uapprox(25.f));
|
||||
|
||||
STATIC_REQUIRE(dot(int2(1,2),int2(3,4)) == 11);
|
||||
STATIC_REQUIRE(cross(int2(1,0),int2(0,1)) == 1);
|
||||
STATIC_REQUIRE(cross(int3(1,0,0),int3(0,1,0)) == int3(0,0,1));
|
||||
REQUIRE(normalize(float2(0.5f,0.f)).x == uapprox(1.f));
|
||||
STATIC_CHECK(dot(int2(1,2),int2(3,4)) == 11);
|
||||
STATIC_CHECK(cross(int2(1,0),int2(0,1)) == 1);
|
||||
STATIC_CHECK(cross(int3(1,0,0),int3(0,1,0)) == int3(0,0,1));
|
||||
CHECK(normalize(float2(0.5f,0.f)).x == uapprox(1.f));
|
||||
|
||||
STATIC_REQUIRE(faceforward(float2(1.f), float2(2.f), float2(3.f)).x == uapprox(-1.f));
|
||||
STATIC_REQUIRE(reflect(float2(1.f), float2(2.f)).x == uapprox(-15.f));
|
||||
REQUIRE(refract(float2(1.f), float2(2.f), 1.f).x == uapprox(-15.f));
|
||||
STATIC_CHECK(faceforward(float2(1.f), float2(2.f), float2(3.f)).x == uapprox(-1.f));
|
||||
STATIC_CHECK(reflect(float2(1.f), float2(2.f)).x == uapprox(-15.f));
|
||||
CHECK(refract(float2(1.f), float2(2.f), 1.f).x == uapprox(-15.f));
|
||||
}
|
||||
|
||||
SUBCASE("Relational Functions") {
|
||||
STATIC_REQUIRE_FALSE(any(bool2(false, false)));
|
||||
STATIC_REQUIRE(any(bool2(true, false)));
|
||||
STATIC_REQUIRE(any(bool2(false, true)));
|
||||
STATIC_REQUIRE(any(bool2(true, true)));
|
||||
STATIC_CHECK_FALSE(any(bool2(false, false)));
|
||||
STATIC_CHECK(any(bool2(true, false)));
|
||||
STATIC_CHECK(any(bool2(false, true)));
|
||||
STATIC_CHECK(any(bool2(true, true)));
|
||||
|
||||
STATIC_REQUIRE_FALSE(any(int2(0, 0)));
|
||||
STATIC_REQUIRE(any(int2(1, 0)));
|
||||
STATIC_REQUIRE(any(int2(0, 1)));
|
||||
STATIC_REQUIRE(any(int2(1, 1)));
|
||||
STATIC_CHECK_FALSE(any(int2(0, 0)));
|
||||
STATIC_CHECK(any(int2(1, 0)));
|
||||
STATIC_CHECK(any(int2(0, 1)));
|
||||
STATIC_CHECK(any(int2(1, 1)));
|
||||
|
||||
STATIC_REQUIRE_FALSE(all(bool2(false, false)));
|
||||
STATIC_REQUIRE_FALSE(all(bool2(true, false)));
|
||||
STATIC_REQUIRE_FALSE(all(bool2(false, true)));
|
||||
STATIC_REQUIRE(all(bool2(true, true)));
|
||||
STATIC_CHECK_FALSE(all(bool2(false, false)));
|
||||
STATIC_CHECK_FALSE(all(bool2(true, false)));
|
||||
STATIC_CHECK_FALSE(all(bool2(false, true)));
|
||||
STATIC_CHECK(all(bool2(true, true)));
|
||||
|
||||
STATIC_REQUIRE_FALSE(all(int2(0, 0)));
|
||||
STATIC_REQUIRE_FALSE(all(int2(1, 0)));
|
||||
STATIC_REQUIRE_FALSE(all(int2(0, 1)));
|
||||
STATIC_REQUIRE(all(int2(1, 1)));
|
||||
STATIC_CHECK_FALSE(all(int2(0, 0)));
|
||||
STATIC_CHECK_FALSE(all(int2(1, 0)));
|
||||
STATIC_CHECK_FALSE(all(int2(0, 1)));
|
||||
STATIC_CHECK(all(int2(1, 1)));
|
||||
|
||||
STATIC_REQUIRE(approx(int3(1,1,1), int3(0,1,2)) == bool3(false, true, false));
|
||||
STATIC_REQUIRE(approx(int3(0,1,2),1) == bool3(false, true, false));
|
||||
STATIC_REQUIRE(approx(1,int3(0,1,2)) == bool3(false, true, false));
|
||||
STATIC_CHECK(approx(int3(1,1,1), int3(0,1,2)) == bool3(false, true, false));
|
||||
STATIC_CHECK(approx(int4(1,1,1,1), int4(0,1,2,3), 0) == bool4(false, true, false, false));
|
||||
STATIC_CHECK(approx(int4(1,1,1,1), int4(0,1,2,3), 1) == bool4(true, true, true, false));
|
||||
STATIC_CHECK(approx(int4(1,1,1,1), int4(0,1,2,3), 2) == bool4(true, true, true, true));
|
||||
|
||||
STATIC_REQUIRE(approx(int4(1,1,1,1), int4(0,1,2,3), 0) == bool4(false, true, false, false));
|
||||
STATIC_REQUIRE(approx(int4(0,1,2,3), 1, 0) == bool4(false, true, false, false));
|
||||
STATIC_REQUIRE(approx(1, int4(0,1,2,3), 0) == bool4(false, true, false, false));
|
||||
STATIC_CHECK(less(int3(1,1,1), int3(0,1,2)) == bool3(false, false, true));
|
||||
STATIC_CHECK(less_equal(int3(1,1,1), int3(0,1,2)) == bool3(false, true, true));
|
||||
STATIC_CHECK(greater(int3(1,1,1), int3(0,1,2)) == bool3(true, false, false));
|
||||
STATIC_CHECK(greater_equal(int3(1,1,1), int3(0,1,2)) == bool3(true, true, false));
|
||||
|
||||
STATIC_REQUIRE(approx(int4(1,1,1,1), int4(0,1,2,3), 1) == bool4(true, true, true, false));
|
||||
STATIC_REQUIRE(approx(int4(0,1,2,3), 1, 1) == bool4(true, true, true, false));
|
||||
STATIC_REQUIRE(approx(1, int4(0,1,2,3), 1) == bool4(true, true, true, false));
|
||||
|
||||
STATIC_REQUIRE(approx(int4(1,1,1,1), int4(0,1,2,3), 2) == bool4(true, true, true, true));
|
||||
STATIC_REQUIRE(approx(int4(0,1,2,3), 1, 2) == bool4(true, true, true, true));
|
||||
STATIC_REQUIRE(approx(1, int4(0,1,2,3), 2) == bool4(true, true, true, true));
|
||||
|
||||
STATIC_REQUIRE(less(int3(1,1,1), int3(0,1,2)) == bool3(false, false, true));
|
||||
STATIC_REQUIRE(less(int3(0,1,2), 1) == bool3(true, false, false));
|
||||
STATIC_REQUIRE(less(1, int3(0,1,2)) == bool3(false, false, true));
|
||||
|
||||
STATIC_REQUIRE(less_equal(int3(1,1,1), int3(0,1,2)) == bool3(false, true, true));
|
||||
STATIC_REQUIRE(less_equal(int3(0,1,2), 1) == bool3(true, true, false));
|
||||
STATIC_REQUIRE(less_equal(1, int3(0,1,2)) == bool3(false, true, true));
|
||||
|
||||
STATIC_REQUIRE(greater(int3(1,1,1), int3(0,1,2)) == bool3(true, false, false));
|
||||
STATIC_REQUIRE(greater(int3(0,1,2), 1) == bool3(false, false, true));
|
||||
STATIC_REQUIRE(greater(1, int3(0,1,2)) == bool3(true, false, false));
|
||||
|
||||
STATIC_REQUIRE(greater_equal(int3(1,1,1), int3(0,1,2)) == bool3(true, true, false));
|
||||
STATIC_REQUIRE(greater_equal(int3(0,1,2), 1) == bool3(false, true, true));
|
||||
STATIC_REQUIRE(greater_equal(1, int3(0,1,2)) == bool3(true, true, false));
|
||||
|
||||
STATIC_REQUIRE(equal_to(int3(1,1,1), int3(0,1,2)) == bool3(false, true, false));
|
||||
STATIC_REQUIRE(equal_to(int3(0,1,2),1) == bool3(false, true, false));
|
||||
STATIC_REQUIRE(equal_to(1,int3(0,1,2)) == bool3(false, true, false));
|
||||
|
||||
STATIC_REQUIRE(not_equal_to(int3(1,1,1), int3(0,1,2)) == bool3(true, false, true));
|
||||
STATIC_REQUIRE(not_equal_to(int3(0,1,2),1) == bool3(true, false, true));
|
||||
STATIC_REQUIRE(not_equal_to(1,int3(0,1,2)) == bool3(true, false, true));
|
||||
STATIC_CHECK(equal_to(int3(1,1,1), int3(0,1,2)) == bool3(false, true, false));
|
||||
STATIC_CHECK(not_equal_to(int3(1,1,1), int3(0,1,2)) == bool3(true, false, true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "vmath_tests.hpp"
|
||||
#include "doctest/doctest.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -15,74 +14,74 @@ namespace
|
||||
|
||||
TEST_CASE("vmath/vec") {
|
||||
SUBCASE("size/sizeof") {
|
||||
STATIC_REQUIRE(int2{}.size == 2);
|
||||
STATIC_REQUIRE(int3{}.size == 3);
|
||||
STATIC_REQUIRE(int4{}.size == 4);
|
||||
STATIC_CHECK(int2{}.size == 2);
|
||||
STATIC_CHECK(int3{}.size == 3);
|
||||
STATIC_CHECK(int4{}.size == 4);
|
||||
|
||||
STATIC_REQUIRE(sizeof(int2{}) == sizeof(int) * 2);
|
||||
STATIC_REQUIRE(sizeof(int3{}) == sizeof(int) * 3);
|
||||
STATIC_REQUIRE(sizeof(int4{}) == sizeof(int) * 4);
|
||||
STATIC_CHECK(sizeof(int2{}) == sizeof(int) * 2);
|
||||
STATIC_CHECK(sizeof(int3{}) == sizeof(int) * 3);
|
||||
STATIC_CHECK(sizeof(int4{}) == sizeof(int) * 4);
|
||||
}
|
||||
|
||||
SUBCASE("guides") {
|
||||
STATIC_REQUIRE(vec{1,2}.size == 2);
|
||||
STATIC_CHECK(vec{1,2}.size == 2);
|
||||
|
||||
STATIC_REQUIRE(vec{1,2,3}.size == 3);
|
||||
STATIC_REQUIRE(vec{{1,2},3}.size == 3);
|
||||
STATIC_REQUIRE(vec{1,{2,3}}.size == 3);
|
||||
STATIC_CHECK(vec{1,2,3}.size == 3);
|
||||
STATIC_CHECK(vec{{1,2},3}.size == 3);
|
||||
STATIC_CHECK(vec{1,{2,3}}.size == 3);
|
||||
|
||||
STATIC_REQUIRE(vec{1,2,3,4}.size == 4);
|
||||
STATIC_REQUIRE(vec{vec{1,2},3,4}.size == 4);
|
||||
STATIC_REQUIRE(vec{1,vec{2,3},4}.size == 4);
|
||||
STATIC_REQUIRE(vec{1,2,vec{3,4}}.size == 4);
|
||||
STATIC_REQUIRE(vec{vec{1,2},vec{3,4}}.size == 4);
|
||||
STATIC_REQUIRE(vec{vec{1,2,3},4}.size == 4);
|
||||
STATIC_REQUIRE(vec{1,vec{2,3,4}}.size == 4);
|
||||
STATIC_CHECK(vec{1,2,3,4}.size == 4);
|
||||
STATIC_CHECK(vec{vec{1,2},3,4}.size == 4);
|
||||
STATIC_CHECK(vec{1,vec{2,3},4}.size == 4);
|
||||
STATIC_CHECK(vec{1,2,vec{3,4}}.size == 4);
|
||||
STATIC_CHECK(vec{vec{1,2},vec{3,4}}.size == 4);
|
||||
STATIC_CHECK(vec{vec{1,2,3},4}.size == 4);
|
||||
STATIC_CHECK(vec{1,vec{2,3,4}}.size == 4);
|
||||
}
|
||||
|
||||
SUBCASE("ctors") {
|
||||
{
|
||||
STATIC_REQUIRE(int2().x == 0);
|
||||
STATIC_REQUIRE(int2().y == 0);
|
||||
STATIC_CHECK(int2().x == 0);
|
||||
STATIC_CHECK(int2().y == 0);
|
||||
|
||||
STATIC_REQUIRE(int2(1).x == 1);
|
||||
STATIC_REQUIRE(int2(1).y == 1);
|
||||
STATIC_CHECK(int2(1).x == 1);
|
||||
STATIC_CHECK(int2(1).y == 1);
|
||||
|
||||
STATIC_REQUIRE(int2(1,2).x == 1);
|
||||
STATIC_REQUIRE(int2(1,2).y == 2);
|
||||
STATIC_CHECK(int2(1,2).x == 1);
|
||||
STATIC_CHECK(int2(1,2).y == 2);
|
||||
}
|
||||
{
|
||||
constexpr int2 v(1,2);
|
||||
constexpr int2 v2 = v;
|
||||
STATIC_REQUIRE(v2 == int2(1,2));
|
||||
STATIC_CHECK(v2 == int2(1,2));
|
||||
}
|
||||
{
|
||||
constexpr int2 v(1,2);
|
||||
constexpr int2 v2 = std::move(v);
|
||||
STATIC_REQUIRE(v2 == int2(1,2));
|
||||
STATIC_CHECK(v2 == int2(1,2));
|
||||
}
|
||||
{
|
||||
STATIC_REQUIRE(int2(1) == int2(1,1));
|
||||
STATIC_REQUIRE(int2(1,2) == int2(1,2));
|
||||
STATIC_REQUIRE(int2(int2(1,2)) == int2(1,2));
|
||||
STATIC_REQUIRE(int2(int3(1,2,3)) == int2(1,2));
|
||||
STATIC_REQUIRE(int2(int4(1,2,3,4)) == int2(1,2));
|
||||
STATIC_CHECK(int2(1) == int2(1,1));
|
||||
STATIC_CHECK(int2(1,2) == int2(1,2));
|
||||
STATIC_CHECK(int2(int2(1,2)) == int2(1,2));
|
||||
STATIC_CHECK(int2(int3(1,2,3)) == int2(1,2));
|
||||
STATIC_CHECK(int2(int4(1,2,3,4)) == int2(1,2));
|
||||
|
||||
STATIC_REQUIRE(int3(1) == int3(1,1,1));
|
||||
STATIC_REQUIRE(int3(1,2,3) == int3(1,2,3));
|
||||
STATIC_REQUIRE(int3(int2(1,2),3) == int3(1,2,3));
|
||||
STATIC_REQUIRE(int3(1,int2(2,3)) == int3(1,2,3));
|
||||
STATIC_REQUIRE(int3(int3(1,2,3)) == int3(1,2,3));
|
||||
STATIC_REQUIRE(int3(int4(1,2,3,4)) == int3(1,2,3));
|
||||
STATIC_CHECK(int3(1) == int3(1,1,1));
|
||||
STATIC_CHECK(int3(1,2,3) == int3(1,2,3));
|
||||
STATIC_CHECK(int3(int2(1,2),3) == int3(1,2,3));
|
||||
STATIC_CHECK(int3(1,int2(2,3)) == int3(1,2,3));
|
||||
STATIC_CHECK(int3(int3(1,2,3)) == int3(1,2,3));
|
||||
STATIC_CHECK(int3(int4(1,2,3,4)) == int3(1,2,3));
|
||||
|
||||
STATIC_REQUIRE(int4(1) == int4(1,1,1,1));
|
||||
STATIC_REQUIRE(int4(1,2,3,4) == int4(1,2,3,4));
|
||||
STATIC_REQUIRE(int4(int2(1,2),3,4) == int4(1,2,3,4));
|
||||
STATIC_REQUIRE(int4(1,int2(2,3),4) == int4(1,2,3,4));
|
||||
STATIC_REQUIRE(int4(1,2,int2(3,4)) == int4(1,2,3,4));
|
||||
STATIC_REQUIRE(int4(int2(1,2),int2(3,4)) == int4(1,2,3,4));
|
||||
STATIC_REQUIRE(int4(int3(1,2,3),4) == int4(1,2,3,4));
|
||||
STATIC_REQUIRE(int4(1,int3(2,3,4)) == int4(1,2,3,4));
|
||||
STATIC_CHECK(int4(1) == int4(1,1,1,1));
|
||||
STATIC_CHECK(int4(1,2,3,4) == int4(1,2,3,4));
|
||||
STATIC_CHECK(int4(int2(1,2),3,4) == int4(1,2,3,4));
|
||||
STATIC_CHECK(int4(1,int2(2,3),4) == int4(1,2,3,4));
|
||||
STATIC_CHECK(int4(1,2,int2(3,4)) == int4(1,2,3,4));
|
||||
STATIC_CHECK(int4(int2(1,2),int2(3,4)) == int4(1,2,3,4));
|
||||
STATIC_CHECK(int4(int3(1,2,3),4) == int4(1,2,3,4));
|
||||
STATIC_CHECK(int4(1,int3(2,3,4)) == int4(1,2,3,4));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,13 +90,13 @@ TEST_CASE("vmath/vec") {
|
||||
int2 v(1,2);
|
||||
int2 v2;
|
||||
v2 = v;
|
||||
REQUIRE(v2 == int2(1,2));
|
||||
CHECK(v2 == int2(1,2));
|
||||
}
|
||||
{
|
||||
int2 v(1,2);
|
||||
int2 v2;
|
||||
v2 = std::move(v);
|
||||
REQUIRE(v2 == int2(1,2));
|
||||
CHECK(v2 == int2(1,2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,15 +105,15 @@ TEST_CASE("vmath/vec") {
|
||||
int2 v1(1,2);
|
||||
int2 v2(4,5);
|
||||
v1.swap(v2);
|
||||
REQUIRE(v1 == int2(4,5));
|
||||
REQUIRE(v2 == int2(1,2));
|
||||
CHECK(v1 == int2(4,5));
|
||||
CHECK(v2 == int2(1,2));
|
||||
}
|
||||
{
|
||||
int2 v1(1,2);
|
||||
int2 v2(4,5);
|
||||
swap(v1, v2);
|
||||
REQUIRE(v1 == int2(4,5));
|
||||
REQUIRE(v2 == int2(1,2));
|
||||
CHECK(v1 == int2(4,5));
|
||||
CHECK(v2 == int2(1,2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,125 +121,130 @@ TEST_CASE("vmath/vec") {
|
||||
{
|
||||
int2 v{1,2};
|
||||
|
||||
REQUIRE(*v.begin() == 1);
|
||||
REQUIRE(*(v.begin() + 1) == 2);
|
||||
REQUIRE(*(v.end() - 1) == 2);
|
||||
REQUIRE(*(v.end() - 2) == 1);
|
||||
REQUIRE(v.begin() + 2 == v.end());
|
||||
REQUIRE(v.end() - 2 == v.begin());
|
||||
CHECK(*v.begin() == 1);
|
||||
CHECK(*(v.begin() + 1) == 2);
|
||||
CHECK(*(v.end() - 1) == 2);
|
||||
CHECK(*(v.end() - 2) == 1);
|
||||
CHECK(v.begin() + 2 == v.end());
|
||||
CHECK(v.end() - 2 == v.begin());
|
||||
|
||||
REQUIRE(*v.cbegin() == 1);
|
||||
REQUIRE(*(v.cbegin() + 1) == 2);
|
||||
REQUIRE(*(v.cend() - 1) == 2);
|
||||
REQUIRE(*(v.cend() - 2) == 1);
|
||||
REQUIRE(v.cbegin() + 2 == v.cend());
|
||||
REQUIRE(v.cend() - 2 == v.cbegin());
|
||||
CHECK(*v.cbegin() == 1);
|
||||
CHECK(*(v.cbegin() + 1) == 2);
|
||||
CHECK(*(v.cend() - 1) == 2);
|
||||
CHECK(*(v.cend() - 2) == 1);
|
||||
CHECK(v.cbegin() + 2 == v.cend());
|
||||
CHECK(v.cend() - 2 == v.cbegin());
|
||||
|
||||
REQUIRE(*v.rbegin() == 2);
|
||||
REQUIRE(*(v.rbegin() + 1) == 1);
|
||||
REQUIRE(*(v.rend() - 1) == 1);
|
||||
REQUIRE(*(v.rend() - 2) == 2);
|
||||
REQUIRE(v.rbegin() + 2 == v.rend());
|
||||
REQUIRE(v.rend() - 2 == v.rbegin());
|
||||
CHECK(*v.rbegin() == 2);
|
||||
CHECK(*(v.rbegin() + 1) == 1);
|
||||
CHECK(*(v.rend() - 1) == 1);
|
||||
CHECK(*(v.rend() - 2) == 2);
|
||||
CHECK(v.rbegin() + 2 == v.rend());
|
||||
CHECK(v.rend() - 2 == v.rbegin());
|
||||
|
||||
REQUIRE(*v.crbegin() == 2);
|
||||
REQUIRE(*(v.crbegin() + 1) == 1);
|
||||
REQUIRE(*(v.crend() - 1) == 1);
|
||||
REQUIRE(*(v.crend() - 2) == 2);
|
||||
REQUIRE(v.crbegin() + 2 == v.crend());
|
||||
REQUIRE(v.crend() - 2 == v.crbegin());
|
||||
CHECK(*v.crbegin() == 2);
|
||||
CHECK(*(v.crbegin() + 1) == 1);
|
||||
CHECK(*(v.crend() - 1) == 1);
|
||||
CHECK(*(v.crend() - 2) == 2);
|
||||
CHECK(v.crbegin() + 2 == v.crend());
|
||||
CHECK(v.crend() - 2 == v.crbegin());
|
||||
|
||||
*v.begin() = 3;
|
||||
REQUIRE(v == int2{3,2});
|
||||
CHECK(v == int2{3,2});
|
||||
*v.rbegin() = 4;
|
||||
REQUIRE(v == int2{3,4});
|
||||
CHECK(v == int2{3,4});
|
||||
}
|
||||
{
|
||||
const int2 v{1,2};
|
||||
|
||||
REQUIRE(*v.begin() == 1);
|
||||
REQUIRE(*(v.begin() + 1) == 2);
|
||||
REQUIRE(*(v.end() - 1) == 2);
|
||||
REQUIRE(*(v.end() - 2) == 1);
|
||||
REQUIRE(v.begin() + 2 == v.end());
|
||||
REQUIRE(v.end() - 2 == v.begin());
|
||||
CHECK(*v.begin() == 1);
|
||||
CHECK(*(v.begin() + 1) == 2);
|
||||
CHECK(*(v.end() - 1) == 2);
|
||||
CHECK(*(v.end() - 2) == 1);
|
||||
CHECK(v.begin() + 2 == v.end());
|
||||
CHECK(v.end() - 2 == v.begin());
|
||||
|
||||
REQUIRE(*v.cbegin() == 1);
|
||||
REQUIRE(*(v.cbegin() + 1) == 2);
|
||||
REQUIRE(*(v.cend() - 1) == 2);
|
||||
REQUIRE(*(v.cend() - 2) == 1);
|
||||
REQUIRE(v.cbegin() + 2 == v.cend());
|
||||
REQUIRE(v.cend() - 2 == v.cbegin());
|
||||
CHECK(*v.cbegin() == 1);
|
||||
CHECK(*(v.cbegin() + 1) == 2);
|
||||
CHECK(*(v.cend() - 1) == 2);
|
||||
CHECK(*(v.cend() - 2) == 1);
|
||||
CHECK(v.cbegin() + 2 == v.cend());
|
||||
CHECK(v.cend() - 2 == v.cbegin());
|
||||
|
||||
REQUIRE(*v.rbegin() == 2);
|
||||
REQUIRE(*(v.rbegin() + 1) == 1);
|
||||
REQUIRE(*(v.rend() - 1) == 1);
|
||||
REQUIRE(*(v.rend() - 2) == 2);
|
||||
REQUIRE(v.rbegin() + 2 == v.rend());
|
||||
REQUIRE(v.rend() - 2 == v.rbegin());
|
||||
CHECK(*v.rbegin() == 2);
|
||||
CHECK(*(v.rbegin() + 1) == 1);
|
||||
CHECK(*(v.rend() - 1) == 1);
|
||||
CHECK(*(v.rend() - 2) == 2);
|
||||
CHECK(v.rbegin() + 2 == v.rend());
|
||||
CHECK(v.rend() - 2 == v.rbegin());
|
||||
|
||||
REQUIRE(*v.crbegin() == 2);
|
||||
REQUIRE(*(v.crbegin() + 1) == 1);
|
||||
REQUIRE(*(v.crend() - 1) == 1);
|
||||
REQUIRE(*(v.crend() - 2) == 2);
|
||||
REQUIRE(v.crbegin() + 2 == v.crend());
|
||||
REQUIRE(v.crend() - 2 == v.crbegin());
|
||||
CHECK(*v.crbegin() == 2);
|
||||
CHECK(*(v.crbegin() + 1) == 1);
|
||||
CHECK(*(v.crend() - 1) == 1);
|
||||
CHECK(*(v.crend() - 2) == 2);
|
||||
CHECK(v.crbegin() + 2 == v.crend());
|
||||
CHECK(v.crend() - 2 == v.crbegin());
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("data") {
|
||||
{
|
||||
int2 i2;
|
||||
REQUIRE(i2.data() == &i2[0]);
|
||||
CHECK(i2.data() == &i2[0]);
|
||||
|
||||
int3 i3;
|
||||
REQUIRE(i3.data() == &i3[0]);
|
||||
CHECK(i3.data() == &i3[0]);
|
||||
|
||||
int4 i4;
|
||||
REQUIRE(i4.data() == &i4[0]);
|
||||
CHECK(i4.data() == &i4[0]);
|
||||
}
|
||||
{
|
||||
const int2 i2;
|
||||
REQUIRE(i2.data() == &i2[0]);
|
||||
CHECK(i2.data() == &i2[0]);
|
||||
|
||||
const int3 i3;
|
||||
REQUIRE(i3.data() == &i3[0]);
|
||||
CHECK(i3.data() == &i3[0]);
|
||||
|
||||
const int4 i4;
|
||||
REQUIRE(i4.data() == &i4[0]);
|
||||
CHECK(i4.data() == &i4[0]);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("operator[]") {
|
||||
{
|
||||
STATIC_REQUIRE(int2(1,2).x == 1);
|
||||
STATIC_REQUIRE(int2(1,2).y == 2);
|
||||
STATIC_CHECK(int2(1,2).x == 1);
|
||||
STATIC_CHECK(int2(1,2).y == 2);
|
||||
|
||||
STATIC_REQUIRE(int3(1,2,3).x == 1);
|
||||
STATIC_REQUIRE(int3(1,2,3).y == 2);
|
||||
STATIC_REQUIRE(int3(1,2,3).z == 3);
|
||||
STATIC_CHECK(int3(1,2,3).x == 1);
|
||||
STATIC_CHECK(int3(1,2,3).y == 2);
|
||||
STATIC_CHECK(int3(1,2,3).z == 3);
|
||||
|
||||
STATIC_REQUIRE(int4(1,2,3,4).x == 1);
|
||||
STATIC_REQUIRE(int4(1,2,3,4).y == 2);
|
||||
STATIC_REQUIRE(int4(1,2,3,4).z == 3);
|
||||
STATIC_REQUIRE(int4(1,2,3,4).w == 4);
|
||||
STATIC_CHECK(int4(1,2,3,4).x == 1);
|
||||
STATIC_CHECK(int4(1,2,3,4).y == 2);
|
||||
STATIC_CHECK(int4(1,2,3,4).z == 3);
|
||||
STATIC_CHECK(int4(1,2,3,4).w == 4);
|
||||
}
|
||||
{
|
||||
STATIC_REQUIRE(int2(1,2)[0] == 1);
|
||||
STATIC_REQUIRE(int2(1,2)[1] == 2);
|
||||
STATIC_CHECK(int2(1,2)[0] == 1);
|
||||
STATIC_CHECK(int2(1,2)[1] == 2);
|
||||
}
|
||||
{
|
||||
int2 v;
|
||||
v.x = 1;
|
||||
v.y = 2;
|
||||
REQUIRE(v == int2(1,2));
|
||||
CHECK(v == int2(1,2));
|
||||
CHECK(std::as_const(v).at(0) == 1);
|
||||
CHECK(std::as_const(v).at(1) == 2);
|
||||
}
|
||||
{
|
||||
int3 v;
|
||||
v.x = 1;
|
||||
v.y = 2;
|
||||
v.z = 3;
|
||||
REQUIRE(v == int3(1,2,3));
|
||||
CHECK(v == int3(1,2,3));
|
||||
CHECK(std::as_const(v).at(0) == 1);
|
||||
CHECK(std::as_const(v).at(1) == 2);
|
||||
CHECK(std::as_const(v).at(2) == 3);
|
||||
}
|
||||
{
|
||||
int4 v;
|
||||
@@ -248,33 +252,39 @@ TEST_CASE("vmath/vec") {
|
||||
v.y = 2;
|
||||
v.z = 3;
|
||||
v.w = 4;
|
||||
REQUIRE(v == int4(1,2,3,4));
|
||||
CHECK(v == int4(1,2,3,4));
|
||||
CHECK(std::as_const(v).at(0) == 1);
|
||||
CHECK(std::as_const(v).at(1) == 2);
|
||||
CHECK(std::as_const(v).at(2) == 3);
|
||||
CHECK(std::as_const(v).at(3) == 4);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("at") {
|
||||
STATIC_REQUIRE(int2(1,2).at(0) == 1);
|
||||
STATIC_REQUIRE(int2(1,2).at(1) == 2);
|
||||
REQUIRE_THROWS_AS((void)int2(1,2).at(2), std::out_of_range);
|
||||
STATIC_CHECK(int2(1,2).at(0) == 1);
|
||||
STATIC_CHECK(int2(1,2).at(1) == 2);
|
||||
#ifndef VMATH_HPP_NO_EXCEPTIONS
|
||||
CHECK_THROWS_AS((void)int2(1,2).at(2), std::out_of_range);
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("operator==/operator!=") {
|
||||
STATIC_REQUIRE(int2(1,2) == int2(1,2));
|
||||
STATIC_REQUIRE_FALSE(int2(1,2) == int2(2,2));
|
||||
STATIC_REQUIRE_FALSE(int2(1,2) == int2(1,3));
|
||||
STATIC_CHECK(int2(1,2) == int2(1,2));
|
||||
STATIC_CHECK_FALSE(int2(1,2) == int2(2,2));
|
||||
STATIC_CHECK_FALSE(int2(1,2) == int2(1,3));
|
||||
|
||||
STATIC_REQUIRE_FALSE(int2(1,2) != int2(1,2));
|
||||
STATIC_REQUIRE(int2(1,2) != int2(2,2));
|
||||
STATIC_REQUIRE(int2(1,2) != int2(1,3));
|
||||
STATIC_CHECK_FALSE(int2(1,2) != int2(1,2));
|
||||
STATIC_CHECK(int2(1,2) != int2(2,2));
|
||||
STATIC_CHECK(int2(1,2) != int2(1,3));
|
||||
}
|
||||
|
||||
SUBCASE("operator<") {
|
||||
STATIC_REQUIRE_FALSE(int2(1,2) < int2(1,2));
|
||||
STATIC_CHECK_FALSE(int2(1,2) < int2(1,2));
|
||||
|
||||
STATIC_REQUIRE(int2(1,1) < int2(1,2));
|
||||
STATIC_REQUIRE_FALSE(int2(1,2) < int2(1,1));
|
||||
STATIC_CHECK(int2(1,1) < int2(1,2));
|
||||
STATIC_CHECK_FALSE(int2(1,2) < int2(1,1));
|
||||
|
||||
STATIC_REQUIRE(int2(0,3) < int2(1,2));
|
||||
STATIC_REQUIRE_FALSE(int2(1,2) < int2(0,3));
|
||||
STATIC_CHECK(int2(0,3) < int2(1,2));
|
||||
STATIC_CHECK_FALSE(int2(1,2) < int2(0,3));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user