From 98b11af392319c6708acff65fa3e4bc53716ea6a Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 20 Nov 2020 22:24:15 +0700 Subject: [PATCH 01/53] basic vector type --- headers/vmath.hpp/vmath.hpp | 233 ++++++++++++++++++++++++++++++++++++ untests/vmath_tests.cpp | 182 +++++++++++++++++++++++++++- 2 files changed, 413 insertions(+), 2 deletions(-) diff --git a/headers/vmath.hpp/vmath.hpp b/headers/vmath.hpp/vmath.hpp index 823789d..82d7d82 100644 --- a/headers/vmath.hpp/vmath.hpp +++ b/headers/vmath.hpp/vmath.hpp @@ -6,6 +6,239 @@ #pragma once +#include + +#include +#include +#include +#include +#include +#include + namespace vmath_hpp { + struct uninit_t {}; + inline constexpr uninit_t uninit; +} + +namespace vmath_hpp::detail +{ + template < typename T, std::size_t Size > + class vec_base; + + template < typename T > + class vec_base { + public: + T x, y; + public: + constexpr vec_base() : x{}, y{} {} + constexpr explicit vec_base(uninit_t) {} + + constexpr explicit vec_base(const T& v) + : x{v}, y{v} {} + + constexpr vec_base(T x, T y) + : x{std::move(x)}, y{std::move(y)} {} + + constexpr explicit vec_base(vec_base&& xy) + : x{std::move(xy.x)} , y{std::move(xy.y)} {} + constexpr explicit vec_base(const vec_base& xy) + : x{xy.x} , y{xy.y} {} + + constexpr explicit vec_base(vec_base&& xy) + : x{std::move(xy.x)} , y{std::move(xy.y)} {} + constexpr explicit vec_base(const vec_base& xy) + : x{xy.x} , y{xy.y} {} + + constexpr T* data() noexcept { + return std::addressof(x); + } + + constexpr const T* data() const noexcept { + return std::addressof(x); + } + }; + + template < typename T > + class vec_base { + public: + T x, y, z; + public: + constexpr vec_base() : x{}, y{}, z{} {} + constexpr explicit vec_base(uninit_t) {} + + constexpr explicit vec_base(const T& v) + : x{v}, y{v}, z{v} {} + + constexpr vec_base(T x, T y, T z) + : x{std::move(x)}, y{std::move(y)}, z{std::move(z)} {} + + constexpr explicit vec_base(vec_base&& xy, T z) + : x{std::move(xy.x)} , y{std::move(xy.y)} , z{std::move(z)} {} + constexpr explicit vec_base(const vec_base& xy, T z) + : x{xy.x} , y{xy.y} , z{std::move(z)} {} + + constexpr explicit vec_base(vec_base&& xyz) + : x{std::move(xyz.x)} , y{std::move(xyz.y)} , z{std::move(xyz.z)} {} + constexpr explicit vec_base(const vec_base& xyz) + : x{xyz.x} , y{xyz.y} , z{xyz.z} {} + + constexpr T* data() noexcept { + return std::addressof(x); + } + + constexpr const T* data() const noexcept { + return std::addressof(x); + } + }; + + template < typename T > + class vec_base { + public: + T x, y, z, w; + public: + constexpr vec_base() : x{}, y{}, z{}, w{} {} + constexpr explicit vec_base(uninit_t) {} + + constexpr explicit vec_base(const T& v) + : x{v}, y{v}, z{v}, w{v} {} + + constexpr vec_base(T x, T y, T z, T w) + : x{std::move(x)}, y{std::move(y)}, z{std::move(z)}, w{std::move(w)} {} + + constexpr explicit vec_base(vec_base&& xy, T z, T w) + : x{std::move(xy.x)} , y{std::move(xy.y)} , z{std::move(z)} , w{std::move(w)} {} + constexpr explicit vec_base(const vec_base& xy, T z, T w) + : x{xy.x} , y{xy.y} , z{std::move(z)} , w{std::move(w)} {} + + constexpr explicit vec_base(vec_base&& xyz, T w) + : x{std::move(xyz.x)} , y{std::move(xyz.y)} , z{std::move(xyz.z)} , w{std::move(w)} {} + constexpr explicit vec_base(const vec_base& xyz, T w) + : x{xyz.x} , y{xyz.y} , z{xyz.z} , w{std::move(w)} {} + + constexpr T* data() noexcept { + return std::addressof(x); + } + + constexpr const T* data() const noexcept { + return std::addressof(x); + } + }; +} + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + class vec final : public detail::vec_base { + public: + using self_type = vec; + using value_type = T; + + using pointer = value_type*; + using const_pointer = const value_type*; + + using reference = value_type&; + using const_reference = const value_type&; + + using iterator = value_type*; + using const_iterator = const value_type*; + + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + public: + using detail::vec_base::data; + using detail::vec_base::vec_base; + + vec(vec&&) = default; + vec& operator=(vec&&) = default; + + vec(const vec&) = default; + vec& operator=(const vec&) = default; + + void fill(const value_type& v) { + std::fill_n(begin(), size(), v); + } + + void swap(vec& other) noexcept(std::is_nothrow_swappable_v) { + std::swap_ranges(begin(), end(), other.begin()); + } + + constexpr iterator begin() noexcept { return iterator(data()); } + constexpr const_iterator begin() const noexcept { return const_iterator(data()); } + constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); } + + constexpr iterator end() noexcept { return iterator(data() + size()); } + constexpr const_iterator end() const noexcept { return const_iterator(data() + size()); } + constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); } + + constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } + constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } + constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } + + constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); } + constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } + constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } + + constexpr size_type size() const noexcept { return Size; } + constexpr size_type max_size() const noexcept { return Size; } + constexpr bool empty() const noexcept { return !Size; } + + constexpr reference operator[](size_type index) noexcept { return data()[index]; } + constexpr const_reference operator[](size_type index) const noexcept { return data()[index]; } + + constexpr reference at(size_type index) { + if ( index >= size() ) { + throw std::out_of_range("vec::at"); + } + return data()[index]; + } + + constexpr const_reference at(size_type index) const { + if ( index >= size() ) { + throw std::out_of_range("vec::at"); + } + return data()[index]; + } + }; + + template < typename T, std::size_t Size > + void swap(vec& l, vec& r) noexcept(noexcept(l.swap(r))) { + l.swap(r); + } +} + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + bool operator==(const vec& l, const vec& r) { + return std::equal(l.begin(), l.end(), r.begin()); + } + + template < typename T, std::size_t Size > + bool operator!=(const vec& l, const vec& r) { + return !(l == r); + } + + template < typename T, std::size_t Size > + bool operator<(const vec& l, const vec& r) { + return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); + } +} + +namespace vmath_hpp +{ + using vec2i = vec; + using vec3i = vec; + using vec4i = vec; + + using vec2b = vec; + using vec3b = vec; + using vec4b = vec; + + using vec2f = vec; + using vec3f = vec; + using vec4f = vec; } diff --git a/untests/vmath_tests.cpp b/untests/vmath_tests.cpp index 2407089..26a7419 100644 --- a/untests/vmath_tests.cpp +++ b/untests/vmath_tests.cpp @@ -13,6 +13,184 @@ namespace { } -TEST_CASE("vmath") { - REQUIRE(true); +TEST_CASE("vmath/vec") { + using namespace vmath_hpp; + + SECTION("sizeof") { + STATIC_REQUIRE(sizeof(vec2i{}) == sizeof(int) * 2); + STATIC_REQUIRE(sizeof(vec3i{}) == sizeof(int) * 3); + STATIC_REQUIRE(sizeof(vec4i{}) == sizeof(int) * 4); + } + + SECTION("ctors") { + { + REQUIRE(vec2i().x == 0); + REQUIRE(vec2i().y == 0); + + REQUIRE(vec2i(1).x == 1); + REQUIRE(vec2i(1).y == 1); + + REQUIRE(vec2i(1,2).x == 1); + REQUIRE(vec2i(1,2).y == 2); + } + { + vec2i v(1,2); + vec2i v2 = v; + REQUIRE(v2 == vec2i(1,2)); + } + { + vec2i v(1,2); + vec2i v2 = std::move(v); + REQUIRE(v2 == vec2i(1,2)); + } + { + REQUIRE(vec2i(vec3i(1,2,3)) == vec2i(1,2)); + REQUIRE(vec2i(vec4i(1,2,3,4)) == vec2i(1,2)); + + REQUIRE(vec3i(vec2i(1,2),3) == vec3i(1,2,3)); + REQUIRE(vec3i(vec4i(1,2,3,4)) == vec3i(1,2,3)); + + REQUIRE(vec4i(vec2i(1,2),3,4) == vec4i(1,2,3,4)); + REQUIRE(vec4i(vec3i(1,2,3),4) == vec4i(1,2,3,4)); + } + } + + SECTION("operator=") { + { + vec2i v(1,2); + vec2i v2; + v2 = v; + REQUIRE(v2 == vec2i(1,2)); + } + { + vec2i v(1,2); + vec2i v2; + v2 = std::move(v); + REQUIRE(v2 == vec2i(1,2)); + } + } + + SECTION("fill") { + vec2i v(1,2); + v.fill(4); + REQUIRE(v == vec2i(4)); + } + + SECTION("swap") { + { + vec2i v1(1,2); + vec2i v2(4,5); + v1.swap(v2); + REQUIRE(v1 == vec2i(4,5)); + REQUIRE(v2 == vec2i(1,2)); + } + { + vec2i v1(1,2); + vec2i v2(4,5); + swap(v1, v2); + REQUIRE(v1 == vec2i(4,5)); + REQUIRE(v2 == vec2i(1,2)); + } + } + + SECTION("data") { + vec2i v(1,2); + REQUIRE(v.data() == &v.x); + REQUIRE(std::as_const(v).data() == &v.x); + } + + SECTION("iter") { + { + vec2i v(1,2); + vec2i::iterator i = v.begin(); + REQUIRE(*i++ == 1); + REQUIRE(*i++ == 2); + REQUIRE(v.end() == i); + } + { + const vec2i v(1,2); + vec2i::const_iterator i = v.begin(); + REQUIRE(*i++ == 1); + REQUIRE(*i++ == 2); + REQUIRE(v.end() == i); + } + { + vec2i v(1,2); + for ( auto i = v.begin(); i < v.end(); ++i ) { + *i = *i * 2; + } + REQUIRE(v == vec2i(2,4)); + } + } + + SECTION("riter") { + { + vec2i v(1,2); + vec2i::reverse_iterator i = v.rbegin(); + REQUIRE(*i++ == 2); + REQUIRE(*i++ == 1); + REQUIRE(v.rend() == i); + for ( auto j = v.rbegin(); j < v.rend(); ++j ) { + *j = *j * 2; + } + REQUIRE(v == vec2i(2,4)); + } + { + const vec2i v(1,2); + vec2i::const_reverse_iterator i = v.rbegin(); + REQUIRE(*i++ == 2); + REQUIRE(*i++ == 1); + REQUIRE(v.rend() == i); + } + { + vec2i v(1,2); + for ( auto i = v.rbegin(); i < v.rend(); ++i ) { + *i = *i * 2; + } + REQUIRE(v == vec2i(2,4)); + } + } + + SECTION("size/max_size/empty") { + STATIC_REQUIRE(vec().size() == 2); + STATIC_REQUIRE(vec().max_size() == 2); + STATIC_REQUIRE_FALSE(vec().empty()); + + STATIC_REQUIRE(vec().size() == 3); + STATIC_REQUIRE(vec().max_size() == 3); + STATIC_REQUIRE_FALSE(vec().empty()); + } + + SECTION("operator[]") { + REQUIRE(vec2i(1,2).x == 1); + REQUIRE(vec2i(1,2).y == 2); + REQUIRE(vec2i(1,2)[0] == 1); + REQUIRE(vec2i(1,2)[1] == 2); + } + + SECTION("at") { + REQUIRE(vec2i(1,2).at(0) == 1); + REQUIRE(vec2i(1,2).at(1) == 2); + REQUIRE_THROWS_AS(vec2i(1,2).at(2), std::out_of_range); + } + + SECTION("operator==/operator!=") { + REQUIRE(vec2i(1,2) == vec2i(1,2)); + REQUIRE_FALSE(vec2i(1,2) == vec2i(2,2)); + REQUIRE_FALSE(vec2i(1,2) == vec2i(1,3)); + + REQUIRE_FALSE(vec2i(1,2) != vec2i(1,2)); + REQUIRE(vec2i(1,2) != vec2i(2,2)); + REQUIRE(vec2i(1,2) != vec2i(1,3)); + } + + SECTION("operator<") { + REQUIRE_FALSE(vec2i(1,2) < vec2i(1,2)); + + REQUIRE(vec2i(1,1) < vec2i(1,2)); + REQUIRE_FALSE(vec2i(1,2) < vec2i(1,1)); + + REQUIRE(vec2i(0,3) < vec2i(1,2)); + REQUIRE_FALSE(vec2i(1,2) < vec2i(0,3)); + } } From 9c5acfdc1cf76a31c219ef7ab58c4934d8db60f1 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 20 Nov 2020 23:31:56 +0700 Subject: [PATCH 02/53] more constexpr --- headers/vmath.hpp/vmath.hpp | 155 ++++++++++++++++++++---------------- untests/vmath_tests.cpp | 120 ++++++++++++++++------------ 2 files changed, 157 insertions(+), 118 deletions(-) diff --git a/headers/vmath.hpp/vmath.hpp b/headers/vmath.hpp/vmath.hpp index 82d7d82..89242df 100644 --- a/headers/vmath.hpp/vmath.hpp +++ b/headers/vmath.hpp/vmath.hpp @@ -7,9 +7,6 @@ #pragma once #include - -#include -#include #include #include #include @@ -29,100 +26,103 @@ namespace vmath_hpp::detail template < typename T > class vec_base { public: - T x, y; + T data[2]; public: - constexpr vec_base() : x{}, y{} {} + constexpr vec_base() : data{} {} constexpr explicit vec_base(uninit_t) {} constexpr explicit vec_base(const T& v) - : x{v}, y{v} {} + : data{v, v} {} constexpr vec_base(T x, T y) - : x{std::move(x)}, y{std::move(y)} {} + : data{std::move(x), std::move(y)} {} constexpr explicit vec_base(vec_base&& xy) - : x{std::move(xy.x)} , y{std::move(xy.y)} {} + : data{std::move(xy.x()), std::move(xy.y())} {} constexpr explicit vec_base(const vec_base& xy) - : x{xy.x} , y{xy.y} {} + : data{xy.x(), xy.y()} {} constexpr explicit vec_base(vec_base&& xy) - : x{std::move(xy.x)} , y{std::move(xy.y)} {} + : data{std::move(xy.x()), std::move(xy.y())} {} constexpr explicit vec_base(const vec_base& xy) - : x{xy.x} , y{xy.y} {} + : data{xy.x(), xy.y()} {} - constexpr T* data() noexcept { - return std::addressof(x); - } + constexpr T& x() noexcept { return data[0]; } + constexpr const T& x() const noexcept { return data[0]; } - constexpr const T* data() const noexcept { - return std::addressof(x); - } + constexpr T& y() noexcept { return data[1]; } + constexpr const T& y() const noexcept { return data[1]; } }; template < typename T > class vec_base { public: - T x, y, z; + T data[3]; public: - constexpr vec_base() : x{}, y{}, z{} {} + constexpr vec_base() : data{} {} constexpr explicit vec_base(uninit_t) {} constexpr explicit vec_base(const T& v) - : x{v}, y{v}, z{v} {} + : data{v, v, v} {} constexpr vec_base(T x, T y, T z) - : x{std::move(x)}, y{std::move(y)}, z{std::move(z)} {} + : data{std::move(x), std::move(y), std::move(z)} {} constexpr explicit vec_base(vec_base&& xy, T z) - : x{std::move(xy.x)} , y{std::move(xy.y)} , z{std::move(z)} {} + : data{std::move(xy.x()), std::move(xy.y()), std::move(z)} {} constexpr explicit vec_base(const vec_base& xy, T z) - : x{xy.x} , y{xy.y} , z{std::move(z)} {} + : data{xy.x(), xy.y(), std::move(z)} {} constexpr explicit vec_base(vec_base&& xyz) - : x{std::move(xyz.x)} , y{std::move(xyz.y)} , z{std::move(xyz.z)} {} + : data{std::move(xyz.x()), std::move(xyz.y()), std::move(xyz.z())} {} constexpr explicit vec_base(const vec_base& xyz) - : x{xyz.x} , y{xyz.y} , z{xyz.z} {} + : data{xyz.x(), xyz.y(), xyz.z()} {} - constexpr T* data() noexcept { - return std::addressof(x); - } + constexpr T& x() noexcept { return data[0]; } + constexpr const T& x() const noexcept { return data[0]; } - constexpr const T* data() const noexcept { - return std::addressof(x); - } + constexpr T& y() noexcept { return data[1]; } + constexpr const T& y() const noexcept { return data[1]; } + + constexpr T& z() noexcept { return data[2]; } + constexpr const T& z() const noexcept { return data[2]; } }; template < typename T > class vec_base { public: - T x, y, z, w; + T data[4]; public: - constexpr vec_base() : x{}, y{}, z{}, w{} {} + constexpr vec_base() : data{} {} constexpr explicit vec_base(uninit_t) {} constexpr explicit vec_base(const T& v) - : x{v}, y{v}, z{v}, w{v} {} + : data{v, v, v, v} {} constexpr vec_base(T x, T y, T z, T w) - : x{std::move(x)}, y{std::move(y)}, z{std::move(z)}, w{std::move(w)} {} + : data{std::move(x), std::move(y), std::move(z), std::move(w)} {} constexpr explicit vec_base(vec_base&& xy, T z, T w) - : x{std::move(xy.x)} , y{std::move(xy.y)} , z{std::move(z)} , w{std::move(w)} {} + : data{std::move(xy.x()), std::move(xy.y()), std::move(z), std::move(w)} {} constexpr explicit vec_base(const vec_base& xy, T z, T w) - : x{xy.x} , y{xy.y} , z{std::move(z)} , w{std::move(w)} {} + : data{xy.x(), xy.y(), std::move(z), std::move(w)} {} constexpr explicit vec_base(vec_base&& xyz, T w) - : x{std::move(xyz.x)} , y{std::move(xyz.y)} , z{std::move(xyz.z)} , w{std::move(w)} {} + : data{std::move(xyz.x()), std::move(xyz.y()), std::move(xyz.z()), std::move(w)} {} constexpr explicit vec_base(const vec_base& xyz, T w) - : x{xyz.x} , y{xyz.y} , z{xyz.z} , w{std::move(w)} {} + : data{xyz.x(), xyz.y(), xyz.z(), std::move(w)} {} - constexpr T* data() noexcept { - return std::addressof(x); - } + constexpr T& x() noexcept { return data[0]; } + constexpr const T& x() const noexcept { return data[0]; } - constexpr const T* data() const noexcept { - return std::addressof(x); - } + constexpr T& y() noexcept { return data[1]; } + constexpr const T& y() const noexcept { return data[1]; } + + constexpr T& z() noexcept { return data[2]; } + constexpr const T& z() const noexcept { return data[2]; } + + constexpr T& w() noexcept { return data[3]; } + constexpr const T& w() const noexcept { return data[3]; } }; } @@ -158,21 +158,20 @@ namespace vmath_hpp vec(const vec&) = default; vec& operator=(const vec&) = default; - void fill(const value_type& v) { - std::fill_n(begin(), size(), v); - } - void swap(vec& other) noexcept(std::is_nothrow_swappable_v) { - std::swap_ranges(begin(), end(), other.begin()); + for ( std::size_t i = 0; i < Size; ++i ) { + using std::swap; + swap(data[i], other.data[i]); + } } - constexpr iterator begin() noexcept { return iterator(data()); } - constexpr const_iterator begin() const noexcept { return const_iterator(data()); } - constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); } + constexpr iterator begin() noexcept { return iterator(data); } + constexpr const_iterator begin() const noexcept { return const_iterator(data); } + constexpr const_iterator cbegin() const noexcept { return const_iterator(data); } - constexpr iterator end() noexcept { return iterator(data() + size()); } - constexpr const_iterator end() const noexcept { return const_iterator(data() + size()); } - constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); } + constexpr iterator end() noexcept { return iterator(data + Size); } + constexpr const_iterator end() const noexcept { return const_iterator(data + Size); } + constexpr const_iterator cend() const noexcept { return const_iterator(data + Size); } constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } @@ -186,21 +185,26 @@ namespace vmath_hpp constexpr size_type max_size() const noexcept { return Size; } constexpr bool empty() const noexcept { return !Size; } - constexpr reference operator[](size_type index) noexcept { return data()[index]; } - constexpr const_reference operator[](size_type index) const noexcept { return data()[index]; } + constexpr reference operator[](size_type index) noexcept { + return data[index]; + } + + constexpr const_reference operator[](size_type index) const noexcept { + return data[index]; + } constexpr reference at(size_type index) { - if ( index >= size() ) { - throw std::out_of_range("vec::at"); + if ( index < Size ) { + return data[index]; } - return data()[index]; + throw std::out_of_range("vec::at"); } constexpr const_reference at(size_type index) const { - if ( index >= size() ) { - throw std::out_of_range("vec::at"); + if ( index < Size ) { + return data[index]; } - return data()[index]; + throw std::out_of_range("vec::at"); } }; @@ -213,18 +217,31 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T, std::size_t Size > - bool operator==(const vec& l, const vec& r) { - return std::equal(l.begin(), l.end(), r.begin()); + constexpr bool operator==(const vec& l, const vec& r) { + for ( std::size_t i = 0; i < Size; ++i ) { + if ( !(l[i] == r[i]) ) { + return false; + } + } + return true; } template < typename T, std::size_t Size > - bool operator!=(const vec& l, const vec& r) { + constexpr bool operator!=(const vec& l, const vec& r) { return !(l == r); } template < typename T, std::size_t Size > - bool operator<(const vec& l, const vec& r) { - return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); + constexpr bool operator<(const vec& l, const vec& r) { + for ( std::size_t i = 0; i < Size; ++i ) { + if ( l[i] < r[i] ) { + return true; + } + if ( r[i] < l[i] ) { + return false; + } + } + return false; } } diff --git a/untests/vmath_tests.cpp b/untests/vmath_tests.cpp index 26a7419..89e5322 100644 --- a/untests/vmath_tests.cpp +++ b/untests/vmath_tests.cpp @@ -4,11 +4,11 @@ * Copyright (C) 2020, by Matvey Cherevko (blackmatov@gmail.com) ******************************************************************************/ +#include + #define CATCH_CONFIG_FAST_COMPILE #include -#include - namespace { } @@ -24,34 +24,34 @@ TEST_CASE("vmath/vec") { SECTION("ctors") { { - REQUIRE(vec2i().x == 0); - REQUIRE(vec2i().y == 0); + STATIC_REQUIRE(vec2i().x() == 0); + STATIC_REQUIRE(vec2i().y() == 0); - REQUIRE(vec2i(1).x == 1); - REQUIRE(vec2i(1).y == 1); + STATIC_REQUIRE(vec2i(1).x() == 1); + STATIC_REQUIRE(vec2i(1).y() == 1); - REQUIRE(vec2i(1,2).x == 1); - REQUIRE(vec2i(1,2).y == 2); + STATIC_REQUIRE(vec2i(1,2).x() == 1); + STATIC_REQUIRE(vec2i(1,2).y() == 2); } { - vec2i v(1,2); - vec2i v2 = v; - REQUIRE(v2 == vec2i(1,2)); + constexpr vec2i v(1,2); + constexpr vec2i v2 = v; + STATIC_REQUIRE(v2 == vec2i(1,2)); } { - vec2i v(1,2); - vec2i v2 = std::move(v); - REQUIRE(v2 == vec2i(1,2)); + constexpr vec2i v(1,2); + constexpr vec2i v2 = std::move(v); + STATIC_REQUIRE(v2 == vec2i(1,2)); } { - REQUIRE(vec2i(vec3i(1,2,3)) == vec2i(1,2)); - REQUIRE(vec2i(vec4i(1,2,3,4)) == vec2i(1,2)); + STATIC_REQUIRE(vec2i(vec3i(1,2,3)) == vec2i(1,2)); + STATIC_REQUIRE(vec2i(vec4i(1,2,3,4)) == vec2i(1,2)); - REQUIRE(vec3i(vec2i(1,2),3) == vec3i(1,2,3)); - REQUIRE(vec3i(vec4i(1,2,3,4)) == vec3i(1,2,3)); + STATIC_REQUIRE(vec3i(vec2i(1,2),3) == vec3i(1,2,3)); + STATIC_REQUIRE(vec3i(vec4i(1,2,3,4)) == vec3i(1,2,3)); - REQUIRE(vec4i(vec2i(1,2),3,4) == vec4i(1,2,3,4)); - REQUIRE(vec4i(vec3i(1,2,3),4) == vec4i(1,2,3,4)); + STATIC_REQUIRE(vec4i(vec2i(1,2),3,4) == vec4i(1,2,3,4)); + STATIC_REQUIRE(vec4i(vec3i(1,2,3),4) == vec4i(1,2,3,4)); } } @@ -70,12 +70,6 @@ TEST_CASE("vmath/vec") { } } - SECTION("fill") { - vec2i v(1,2); - v.fill(4); - REQUIRE(v == vec2i(4)); - } - SECTION("swap") { { vec2i v1(1,2); @@ -93,12 +87,6 @@ TEST_CASE("vmath/vec") { } } - SECTION("data") { - vec2i v(1,2); - REQUIRE(v.data() == &v.x); - REQUIRE(std::as_const(v).data() == &v.x); - } - SECTION("iter") { { vec2i v(1,2); @@ -162,35 +150,69 @@ TEST_CASE("vmath/vec") { } SECTION("operator[]") { - REQUIRE(vec2i(1,2).x == 1); - REQUIRE(vec2i(1,2).y == 2); - REQUIRE(vec2i(1,2)[0] == 1); - REQUIRE(vec2i(1,2)[1] == 2); + { + STATIC_REQUIRE(vec2i(1,2).x() == 1); + STATIC_REQUIRE(vec2i(1,2).y() == 2); + + STATIC_REQUIRE(vec3i(1,2,3).x() == 1); + STATIC_REQUIRE(vec3i(1,2,3).y() == 2); + STATIC_REQUIRE(vec3i(1,2,3).z() == 3); + + STATIC_REQUIRE(vec4i(1,2,3,4).x() == 1); + STATIC_REQUIRE(vec4i(1,2,3,4).y() == 2); + STATIC_REQUIRE(vec4i(1,2,3,4).z() == 3); + STATIC_REQUIRE(vec4i(1,2,3,4).w() == 4); + } + { + STATIC_REQUIRE(vec2i(1,2)[0] == 1); + STATIC_REQUIRE(vec2i(1,2)[1] == 2); + } + { + vec2i v; + v.x() = 1; + v.y() = 2; + REQUIRE(v == vec2i(1,2)); + } + { + vec3i v; + v.x() = 1; + v.y() = 2; + v.z() = 3; + REQUIRE(v == vec3i(1,2,3)); + } + { + vec4i v; + v.x() = 1; + v.y() = 2; + v.z() = 3; + v.w() = 4; + REQUIRE(v == vec4i(1,2,3,4)); + } } SECTION("at") { - REQUIRE(vec2i(1,2).at(0) == 1); - REQUIRE(vec2i(1,2).at(1) == 2); + STATIC_REQUIRE(vec2i(1,2).at(0) == 1); + STATIC_REQUIRE(vec2i(1,2).at(1) == 2); REQUIRE_THROWS_AS(vec2i(1,2).at(2), std::out_of_range); } SECTION("operator==/operator!=") { - REQUIRE(vec2i(1,2) == vec2i(1,2)); - REQUIRE_FALSE(vec2i(1,2) == vec2i(2,2)); - REQUIRE_FALSE(vec2i(1,2) == vec2i(1,3)); + STATIC_REQUIRE(vec2i(1,2) == vec2i(1,2)); + STATIC_REQUIRE_FALSE(vec2i(1,2) == vec2i(2,2)); + STATIC_REQUIRE_FALSE(vec2i(1,2) == vec2i(1,3)); - REQUIRE_FALSE(vec2i(1,2) != vec2i(1,2)); - REQUIRE(vec2i(1,2) != vec2i(2,2)); - REQUIRE(vec2i(1,2) != vec2i(1,3)); + STATIC_REQUIRE_FALSE(vec2i(1,2) != vec2i(1,2)); + STATIC_REQUIRE(vec2i(1,2) != vec2i(2,2)); + STATIC_REQUIRE(vec2i(1,2) != vec2i(1,3)); } SECTION("operator<") { - REQUIRE_FALSE(vec2i(1,2) < vec2i(1,2)); + STATIC_REQUIRE_FALSE(vec2i(1,2) < vec2i(1,2)); - REQUIRE(vec2i(1,1) < vec2i(1,2)); - REQUIRE_FALSE(vec2i(1,2) < vec2i(1,1)); + STATIC_REQUIRE(vec2i(1,1) < vec2i(1,2)); + STATIC_REQUIRE_FALSE(vec2i(1,2) < vec2i(1,1)); - REQUIRE(vec2i(0,3) < vec2i(1,2)); - REQUIRE_FALSE(vec2i(1,2) < vec2i(0,3)); + STATIC_REQUIRE(vec2i(0,3) < vec2i(1,2)); + STATIC_REQUIRE_FALSE(vec2i(1,2) < vec2i(0,3)); } } From bdbb254db5d6a3d58cb5d87bcd1fdc1495a54b26 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 20 Nov 2020 23:49:53 +0700 Subject: [PATCH 03/53] new headers structure --- headers/vmath.hpp/vmath.hpp | 254 +----------------- headers/vmath.hpp/vmath_fwd.hpp | 37 +++ headers/vmath.hpp/vmath_vec.hpp | 236 ++++++++++++++++ .../{vmath_tests.cpp => vmath_vec_tests.cpp} | 2 +- 4 files changed, 275 insertions(+), 254 deletions(-) create mode 100644 headers/vmath.hpp/vmath_fwd.hpp create mode 100644 headers/vmath.hpp/vmath_vec.hpp rename untests/{vmath_tests.cpp => vmath_vec_tests.cpp} (99%) diff --git a/headers/vmath.hpp/vmath.hpp b/headers/vmath.hpp/vmath.hpp index 89242df..88a871e 100644 --- a/headers/vmath.hpp/vmath.hpp +++ b/headers/vmath.hpp/vmath.hpp @@ -6,256 +6,4 @@ #pragma once -#include -#include -#include -#include -#include - -namespace vmath_hpp -{ - struct uninit_t {}; - inline constexpr uninit_t uninit; -} - -namespace vmath_hpp::detail -{ - template < typename T, std::size_t Size > - class vec_base; - - template < typename T > - class vec_base { - public: - T data[2]; - public: - constexpr vec_base() : data{} {} - constexpr explicit vec_base(uninit_t) {} - - constexpr explicit vec_base(const T& v) - : data{v, v} {} - - constexpr vec_base(T x, T y) - : data{std::move(x), std::move(y)} {} - - constexpr explicit vec_base(vec_base&& xy) - : data{std::move(xy.x()), std::move(xy.y())} {} - constexpr explicit vec_base(const vec_base& xy) - : data{xy.x(), xy.y()} {} - - constexpr explicit vec_base(vec_base&& xy) - : data{std::move(xy.x()), std::move(xy.y())} {} - constexpr explicit vec_base(const vec_base& xy) - : data{xy.x(), xy.y()} {} - - constexpr T& x() noexcept { return data[0]; } - constexpr const T& x() const noexcept { return data[0]; } - - constexpr T& y() noexcept { return data[1]; } - constexpr const T& y() const noexcept { return data[1]; } - }; - - template < typename T > - class vec_base { - public: - T data[3]; - public: - constexpr vec_base() : data{} {} - constexpr explicit vec_base(uninit_t) {} - - constexpr explicit vec_base(const T& v) - : data{v, v, v} {} - - constexpr vec_base(T x, T y, T z) - : data{std::move(x), std::move(y), std::move(z)} {} - - constexpr explicit vec_base(vec_base&& xy, T z) - : data{std::move(xy.x()), std::move(xy.y()), std::move(z)} {} - constexpr explicit vec_base(const vec_base& xy, T z) - : data{xy.x(), xy.y(), std::move(z)} {} - - constexpr explicit vec_base(vec_base&& xyz) - : data{std::move(xyz.x()), std::move(xyz.y()), std::move(xyz.z())} {} - constexpr explicit vec_base(const vec_base& xyz) - : data{xyz.x(), xyz.y(), xyz.z()} {} - - constexpr T& x() noexcept { return data[0]; } - constexpr const T& x() const noexcept { return data[0]; } - - constexpr T& y() noexcept { return data[1]; } - constexpr const T& y() const noexcept { return data[1]; } - - constexpr T& z() noexcept { return data[2]; } - constexpr const T& z() const noexcept { return data[2]; } - }; - - template < typename T > - class vec_base { - public: - T data[4]; - public: - constexpr vec_base() : data{} {} - constexpr explicit vec_base(uninit_t) {} - - constexpr explicit vec_base(const T& v) - : data{v, v, v, v} {} - - constexpr vec_base(T x, T y, T z, T w) - : data{std::move(x), std::move(y), std::move(z), std::move(w)} {} - - constexpr explicit vec_base(vec_base&& xy, T z, T w) - : data{std::move(xy.x()), std::move(xy.y()), std::move(z), std::move(w)} {} - constexpr explicit vec_base(const vec_base& xy, T z, T w) - : data{xy.x(), xy.y(), std::move(z), std::move(w)} {} - - constexpr explicit vec_base(vec_base&& xyz, T w) - : data{std::move(xyz.x()), std::move(xyz.y()), std::move(xyz.z()), std::move(w)} {} - constexpr explicit vec_base(const vec_base& xyz, T w) - : data{xyz.x(), xyz.y(), xyz.z(), std::move(w)} {} - - constexpr T& x() noexcept { return data[0]; } - constexpr const T& x() const noexcept { return data[0]; } - - constexpr T& y() noexcept { return data[1]; } - constexpr const T& y() const noexcept { return data[1]; } - - constexpr T& z() noexcept { return data[2]; } - constexpr const T& z() const noexcept { return data[2]; } - - constexpr T& w() noexcept { return data[3]; } - constexpr const T& w() const noexcept { return data[3]; } - }; -} - -namespace vmath_hpp -{ - template < typename T, std::size_t Size > - class vec final : public detail::vec_base { - public: - using self_type = vec; - using value_type = T; - - using pointer = value_type*; - using const_pointer = const value_type*; - - using reference = value_type&; - using const_reference = const value_type&; - - using iterator = value_type*; - using const_iterator = const value_type*; - - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - public: - using detail::vec_base::data; - using detail::vec_base::vec_base; - - vec(vec&&) = default; - vec& operator=(vec&&) = default; - - vec(const vec&) = default; - vec& operator=(const vec&) = default; - - void swap(vec& other) noexcept(std::is_nothrow_swappable_v) { - for ( std::size_t i = 0; i < Size; ++i ) { - using std::swap; - swap(data[i], other.data[i]); - } - } - - constexpr iterator begin() noexcept { return iterator(data); } - constexpr const_iterator begin() const noexcept { return const_iterator(data); } - constexpr const_iterator cbegin() const noexcept { return const_iterator(data); } - - constexpr iterator end() noexcept { return iterator(data + Size); } - constexpr const_iterator end() const noexcept { return const_iterator(data + Size); } - constexpr const_iterator cend() const noexcept { return const_iterator(data + Size); } - - constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } - - constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } - constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } - - constexpr size_type size() const noexcept { return Size; } - constexpr size_type max_size() const noexcept { return Size; } - constexpr bool empty() const noexcept { return !Size; } - - constexpr reference operator[](size_type index) noexcept { - return data[index]; - } - - constexpr const_reference operator[](size_type index) const noexcept { - return data[index]; - } - - constexpr reference at(size_type index) { - if ( index < Size ) { - return data[index]; - } - throw std::out_of_range("vec::at"); - } - - constexpr const_reference at(size_type index) const { - if ( index < Size ) { - return data[index]; - } - throw std::out_of_range("vec::at"); - } - }; - - template < typename T, std::size_t Size > - void swap(vec& l, vec& r) noexcept(noexcept(l.swap(r))) { - l.swap(r); - } -} - -namespace vmath_hpp -{ - template < typename T, std::size_t Size > - constexpr bool operator==(const vec& l, const vec& r) { - for ( std::size_t i = 0; i < Size; ++i ) { - if ( !(l[i] == r[i]) ) { - return false; - } - } - return true; - } - - template < typename T, std::size_t Size > - constexpr bool operator!=(const vec& l, const vec& r) { - return !(l == r); - } - - template < typename T, std::size_t Size > - constexpr bool operator<(const vec& l, const vec& r) { - for ( std::size_t i = 0; i < Size; ++i ) { - if ( l[i] < r[i] ) { - return true; - } - if ( r[i] < l[i] ) { - return false; - } - } - return false; - } -} - -namespace vmath_hpp -{ - using vec2i = vec; - using vec3i = vec; - using vec4i = vec; - - using vec2b = vec; - using vec3b = vec; - using vec4b = vec; - - using vec2f = vec; - using vec3f = vec; - using vec4f = vec; -} +#include "vmath_vec.hpp" diff --git a/headers/vmath.hpp/vmath_fwd.hpp b/headers/vmath.hpp/vmath_fwd.hpp new file mode 100644 index 0000000..31621fe --- /dev/null +++ b/headers/vmath.hpp/vmath_fwd.hpp @@ -0,0 +1,37 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include + +namespace vmath_hpp +{ + struct uninit_t {}; + inline constexpr uninit_t uninit; +} + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + class vec; + + using vec2i = vec; + using vec3i = vec; + using vec4i = vec; + + using vec2b = vec; + using vec3b = vec; + using vec4b = vec; + + using vec2f = vec; + using vec3f = vec; + using vec4f = vec; +} diff --git a/headers/vmath.hpp/vmath_vec.hpp b/headers/vmath.hpp/vmath_vec.hpp new file mode 100644 index 0000000..22e8056 --- /dev/null +++ b/headers/vmath.hpp/vmath_vec.hpp @@ -0,0 +1,236 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "vmath_fwd.hpp" + +namespace vmath_hpp::detail +{ + template < typename T, std::size_t Size > + class vec_base; + + template < typename T > + class vec_base { + public: + T data[2]; + public: + constexpr vec_base() : data{} {} + constexpr explicit vec_base(uninit_t) {} + + constexpr explicit vec_base(const T& v) + : data{v, v} {} + + constexpr vec_base(T x, T y) + : data{std::move(x), std::move(y)} {} + + constexpr explicit vec_base(vec_base&& xy) + : data{std::move(xy.x()), std::move(xy.y())} {} + constexpr explicit vec_base(const vec_base& xy) + : data{xy.x(), xy.y()} {} + + constexpr explicit vec_base(vec_base&& xy) + : data{std::move(xy.x()), std::move(xy.y())} {} + constexpr explicit vec_base(const vec_base& xy) + : data{xy.x(), xy.y()} {} + + constexpr T& x() noexcept { return data[0]; } + constexpr const T& x() const noexcept { return data[0]; } + + constexpr T& y() noexcept { return data[1]; } + constexpr const T& y() const noexcept { return data[1]; } + }; + + template < typename T > + class vec_base { + public: + T data[3]; + public: + constexpr vec_base() : data{} {} + constexpr explicit vec_base(uninit_t) {} + + constexpr explicit vec_base(const T& v) + : data{v, v, v} {} + + constexpr vec_base(T x, T y, T z) + : data{std::move(x), std::move(y), std::move(z)} {} + + constexpr explicit vec_base(vec_base&& xy, T z) + : data{std::move(xy.x()), std::move(xy.y()), std::move(z)} {} + constexpr explicit vec_base(const vec_base& xy, T z) + : data{xy.x(), xy.y(), std::move(z)} {} + + constexpr explicit vec_base(vec_base&& xyz) + : data{std::move(xyz.x()), std::move(xyz.y()), std::move(xyz.z())} {} + constexpr explicit vec_base(const vec_base& xyz) + : data{xyz.x(), xyz.y(), xyz.z()} {} + + constexpr T& x() noexcept { return data[0]; } + constexpr const T& x() const noexcept { return data[0]; } + + constexpr T& y() noexcept { return data[1]; } + constexpr const T& y() const noexcept { return data[1]; } + + constexpr T& z() noexcept { return data[2]; } + constexpr const T& z() const noexcept { return data[2]; } + }; + + template < typename T > + class vec_base { + public: + T data[4]; + public: + constexpr vec_base() : data{} {} + constexpr explicit vec_base(uninit_t) {} + + constexpr explicit vec_base(const T& v) + : data{v, v, v, v} {} + + constexpr vec_base(T x, T y, T z, T w) + : data{std::move(x), std::move(y), std::move(z), std::move(w)} {} + + constexpr explicit vec_base(vec_base&& xy, T z, T w) + : data{std::move(xy.x()), std::move(xy.y()), std::move(z), std::move(w)} {} + constexpr explicit vec_base(const vec_base& xy, T z, T w) + : data{xy.x(), xy.y(), std::move(z), std::move(w)} {} + + constexpr explicit vec_base(vec_base&& xyz, T w) + : data{std::move(xyz.x()), std::move(xyz.y()), std::move(xyz.z()), std::move(w)} {} + constexpr explicit vec_base(const vec_base& xyz, T w) + : data{xyz.x(), xyz.y(), xyz.z(), std::move(w)} {} + + constexpr T& x() noexcept { return data[0]; } + constexpr const T& x() const noexcept { return data[0]; } + + constexpr T& y() noexcept { return data[1]; } + constexpr const T& y() const noexcept { return data[1]; } + + constexpr T& z() noexcept { return data[2]; } + constexpr const T& z() const noexcept { return data[2]; } + + constexpr T& w() noexcept { return data[3]; } + constexpr const T& w() const noexcept { return data[3]; } + }; +} + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + class vec final : public detail::vec_base { + public: + using self_type = vec; + using value_type = T; + + using pointer = value_type*; + using const_pointer = const value_type*; + + using reference = value_type&; + using const_reference = const value_type&; + + using iterator = value_type*; + using const_iterator = const value_type*; + + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + public: + using detail::vec_base::data; + using detail::vec_base::vec_base; + + vec(vec&&) = default; + vec& operator=(vec&&) = default; + + vec(const vec&) = default; + vec& operator=(const vec&) = default; + + void swap(vec& other) noexcept(std::is_nothrow_swappable_v) { + for ( std::size_t i = 0; i < Size; ++i ) { + using std::swap; + swap(data[i], other.data[i]); + } + } + + constexpr iterator begin() noexcept { return iterator(data); } + constexpr const_iterator begin() const noexcept { return const_iterator(data); } + constexpr const_iterator cbegin() const noexcept { return const_iterator(data); } + + constexpr iterator end() noexcept { return iterator(data + Size); } + constexpr const_iterator end() const noexcept { return const_iterator(data + Size); } + constexpr const_iterator cend() const noexcept { return const_iterator(data + Size); } + + constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } + constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } + constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } + + constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); } + constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } + constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } + + constexpr size_type size() const noexcept { return Size; } + constexpr size_type max_size() const noexcept { return Size; } + constexpr bool empty() const noexcept { return !Size; } + + constexpr reference operator[](size_type index) noexcept { + return data[index]; + } + + constexpr const_reference operator[](size_type index) const noexcept { + return data[index]; + } + + constexpr reference at(size_type index) { + if ( index < Size ) { + return data[index]; + } + throw std::out_of_range("vec::at"); + } + + constexpr const_reference at(size_type index) const { + if ( index < Size ) { + return data[index]; + } + throw std::out_of_range("vec::at"); + } + }; + + template < typename T, std::size_t Size > + void swap(vec& l, vec& r) noexcept(noexcept(l.swap(r))) { + l.swap(r); + } +} + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + constexpr bool operator==(const vec& l, const vec& r) { + for ( std::size_t i = 0; i < Size; ++i ) { + if ( !(l[i] == r[i]) ) { + return false; + } + } + return true; + } + + template < typename T, std::size_t Size > + constexpr bool operator!=(const vec& l, const vec& r) { + return !(l == r); + } + + template < typename T, std::size_t Size > + constexpr bool operator<(const vec& l, const vec& r) { + for ( std::size_t i = 0; i < Size; ++i ) { + if ( l[i] < r[i] ) { + return true; + } + if ( r[i] < l[i] ) { + return false; + } + } + return false; + } +} diff --git a/untests/vmath_tests.cpp b/untests/vmath_vec_tests.cpp similarity index 99% rename from untests/vmath_tests.cpp rename to untests/vmath_vec_tests.cpp index 89e5322..6ba6642 100644 --- a/untests/vmath_tests.cpp +++ b/untests/vmath_vec_tests.cpp @@ -4,7 +4,7 @@ * Copyright (C) 2020, by Matvey Cherevko (blackmatov@gmail.com) ******************************************************************************/ -#include +#include #define CATCH_CONFIG_FAST_COMPILE #include From 8c8a936cae4e444551be4b975d30e8dd574ab967 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sat, 21 Nov 2020 00:58:05 +0700 Subject: [PATCH 04/53] remove value type moving --- headers/vmath.hpp/vmath_vec.hpp | 35 +++++++++++---------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/headers/vmath.hpp/vmath_vec.hpp b/headers/vmath.hpp/vmath_vec.hpp index 22e8056..7f2afec 100644 --- a/headers/vmath.hpp/vmath_vec.hpp +++ b/headers/vmath.hpp/vmath_vec.hpp @@ -21,19 +21,15 @@ namespace vmath_hpp::detail constexpr vec_base() : data{} {} constexpr explicit vec_base(uninit_t) {} - constexpr explicit vec_base(const T& v) + constexpr explicit vec_base(T v) : data{v, v} {} constexpr vec_base(T x, T y) - : data{std::move(x), std::move(y)} {} + : data{x, y} {} - constexpr explicit vec_base(vec_base&& xy) - : data{std::move(xy.x()), std::move(xy.y())} {} constexpr explicit vec_base(const vec_base& xy) : data{xy.x(), xy.y()} {} - constexpr explicit vec_base(vec_base&& xy) - : data{std::move(xy.x()), std::move(xy.y())} {} constexpr explicit vec_base(const vec_base& xy) : data{xy.x(), xy.y()} {} @@ -52,19 +48,15 @@ namespace vmath_hpp::detail constexpr vec_base() : data{} {} constexpr explicit vec_base(uninit_t) {} - constexpr explicit vec_base(const T& v) + constexpr explicit vec_base(T v) : data{v, v, v} {} constexpr vec_base(T x, T y, T z) - : data{std::move(x), std::move(y), std::move(z)} {} + : data{x, y, z} {} - constexpr explicit vec_base(vec_base&& xy, T z) - : data{std::move(xy.x()), std::move(xy.y()), std::move(z)} {} constexpr explicit vec_base(const vec_base& xy, T z) - : data{xy.x(), xy.y(), std::move(z)} {} + : data{xy.x(), xy.y(), z} {} - constexpr explicit vec_base(vec_base&& xyz) - : data{std::move(xyz.x()), std::move(xyz.y()), std::move(xyz.z())} {} constexpr explicit vec_base(const vec_base& xyz) : data{xyz.x(), xyz.y(), xyz.z()} {} @@ -86,21 +78,17 @@ namespace vmath_hpp::detail constexpr vec_base() : data{} {} constexpr explicit vec_base(uninit_t) {} - constexpr explicit vec_base(const T& v) + constexpr explicit vec_base(T v) : data{v, v, v, v} {} constexpr vec_base(T x, T y, T z, T w) - : data{std::move(x), std::move(y), std::move(z), std::move(w)} {} + : data{x, y, z, w} {} - constexpr explicit vec_base(vec_base&& xy, T z, T w) - : data{std::move(xy.x()), std::move(xy.y()), std::move(z), std::move(w)} {} constexpr explicit vec_base(const vec_base& xy, T z, T w) - : data{xy.x(), xy.y(), std::move(z), std::move(w)} {} + : data{xy.x(), xy.y(), z, w} {} - constexpr explicit vec_base(vec_base&& xyz, T w) - : data{std::move(xyz.x()), std::move(xyz.y()), std::move(xyz.z()), std::move(w)} {} constexpr explicit vec_base(const vec_base& xyz, T w) - : data{xyz.x(), xyz.y(), xyz.z(), std::move(w)} {} + : data{xyz.x(), xyz.y(), xyz.z(), w} {} constexpr T& x() noexcept { return data[0]; } constexpr const T& x() const noexcept { return data[0]; } @@ -122,6 +110,7 @@ namespace vmath_hpp class vec final : public detail::vec_base { public: using self_type = vec; + using base_type = detail::vec_base; using value_type = T; using pointer = value_type*; @@ -139,8 +128,8 @@ namespace vmath_hpp using size_type = std::size_t; using difference_type = std::ptrdiff_t; public: - using detail::vec_base::data; - using detail::vec_base::vec_base; + using base_type::data; + using base_type::vec_base; vec(vec&&) = default; vec& operator=(vec&&) = default; From c256523102f4a2da2f30d28d110503ac2ee5b401 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sat, 21 Nov 2020 00:58:46 +0700 Subject: [PATCH 05/53] basic matrix type --- headers/vmath.hpp/vmath.hpp | 1 + headers/vmath.hpp/vmath_fwd.hpp | 18 +++ headers/vmath.hpp/vmath_mat.hpp | 223 ++++++++++++++++++++++++++++++++ untests/vmath_mat_tests.cpp | 204 +++++++++++++++++++++++++++++ 4 files changed, 446 insertions(+) create mode 100644 headers/vmath.hpp/vmath_mat.hpp create mode 100644 untests/vmath_mat_tests.cpp diff --git a/headers/vmath.hpp/vmath.hpp b/headers/vmath.hpp/vmath.hpp index 88a871e..cf975dc 100644 --- a/headers/vmath.hpp/vmath.hpp +++ b/headers/vmath.hpp/vmath.hpp @@ -6,4 +6,5 @@ #pragma once +#include "vmath_mat.hpp" #include "vmath_vec.hpp" diff --git a/headers/vmath.hpp/vmath_fwd.hpp b/headers/vmath.hpp/vmath_fwd.hpp index 31621fe..30ff35f 100644 --- a/headers/vmath.hpp/vmath_fwd.hpp +++ b/headers/vmath.hpp/vmath_fwd.hpp @@ -35,3 +35,21 @@ namespace vmath_hpp using vec3f = vec; using vec4f = vec; } + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + class mat; + + using mat2i = mat; + using mat3i = mat; + using mat4i = mat; + + using mat2b = mat; + using mat3b = mat; + using mat4b = mat; + + using mat2f = mat; + using mat3f = mat; + using mat4f = mat; +} diff --git a/headers/vmath.hpp/vmath_mat.hpp b/headers/vmath.hpp/vmath_mat.hpp new file mode 100644 index 0000000..2acbdbd --- /dev/null +++ b/headers/vmath.hpp/vmath_mat.hpp @@ -0,0 +1,223 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "vmath_fwd.hpp" +#include "vmath_vec.hpp" + +namespace vmath_hpp::detail +{ + template < typename T, std::size_t Size > + class mat_base; + + template < typename T > + class mat_base { + public: + vec rows[2]; + public: + constexpr mat_base() : rows{ + {1, 0}, + {0, 1}, + } {} + + constexpr explicit mat_base(uninit_t) {} + + constexpr mat_base( + T m11, T m12, + T m21, T m22) + : rows{ + {m11, m12}, + {m21, m22}} {} + + constexpr mat_base( + const vec& row0, + const vec& row1) + : rows{row0, row1} {} + }; + + template < typename T > + class mat_base { + public: + vec rows[3]; + public: + constexpr mat_base() : rows{ + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, + } {} + + constexpr explicit mat_base(uninit_t) {} + + constexpr mat_base( + T m11, T m12, T m13, + T m21, T m22, T m23, + T m31, T m32, T m33) + : rows{ + {m11, m12, m13}, + {m21, m22, m23}, + {m31, m32, m33}} {} + + constexpr mat_base( + const vec& row0, + const vec& row1, + const vec& row2) + : rows{row0, row1, row2} {} + }; + + template < typename T > + class mat_base { + public: + vec rows[4]; + public: + constexpr mat_base() : rows{ + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}, + } {} + + constexpr explicit mat_base(uninit_t) {} + + constexpr mat_base( + T m11, T m12, T m13, T m14, + T m21, T m22, T m23, T m24, + T m31, T m32, T m33, T m34, + T m41, T m42, T m43, T m44) + : rows{ + {m11, m12, m13, m14}, + {m21, m22, m23, m24}, + {m31, m32, m33, m34}, + {m41, m42, m43, m44}} {} + + constexpr mat_base( + const vec& row0, + const vec& row1, + const vec& row2, + const vec& row3) + : rows{row0, row1, row2, row3} {} + }; +} + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + class mat final : public detail::mat_base { + public: + using self_type = mat; + using base_type = detail::mat_base; + using value_type = vec; + + using pointer = value_type*; + using const_pointer = const value_type*; + + using reference = value_type&; + using const_reference = const value_type&; + + using iterator = value_type*; + using const_iterator = const value_type*; + + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + public: + using base_type::rows; + using base_type::mat_base; + + mat(mat&&) = default; + mat& operator=(mat&&) = default; + + mat(const mat&) = default; + mat& operator=(const mat&) = default; + + void swap(mat& other) noexcept(std::is_nothrow_swappable_v) { + for ( std::size_t i = 0; i < Size; ++i ) { + using std::swap; + swap(rows[i], other.rows[i]); + } + } + + constexpr iterator begin() noexcept { return iterator(rows); } + constexpr const_iterator begin() const noexcept { return const_iterator(rows); } + constexpr const_iterator cbegin() const noexcept { return const_iterator(rows); } + + constexpr iterator end() noexcept { return iterator(rows + Size); } + constexpr const_iterator end() const noexcept { return const_iterator(rows + Size); } + constexpr const_iterator cend() const noexcept { return const_iterator(rows + Size); } + + constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } + constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } + constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } + + constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); } + constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } + constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } + + constexpr size_type size() const noexcept { return Size; } + constexpr size_type max_size() const noexcept { return Size; } + constexpr bool empty() const noexcept { return !Size; } + + constexpr value_type& operator[](size_type index) noexcept { + return rows[index]; + } + + constexpr const value_type& operator[](size_type index) const noexcept { + return rows[index]; + } + + constexpr value_type& at(size_type index) { + if ( index < Size ) { + return rows[index]; + } + throw std::out_of_range("mat::at"); + } + + constexpr const value_type& at(size_type index) const { + if ( index < Size ) { + return rows[index]; + } + throw std::out_of_range("mat::at"); + } + }; + + template < typename T, std::size_t Size > + void swap(mat& l, mat& r) noexcept(noexcept(l.swap(r))) { + l.swap(r); + } +} + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + constexpr bool operator==(const mat& l, const mat& r) { + for ( std::size_t i = 0; i < Size; ++i ) { + if ( !(l[i] == r[i]) ) { + return false; + } + } + return true; + } + + template < typename T, std::size_t Size > + constexpr bool operator!=(const mat& l, const mat& r) { + return !(l == r); + } + + template < typename T, std::size_t Size > + constexpr bool operator<(const mat& l, const mat& r) { + for ( std::size_t i = 0; i < Size; ++i ) { + if ( l[i] < r[i] ) { + return true; + } + if ( r[i] < l[i] ) { + return false; + } + } + return false; + } +} diff --git a/untests/vmath_mat_tests.cpp b/untests/vmath_mat_tests.cpp new file mode 100644 index 0000000..53f3b10 --- /dev/null +++ b/untests/vmath_mat_tests.cpp @@ -0,0 +1,204 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include + +#define CATCH_CONFIG_FAST_COMPILE +#include + +namespace +{ +} + +TEST_CASE("vmath/mat") { + using namespace vmath_hpp; + + SECTION("sizeof") { + STATIC_REQUIRE(sizeof(mat2i{}) == sizeof(int) * 2 * 2); + STATIC_REQUIRE(sizeof(mat3i{}) == sizeof(int) * 3 * 3); + STATIC_REQUIRE(sizeof(mat4i{}) == sizeof(int) * 4 * 4); + } + + SECTION("ctors") { + { + STATIC_REQUIRE(mat2i()[0] == vec2i(1,0)); + STATIC_REQUIRE(mat2i()[1] == vec2i(0,1)); + + STATIC_REQUIRE(mat2i(1,2,3,4)[0] == vec2i(1,2)); + STATIC_REQUIRE(mat2i(1,2,3,4)[1] == vec2i(3,4)); + + STATIC_REQUIRE(mat2i({1,2},{3,4})[0] == vec2i(1,2)); + STATIC_REQUIRE(mat2i({1,2},{3,4})[1] == vec2i(3,4)); + } + { + constexpr mat2i v(1,2,3,4); + constexpr mat2i v2 = v; + STATIC_REQUIRE(v2 == mat2i(1,2,3,4)); + } + { + constexpr mat2i v(1,2,3,4); + constexpr mat2i v2 = std::move(v); + STATIC_REQUIRE(v2 == mat2i(1,2,3,4)); + } + } + + SECTION("operator=") { + { + mat2i v(1,2,3,4); + mat2i v2; + v2 = v; + REQUIRE(v2 == mat2i(1,2,3,4)); + } + { + mat2i v(1,2,3,4); + mat2i v2; + v2 = std::move(v); + REQUIRE(v2 == mat2i(1,2,3,4)); + } + } + + SECTION("swap") { + { + mat2i v1(1,2,3,4); + mat2i v2(4,5,6,7); + v1.swap(v2); + REQUIRE(v1 == mat2i(4,5,6,7)); + REQUIRE(v2 == mat2i(1,2,3,4)); + } + { + mat2i v1(1,2,3,4); + mat2i v2(4,5,6,7); + swap(v1, v2); + REQUIRE(v1 == mat2i(4,5,6,7)); + REQUIRE(v2 == mat2i(1,2,3,4)); + } + } + + SECTION("iter") { + { + mat2i v{1,2,3,4}; + mat2i::iterator i = v.begin(); + REQUIRE(*i++ == vec2i{1,2}); + REQUIRE(*i++ == vec2i{3,4}); + REQUIRE(v.end() == i); + } + { + const mat2i v{1,2,3,4}; + mat2i::const_iterator i = v.begin(); + REQUIRE(*i++ == vec2i{1,2}); + REQUIRE(*i++ == vec2i{3,4}); + REQUIRE(v.end() == i); + } + { + mat2i v{1,2,3,4}; + for ( auto i = v.begin(); i < v.end(); ++i ) { + *i = vec2i(i->x() * 2, i->y() * 2); + } + REQUIRE(v == mat2i(2,4,6,8)); + } + } + + SECTION("riter") { + { + mat2i v{1,2,3,4}; + mat2i::reverse_iterator i = v.rbegin(); + REQUIRE(*i++ == vec2i{3,4}); + REQUIRE(*i++ == vec2i{1,2}); + REQUIRE(v.rend() == i); + for ( auto j = v.rbegin(); j < v.rend(); ++j ) { + *j = vec2i(j->x() * 2, j->y() * 2); + } + REQUIRE(v == mat2i(2,4,6,8)); + } + { + const mat2i v{1,2,3,4}; + mat2i::const_reverse_iterator i = v.rbegin(); + REQUIRE(*i++ == vec2i{3,4}); + REQUIRE(*i++ == vec2i{1,2}); + REQUIRE(v.rend() == i); + } + { + mat2i v{1,2,3,4}; + for ( auto i = v.rbegin(); i < v.rend(); ++i ) { + *i = vec2i(i->x() * 2, i->y() * 2); + } + REQUIRE(v == mat2i(2,4,6,8)); + } + } + + SECTION("size/max_size/empty") { + STATIC_REQUIRE(mat().size() == 2); + STATIC_REQUIRE(mat().max_size() == 2); + STATIC_REQUIRE_FALSE(mat().empty()); + + STATIC_REQUIRE(mat().size() == 3); + STATIC_REQUIRE(mat().max_size() == 3); + STATIC_REQUIRE_FALSE(mat().empty()); + } + + SECTION("operator[]") { + { + STATIC_REQUIRE(mat2i()[0] == vec2i(1,0)); + STATIC_REQUIRE(mat2i()[1] == vec2i(0,1)); + + STATIC_REQUIRE(mat3i()[0] == vec3i(1,0,0)); + STATIC_REQUIRE(mat3i()[1] == vec3i(0,1,0)); + STATIC_REQUIRE(mat3i()[2] == vec3i(0,0,1)); + + STATIC_REQUIRE(mat4i()[0] == vec4i(1,0,0,0)); + STATIC_REQUIRE(mat4i()[1] == vec4i(0,1,0,0)); + STATIC_REQUIRE(mat4i()[2] == vec4i(0,0,1,0)); + STATIC_REQUIRE(mat4i()[3] == vec4i(0,0,0,1)); + } + { + mat2i v; + v[0] = vec2i(1,2); + v[1] = vec2i(3,4); + REQUIRE(v == mat2i(1,2,3,4)); + } + { + mat3i v; + v[0] = vec3i(1,2,3); + v[1] = vec3i(4,5,6); + v[2] = vec3i(7,8,9); + REQUIRE(v == mat3i(1,2,3,4,5,6,7,8,9)); + } + { + mat4i v; + v[0] = vec4i(1,2,3,4); + v[1] = vec4i(5,6,7,8); + v[2] = vec4i(9,10,11,12); + v[3] = vec4i(13,14,15,16); + REQUIRE(v == mat4i(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)); + } + } + + SECTION("at") { + STATIC_REQUIRE(mat2i(1,2,3,4).at(0) == vec2i(1,2)); + STATIC_REQUIRE(mat2i(1,2,3,4).at(1) == vec2i(3,4)); + REQUIRE_THROWS_AS(mat2i(1,2,3,4).at(2), std::out_of_range); + } + + SECTION("operator==/operator!=") { + STATIC_REQUIRE(mat2i(1,2,3,4) == mat2i(1,2,3,4)); + STATIC_REQUIRE_FALSE(mat2i(1,2,3,4) == mat2i(2,2,3,4)); + STATIC_REQUIRE_FALSE(mat2i(1,2,3,4) == mat2i(1,3,3,4)); + + STATIC_REQUIRE_FALSE(mat2i(1,2,3,4) != mat2i(1,2,3,4)); + STATIC_REQUIRE(mat2i(1,2,3,4) != mat2i(2,2,3,4)); + STATIC_REQUIRE(mat2i(1,2,3,4) != mat2i(1,3,3,4)); + } + + SECTION("operator<") { + STATIC_REQUIRE_FALSE(mat2i(1,2,3,4) < mat2i(1,2,3,4)); + + STATIC_REQUIRE(mat2i(1,1,3,4) < mat2i(1,2,3,4)); + STATIC_REQUIRE_FALSE(mat2i(1,2,3,4) < mat2i(1,1,3,4)); + + STATIC_REQUIRE(mat2i(0,3,3,4) < mat2i(1,2,3,4)); + STATIC_REQUIRE_FALSE(mat2i(1,2,3,4) < mat2i(0,3,3,4)); + } +} From 4edfa973d248952a7a4a27f13e97c6087deaab94 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sat, 21 Nov 2020 22:14:28 +0700 Subject: [PATCH 06/53] more vector ctors --- headers/vmath.hpp/vmath_fwd.hpp | 16 ++++++++++++ headers/vmath.hpp/vmath_mat.hpp | 12 ++++----- headers/vmath.hpp/vmath_vec.hpp | 45 ++++++++++++++++++++++----------- untests/vmath_vec_tests.cpp | 13 ++++++++++ 4 files changed, 65 insertions(+), 21 deletions(-) diff --git a/headers/vmath.hpp/vmath_fwd.hpp b/headers/vmath.hpp/vmath_fwd.hpp index 30ff35f..627567b 100644 --- a/headers/vmath.hpp/vmath_fwd.hpp +++ b/headers/vmath.hpp/vmath_fwd.hpp @@ -34,6 +34,14 @@ namespace vmath_hpp using vec2f = vec; using vec3f = vec; using vec4f = vec; + + using vec2d = vec; + using vec3d = vec; + using vec4d = vec; + + using vec2u = vec; + using vec3u = vec; + using vec4u = vec; } namespace vmath_hpp @@ -52,4 +60,12 @@ namespace vmath_hpp using mat2f = mat; using mat3f = mat; using mat4f = mat; + + using mat2d = mat; + using mat3d = mat; + using mat4d = mat; + + using mat2u = mat; + using mat3u = mat; + using mat4u = mat; } diff --git a/headers/vmath.hpp/vmath_mat.hpp b/headers/vmath.hpp/vmath_mat.hpp index 2acbdbd..6379025 100644 --- a/headers/vmath.hpp/vmath_mat.hpp +++ b/headers/vmath.hpp/vmath_mat.hpp @@ -171,17 +171,17 @@ namespace vmath_hpp } constexpr value_type& at(size_type index) { - if ( index < Size ) { - return rows[index]; + if ( index >= Size ) { + throw std::out_of_range("mat::at"); } - throw std::out_of_range("mat::at"); + return rows[index]; } constexpr const value_type& at(size_type index) const { - if ( index < Size ) { - return rows[index]; + if ( index >= Size ) { + throw std::out_of_range("mat::at"); } - throw std::out_of_range("mat::at"); + return rows[index]; } }; diff --git a/headers/vmath.hpp/vmath_vec.hpp b/headers/vmath.hpp/vmath_vec.hpp index 7f2afec..0486be1 100644 --- a/headers/vmath.hpp/vmath_vec.hpp +++ b/headers/vmath.hpp/vmath_vec.hpp @@ -28,10 +28,10 @@ namespace vmath_hpp::detail : data{x, y} {} constexpr explicit vec_base(const vec_base& xy) - : data{xy.x(), xy.y()} {} + : data{xy.data[0], xy.data[1]} {} constexpr explicit vec_base(const vec_base& xy) - : data{xy.x(), xy.y()} {} + : data{xy.data[0], xy.data[1]} {} constexpr T& x() noexcept { return data[0]; } constexpr const T& x() const noexcept { return data[0]; } @@ -54,11 +54,14 @@ namespace vmath_hpp::detail constexpr vec_base(T x, T y, T z) : data{x, y, z} {} - constexpr explicit vec_base(const vec_base& xy, T z) - : data{xy.x(), xy.y(), z} {} + constexpr vec_base(const vec_base& xy, T z) + : data{xy.data[0], xy.data[1], z} {} + + constexpr vec_base(T x, const vec_base& yz) + : data{x, yz.data[0], yz.data[1]} {} constexpr explicit vec_base(const vec_base& xyz) - : data{xyz.x(), xyz.y(), xyz.z()} {} + : data{xyz.data[0], xyz.data[1], xyz.data[2]} {} constexpr T& x() noexcept { return data[0]; } constexpr const T& x() const noexcept { return data[0]; } @@ -84,11 +87,23 @@ namespace vmath_hpp::detail constexpr vec_base(T x, T y, T z, T w) : data{x, y, z, w} {} - constexpr explicit vec_base(const vec_base& xy, T z, T w) - : data{xy.x(), xy.y(), z, w} {} + constexpr vec_base(const vec_base& xy, T z, T w) + : data{xy.data[0], xy.data[1], z, w} {} - constexpr explicit vec_base(const vec_base& xyz, T w) - : data{xyz.x(), xyz.y(), xyz.z(), w} {} + constexpr vec_base(T x, const vec_base& yz, T w) + : data{x, yz.data[0], yz.data[1], w} {} + + constexpr vec_base(T x, T y, const vec_base& zw) + : data{x, y, zw.data[0], zw.data[1]} {} + + constexpr vec_base(const vec_base& xy, const vec_base& zw) + : data{xy.data[0], xy.data[1], zw.data[0], zw.data[1]} {} + + constexpr vec_base(const vec_base& xyz, T w) + : data{xyz.data[0], xyz.data[1], xyz.data[2], w} {} + + constexpr vec_base(T x, const vec_base& yzw) + : data{x, yzw.data[0], yzw.data[1], yzw.data[2]} {} constexpr T& x() noexcept { return data[0]; } constexpr const T& x() const noexcept { return data[0]; } @@ -173,17 +188,17 @@ namespace vmath_hpp } constexpr reference at(size_type index) { - if ( index < Size ) { - return data[index]; + if ( index >= Size ) { + throw std::out_of_range("vec::at"); } - throw std::out_of_range("vec::at"); + return data[index]; } constexpr const_reference at(size_type index) const { - if ( index < Size ) { - return data[index]; + if ( index >= Size ) { + throw std::out_of_range("vec::at"); } - throw std::out_of_range("vec::at"); + return data[index]; } }; diff --git a/untests/vmath_vec_tests.cpp b/untests/vmath_vec_tests.cpp index 6ba6642..18534d9 100644 --- a/untests/vmath_vec_tests.cpp +++ b/untests/vmath_vec_tests.cpp @@ -44,14 +44,27 @@ TEST_CASE("vmath/vec") { STATIC_REQUIRE(v2 == vec2i(1,2)); } { + STATIC_REQUIRE(vec2i(1) == vec2i(1,1)); + STATIC_REQUIRE(vec2i(1,2) == vec2i(1,2)); + STATIC_REQUIRE(vec2i(vec2i(1,2)) == vec2i(1,2)); STATIC_REQUIRE(vec2i(vec3i(1,2,3)) == vec2i(1,2)); STATIC_REQUIRE(vec2i(vec4i(1,2,3,4)) == vec2i(1,2)); + STATIC_REQUIRE(vec3i(1) == vec3i(1,1,1)); + STATIC_REQUIRE(vec3i(1,2,3) == vec3i(1,2,3)); STATIC_REQUIRE(vec3i(vec2i(1,2),3) == vec3i(1,2,3)); + STATIC_REQUIRE(vec3i(1,vec2i(2,3)) == vec3i(1,2,3)); + STATIC_REQUIRE(vec3i(vec3i(1,2,3)) == vec3i(1,2,3)); STATIC_REQUIRE(vec3i(vec4i(1,2,3,4)) == vec3i(1,2,3)); + STATIC_REQUIRE(vec4i(1) == vec4i(1,1,1,1)); + STATIC_REQUIRE(vec4i(1,2,3,4) == vec4i(1,2,3,4)); STATIC_REQUIRE(vec4i(vec2i(1,2),3,4) == vec4i(1,2,3,4)); + STATIC_REQUIRE(vec4i(1,vec2i(2,3),4) == vec4i(1,2,3,4)); + STATIC_REQUIRE(vec4i(1,2,vec2i(3,4)) == vec4i(1,2,3,4)); + STATIC_REQUIRE(vec4i(vec2i(1,2),vec2i(3,4)) == vec4i(1,2,3,4)); STATIC_REQUIRE(vec4i(vec3i(1,2,3),4) == vec4i(1,2,3,4)); + STATIC_REQUIRE(vec4i(1,vec3i(2,3,4)) == vec4i(1,2,3,4)); } } From 09062d3988ae44752dfee6ec15ab89473f1fe35f Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sat, 21 Nov 2020 23:14:47 +0700 Subject: [PATCH 07/53] more matrix ctors --- headers/vmath.hpp/vmath_mat.hpp | 69 +++++++++++++++++++++++++++++++-- headers/vmath.hpp/vmath_vec.hpp | 1 + untests/vmath_mat_tests.cpp | 25 ++++++++++++ 3 files changed, 91 insertions(+), 4 deletions(-) diff --git a/headers/vmath.hpp/vmath_mat.hpp b/headers/vmath.hpp/vmath_mat.hpp index 6379025..aa1794d 100644 --- a/headers/vmath.hpp/vmath_mat.hpp +++ b/headers/vmath.hpp/vmath_mat.hpp @@ -26,6 +26,11 @@ namespace vmath_hpp::detail constexpr explicit mat_base(uninit_t) {} + constexpr explicit mat_base(T v) + : rows{ + {v, 0}, + {0, v}} {} + constexpr mat_base( T m11, T m12, T m21, T m22) @@ -37,6 +42,18 @@ namespace vmath_hpp::detail const vec& row0, const vec& row1) : rows{row0, row1} {} + + constexpr explicit mat_base( + const mat_base& other) + : rows{ + vec{other.rows[0]}, + vec{other.rows[1]}} {} + + constexpr explicit mat_base( + const mat_base& other) + : rows{ + vec{other.rows[0]}, + vec{other.rows[1]}} {} }; template < typename T > @@ -52,6 +69,12 @@ namespace vmath_hpp::detail constexpr explicit mat_base(uninit_t) {} + constexpr explicit mat_base(T v) + : rows{ + {v, 0, 0}, + {0, v, 0}, + {0, 0, v}} {} + constexpr mat_base( T m11, T m12, T m13, T m21, T m22, T m23, @@ -66,6 +89,20 @@ namespace vmath_hpp::detail const vec& row1, const vec& row2) : rows{row0, row1, row2} {} + + constexpr explicit mat_base( + const mat_base& other) + : rows{ + {other.rows[0], 0}, + {other.rows[1], 0}, + {0, 0, 1}} {} + + constexpr explicit mat_base( + const mat_base& other) + : rows{ + vec{other.rows[0]}, + vec{other.rows[1]}, + vec{other.rows[2]}} {} }; template < typename T > @@ -82,6 +119,13 @@ namespace vmath_hpp::detail constexpr explicit mat_base(uninit_t) {} + constexpr explicit mat_base(T v) + : rows{ + {v, 0, 0, 0}, + {0, v, 0, 0}, + {0, 0, v, 0}, + {0, 0, 0, v}} {} + constexpr mat_base( T m11, T m12, T m13, T m14, T m21, T m22, T m23, T m24, @@ -99,6 +143,22 @@ namespace vmath_hpp::detail const vec& row2, const vec& row3) : rows{row0, row1, row2, row3} {} + + constexpr explicit mat_base( + const mat_base& other) + : rows{ + {other.rows[0], 0, 0}, + {other.rows[1], 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}} {} + + constexpr explicit mat_base( + const mat_base& other) + : rows{ + {other.rows[0], 0}, + {other.rows[1], 0}, + {other.rows[2], 0}, + {0, 0, 0, 1}} {} }; } @@ -109,6 +169,7 @@ namespace vmath_hpp public: using self_type = mat; using base_type = detail::mat_base; + public: using value_type = vec; using pointer = value_type*; @@ -162,22 +223,22 @@ namespace vmath_hpp constexpr size_type max_size() const noexcept { return Size; } constexpr bool empty() const noexcept { return !Size; } - constexpr value_type& operator[](size_type index) noexcept { + constexpr reference operator[](size_type index) noexcept { return rows[index]; } - constexpr const value_type& operator[](size_type index) const noexcept { + constexpr const_reference operator[](size_type index) const noexcept { return rows[index]; } - constexpr value_type& at(size_type index) { + constexpr reference at(size_type index) { if ( index >= Size ) { throw std::out_of_range("mat::at"); } return rows[index]; } - constexpr const value_type& at(size_type index) const { + constexpr const_reference at(size_type index) const { if ( index >= Size ) { throw std::out_of_range("mat::at"); } diff --git a/headers/vmath.hpp/vmath_vec.hpp b/headers/vmath.hpp/vmath_vec.hpp index 0486be1..336fe96 100644 --- a/headers/vmath.hpp/vmath_vec.hpp +++ b/headers/vmath.hpp/vmath_vec.hpp @@ -126,6 +126,7 @@ namespace vmath_hpp public: using self_type = vec; using base_type = detail::vec_base; + public: using value_type = T; using pointer = value_type*; diff --git a/untests/vmath_mat_tests.cpp b/untests/vmath_mat_tests.cpp index 53f3b10..0a4e059 100644 --- a/untests/vmath_mat_tests.cpp +++ b/untests/vmath_mat_tests.cpp @@ -43,6 +43,31 @@ TEST_CASE("vmath/mat") { constexpr mat2i v2 = std::move(v); STATIC_REQUIRE(v2 == mat2i(1,2,3,4)); } + { + STATIC_REQUIRE(mat2i() == mat2i(1,0,0,1)); + STATIC_REQUIRE(mat2i(2) == mat2i(2,0,0,2)); + STATIC_REQUIRE(mat2i(1,2,3,4) == mat2i(1,2,3,4)); + STATIC_REQUIRE(mat2i({1,2},{3,4}) == mat2i(1,2,3,4)); + STATIC_REQUIRE(mat2i(mat2i({1,2},{3,4})) == mat2i(1,2,3,4)); + STATIC_REQUIRE(mat2i(mat3i({1,2,3},{4,5,6},{7,8,9})) == mat2i(1,2,4,5)); + STATIC_REQUIRE(mat2i(mat4i({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == mat2i(1,2,5,6)); + + STATIC_REQUIRE(mat3i() == mat3i(1,0,0,0,1,0,0,0,1)); + STATIC_REQUIRE(mat3i(2) == mat3i(2,0,0,0,2,0,0,0,2)); + STATIC_REQUIRE(mat3i(1,2,3,4,5,6,7,8,9) == mat3i(1,2,3,4,5,6,7,8,9)); + STATIC_REQUIRE(mat3i({1,2,3},{4,5,6},{7,8,9}) == mat3i(1,2,3,4,5,6,7,8,9)); + STATIC_REQUIRE(mat3i(mat3i({1,2,3},{4,5,6},{7,8,9})) == mat3i(1,2,3,4,5,6,7,8,9)); + STATIC_REQUIRE(mat3i(mat2i({1,2},{3,4})) == mat3i(1,2,0,3,4,0,0,0,1)); + STATIC_REQUIRE(mat3i(mat4i({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == mat3i(1,2,3,5,6,7,9,10,11)); + + STATIC_REQUIRE(mat4i() == mat4i(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)); + STATIC_REQUIRE(mat4i(2) == mat4i(2,0,0,0,0,2,0,0,0,0,2,0,0,0,0,2)); + STATIC_REQUIRE(mat4i(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) == mat4i(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)); + STATIC_REQUIRE(mat4i({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}) == mat4i(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)); + STATIC_REQUIRE(mat4i(mat4i({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == mat4i(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)); + STATIC_REQUIRE(mat4i(mat2i({1,2},{3,4})) == mat4i(1,2,0,0,3,4,0,0,0,0,1,0,0,0,0,1)); + STATIC_REQUIRE(mat4i(mat3i({1,2,3},{4,5,6},{7,8,9})) == mat4i(1,2,3,0,4,5,6,0,7,8,9,0,0,0,0,1)); + } } SECTION("operator=") { From ab23e30cd588a99227a125c61ff1f7ce625bec48 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sun, 22 Nov 2020 00:51:31 +0700 Subject: [PATCH 08/53] vector relational functions --- headers/vmath.hpp/vmath.hpp | 1 + headers/vmath.hpp/vmath_fwd.hpp | 4 ++ headers/vmath.hpp/vmath_vec_ops.hpp | 91 +++++++++++++++++++++++++++++ untests/vmath_vec_ops_tests.cpp | 44 ++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 headers/vmath.hpp/vmath_vec_ops.hpp create mode 100644 untests/vmath_vec_ops_tests.cpp diff --git a/headers/vmath.hpp/vmath.hpp b/headers/vmath.hpp/vmath.hpp index cf975dc..6c98170 100644 --- a/headers/vmath.hpp/vmath.hpp +++ b/headers/vmath.hpp/vmath.hpp @@ -7,4 +7,5 @@ #pragma once #include "vmath_mat.hpp" +#include "vmath_vec_ops.hpp" #include "vmath_vec.hpp" diff --git a/headers/vmath.hpp/vmath_fwd.hpp b/headers/vmath.hpp/vmath_fwd.hpp index 627567b..ae546da 100644 --- a/headers/vmath.hpp/vmath_fwd.hpp +++ b/headers/vmath.hpp/vmath_fwd.hpp @@ -6,7 +6,11 @@ #pragma once +#include +#include #include + +#include #include #include #include diff --git a/headers/vmath.hpp/vmath_vec_ops.hpp b/headers/vmath.hpp/vmath_vec_ops.hpp new file mode 100644 index 0000000..7fa1f12 --- /dev/null +++ b/headers/vmath.hpp/vmath_vec_ops.hpp @@ -0,0 +1,91 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "vmath_fwd.hpp" +#include "vmath_vec.hpp" + +namespace vmath_hpp::detail +{ + template < typename T, std::size_t Size, typename F > + constexpr auto map(const vec& v, F&& f) { + vec, Size> result(uninit); + for ( std::size_t i = 0; i < Size; ++i ) { + result[i] = f(v[i]); + } + return result; + } + + template < typename T, typename U, std::size_t Size, typename F > + constexpr auto zip(const vec& l, const vec& r, F&& f) { + vec, Size> result(uninit); + for ( std::size_t i = 0; i < Size; ++i ) { + result[i] = f(l[i], r[i]); + } + return result; + } + + template < typename T, typename U, std::size_t Size, typename F > + constexpr auto fold(const vec& v, U init, F&& f) { + for ( std::size_t i = 0; i < Size; ++i ) { + init = f(init, v[i]); + } + return init; + } +} + +// +// Vector Relational Functions +// + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + constexpr vec less(const vec& x, const vec& y) { + return detail::zip(x, y, std::less<>()); + } + + template < typename T, std::size_t Size > + constexpr vec less_equal(const vec& x, const vec& y) { + return detail::zip(x, y, std::less_equal<>()); + } + + template < typename T, std::size_t Size > + constexpr vec greater(const vec& x, const vec& y) { + return detail::zip(x, y, std::greater<>()); + } + + template < typename T, std::size_t Size > + constexpr vec greater_equal(const vec& x, const vec& y) { + return detail::zip(x, y, std::greater_equal<>()); + } + + template < typename T, std::size_t Size > + constexpr vec equal(const vec& x, const vec& y) { + return detail::zip(x, y, std::equal_to<>()); + } + + template < typename T, std::size_t Size > + constexpr vec not_equal(const vec& x, const vec& y) { + return detail::zip(x, y, std::not_equal_to<>()); + } + + template < std::size_t Size > + constexpr bool any(const vec& x) { + return detail::fold(x, false, std::logical_or<>()); + } + + template < std::size_t Size > + constexpr bool all(const vec& x) { + return detail::fold(x, true, std::logical_and<>()); + } + + template < std::size_t Size > + constexpr vec not_(const vec& x) { + return detail::map(x, std::logical_not<>()); + } +} diff --git a/untests/vmath_vec_ops_tests.cpp b/untests/vmath_vec_ops_tests.cpp new file mode 100644 index 0000000..92bb3c3 --- /dev/null +++ b/untests/vmath_vec_ops_tests.cpp @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include + +#define CATCH_CONFIG_FAST_COMPILE +#include + +namespace +{ +} + +TEST_CASE("vmath/vec_ops") { + using namespace vmath_hpp; + + SECTION("Vector Relational Functions") { + STATIC_REQUIRE(less(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(false, false, true)); + STATIC_REQUIRE(less_equal(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(false, true, true)); + + STATIC_REQUIRE(greater(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(true, false, false)); + STATIC_REQUIRE(greater_equal(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(true, true, false)); + + STATIC_REQUIRE(equal(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(false, true, false)); + STATIC_REQUIRE(not_equal(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(true, false, true)); + + STATIC_REQUIRE_FALSE(any(vec2b(false, false))); + STATIC_REQUIRE(any(vec2b(true, false))); + STATIC_REQUIRE(any(vec2b(false, true))); + STATIC_REQUIRE(any(vec2b(true, true))); + + STATIC_REQUIRE_FALSE(all(vec2b(false, false))); + STATIC_REQUIRE_FALSE(all(vec2b(true, false))); + STATIC_REQUIRE_FALSE(all(vec2b(false, true))); + STATIC_REQUIRE(all(vec2b(true, true))); + + STATIC_REQUIRE(not_(vec2b(false, false)) == vec2b(true, true)); + STATIC_REQUIRE(not_(vec2b(true, false)) == vec2b(false, true)); + STATIC_REQUIRE(not_(vec2b(false, true)) == vec2b(true, false)); + STATIC_REQUIRE(not_(vec2b(true, true)) == vec2b(false, false)); + } +} From 59739ea85bfcbc1459409ab91432b18f25db61d6 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sun, 22 Nov 2020 04:01:17 +0700 Subject: [PATCH 09/53] remove uninit ctors --- headers/vmath.hpp/vmath_fwd.hpp | 6 ------ headers/vmath.hpp/vmath_mat.hpp | 8 ++------ headers/vmath.hpp/vmath_vec.hpp | 17 ++++++++--------- headers/vmath.hpp/vmath_vec_ops.hpp | 4 ++-- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/headers/vmath.hpp/vmath_fwd.hpp b/headers/vmath.hpp/vmath_fwd.hpp index ae546da..7657dbb 100644 --- a/headers/vmath.hpp/vmath_fwd.hpp +++ b/headers/vmath.hpp/vmath_fwd.hpp @@ -16,12 +16,6 @@ #include #include -namespace vmath_hpp -{ - struct uninit_t {}; - inline constexpr uninit_t uninit; -} - namespace vmath_hpp { template < typename T, std::size_t Size > diff --git a/headers/vmath.hpp/vmath_mat.hpp b/headers/vmath.hpp/vmath_mat.hpp index aa1794d..d7acdde 100644 --- a/headers/vmath.hpp/vmath_mat.hpp +++ b/headers/vmath.hpp/vmath_mat.hpp @@ -24,8 +24,6 @@ namespace vmath_hpp::detail {0, 1}, } {} - constexpr explicit mat_base(uninit_t) {} - constexpr explicit mat_base(T v) : rows{ {v, 0}, @@ -67,8 +65,6 @@ namespace vmath_hpp::detail {0, 0, 1}, } {} - constexpr explicit mat_base(uninit_t) {} - constexpr explicit mat_base(T v) : rows{ {v, 0, 0}, @@ -117,8 +113,6 @@ namespace vmath_hpp::detail {0, 0, 0, 1}, } {} - constexpr explicit mat_base(uninit_t) {} - constexpr explicit mat_base(T v) : rows{ {v, 0, 0, 0}, @@ -190,6 +184,8 @@ namespace vmath_hpp using base_type::rows; using base_type::mat_base; + mat() = default; + mat(mat&&) = default; mat& operator=(mat&&) = default; diff --git a/headers/vmath.hpp/vmath_vec.hpp b/headers/vmath.hpp/vmath_vec.hpp index 336fe96..58a9a4f 100644 --- a/headers/vmath.hpp/vmath_vec.hpp +++ b/headers/vmath.hpp/vmath_vec.hpp @@ -16,10 +16,9 @@ namespace vmath_hpp::detail template < typename T > class vec_base { public: - T data[2]; + T data[2]{}; public: - constexpr vec_base() : data{} {} - constexpr explicit vec_base(uninit_t) {} + vec_base() = default; constexpr explicit vec_base(T v) : data{v, v} {} @@ -43,10 +42,9 @@ namespace vmath_hpp::detail template < typename T > class vec_base { public: - T data[3]; + T data[3]{}; public: - constexpr vec_base() : data{} {} - constexpr explicit vec_base(uninit_t) {} + vec_base() = default; constexpr explicit vec_base(T v) : data{v, v, v} {} @@ -76,10 +74,9 @@ namespace vmath_hpp::detail template < typename T > class vec_base { public: - T data[4]; + T data[4]{}; public: - constexpr vec_base() : data{} {} - constexpr explicit vec_base(uninit_t) {} + vec_base() = default; constexpr explicit vec_base(T v) : data{v, v, v, v} {} @@ -147,6 +144,8 @@ namespace vmath_hpp using base_type::data; using base_type::vec_base; + vec() = default; + vec(vec&&) = default; vec& operator=(vec&&) = default; diff --git a/headers/vmath.hpp/vmath_vec_ops.hpp b/headers/vmath.hpp/vmath_vec_ops.hpp index 7fa1f12..a20bfd5 100644 --- a/headers/vmath.hpp/vmath_vec_ops.hpp +++ b/headers/vmath.hpp/vmath_vec_ops.hpp @@ -13,7 +13,7 @@ namespace vmath_hpp::detail { template < typename T, std::size_t Size, typename F > constexpr auto map(const vec& v, F&& f) { - vec, Size> result(uninit); + vec, Size> result; for ( std::size_t i = 0; i < Size; ++i ) { result[i] = f(v[i]); } @@ -22,7 +22,7 @@ namespace vmath_hpp::detail template < typename T, typename U, std::size_t Size, typename F > constexpr auto zip(const vec& l, const vec& r, F&& f) { - vec, Size> result(uninit); + vec, Size> result; for ( std::size_t i = 0; i < Size; ++i ) { result[i] = f(l[i], r[i]); } From 2cee3a4d42ea7e02a78ae5913f88fea7e3dd5f06 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Mon, 23 Nov 2020 05:37:15 +0700 Subject: [PATCH 10/53] single value math funcs --- headers/vmath.hpp/vmath_fun.hpp | 169 ++++++++++++++++++++++++++++++++ headers/vmath.hpp/vmath_fwd.hpp | 1 + untests/vmath_fun_tests.cpp | 135 +++++++++++++++++++++++++ 3 files changed, 305 insertions(+) create mode 100644 headers/vmath.hpp/vmath_fun.hpp create mode 100644 untests/vmath_fun_tests.cpp diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp new file mode 100644 index 0000000..de6146e --- /dev/null +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -0,0 +1,169 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "vmath_fwd.hpp" + +// +// Angle and Trigonometry Functions +// + +namespace vmath_hpp +{ + template < typename T > + constexpr T radians(T degrees) noexcept { + return degrees * T(0.01745329251994329576923690768489); + } + + template < typename T > + constexpr T degrees(T radians) noexcept { + return radians * T(57.295779513082320876798154814105); + } + + using ::std::sin; + using ::std::cos; + using ::std::tan; + + using ::std::asin; + using ::std::acos; + using ::std::atan; + using ::std::atan2; + + using ::std::sinh; + using ::std::cosh; + using ::std::tanh; + + using ::std::asinh; + using ::std::acosh; + using ::std::atanh; +} + +// +// Exponential Functions +// + +namespace vmath_hpp +{ + using ::std::pow; + using ::std::exp; + using ::std::log; + using ::std::exp2; + using ::std::log2; + using ::std::sqrt; + + template < typename T > + T invsqrt(T x) noexcept { + return T(1) / sqrt(x); + } +} + +// +// Common Functions +// + +namespace vmath_hpp +{ + using ::std::abs; + + template < typename T > + T sign(T x) noexcept { + return (T(0) < x) - (x < T(0)); + } + + using ::std::floor; + using ::std::trunc; + using ::std::round; + using ::std::ceil; + + template < typename T > + T fract(T x) noexcept { + return x - floor(x); + } + + using ::std::fmod; + using ::std::modf; + + using ::std::min; + using ::std::max; + + template < typename T > + constexpr T clamp(T x, T min_x, T max_x) noexcept { + return min(max(x, min_x), max_x); + } + + template < typename T > + constexpr T mix(T x, T y, T a) noexcept { + return x * (T(1) - a) + y * a; + } + + template < typename T > + constexpr T mix(T x, T y, bool a) noexcept { + return a ? y : x; + } + + template < typename T > + constexpr T step(T edge, T x) noexcept { + return x < edge ? T(0) : T(1); + } + + template < typename T > + constexpr T smoothstep(T edge0, T edge1, T x) noexcept { + const T t = clamp((x - edge0) / (edge1 - edge0), T(0), T(1)); + return t * t * (T(3) - T(2) * t); + } + + using ::std::isnan; + using ::std::isinf; + using ::std::fma; + + using ::std::frexp; + using ::std::ldexp; +} + +// +// Geometric Functions +// + +namespace vmath_hpp +{ + template < typename T > + T length(T x) noexcept { + return abs(x); + } + + template < typename T > + T distance(T p0, T p1) noexcept { + return length(p0 - p1); + } + + template < typename T > + T dot(T x, T y) noexcept { + return x * y; + } + + template < typename T > + T normalize(T x) noexcept { + return x * invsqrt(dot(x, x)); + } + + template < typename T > + T faceforward(T n, T i, T nref) noexcept { + return dot(nref, i) < T(0) ? n : -n; + } + + template < typename T > + T reflect(T i, T n) noexcept { + return i - n * dot(n, i) * T(2); + } + + template < typename T > + T refract(T i, T n, T eta) noexcept { + const T d = dot(n, i); + const T k = T(1) - eta * eta * (T(1) - d * d); + return T(k >= T(0)) * (eta * i - (eta * d + sqrt(k)) * n); + } +} diff --git a/headers/vmath.hpp/vmath_fwd.hpp b/headers/vmath.hpp/vmath_fwd.hpp index 7657dbb..be41369 100644 --- a/headers/vmath.hpp/vmath_fwd.hpp +++ b/headers/vmath.hpp/vmath_fwd.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp new file mode 100644 index 0000000..715bc58 --- /dev/null +++ b/untests/vmath_fun_tests.cpp @@ -0,0 +1,135 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include + +#define CATCH_CONFIG_FAST_COMPILE +#include + +namespace +{ + template < typename T > + class approx { + public: + explicit constexpr approx(T v) : value_(v) {} + + friend constexpr bool operator==(const T& l, const approx& r) { + return (r.value_ < l + epsilon) + && (l < r.value_ + epsilon); + } + private: + T value_; + static constexpr T epsilon = std::numeric_limits::epsilon() * 100; + }; +} + +TEST_CASE("vmath/fun") { + using namespace vmath_hpp; + + SECTION("Angle and Trigonometry Functions") { + STATIC_REQUIRE(radians(degrees(12.13f)) == approx(12.13f)); + STATIC_REQUIRE(degrees(radians(12.13f)) == approx(12.13f)); + + sin(0.f); + cos(0.f); + tan(0.f); + + asin(0.f); + acos(0.f); + atan(0.f); + atan2(0.f, 0.f); + + sinh(0.f); + cosh(0.f); + tanh(0.f); + + asinh(0.f); + acosh(0.f); + atanh(0.f); + } + + SECTION("Exponential Functions") { + pow(2.f, 3.f); + exp(2.f); + log(2.f); + exp2(2.f); + log2(2.f); + sqrt(2.f); + invsqrt(2.f); + } + + SECTION("Common Functions") { + REQUIRE(abs(1) == 1); + REQUIRE(abs(-1) == 1); + REQUIRE(abs(1.f) == approx(1.f)); + REQUIRE(abs(-1.f) == approx(1.f)); + + REQUIRE(sign(2) == 1); + REQUIRE(sign(-2) == -1); + REQUIRE(sign(0) == 0); + REQUIRE(sign(2.f) == approx(1.f)); + REQUIRE(sign(-2.f) == approx(-1.f)); + REQUIRE(sign(0.f) == approx(0.f)); + + REQUIRE(floor(1.7f) == approx(1.f)); + REQUIRE(trunc(1.7f) == approx(1.f)); + REQUIRE(round(1.7f) == approx(2.f)); + REQUIRE(ceil(1.7f) == approx(2.f)); + + REQUIRE(fract(1.7f) == approx(0.7f)); + REQUIRE(fract(-2.3f) == approx(0.7f)); + + REQUIRE(fmod(1.7f, 1.2f) == approx(0.5f)); + + { + float out_i{}; + REQUIRE(modf(1.7f, &out_i) == approx(0.7f)); + REQUIRE(out_i == approx(1.f)); + } + + STATIC_REQUIRE(min(1.f, 2.f) == approx(1.f)); + STATIC_REQUIRE(max(1.f, 2.f) == approx(2.f)); + + STATIC_REQUIRE(clamp(1.0f, 2.f, 3.f) == approx(2.0f)); + STATIC_REQUIRE(clamp(2.5f, 2.f, 3.f) == approx(2.5f)); + STATIC_REQUIRE(clamp(3.5f, 2.f, 3.f) == approx(3.0f)); + + STATIC_REQUIRE(mix(0.f, 10.f, 0.5f) == approx(5.f)); + STATIC_REQUIRE(mix(0.f, 10.f, false) == approx(0.f)); + STATIC_REQUIRE(mix(0.f, 10.f, true) == approx(10.f)); + STATIC_REQUIRE(step(0.5f, 0.4f) == approx(0.f)); + STATIC_REQUIRE(step(0.5f, 0.6f) == approx(1.f)); + STATIC_REQUIRE(smoothstep(0.f, 1.f, 0.1f) == approx(0.028f)); + + REQUIRE_FALSE(isnan(1.f)); + REQUIRE_FALSE(isinf(1.f)); + + REQUIRE(fma(2.f, 3.f, 4.f) == approx(10.f)); + + { + int out_exp{}; + REQUIRE(frexp(1.7f, &out_exp) == approx(0.85f)); + REQUIRE(out_exp == 1); + } + + REQUIRE(ldexp(0.85f, 1) == approx(1.7f)); + } + + SECTION("Geometric Functions") { + REQUIRE(length(10.f) == approx(10.f)); + REQUIRE(length(-10.f) == approx(10.f)); + + REQUIRE(distance(5.f, 10.f) == approx(5.f)); + REQUIRE(distance(-5.f, -10.f) == approx(5.f)); + + REQUIRE(dot(2.f, 5.f) == approx(10.f)); + REQUIRE(normalize(0.5f) == approx(1.f)); + + REQUIRE(faceforward(1.f, 2.f, 3.f) == approx(-1.f)); + REQUIRE(reflect(1.f, 2.f) == approx(-7.f)); + REQUIRE(refract(1.f, 2.f, 1.f) == approx(-7.f)); + } +} From 059723049e50bbec0ac463b3e78e51b51d93e09e Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Mon, 23 Nov 2020 05:38:50 +0700 Subject: [PATCH 11/53] union constexpr data --- headers/vmath.hpp/vmath_mat.hpp | 37 +----- headers/vmath.hpp/vmath_vec.hpp | 196 ++++++++++++++++++-------------- untests/vmath_mat_tests.cpp | 68 +---------- untests/vmath_vec_tests.cpp | 116 +++++-------------- 4 files changed, 149 insertions(+), 268 deletions(-) diff --git a/headers/vmath.hpp/vmath_mat.hpp b/headers/vmath.hpp/vmath_mat.hpp index d7acdde..67bf6b6 100644 --- a/headers/vmath.hpp/vmath_mat.hpp +++ b/headers/vmath.hpp/vmath_mat.hpp @@ -172,14 +172,7 @@ namespace vmath_hpp using reference = value_type&; using const_reference = const value_type&; - using iterator = value_type*; - using const_iterator = const value_type*; - - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; + static constexpr std::size_t size = Size; public: using base_type::rows; using base_type::mat_base; @@ -199,42 +192,22 @@ namespace vmath_hpp } } - constexpr iterator begin() noexcept { return iterator(rows); } - constexpr const_iterator begin() const noexcept { return const_iterator(rows); } - constexpr const_iterator cbegin() const noexcept { return const_iterator(rows); } - - constexpr iterator end() noexcept { return iterator(rows + Size); } - constexpr const_iterator end() const noexcept { return const_iterator(rows + Size); } - constexpr const_iterator cend() const noexcept { return const_iterator(rows + Size); } - - constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } - - constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } - constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } - - constexpr size_type size() const noexcept { return Size; } - constexpr size_type max_size() const noexcept { return Size; } - constexpr bool empty() const noexcept { return !Size; } - - constexpr reference operator[](size_type index) noexcept { + constexpr reference operator[](std::size_t index) noexcept { return rows[index]; } - constexpr const_reference operator[](size_type index) const noexcept { + constexpr const_reference operator[](std::size_t index) const noexcept { return rows[index]; } - constexpr reference at(size_type index) { + constexpr reference at(std::size_t index) { if ( index >= Size ) { throw std::out_of_range("mat::at"); } return rows[index]; } - constexpr const_reference at(size_type index) const { + constexpr const_reference at(std::size_t index) const { if ( index >= Size ) { throw std::out_of_range("mat::at"); } diff --git a/headers/vmath.hpp/vmath_vec.hpp b/headers/vmath.hpp/vmath_vec.hpp index 58a9a4f..2f2aafd 100644 --- a/headers/vmath.hpp/vmath_vec.hpp +++ b/headers/vmath.hpp/vmath_vec.hpp @@ -8,6 +8,18 @@ #include "vmath_fwd.hpp" +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +#elif defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +# pragma clang diagnostic ignored "-Wnested-anon-types" +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable: 4201) +#endif + namespace vmath_hpp::detail { template < typename T, std::size_t Size > @@ -16,106 +28,153 @@ namespace vmath_hpp::detail template < typename T > class vec_base { public: - T data[2]{}; + union { + struct { T x, y; }; + T data[2]; + }; public: - vec_base() = default; + constexpr vec_base() + : x{0}, y{0} {} constexpr explicit vec_base(T v) - : data{v, v} {} + : x{v}, y{v} {} constexpr vec_base(T x, T y) - : data{x, y} {} + : x{x}, y{y} {} constexpr explicit vec_base(const vec_base& xy) - : data{xy.data[0], xy.data[1]} {} + : x{xy.x}, y{xy.y} {} constexpr explicit vec_base(const vec_base& xy) - : data{xy.data[0], xy.data[1]} {} + : x{xy.x}, y{xy.y} {} - constexpr T& x() noexcept { return data[0]; } - constexpr const T& x() const noexcept { return data[0]; } + constexpr T& operator[](std::size_t index) noexcept { + switch ( index ) { + default: + case 0: return x; + case 1: return y; + } + } - constexpr T& y() noexcept { return data[1]; } - constexpr const T& y() const noexcept { return data[1]; } + constexpr const T& operator[](std::size_t index) const noexcept { + switch ( index ) { + default: + case 0: return x; + case 1: return y; + } + } }; template < typename T > class vec_base { public: - T data[3]{}; + union { + struct { T x, y, z; }; + T data[3]; + }; public: - vec_base() = default; + constexpr vec_base() + : x{0}, y{0}, z{0} {} constexpr explicit vec_base(T v) - : data{v, v, v} {} + : x{v}, y{v}, z{v} {} constexpr vec_base(T x, T y, T z) - : data{x, y, z} {} + : x{x}, y{y}, z{z} {} constexpr vec_base(const vec_base& xy, T z) - : data{xy.data[0], xy.data[1], z} {} + : x{xy.x}, y{xy.y}, z{z} {} constexpr vec_base(T x, const vec_base& yz) - : data{x, yz.data[0], yz.data[1]} {} + : x{x}, y{yz.x}, z{yz.y} {} constexpr explicit vec_base(const vec_base& xyz) - : data{xyz.data[0], xyz.data[1], xyz.data[2]} {} + : x{xyz.x}, y{xyz.y}, z{xyz.z} {} - constexpr T& x() noexcept { return data[0]; } - constexpr const T& x() const noexcept { return data[0]; } + constexpr T& operator[](std::size_t index) noexcept { + switch ( index ) { + default: + case 0: return x; + case 1: return y; + case 2: return z; + } + } - constexpr T& y() noexcept { return data[1]; } - constexpr const T& y() const noexcept { return data[1]; } - - constexpr T& z() noexcept { return data[2]; } - constexpr const T& z() const noexcept { return data[2]; } + constexpr const T& operator[](std::size_t index) const noexcept { + switch ( index ) { + default: + case 0: return x; + case 1: return y; + case 2: return z; + } + } }; template < typename T > class vec_base { public: - T data[4]{}; + union { + struct { T x, y, z, w; }; + T data[4]; + }; public: - vec_base() = default; + constexpr vec_base() + : x{0}, y{0}, z{0}, w{0} {} constexpr explicit vec_base(T v) - : data{v, v, v, v} {} + : x{v}, y{v}, z{v}, w{v} {} constexpr vec_base(T x, T y, T z, T w) - : data{x, y, z, w} {} + : x{x}, y{y}, z{z}, w{w} {} constexpr vec_base(const vec_base& xy, T z, T w) - : data{xy.data[0], xy.data[1], z, w} {} + : x{xy.x}, y{xy.y}, z{z}, w{w} {} constexpr vec_base(T x, const vec_base& yz, T w) - : data{x, yz.data[0], yz.data[1], w} {} + : x{x}, y{yz.x}, z{yz.y}, w{w} {} constexpr vec_base(T x, T y, const vec_base& zw) - : data{x, y, zw.data[0], zw.data[1]} {} + : x{x}, y{y}, z{zw.x}, w{zw.y} {} constexpr vec_base(const vec_base& xy, const vec_base& zw) - : data{xy.data[0], xy.data[1], zw.data[0], zw.data[1]} {} + : x{xy.x}, y{xy.y}, z{zw.x}, w{zw.y} {} constexpr vec_base(const vec_base& xyz, T w) - : data{xyz.data[0], xyz.data[1], xyz.data[2], w} {} + : x{xyz.x}, y{xyz.y}, z{xyz.z}, w{w} {} constexpr vec_base(T x, const vec_base& yzw) - : data{x, yzw.data[0], yzw.data[1], yzw.data[2]} {} + : x{x}, y{yzw.x}, z{yzw.y}, w{yzw.z} {} - constexpr T& x() noexcept { return data[0]; } - constexpr const T& x() const noexcept { return data[0]; } + constexpr T& operator[](std::size_t index) noexcept { + switch ( index ) { + default: + case 0: return x; + case 1: return y; + case 2: return z; + case 3: return w; + } + } - constexpr T& y() noexcept { return data[1]; } - constexpr const T& y() const noexcept { return data[1]; } - - constexpr T& z() noexcept { return data[2]; } - constexpr const T& z() const noexcept { return data[2]; } - - constexpr T& w() noexcept { return data[3]; } - constexpr const T& w() const noexcept { return data[3]; } + constexpr const T& operator[](std::size_t index) const noexcept { + switch ( index ) { + default: + case 0: return x; + case 1: return y; + case 2: return z; + case 3: return w; + } + } }; } +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#elif defined(__clang__) +# pragma clang diagnostic pop +#elif defined(_MSC_VER) +# pragma warning(pop) +#endif + namespace vmath_hpp { template < typename T, std::size_t Size > @@ -132,17 +191,10 @@ namespace vmath_hpp using reference = value_type&; using const_reference = const value_type&; - using iterator = value_type*; - using const_iterator = const value_type*; - - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; + static constexpr std::size_t size = Size; public: - using base_type::data; using base_type::vec_base; + using base_type::operator[]; vec() = default; @@ -155,50 +207,22 @@ namespace vmath_hpp void swap(vec& other) noexcept(std::is_nothrow_swappable_v) { for ( std::size_t i = 0; i < Size; ++i ) { using std::swap; - swap(data[i], other.data[i]); + swap((*this)[i], other[i]); } } - constexpr iterator begin() noexcept { return iterator(data); } - constexpr const_iterator begin() const noexcept { return const_iterator(data); } - constexpr const_iterator cbegin() const noexcept { return const_iterator(data); } - - constexpr iterator end() noexcept { return iterator(data + Size); } - constexpr const_iterator end() const noexcept { return const_iterator(data + Size); } - constexpr const_iterator cend() const noexcept { return const_iterator(data + Size); } - - constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } - - constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } - constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } - - constexpr size_type size() const noexcept { return Size; } - constexpr size_type max_size() const noexcept { return Size; } - constexpr bool empty() const noexcept { return !Size; } - - constexpr reference operator[](size_type index) noexcept { - return data[index]; - } - - constexpr const_reference operator[](size_type index) const noexcept { - return data[index]; - } - - constexpr reference at(size_type index) { + constexpr reference at(std::size_t index) { if ( index >= Size ) { throw std::out_of_range("vec::at"); } - return data[index]; + return (*this)[index]; } - constexpr const_reference at(size_type index) const { + constexpr const_reference at(std::size_t index) const { if ( index >= Size ) { throw std::out_of_range("vec::at"); } - return data[index]; + return (*this)[index]; } }; diff --git a/untests/vmath_mat_tests.cpp b/untests/vmath_mat_tests.cpp index 0a4e059..00ce90f 100644 --- a/untests/vmath_mat_tests.cpp +++ b/untests/vmath_mat_tests.cpp @@ -16,7 +16,11 @@ namespace TEST_CASE("vmath/mat") { using namespace vmath_hpp; - SECTION("sizeof") { + SECTION("size/sizeof") { + STATIC_REQUIRE(mat2i{}.size == 2); + STATIC_REQUIRE(mat3i{}.size == 3); + STATIC_REQUIRE(mat4i{}.size == 4); + STATIC_REQUIRE(sizeof(mat2i{}) == sizeof(int) * 2 * 2); STATIC_REQUIRE(sizeof(mat3i{}) == sizeof(int) * 3 * 3); STATIC_REQUIRE(sizeof(mat4i{}) == sizeof(int) * 4 * 4); @@ -102,68 +106,6 @@ TEST_CASE("vmath/mat") { } } - SECTION("iter") { - { - mat2i v{1,2,3,4}; - mat2i::iterator i = v.begin(); - REQUIRE(*i++ == vec2i{1,2}); - REQUIRE(*i++ == vec2i{3,4}); - REQUIRE(v.end() == i); - } - { - const mat2i v{1,2,3,4}; - mat2i::const_iterator i = v.begin(); - REQUIRE(*i++ == vec2i{1,2}); - REQUIRE(*i++ == vec2i{3,4}); - REQUIRE(v.end() == i); - } - { - mat2i v{1,2,3,4}; - for ( auto i = v.begin(); i < v.end(); ++i ) { - *i = vec2i(i->x() * 2, i->y() * 2); - } - REQUIRE(v == mat2i(2,4,6,8)); - } - } - - SECTION("riter") { - { - mat2i v{1,2,3,4}; - mat2i::reverse_iterator i = v.rbegin(); - REQUIRE(*i++ == vec2i{3,4}); - REQUIRE(*i++ == vec2i{1,2}); - REQUIRE(v.rend() == i); - for ( auto j = v.rbegin(); j < v.rend(); ++j ) { - *j = vec2i(j->x() * 2, j->y() * 2); - } - REQUIRE(v == mat2i(2,4,6,8)); - } - { - const mat2i v{1,2,3,4}; - mat2i::const_reverse_iterator i = v.rbegin(); - REQUIRE(*i++ == vec2i{3,4}); - REQUIRE(*i++ == vec2i{1,2}); - REQUIRE(v.rend() == i); - } - { - mat2i v{1,2,3,4}; - for ( auto i = v.rbegin(); i < v.rend(); ++i ) { - *i = vec2i(i->x() * 2, i->y() * 2); - } - REQUIRE(v == mat2i(2,4,6,8)); - } - } - - SECTION("size/max_size/empty") { - STATIC_REQUIRE(mat().size() == 2); - STATIC_REQUIRE(mat().max_size() == 2); - STATIC_REQUIRE_FALSE(mat().empty()); - - STATIC_REQUIRE(mat().size() == 3); - STATIC_REQUIRE(mat().max_size() == 3); - STATIC_REQUIRE_FALSE(mat().empty()); - } - SECTION("operator[]") { { STATIC_REQUIRE(mat2i()[0] == vec2i(1,0)); diff --git a/untests/vmath_vec_tests.cpp b/untests/vmath_vec_tests.cpp index 18534d9..8b0a985 100644 --- a/untests/vmath_vec_tests.cpp +++ b/untests/vmath_vec_tests.cpp @@ -16,7 +16,11 @@ namespace TEST_CASE("vmath/vec") { using namespace vmath_hpp; - SECTION("sizeof") { + SECTION("size/sizeof") { + STATIC_REQUIRE(vec2i{}.size == 2); + STATIC_REQUIRE(vec3i{}.size == 3); + STATIC_REQUIRE(vec4i{}.size == 4); + STATIC_REQUIRE(sizeof(vec2i{}) == sizeof(int) * 2); STATIC_REQUIRE(sizeof(vec3i{}) == sizeof(int) * 3); STATIC_REQUIRE(sizeof(vec4i{}) == sizeof(int) * 4); @@ -24,14 +28,14 @@ TEST_CASE("vmath/vec") { SECTION("ctors") { { - STATIC_REQUIRE(vec2i().x() == 0); - STATIC_REQUIRE(vec2i().y() == 0); + STATIC_REQUIRE(vec2i().x == 0); + STATIC_REQUIRE(vec2i().y == 0); - STATIC_REQUIRE(vec2i(1).x() == 1); - STATIC_REQUIRE(vec2i(1).y() == 1); + STATIC_REQUIRE(vec2i(1).x == 1); + STATIC_REQUIRE(vec2i(1).y == 1); - STATIC_REQUIRE(vec2i(1,2).x() == 1); - STATIC_REQUIRE(vec2i(1,2).y() == 2); + STATIC_REQUIRE(vec2i(1,2).x == 1); + STATIC_REQUIRE(vec2i(1,2).y == 2); } { constexpr vec2i v(1,2); @@ -100,81 +104,19 @@ TEST_CASE("vmath/vec") { } } - SECTION("iter") { - { - vec2i v(1,2); - vec2i::iterator i = v.begin(); - REQUIRE(*i++ == 1); - REQUIRE(*i++ == 2); - REQUIRE(v.end() == i); - } - { - const vec2i v(1,2); - vec2i::const_iterator i = v.begin(); - REQUIRE(*i++ == 1); - REQUIRE(*i++ == 2); - REQUIRE(v.end() == i); - } - { - vec2i v(1,2); - for ( auto i = v.begin(); i < v.end(); ++i ) { - *i = *i * 2; - } - REQUIRE(v == vec2i(2,4)); - } - } - - SECTION("riter") { - { - vec2i v(1,2); - vec2i::reverse_iterator i = v.rbegin(); - REQUIRE(*i++ == 2); - REQUIRE(*i++ == 1); - REQUIRE(v.rend() == i); - for ( auto j = v.rbegin(); j < v.rend(); ++j ) { - *j = *j * 2; - } - REQUIRE(v == vec2i(2,4)); - } - { - const vec2i v(1,2); - vec2i::const_reverse_iterator i = v.rbegin(); - REQUIRE(*i++ == 2); - REQUIRE(*i++ == 1); - REQUIRE(v.rend() == i); - } - { - vec2i v(1,2); - for ( auto i = v.rbegin(); i < v.rend(); ++i ) { - *i = *i * 2; - } - REQUIRE(v == vec2i(2,4)); - } - } - - SECTION("size/max_size/empty") { - STATIC_REQUIRE(vec().size() == 2); - STATIC_REQUIRE(vec().max_size() == 2); - STATIC_REQUIRE_FALSE(vec().empty()); - - STATIC_REQUIRE(vec().size() == 3); - STATIC_REQUIRE(vec().max_size() == 3); - STATIC_REQUIRE_FALSE(vec().empty()); - } - SECTION("operator[]") { { - STATIC_REQUIRE(vec2i(1,2).x() == 1); - STATIC_REQUIRE(vec2i(1,2).y() == 2); + STATIC_REQUIRE(vec2i(1,2).x == 1); + STATIC_REQUIRE(vec2i(1,2).y == 2); - STATIC_REQUIRE(vec3i(1,2,3).x() == 1); - STATIC_REQUIRE(vec3i(1,2,3).y() == 2); - STATIC_REQUIRE(vec3i(1,2,3).z() == 3); + STATIC_REQUIRE(vec3i(1,2,3).x == 1); + STATIC_REQUIRE(vec3i(1,2,3).y == 2); + STATIC_REQUIRE(vec3i(1,2,3).z == 3); - STATIC_REQUIRE(vec4i(1,2,3,4).x() == 1); - STATIC_REQUIRE(vec4i(1,2,3,4).y() == 2); - STATIC_REQUIRE(vec4i(1,2,3,4).z() == 3); - STATIC_REQUIRE(vec4i(1,2,3,4).w() == 4); + STATIC_REQUIRE(vec4i(1,2,3,4).x == 1); + STATIC_REQUIRE(vec4i(1,2,3,4).y == 2); + STATIC_REQUIRE(vec4i(1,2,3,4).z == 3); + STATIC_REQUIRE(vec4i(1,2,3,4).w == 4); } { STATIC_REQUIRE(vec2i(1,2)[0] == 1); @@ -182,23 +124,23 @@ TEST_CASE("vmath/vec") { } { vec2i v; - v.x() = 1; - v.y() = 2; + v.x = 1; + v.y = 2; REQUIRE(v == vec2i(1,2)); } { vec3i v; - v.x() = 1; - v.y() = 2; - v.z() = 3; + v.x = 1; + v.y = 2; + v.z = 3; REQUIRE(v == vec3i(1,2,3)); } { vec4i v; - v.x() = 1; - v.y() = 2; - v.z() = 3; - v.w() = 4; + v.x = 1; + v.y = 2; + v.z = 3; + v.w = 4; REQUIRE(v == vec4i(1,2,3,4)); } } From ad55131316881d3564f92a37389adb51c18b20f8 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Mon, 23 Nov 2020 05:42:26 +0700 Subject: [PATCH 12/53] vector math funcs --- headers/vmath.hpp/vmath.hpp | 3 +- headers/vmath.hpp/vmath_vec_fun.hpp | 544 ++++++++++++++++++++++++++++ headers/vmath.hpp/vmath_vec_ops.hpp | 91 ----- untests/vmath_vec_fun_tests.cpp | 205 +++++++++++ untests/vmath_vec_ops_tests.cpp | 44 --- 5 files changed, 751 insertions(+), 136 deletions(-) create mode 100644 headers/vmath.hpp/vmath_vec_fun.hpp delete mode 100644 headers/vmath.hpp/vmath_vec_ops.hpp create mode 100644 untests/vmath_vec_fun_tests.cpp delete mode 100644 untests/vmath_vec_ops_tests.cpp diff --git a/headers/vmath.hpp/vmath.hpp b/headers/vmath.hpp/vmath.hpp index 6c98170..25faaf7 100644 --- a/headers/vmath.hpp/vmath.hpp +++ b/headers/vmath.hpp/vmath.hpp @@ -6,6 +6,7 @@ #pragma once +#include "vmath_fun.hpp" #include "vmath_mat.hpp" -#include "vmath_vec_ops.hpp" #include "vmath_vec.hpp" +#include "vmath_vec_fun.hpp" diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp new file mode 100644 index 0000000..c605411 --- /dev/null +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -0,0 +1,544 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "vmath_fwd.hpp" + +#include "vmath_fun.hpp" +#include "vmath_vec.hpp" + +namespace vmath_hpp::detail +{ + namespace impl + { + template < typename A, std::size_t Size, typename F, std::size_t... Is > + constexpr auto map_impl(F&& f, const vec& v, std::index_sequence) + -> vec, Size> + { + return { f(v[Is])... }; + } + + template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > + constexpr auto zip_impl(F&& f, const vec& a, const vec& b, std::index_sequence) + -> vec, Size> + { + return { f(a[Is], b[Is])... }; + } + + template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > + constexpr auto zip_impl(F&& f, const vec& a, const vec& b, const vec& c, std::index_sequence) + -> vec, Size> + { + return { f(a[Is], b[Is], c[Is])... }; + } + + template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > + constexpr auto fold_impl(F&& f, A init, const vec& v, std::index_sequence) + -> A + { + return ((init = f(std::move(init), v[Is])), ...); + } + } + + template < typename T, std::size_t Size, typename F > + constexpr auto map(F&& f, const vec& v) { + return impl::map_impl(std::forward(f), v, std::make_index_sequence{}); + } + + template < typename A, typename B, std::size_t Size, typename F > + constexpr auto zip(F&& f, const vec& a, const vec& b) { + return impl::zip_impl(std::forward(f), a, b, std::make_index_sequence{}); + } + + template < typename A, typename B, typename C, std::size_t Size, typename F > + constexpr auto zip(F&& f, const vec& a, const vec& b, const vec& c) { + return impl::zip_impl(std::forward(f), a, b, c, std::make_index_sequence{}); + } + + template < typename A, typename B, std::size_t Size, typename F > + constexpr auto fold(F&& f, A init, const vec& v) { + return impl::fold_impl(std::forward(f), std::move(init), v, std::make_index_sequence{}); + } +} + +// +// Operators +// + +namespace vmath_hpp +{ + // -operator + + template < typename T, std::size_t Size > + constexpr vec operator-(const vec& xs) { + return map(std::negate<>(), xs); + } + + // operator+ + + template < typename T, std::size_t Size > + constexpr vec operator+(const vec& xs, T y) { + return map([y](T x){ return x + y; }, xs); + } + + template < typename T, std::size_t Size > + constexpr vec operator+(T x, const vec& ys) { + return map([x](T y){ return x + y; }, ys); + } + + template < typename T, std::size_t Size > + constexpr vec operator+(const vec& xs, const vec& ys) { + return zip(std::plus<>(), xs, ys); + } + + // operator- + + template < typename T, std::size_t Size > + constexpr vec operator-(const vec& xs, T y) { + return map([y](T x){ return x - y; }, xs); + } + + template < typename T, std::size_t Size > + constexpr vec operator-(T x, const vec& ys) { + return map([x](T y){ return x - y; }, ys); + } + + template < typename T, std::size_t Size > + constexpr vec operator-(const vec& xs, const vec& ys) { + return zip(std::minus<>(), xs, ys); + } + + // operator* + + template < typename T, std::size_t Size > + constexpr vec operator*(const vec& xs, T y) { + return map([y](T x){ return x * y; }, xs); + } + + template < typename T, std::size_t Size > + constexpr vec operator*(T x, const vec& ys) { + return map([x](T y){ return x * y; }, ys); + } + + template < typename T, std::size_t Size > + constexpr vec operator*(const vec& xs, const vec& ys) { + return zip(std::multiplies<>(), xs, ys); + } + + // operator/ + + template < typename T, std::size_t Size > + constexpr vec operator/(const vec& xs, T y) { + return map([y](T x){ return x / y; }, xs); + } + + template < typename T, std::size_t Size > + constexpr vec operator/(T x, const vec& ys) { + return map([x](T y){ return x / y; }, ys); + } + + template < typename T, std::size_t Size > + constexpr vec operator/(const vec& xs, const vec& ys) { + return zip(std::divides<>(), xs, ys); + } +} + +// +// Angle and Trigonometry Functions +// + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + constexpr vec radians(const vec& degrees) { + return map([](T x) { return radians(x); }, degrees); + } + + template < typename T, std::size_t Size > + constexpr vec degrees(const vec& radians) { + return map([](T x) { return degrees(x); }, radians); + } + + template < typename T, std::size_t Size > + vec sin(const vec& xs) { + return map([](T x) { return sin(x); }, xs); + } + + template < typename T, std::size_t Size > + vec cos(const vec& xs) { + return map([](T x) { return cos(x); }, xs); + } + + template < typename T, std::size_t Size > + vec tan(const vec& xs) { + return map([](T x) { return tan(x); }, xs); + } + + template < typename T, std::size_t Size > + vec asin(const vec& xs) { + return map([](T x) { return asin(x); }, xs); + } + + template < typename T, std::size_t Size > + vec acos(const vec& xs) { + return map([](T x) { return acos(x); }, xs); + } + + template < typename T, std::size_t Size > + vec atan(const vec& xs) { + return map([](T x) { return atan(x); }, xs); + } + + template < typename T, std::size_t Size > + vec atan2(const vec& ys, const vec& xs) { + return zip([](T y, T x) { return atan2(y, x); }, ys, xs); + } + + template < typename T, std::size_t Size > + vec sinh(const vec& xs) { + return map([](T x) { return sinh(x); }, xs); + } + + template < typename T, std::size_t Size > + vec cosh(const vec& xs) { + return map([](T x) { return cosh(x); }, xs); + } + + template < typename T, std::size_t Size > + vec tanh(const vec& xs) { + return map([](T x) { return tanh(x); }, xs); + } + + template < typename T, std::size_t Size > + vec asinh(const vec& xs) { + return map([](T x) { return asinh(x); }, xs); + } + + template < typename T, std::size_t Size > + vec acosh(const vec& xs) { + return map([](T x) { return acosh(x); }, xs); + } + + template < typename T, std::size_t Size > + vec atanh(const vec& xs) { + return map([](T x) { return atanh(x); }, xs); + } +} + +// +// Exponential Functions +// + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + vec pow(const vec& xs, const vec& ys) { + return zip([](T x, T y) { return pow(x, y); }, xs, ys); + } + + template < typename T, std::size_t Size > + vec exp(const vec& xs) { + return map([](T x) { return exp(x); }, xs); + } + + template < typename T, std::size_t Size > + vec log(const vec& xs) { + return map([](T x) { return log(x); }, xs); + } + + template < typename T, std::size_t Size > + vec exp2(const vec& xs) { + return map([](T x) { return exp2(x); }, xs); + } + + template < typename T, std::size_t Size > + vec log2(const vec& xs) { + return map([](T x) { return log2(x); }, xs); + } + + template < typename T, std::size_t Size > + vec sqrt(const vec& xs) { + return map([](T x) { return sqrt(x); }, xs); + } + + template < typename T, std::size_t Size > + vec invsqrt(const vec& xs) { + return map([](T x) { return invsqrt(x); }, xs); + } +} + +// +// Common Functions +// + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + vec abs(const vec& xs) { + return map([](T x) { return abs(x); }, xs); + } + + template < typename T, std::size_t Size > + vec sign(const vec& xs) { + return map([](T x) { return sign(x); }, xs); + } + + template < typename T, std::size_t Size > + vec floor(const vec& xs) { + return map([](T x) { return floor(x); }, xs); + } + + template < typename T, std::size_t Size > + vec trunc(const vec& xs) { + return map([](T x) { return trunc(x); }, xs); + } + + template < typename T, std::size_t Size > + vec round(const vec& xs) { + return map([](T x) { return round(x); }, xs); + } + + template < typename T, std::size_t Size > + vec ceil(const vec& xs) { + return map([](T x) { return ceil(x); }, xs); + } + + template < typename T, std::size_t Size > + vec fract(const vec& xs) { + return map([](T x) { return fract(x); }, xs); + } + + template < typename T, std::size_t Size > + vec fmod(const vec& xs, T y) { + return map([y](T x) { return fmod(x, y); }, xs); + } + + template < typename T, std::size_t Size > + vec fmod(const vec& xs, const vec& ys) { + return zip([](T x, T y) { return fmod(x, y); }, xs, ys); + } + + namespace impl + { + template < typename T, std::size_t Size, std::size_t... Is > + vec modf_impl(const vec& xs, vec* is, std::index_sequence) { + return { modf(xs[Is], &(*is)[Is])... }; + } + } + + template < typename T, std::size_t Size > + vec modf(const vec& xs, vec* is) { + return impl::modf_impl(xs, is, std::make_index_sequence{}); + } + + template < typename T, std::size_t Size > + constexpr vec min(const vec& xs, T y) { + return map([y](T x) { return min(x, y); }, xs); + } + + template < typename T, std::size_t Size > + constexpr vec min(const vec& xs, const vec& ys) { + return zip([](T x, T y) { return min(x, y); }, xs, ys); + } + + template < typename T, std::size_t Size > + constexpr vec max(const vec& xs, T y) { + return map([y](T x) { return max(x, y); }, xs); + } + + template < typename T, std::size_t Size > + constexpr vec max(const vec& xs, const vec& ys) { + return zip([](T x, T y) { return max(x, y); }, xs, ys); + } + + template < typename T, std::size_t Size > + constexpr vec clamp(const vec& xs, T min_x, T max_x) { + return map([min_x, max_x](T x) { return clamp(x, min_x, max_x); }, xs); + } + + template < typename T, std::size_t Size > + constexpr vec clamp(const vec& xs, const vec& min_xs, const vec& max_xs) { + return zip([](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 > + constexpr vec mix(const vec& xs, const vec& ys, T a) { + return zip([a](T x, T y) { return mix(x, y, a); }, xs, ys); + } + + template < typename T, std::size_t Size > + constexpr vec mix(const vec& xs, const vec& ys, bool a) { + return zip([a](T x, T y) { return mix(x, y, a); }, xs, ys); + } + + template < typename T, std::size_t Size > + constexpr vec mix(const vec& xs, const vec& ys, const vec& as) { + return zip([](T x, T y, T a) { return mix(x, y, a); }, xs, ys, as); + } + + template < typename T, std::size_t Size > + constexpr vec mix(const vec& xs, const vec& ys, const vec& as) { + return zip([](T x, T y, bool a) { return mix(x, y, a); }, xs, ys, as); + } + + template < typename T, std::size_t Size > + constexpr vec step(T edge, const vec& xs) { + return map([edge](T x) { return step(edge, x); }, xs); + } + + template < typename T, std::size_t Size > + constexpr vec step(const vec& edges, const vec& xs) { + return zip([](T edge, T x) { return step(edge, x); }, edges, xs); + } + + template < typename T, std::size_t Size > + constexpr vec smoothstep(T edge0, T edge1, const vec& xs) { + return map([edge0, edge1](T x) { return smoothstep(edge0, edge1, x); }, xs); + } + + template < typename T, std::size_t Size > + constexpr vec smoothstep(const vec& edges0, const vec& edges1, const vec& xs) { + return zip([](T edge0, T edge1, T x) { return smoothstep(edge0, edge1, x); }, edges0, edges1, xs); + } + + template < typename T, std::size_t Size > + vec isnan(const vec& xs) { + return map([](T x) { return isnan(x); }, xs); + } + + template < typename T, std::size_t Size > + vec isinf(const vec& xs) { + return map([](T x) { return isinf(x); }, xs); + } + + template < typename T, std::size_t Size > + vec fma(const vec& as, const vec& bs, const vec& cs) { + return zip([](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 > + vec frexp_impl(const vec& xs, vec* exps, std::index_sequence) { + return { frexp(xs.data[Is], &exps->data[Is])... }; + } + } + + template < typename T, std::size_t Size > + vec frexp(const vec& xs, vec* exps) { + return impl::frexp_impl(xs, exps, std::make_index_sequence{}); + } + + template < typename T, std::size_t Size > + vec ldexp(const vec& xs, const vec& exps) { + return zip([](T x, int exp) { return ldexp(x, exp); }, xs, exps); + } +} + +// +// Geometric Functions +// + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + T length(const vec& x) noexcept { + return sqrt(dot(x, x)); + } + + template < typename T, std::size_t Size > + T distance(const vec& p0, const vec& p1) noexcept { + return length(p0 - p1); + } + + template < typename T, std::size_t Size > + constexpr T dot(const vec& x, const vec& y) noexcept { + return fold(std::plus<>(), T(0), zip(std::multiplies<>(), x, y)); + } + + template < typename T > + constexpr vec cross(const vec& x, const vec& y) noexcept { + return { + x.y * y.z - x.z * y.y, + x.z * y.x - x.x * y.z, + x.x * y.y - x.y * y.x}; + } + + template < typename T, std::size_t Size > + vec normalize(const vec& x) noexcept { + return x * invsqrt(dot(x, x)); + } + + template < typename T, std::size_t Size > + vec faceforward(const vec& n, const vec& i, const vec& nref) noexcept { + return dot(nref, i) < T(0) ? n : -n; + } + + template < typename T, std::size_t Size > + vec reflect(const vec& i, const vec& n) noexcept { + return i - n * dot(n, i) * T(2); + } + + template < typename T, std::size_t Size > + vec refract(const vec& i, const vec& n, T eta) noexcept { + const T d = dot(n, i); + const T k = T(1) - eta * eta * (T(1) - d * d); + return T(k >= T(0)) * (eta * i - (eta * d + sqrt(k)) * n); + } +} + +// +// Vector Relational Functions +// + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + constexpr vec less(const vec& x, const vec& y) { + return detail::zip(std::less<>(), x, y); + } + + template < typename T, std::size_t Size > + constexpr vec less_equal(const vec& x, const vec& y) { + return detail::zip(std::less_equal<>(), x, y); + } + + template < typename T, std::size_t Size > + constexpr vec greater(const vec& x, const vec& y) { + return detail::zip(std::greater<>(), x, y); + } + + template < typename T, std::size_t Size > + constexpr vec greater_equal(const vec& x, const vec& y) { + return detail::zip(std::greater_equal<>(), x, y); + } + + template < typename T, std::size_t Size > + constexpr vec equal_to(const vec& x, const vec& y) { + return detail::zip(std::equal_to<>(), x, y); + } + + template < typename T, std::size_t Size > + constexpr vec not_equal_to(const vec& x, const vec& y) { + return detail::zip(std::not_equal_to<>(), x, y); + } + + template < std::size_t Size > + constexpr bool any(const vec& x) { + return detail::fold(std::logical_or<>(), false, x); + } + + template < std::size_t Size > + constexpr bool all(const vec& x) { + return detail::fold(std::logical_and<>(), true, x); + } + + template < std::size_t Size > + constexpr vec not_(const vec& x) { + return detail::map(std::logical_not<>(), x); + } +} diff --git a/headers/vmath.hpp/vmath_vec_ops.hpp b/headers/vmath.hpp/vmath_vec_ops.hpp deleted file mode 100644 index a20bfd5..0000000 --- a/headers/vmath.hpp/vmath_vec_ops.hpp +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * 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, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "vmath_fwd.hpp" -#include "vmath_vec.hpp" - -namespace vmath_hpp::detail -{ - template < typename T, std::size_t Size, typename F > - constexpr auto map(const vec& v, F&& f) { - vec, Size> result; - for ( std::size_t i = 0; i < Size; ++i ) { - result[i] = f(v[i]); - } - return result; - } - - template < typename T, typename U, std::size_t Size, typename F > - constexpr auto zip(const vec& l, const vec& r, F&& f) { - vec, Size> result; - for ( std::size_t i = 0; i < Size; ++i ) { - result[i] = f(l[i], r[i]); - } - return result; - } - - template < typename T, typename U, std::size_t Size, typename F > - constexpr auto fold(const vec& v, U init, F&& f) { - for ( std::size_t i = 0; i < Size; ++i ) { - init = f(init, v[i]); - } - return init; - } -} - -// -// Vector Relational Functions -// - -namespace vmath_hpp -{ - template < typename T, std::size_t Size > - constexpr vec less(const vec& x, const vec& y) { - return detail::zip(x, y, std::less<>()); - } - - template < typename T, std::size_t Size > - constexpr vec less_equal(const vec& x, const vec& y) { - return detail::zip(x, y, std::less_equal<>()); - } - - template < typename T, std::size_t Size > - constexpr vec greater(const vec& x, const vec& y) { - return detail::zip(x, y, std::greater<>()); - } - - template < typename T, std::size_t Size > - constexpr vec greater_equal(const vec& x, const vec& y) { - return detail::zip(x, y, std::greater_equal<>()); - } - - template < typename T, std::size_t Size > - constexpr vec equal(const vec& x, const vec& y) { - return detail::zip(x, y, std::equal_to<>()); - } - - template < typename T, std::size_t Size > - constexpr vec not_equal(const vec& x, const vec& y) { - return detail::zip(x, y, std::not_equal_to<>()); - } - - template < std::size_t Size > - constexpr bool any(const vec& x) { - return detail::fold(x, false, std::logical_or<>()); - } - - template < std::size_t Size > - constexpr bool all(const vec& x) { - return detail::fold(x, true, std::logical_and<>()); - } - - template < std::size_t Size > - constexpr vec not_(const vec& x) { - return detail::map(x, std::logical_not<>()); - } -} diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp new file mode 100644 index 0000000..b1b5730 --- /dev/null +++ b/untests/vmath_vec_fun_tests.cpp @@ -0,0 +1,205 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include + +#define CATCH_CONFIG_FAST_COMPILE +#include + +namespace +{ + using namespace vmath_hpp; + + template < typename T > + class approx2 { + public: + constexpr explicit approx2(T v) : value_(v) {} + constexpr explicit approx2(T x, T y) : value_(x, y) {} + + friend constexpr bool operator==(const vec& l, const approx2& r) { + return (r.value_.x < l.x + epsilon) + && (l.x < r.value_.x + epsilon) + && (r.value_.y < l.y + epsilon) + && (l.y < r.value_.y + epsilon); + } + private: + vec value_; + static constexpr T epsilon = std::numeric_limits::epsilon() * 100; + }; + + template < typename T > + class approx3 { + public: + constexpr explicit approx3(T v) : value_(v) {} + constexpr explicit approx3(T x, T y, T z) : value_(x, y, z) {} + + friend constexpr bool operator==(const vec& l, const approx3& r) { + return (r.value_.x < l.x + epsilon) + && (l.x < r.value_.x + epsilon) + && (r.value_.y < l.y + epsilon) + && (l.y < r.value_.y + epsilon) + && (r.value_.z < l.z + epsilon) + && (l.z < r.value_.z + epsilon); + } + private: + vec value_; + static constexpr T epsilon = std::numeric_limits::epsilon() * 100; + }; +} + +TEST_CASE("vmath/vec_fun") { + SECTION("Operators") { + STATIC_REQUIRE(-vec2i(1,-2) == vec2i(-1,2)); + + STATIC_REQUIRE(vec2i(1,2) + 3 == vec2i(4,5)); + STATIC_REQUIRE(vec2i(1,2) - 3 == vec2i(-2,-1)); + STATIC_REQUIRE(vec2i(1,2) * 3 == vec2i(3,6)); + STATIC_REQUIRE(vec2i(2,4) / 2 == vec2i(1,2)); + + STATIC_REQUIRE(3 + vec2i(1,2) == vec2i(4,5)); + STATIC_REQUIRE(3 - vec2i(1,2) == vec2i(2,1)); + STATIC_REQUIRE(3 * vec2i(1,2) == vec2i(3,6)); + STATIC_REQUIRE(4 / vec2i(2,4) == vec2i(2,1)); + + STATIC_REQUIRE(vec2i(1,2) + vec2i(3,4) == vec2i(4,6)); + STATIC_REQUIRE(vec2i(1,2) - vec2i(3,4) == vec2i(-2,-2)); + STATIC_REQUIRE(vec2i(1,2) * vec2i(3,4) == vec2i(3,8)); + STATIC_REQUIRE(vec2i(3,4) / vec2i(1,2) == vec2i(3,2)); + } + + SECTION("Angle and Trigonometry Functions") { + STATIC_REQUIRE(radians(degrees(vec2f(12.13f))) == approx2(12.13f)); + STATIC_REQUIRE(degrees(radians(vec2f(12.13f))) == approx2(12.13f)); + + sin(vec2f(1.f)); + cos(vec2f(1.f)); + tan(vec2f(1.f)); + + asin(vec2f(1.f)); + acos(vec2f(1.f)); + atan(vec2f(1.f)); + atan2(vec2f(1.f), vec2f(1.f)); + + sinh(vec2f(1.f)); + cosh(vec2f(1.f)); + tanh(vec2f(1.f)); + + asinh(vec2f(1.f)); + acosh(vec2f(1.f)); + atanh(vec2f(1.f)); + } + + SECTION("Exponential Functions") { + pow(vec2f(1.f), vec2f(2.f)); + exp(vec2f(1.f)); + log(vec2f(1.f)); + exp2(vec2f(1.f)); + log2(vec2f(1.f)); + sqrt(vec2f(1.f)); + invsqrt(vec2f(1.f)); + } + + SECTION("Common Functions") { + REQUIRE(abs(vec2f(1.f, -1.f)) == approx2(1.f,1.f)); + REQUIRE(sign(vec3f(1.f, -1.f, 0.f)) == approx3(1.f,-1.f,0.f)); + + floor(vec2f(1.f, -1.f)); + trunc(vec2f(1.f, -1.f)); + round(vec2f(1.f, -1.f)); + ceil(vec2f(1.f, -1.f)); + fract(vec2f(1.f, -1.f)); + + REQUIRE(fmod(vec2f(1.7f), 1.2f) == approx2(0.5f)); + REQUIRE(fmod(vec2f(1.7f), vec2f(1.2f)) == approx2(0.5f)); + + { + vec2f out_i{}; + REQUIRE(modf(vec2f(1.7f), &out_i) == approx2(0.7f)); + REQUIRE(out_i.x == Approx(1.f)); + } + + STATIC_REQUIRE(min(vec2i(1,2), 1) == vec2i(1,1)); + STATIC_REQUIRE(min(vec2i(1,1), vec2i(0,2)) == vec2i(0,1)); + + STATIC_REQUIRE(max(vec2i(1,2), 1) == vec2i(1,2)); + STATIC_REQUIRE(max(vec2i(1,1), vec2i(0,2)) == vec2i(1,2)); + + STATIC_REQUIRE(clamp(vec2i(1,2), 0, 1) == vec2i(1,1)); + STATIC_REQUIRE(clamp(vec2i(1,2), vec2i(0), vec2i(1)) == vec2i(1,1)); + + STATIC_REQUIRE(mix(vec2f(0.f), vec2f(10.f), 0.5f) == approx2(5.f)); + STATIC_REQUIRE(mix(vec2f(0.f), vec2f(10.f), vec2f(0.5f)) == approx2(5.f)); + + STATIC_REQUIRE(mix(vec2f(0.f), vec2f(10.f), true) == approx2(10.f)); + STATIC_REQUIRE(mix(vec2f(0.f), vec2f(10.f), false) == approx2(0.f)); + + STATIC_REQUIRE(mix(vec2f(0.f,5.f), vec2f(10.f,20.f), vec2f(true,false)) == approx2(10.f, 5.f)); + STATIC_REQUIRE(mix(vec2f(0.f,5.f), vec2f(10.f,20.f), vec2f(true,false)) == approx2(10.f, 5.f)); + + STATIC_REQUIRE(step(0.5f, vec2f(0.4f)) == approx2(0.f)); + STATIC_REQUIRE(step(0.5f, vec2f(0.6f)) == approx2(1.f)); + STATIC_REQUIRE(step(vec2f(0.5f), vec2f(0.4f)) == approx2(0.f)); + STATIC_REQUIRE(step(vec2f(0.5f), vec2f(0.6f)) == approx2(1.f)); + + STATIC_REQUIRE(smoothstep(0.f, 1.f, vec2f(0.1f)) == approx2(0.028f)); + STATIC_REQUIRE(smoothstep(vec2f(0.f), vec2f(1.f), vec2f(0.1f)) == approx2(0.028f)); + + REQUIRE_FALSE(isnan(vec2f(1.f)).x); + REQUIRE_FALSE(isinf(vec2f(1.f)).x); + + REQUIRE_FALSE(fma(vec2f(2.f), vec2f(3.f), vec2f(4.f)).x == Approx(12.f)); + + { + vec2i out_exp{}; + REQUIRE(frexp(vec2f(1.7f), &out_exp).x == Approx(0.85f)); + REQUIRE(out_exp == vec2i(1)); + } + + REQUIRE(ldexp(vec2f(0.85f), vec2i(1)).x == Approx(1.7f)); + } + + SECTION("Geometric Functions") { + REQUIRE(length(vec2f(10.f,0.f)) == Approx(10.f)); + REQUIRE(length(vec2f(-10.f,0.f)) == Approx(10.f)); + + REQUIRE(distance(vec2f(5.f,0.f), vec2f(10.f,0.f)) == Approx(5.f)); + REQUIRE(distance(vec2f(-5.f,0.f), vec2f(-10.f,0.f)) == Approx(5.f)); + + STATIC_REQUIRE(dot(vec2i(1,2),vec2i(3,4)) == 11); + STATIC_REQUIRE(cross(vec3i(1,0,0),vec3i(0,1,0)) == vec3i(0,0,1)); + REQUIRE(normalize(vec2f(0.5f,0.f)).x == Approx(1.f)); + + REQUIRE(faceforward(vec2f(1.f), vec2f(2.f), vec2f(3.f)).x == Approx(-1.f)); + REQUIRE(reflect(vec2f(1.f), vec2f(2.f)).x == Approx(-15.f)); + REQUIRE(refract(vec2f(1.f), vec2f(2.f), 1.f).x == Approx(-15.f)); + } + + SECTION("Vector Relational Functions") { + STATIC_REQUIRE(less(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(false, false, true)); + STATIC_REQUIRE(less_equal(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(false, true, true)); + + STATIC_REQUIRE(greater(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(true, false, false)); + STATIC_REQUIRE(greater_equal(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(true, true, false)); + + STATIC_REQUIRE(equal_to(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(false, true, false)); + STATIC_REQUIRE(not_equal_to(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(true, false, true)); + + STATIC_REQUIRE_FALSE(any(vec2b(false, false))); + STATIC_REQUIRE(any(vec2b(true, false))); + STATIC_REQUIRE(any(vec2b(false, true))); + STATIC_REQUIRE(any(vec2b(true, true))); + + STATIC_REQUIRE_FALSE(all(vec2b(false, false))); + STATIC_REQUIRE_FALSE(all(vec2b(true, false))); + STATIC_REQUIRE_FALSE(all(vec2b(false, true))); + STATIC_REQUIRE(all(vec2b(true, true))); + + STATIC_REQUIRE(not_(vec2b(false, false)) == vec2b(true, true)); + STATIC_REQUIRE(not_(vec2b(true, false)) == vec2b(false, true)); + STATIC_REQUIRE(not_(vec2b(false, true)) == vec2b(true, false)); + STATIC_REQUIRE(not_(vec2b(true, true)) == vec2b(false, false)); + } +} diff --git a/untests/vmath_vec_ops_tests.cpp b/untests/vmath_vec_ops_tests.cpp deleted file mode 100644 index 92bb3c3..0000000 --- a/untests/vmath_vec_ops_tests.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * 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, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#include - -#define CATCH_CONFIG_FAST_COMPILE -#include - -namespace -{ -} - -TEST_CASE("vmath/vec_ops") { - using namespace vmath_hpp; - - SECTION("Vector Relational Functions") { - STATIC_REQUIRE(less(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(false, false, true)); - STATIC_REQUIRE(less_equal(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(false, true, true)); - - STATIC_REQUIRE(greater(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(true, false, false)); - STATIC_REQUIRE(greater_equal(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(true, true, false)); - - STATIC_REQUIRE(equal(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(false, true, false)); - STATIC_REQUIRE(not_equal(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(true, false, true)); - - STATIC_REQUIRE_FALSE(any(vec2b(false, false))); - STATIC_REQUIRE(any(vec2b(true, false))); - STATIC_REQUIRE(any(vec2b(false, true))); - STATIC_REQUIRE(any(vec2b(true, true))); - - STATIC_REQUIRE_FALSE(all(vec2b(false, false))); - STATIC_REQUIRE_FALSE(all(vec2b(true, false))); - STATIC_REQUIRE_FALSE(all(vec2b(false, true))); - STATIC_REQUIRE(all(vec2b(true, true))); - - STATIC_REQUIRE(not_(vec2b(false, false)) == vec2b(true, true)); - STATIC_REQUIRE(not_(vec2b(true, false)) == vec2b(false, true)); - STATIC_REQUIRE(not_(vec2b(false, true)) == vec2b(true, false)); - STATIC_REQUIRE(not_(vec2b(true, true)) == vec2b(false, false)); - } -} From a14f719e219d58683e611b0584c0335f446290e7 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Mon, 23 Nov 2020 06:39:06 +0700 Subject: [PATCH 13/53] remove union data --- headers/vmath.hpp/vmath.hpp | 1 + headers/vmath.hpp/vmath_fun.hpp | 2 +- headers/vmath.hpp/vmath_mat.hpp | 33 +--------- headers/vmath.hpp/vmath_mat_fun.hpp | 47 ++++++++++++++ headers/vmath.hpp/vmath_vec.hpp | 97 +++++------------------------ headers/vmath.hpp/vmath_vec_fun.hpp | 47 +++++++++++--- untests/vmath_fun_tests.cpp | 40 ++++++------ untests/vmath_mat_fun_tests.cpp | 18 ++++++ untests/vmath_mat_tests.cpp | 1 + untests/vmath_vec_fun_tests.cpp | 50 +++++++-------- untests/vmath_vec_tests.cpp | 1 + 11 files changed, 170 insertions(+), 167 deletions(-) create mode 100644 headers/vmath.hpp/vmath_mat_fun.hpp create mode 100644 untests/vmath_mat_fun_tests.cpp diff --git a/headers/vmath.hpp/vmath.hpp b/headers/vmath.hpp/vmath.hpp index 25faaf7..770ce34 100644 --- a/headers/vmath.hpp/vmath.hpp +++ b/headers/vmath.hpp/vmath.hpp @@ -8,5 +8,6 @@ #include "vmath_fun.hpp" #include "vmath_mat.hpp" +#include "vmath_mat_fun.hpp" #include "vmath_vec.hpp" #include "vmath_vec_fun.hpp" diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index de6146e..7992d8b 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -71,7 +71,7 @@ namespace vmath_hpp template < typename T > T sign(T x) noexcept { - return (T(0) < x) - (x < T(0)); + return static_cast((T(0) < x) - (x < T(0))); } using ::std::floor; diff --git a/headers/vmath.hpp/vmath_mat.hpp b/headers/vmath.hpp/vmath_mat.hpp index 67bf6b6..d9f3972 100644 --- a/headers/vmath.hpp/vmath_mat.hpp +++ b/headers/vmath.hpp/vmath_mat.hpp @@ -7,7 +7,9 @@ #pragma once #include "vmath_fwd.hpp" + #include "vmath_vec.hpp" +#include "vmath_vec_fun.hpp" namespace vmath_hpp::detail { @@ -220,34 +222,3 @@ namespace vmath_hpp l.swap(r); } } - -namespace vmath_hpp -{ - template < typename T, std::size_t Size > - constexpr bool operator==(const mat& l, const mat& r) { - for ( std::size_t i = 0; i < Size; ++i ) { - if ( !(l[i] == r[i]) ) { - return false; - } - } - return true; - } - - template < typename T, std::size_t Size > - constexpr bool operator!=(const mat& l, const mat& r) { - return !(l == r); - } - - template < typename T, std::size_t Size > - constexpr bool operator<(const mat& l, const mat& r) { - for ( std::size_t i = 0; i < Size; ++i ) { - if ( l[i] < r[i] ) { - return true; - } - if ( r[i] < l[i] ) { - return false; - } - } - return false; - } -} diff --git a/headers/vmath.hpp/vmath_mat_fun.hpp b/headers/vmath.hpp/vmath_mat_fun.hpp new file mode 100644 index 0000000..c194f7a --- /dev/null +++ b/headers/vmath.hpp/vmath_mat_fun.hpp @@ -0,0 +1,47 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "vmath_fwd.hpp" + +#include "vmath_fun.hpp" +#include "vmath_mat.hpp" + +// +// Operators +// + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + constexpr bool operator==(const mat& l, const mat& r) { + for ( std::size_t i = 0; i < Size; ++i ) { + if ( !(l[i] == r[i]) ) { + return false; + } + } + return true; + } + + template < typename T, std::size_t Size > + constexpr bool operator!=(const mat& l, const mat& r) { + return !(l == r); + } + + template < typename T, std::size_t Size > + constexpr bool operator<(const mat& l, const mat& r) { + for ( std::size_t i = 0; i < Size; ++i ) { + if ( l[i] < r[i] ) { + return true; + } + if ( r[i] < l[i] ) { + return false; + } + } + return false; + } +} diff --git a/headers/vmath.hpp/vmath_vec.hpp b/headers/vmath.hpp/vmath_vec.hpp index 2f2aafd..5f14307 100644 --- a/headers/vmath.hpp/vmath_vec.hpp +++ b/headers/vmath.hpp/vmath_vec.hpp @@ -8,18 +8,6 @@ #include "vmath_fwd.hpp" -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wpedantic" -#elif defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wgnu-anonymous-struct" -# pragma clang diagnostic ignored "-Wnested-anon-types" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4201) -#endif - namespace vmath_hpp::detail { template < typename T, std::size_t Size > @@ -28,13 +16,9 @@ namespace vmath_hpp::detail template < typename T > class vec_base { public: - union { - struct { T x, y; }; - T data[2]; - }; + T x{}, y{}; public: - constexpr vec_base() - : x{0}, y{0} {} + vec_base() = default; constexpr explicit vec_base(T v) : x{v}, y{v} {} @@ -43,10 +27,10 @@ namespace vmath_hpp::detail : x{x}, y{y} {} constexpr explicit vec_base(const vec_base& xy) - : x{xy.x}, y{xy.y} {} + : x{xy[0]}, y{xy[1]} {} constexpr explicit vec_base(const vec_base& xy) - : x{xy.x}, y{xy.y} {} + : x{xy[0]}, y{xy[1]} {} constexpr T& operator[](std::size_t index) noexcept { switch ( index ) { @@ -68,13 +52,9 @@ namespace vmath_hpp::detail template < typename T > class vec_base { public: - union { - struct { T x, y, z; }; - T data[3]; - }; + T x{}, y{}, z{}; public: - constexpr vec_base() - : x{0}, y{0}, z{0} {} + vec_base() = default; constexpr explicit vec_base(T v) : x{v}, y{v}, z{v} {} @@ -83,13 +63,13 @@ namespace vmath_hpp::detail : x{x}, y{y}, z{z} {} constexpr vec_base(const vec_base& xy, T z) - : x{xy.x}, y{xy.y}, z{z} {} + : x{xy[0]}, y{xy[1]}, z{z} {} constexpr vec_base(T x, const vec_base& yz) - : x{x}, y{yz.x}, z{yz.y} {} + : x{x}, y{yz[0]}, z{yz[1]} {} constexpr explicit vec_base(const vec_base& xyz) - : x{xyz.x}, y{xyz.y}, z{xyz.z} {} + : x{xyz[0]}, y{xyz[1]}, z{xyz[2]} {} constexpr T& operator[](std::size_t index) noexcept { switch ( index ) { @@ -113,13 +93,9 @@ namespace vmath_hpp::detail template < typename T > class vec_base { public: - union { - struct { T x, y, z, w; }; - T data[4]; - }; + T x{}, y{}, z{}, w{}; public: - constexpr vec_base() - : x{0}, y{0}, z{0}, w{0} {} + vec_base() = default; constexpr explicit vec_base(T v) : x{v}, y{v}, z{v}, w{v} {} @@ -128,22 +104,22 @@ namespace vmath_hpp::detail : x{x}, y{y}, z{z}, w{w} {} constexpr vec_base(const vec_base& xy, T z, T w) - : x{xy.x}, y{xy.y}, z{z}, w{w} {} + : x{xy[0]}, y{xy[1]}, z{z}, w{w} {} constexpr vec_base(T x, const vec_base& yz, T w) - : x{x}, y{yz.x}, z{yz.y}, w{w} {} + : x{x}, y{yz[0]}, z{yz[1]}, w{w} {} constexpr vec_base(T x, T y, const vec_base& zw) - : x{x}, y{y}, z{zw.x}, w{zw.y} {} + : x{x}, y{y}, z{zw[0]}, w{zw[1]} {} constexpr vec_base(const vec_base& xy, const vec_base& zw) - : x{xy.x}, y{xy.y}, z{zw.x}, w{zw.y} {} + : x{xy[0]}, y{xy[1]}, z{zw[0]}, w{zw[1]} {} constexpr vec_base(const vec_base& xyz, T w) - : x{xyz.x}, y{xyz.y}, z{xyz.z}, w{w} {} + : x{xyz[0]}, y{xyz[1]}, z{xyz[2]}, w{w} {} constexpr vec_base(T x, const vec_base& yzw) - : x{x}, y{yzw.x}, z{yzw.y}, w{yzw.z} {} + : x{x}, y{yzw[0]}, z{yzw[1]}, w{yzw[2]} {} constexpr T& operator[](std::size_t index) noexcept { switch ( index ) { @@ -167,14 +143,6 @@ namespace vmath_hpp::detail }; } -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif - namespace vmath_hpp { template < typename T, std::size_t Size > @@ -231,34 +199,3 @@ namespace vmath_hpp l.swap(r); } } - -namespace vmath_hpp -{ - template < typename T, std::size_t Size > - constexpr bool operator==(const vec& l, const vec& r) { - for ( std::size_t i = 0; i < Size; ++i ) { - if ( !(l[i] == r[i]) ) { - return false; - } - } - return true; - } - - template < typename T, std::size_t Size > - constexpr bool operator!=(const vec& l, const vec& r) { - return !(l == r); - } - - template < typename T, std::size_t Size > - constexpr bool operator<(const vec& l, const vec& r) { - for ( std::size_t i = 0; i < Size; ++i ) { - if ( l[i] < r[i] ) { - return true; - } - if ( r[i] < l[i] ) { - return false; - } - } - return false; - } -} diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index c605411..9cad825 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -145,6 +145,33 @@ namespace vmath_hpp constexpr vec operator/(const vec& xs, const vec& ys) { return zip(std::divides<>(), xs, ys); } + + // operator== + + template < typename T, std::size_t Size > + constexpr bool operator==(const vec& xs, const vec& ys) { + return all(zip(std::equal_to<>(), xs, ys)); + } + + template < typename T, std::size_t Size > + constexpr bool operator!=(const vec& xs, const vec& ys) { + return any(zip(std::not_equal_to<>(), xs, ys)); + } + + // operator< + + template < typename T, std::size_t Size > + constexpr bool operator<(const vec& l, const vec& r) { + for ( std::size_t i = 0; i < Size; ++i ) { + if ( l[i] < r[i] ) { + return true; + } + if ( r[i] < l[i] ) { + return false; + } + } + return false; + } } // @@ -424,7 +451,7 @@ namespace vmath_hpp { template < typename T, std::size_t Size, std::size_t... Is > vec frexp_impl(const vec& xs, vec* exps, std::index_sequence) { - return { frexp(xs.data[Is], &exps->data[Is])... }; + return { frexp(xs[Is], &(*exps)[Is])... }; } } @@ -499,46 +526,46 @@ namespace vmath_hpp { template < typename T, std::size_t Size > constexpr vec less(const vec& x, const vec& y) { - return detail::zip(std::less<>(), x, y); + return zip(std::less<>(), x, y); } template < typename T, std::size_t Size > constexpr vec less_equal(const vec& x, const vec& y) { - return detail::zip(std::less_equal<>(), x, y); + return zip(std::less_equal<>(), x, y); } template < typename T, std::size_t Size > constexpr vec greater(const vec& x, const vec& y) { - return detail::zip(std::greater<>(), x, y); + return zip(std::greater<>(), x, y); } template < typename T, std::size_t Size > constexpr vec greater_equal(const vec& x, const vec& y) { - return detail::zip(std::greater_equal<>(), x, y); + return zip(std::greater_equal<>(), x, y); } template < typename T, std::size_t Size > constexpr vec equal_to(const vec& x, const vec& y) { - return detail::zip(std::equal_to<>(), x, y); + return zip(std::equal_to<>(), x, y); } template < typename T, std::size_t Size > constexpr vec not_equal_to(const vec& x, const vec& y) { - return detail::zip(std::not_equal_to<>(), x, y); + return zip(std::not_equal_to<>(), x, y); } template < std::size_t Size > constexpr bool any(const vec& x) { - return detail::fold(std::logical_or<>(), false, x); + return fold(std::logical_or<>(), false, x); } template < std::size_t Size > constexpr bool all(const vec& x) { - return detail::fold(std::logical_and<>(), true, x); + return fold(std::logical_and<>(), true, x); } template < std::size_t Size > constexpr vec not_(const vec& x) { - return detail::map(std::logical_not<>(), x); + return map(std::logical_not<>(), x); } } diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index 715bc58..ca23017 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -33,32 +33,32 @@ TEST_CASE("vmath/fun") { STATIC_REQUIRE(radians(degrees(12.13f)) == approx(12.13f)); STATIC_REQUIRE(degrees(radians(12.13f)) == approx(12.13f)); - sin(0.f); - cos(0.f); - tan(0.f); + (void)sin(0.f); + (void)cos(0.f); + (void)tan(0.f); - asin(0.f); - acos(0.f); - atan(0.f); - atan2(0.f, 0.f); + (void)asin(0.f); + (void)acos(0.f); + (void)atan(0.f); + (void)atan2(0.f, 0.f); - sinh(0.f); - cosh(0.f); - tanh(0.f); + (void)sinh(0.f); + (void)cosh(0.f); + (void)tanh(0.f); - asinh(0.f); - acosh(0.f); - atanh(0.f); + (void)asinh(0.f); + (void)acosh(0.f); + (void)atanh(0.f); } SECTION("Exponential Functions") { - pow(2.f, 3.f); - exp(2.f); - log(2.f); - exp2(2.f); - log2(2.f); - sqrt(2.f); - invsqrt(2.f); + (void)pow(2.f, 3.f); + (void)exp(2.f); + (void)log(2.f); + (void)exp2(2.f); + (void)log2(2.f); + (void)sqrt(2.f); + (void)invsqrt(2.f); } SECTION("Common Functions") { diff --git a/untests/vmath_mat_fun_tests.cpp b/untests/vmath_mat_fun_tests.cpp new file mode 100644 index 0000000..603955d --- /dev/null +++ b/untests/vmath_mat_fun_tests.cpp @@ -0,0 +1,18 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include + +#define CATCH_CONFIG_FAST_COMPILE +#include + +namespace +{ +} + +TEST_CASE("vmath/mat_fun") { + using namespace vmath_hpp; +} diff --git a/untests/vmath_mat_tests.cpp b/untests/vmath_mat_tests.cpp index 00ce90f..06860b9 100644 --- a/untests/vmath_mat_tests.cpp +++ b/untests/vmath_mat_tests.cpp @@ -5,6 +5,7 @@ ******************************************************************************/ #include +#include #define CATCH_CONFIG_FAST_COMPILE #include diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index b1b5730..c90660d 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -74,43 +74,43 @@ TEST_CASE("vmath/vec_fun") { STATIC_REQUIRE(radians(degrees(vec2f(12.13f))) == approx2(12.13f)); STATIC_REQUIRE(degrees(radians(vec2f(12.13f))) == approx2(12.13f)); - sin(vec2f(1.f)); - cos(vec2f(1.f)); - tan(vec2f(1.f)); + (void)sin(vec2f(1.f)); + (void)cos(vec2f(1.f)); + (void)tan(vec2f(1.f)); - asin(vec2f(1.f)); - acos(vec2f(1.f)); - atan(vec2f(1.f)); - atan2(vec2f(1.f), vec2f(1.f)); + (void)asin(vec2f(1.f)); + (void)acos(vec2f(1.f)); + (void)atan(vec2f(1.f)); + (void)atan2(vec2f(1.f), vec2f(1.f)); - sinh(vec2f(1.f)); - cosh(vec2f(1.f)); - tanh(vec2f(1.f)); + (void)sinh(vec2f(1.f)); + (void)cosh(vec2f(1.f)); + (void)tanh(vec2f(1.f)); - asinh(vec2f(1.f)); - acosh(vec2f(1.f)); - atanh(vec2f(1.f)); + (void)asinh(vec2f(1.f)); + (void)acosh(vec2f(1.f)); + (void)atanh(vec2f(1.f)); } SECTION("Exponential Functions") { - pow(vec2f(1.f), vec2f(2.f)); - exp(vec2f(1.f)); - log(vec2f(1.f)); - exp2(vec2f(1.f)); - log2(vec2f(1.f)); - sqrt(vec2f(1.f)); - invsqrt(vec2f(1.f)); + (void)pow(vec2f(1.f), vec2f(2.f)); + (void)exp(vec2f(1.f)); + (void)log(vec2f(1.f)); + (void)exp2(vec2f(1.f)); + (void)log2(vec2f(1.f)); + (void)sqrt(vec2f(1.f)); + (void)invsqrt(vec2f(1.f)); } SECTION("Common Functions") { REQUIRE(abs(vec2f(1.f, -1.f)) == approx2(1.f,1.f)); REQUIRE(sign(vec3f(1.f, -1.f, 0.f)) == approx3(1.f,-1.f,0.f)); - floor(vec2f(1.f, -1.f)); - trunc(vec2f(1.f, -1.f)); - round(vec2f(1.f, -1.f)); - ceil(vec2f(1.f, -1.f)); - fract(vec2f(1.f, -1.f)); + (void)floor(vec2f(1.f, -1.f)); + (void)trunc(vec2f(1.f, -1.f)); + (void)round(vec2f(1.f, -1.f)); + (void)ceil(vec2f(1.f, -1.f)); + (void)fract(vec2f(1.f, -1.f)); REQUIRE(fmod(vec2f(1.7f), 1.2f) == approx2(0.5f)); REQUIRE(fmod(vec2f(1.7f), vec2f(1.2f)) == approx2(0.5f)); diff --git a/untests/vmath_vec_tests.cpp b/untests/vmath_vec_tests.cpp index 8b0a985..5129d58 100644 --- a/untests/vmath_vec_tests.cpp +++ b/untests/vmath_vec_tests.cpp @@ -5,6 +5,7 @@ ******************************************************************************/ #include +#include #define CATCH_CONFIG_FAST_COMPILE #include From d0b72f75365b172848cfd0f037d5c5876fe2ed08 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 24 Nov 2020 04:07:39 +0700 Subject: [PATCH 14/53] vector zip_fold operator== --- headers/vmath.hpp/vmath_fun.hpp | 4 +- headers/vmath.hpp/vmath_vec_fun.hpp | 110 ++++++++++++++++------------ 2 files changed, 65 insertions(+), 49 deletions(-) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index 7992d8b..3ea4c4a 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -136,8 +136,8 @@ namespace vmath_hpp } template < typename T > - T distance(T p0, T p1) noexcept { - return length(p0 - p1); + T distance(T x, T y) noexcept { + return length(x - y); } template < typename T > diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index 9cad825..bc77b64 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -16,10 +16,10 @@ namespace vmath_hpp::detail namespace impl { template < typename A, std::size_t Size, typename F, std::size_t... Is > - constexpr auto map_impl(F&& f, const vec& v, std::index_sequence) + constexpr auto map_impl(F&& f, const vec& a, std::index_sequence) -> vec, Size> { - return { f(v[Is])... }; + return { f(a[Is])... }; } template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > @@ -37,16 +37,23 @@ namespace vmath_hpp::detail } template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > - constexpr auto fold_impl(F&& f, A init, const vec& v, std::index_sequence) + constexpr auto fold_impl(F&& f, A init, const vec& b, std::index_sequence) -> A { - return ((init = f(std::move(init), v[Is])), ...); + return ((init = f(std::move(init), b[Is])), ...); + } + + template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > + constexpr auto fold_impl(F&& f, A init, const vec& b, const vec& c, std::index_sequence) + -> A + { + return ((init = f(std::move(init), b[Is], c[Is])), ...); } } - template < typename T, std::size_t Size, typename F > - constexpr auto map(F&& f, const vec& v) { - return impl::map_impl(std::forward(f), v, std::make_index_sequence{}); + template < typename A, std::size_t Size, typename F > + constexpr auto map(F&& f, const vec& a) { + return impl::map_impl(std::forward(f), a, std::make_index_sequence{}); } template < typename A, typename B, std::size_t Size, typename F > @@ -60,8 +67,13 @@ namespace vmath_hpp::detail } template < typename A, typename B, std::size_t Size, typename F > - constexpr auto fold(F&& f, A init, const vec& v) { - return impl::fold_impl(std::forward(f), std::move(init), v, std::make_index_sequence{}); + constexpr auto fold(F&& f, A init, const vec& b) { + return impl::fold_impl(std::forward(f), std::move(init), b, std::make_index_sequence{}); + } + + template < typename A, typename B, typename C, std::size_t Size, typename F > + constexpr auto fold(F&& f, A init, const vec& b, const vec& c) { + return impl::fold_impl(std::forward(f), std::move(init), b, c, std::make_index_sequence{}); } } @@ -150,23 +162,27 @@ namespace vmath_hpp template < typename T, std::size_t Size > constexpr bool operator==(const vec& xs, const vec& ys) { - return all(zip(std::equal_to<>(), xs, ys)); + return fold([](bool acc, T x, T y){ + return acc && (x == y); + }, true, xs, ys); } template < typename T, std::size_t Size > constexpr bool operator!=(const vec& xs, const vec& ys) { - return any(zip(std::not_equal_to<>(), xs, ys)); + return fold([](bool acc, T x, T y){ + return acc || (x != y); + }, false, xs, ys); } // operator< template < typename T, std::size_t Size > - constexpr bool operator<(const vec& l, const vec& r) { + constexpr bool operator<(const vec& xs, const vec& ys) { for ( std::size_t i = 0; i < Size; ++i ) { - if ( l[i] < r[i] ) { + if ( xs[i] < ys[i] ) { return true; } - if ( r[i] < l[i] ) { + if ( ys[i] < xs[i] ) { return false; } } @@ -473,45 +489,45 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T, std::size_t Size > - T length(const vec& x) noexcept { - return sqrt(dot(x, x)); + T length(const vec& xs) { + return sqrt(dot(xs, xs)); } template < typename T, std::size_t Size > - T distance(const vec& p0, const vec& p1) noexcept { - return length(p0 - p1); + T distance(const vec& xs, const vec& ys) { + return length(xs - ys); } template < typename T, std::size_t Size > - constexpr T dot(const vec& x, const vec& y) noexcept { - return fold(std::plus<>(), T(0), zip(std::multiplies<>(), x, y)); + constexpr T dot(const vec& xs, const vec& ys) { + return fold(std::plus<>(), T(0), zip(std::multiplies<>(), xs, ys)); } template < typename T > - constexpr vec cross(const vec& x, const vec& y) noexcept { + constexpr vec cross(const vec& xs, const vec& ys) { return { - x.y * y.z - x.z * y.y, - x.z * y.x - x.x * y.z, - x.x * y.y - x.y * y.x}; + xs.y * ys.z - xs.z * ys.y, + xs.z * ys.x - xs.x * ys.z, + xs.x * ys.y - xs.y * ys.x}; } template < typename T, std::size_t Size > - vec normalize(const vec& x) noexcept { - return x * invsqrt(dot(x, x)); + vec normalize(const vec& xs) { + return xs * invsqrt(dot(xs, xs)); } template < typename T, std::size_t Size > - vec faceforward(const vec& n, const vec& i, const vec& nref) noexcept { + vec faceforward(const vec& n, const vec& i, const vec& nref) { return dot(nref, i) < T(0) ? n : -n; } template < typename T, std::size_t Size > - vec reflect(const vec& i, const vec& n) noexcept { + vec reflect(const vec& i, const vec& n) { return i - n * dot(n, i) * T(2); } template < typename T, std::size_t Size > - vec refract(const vec& i, const vec& n, T eta) noexcept { + vec refract(const vec& i, const vec& n, T eta) { const T d = dot(n, i); const T k = T(1) - eta * eta * (T(1) - d * d); return T(k >= T(0)) * (eta * i - (eta * d + sqrt(k)) * n); @@ -525,47 +541,47 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T, std::size_t Size > - constexpr vec less(const vec& x, const vec& y) { - return zip(std::less<>(), x, y); + constexpr vec less(const vec& xs, const vec& ys) { + return zip(std::less<>(), xs, ys); } template < typename T, std::size_t Size > - constexpr vec less_equal(const vec& x, const vec& y) { - return zip(std::less_equal<>(), x, y); + constexpr vec less_equal(const vec& xs, const vec& ys) { + return zip(std::less_equal<>(), xs, ys); } template < typename T, std::size_t Size > - constexpr vec greater(const vec& x, const vec& y) { - return zip(std::greater<>(), x, y); + constexpr vec greater(const vec& xs, const vec& ys) { + return zip(std::greater<>(), xs, ys); } template < typename T, std::size_t Size > - constexpr vec greater_equal(const vec& x, const vec& y) { - return zip(std::greater_equal<>(), x, y); + constexpr vec greater_equal(const vec& xs, const vec& ys) { + return zip(std::greater_equal<>(), xs, ys); } template < typename T, std::size_t Size > - constexpr vec equal_to(const vec& x, const vec& y) { - return zip(std::equal_to<>(), x, y); + constexpr vec equal_to(const vec& xs, const vec& ys) { + return zip(std::equal_to<>(), xs, ys); } template < typename T, std::size_t Size > - constexpr vec not_equal_to(const vec& x, const vec& y) { - return zip(std::not_equal_to<>(), x, y); + constexpr vec not_equal_to(const vec& xs, const vec& ys) { + return zip(std::not_equal_to<>(), xs, ys); } template < std::size_t Size > - constexpr bool any(const vec& x) { - return fold(std::logical_or<>(), false, x); + constexpr bool any(const vec& xs) { + return fold(std::logical_or<>(), false, xs); } template < std::size_t Size > - constexpr bool all(const vec& x) { - return fold(std::logical_and<>(), true, x); + constexpr bool all(const vec& xs) { + return fold(std::logical_and<>(), true, xs); } template < std::size_t Size > - constexpr vec not_(const vec& x) { - return map(std::logical_not<>(), x); + constexpr vec not_(const vec& xs) { + return map(std::logical_not<>(), xs); } } From b85cfb8e858deff6bc7285a7870d56510a7ca86c Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 24 Nov 2020 04:26:48 +0700 Subject: [PATCH 15/53] matrix operators --- headers/vmath.hpp/vmath_mat.hpp | 131 +++++++-------- headers/vmath.hpp/vmath_mat_fun.hpp | 237 ++++++++++++++++++++++++++-- untests/vmath_mat_fun_tests.cpp | 26 ++- 3 files changed, 317 insertions(+), 77 deletions(-) diff --git a/headers/vmath.hpp/vmath_mat.hpp b/headers/vmath.hpp/vmath_mat.hpp index d9f3972..004cb89 100644 --- a/headers/vmath.hpp/vmath_mat.hpp +++ b/headers/vmath.hpp/vmath_mat.hpp @@ -19,108 +19,111 @@ namespace vmath_hpp::detail template < typename T > class mat_base { public: - vec rows[2]; + using row_type = vec; + row_type rows[2]; public: constexpr mat_base() : rows{ - {1, 0}, - {0, 1}, + row_type{1, 0}, + row_type{0, 1}, } {} constexpr explicit mat_base(T v) : rows{ - {v, 0}, - {0, v}} {} + row_type{v, 0}, + row_type{0, v}} {} constexpr mat_base( T m11, T m12, T m21, T m22) : rows{ - {m11, m12}, - {m21, m22}} {} + row_type{m11, m12}, + row_type{m21, m22}} {} constexpr mat_base( - const vec& row0, - const vec& row1) + const row_type& row0, + const row_type& row1) : rows{row0, row1} {} constexpr explicit mat_base( const mat_base& other) : rows{ - vec{other.rows[0]}, - vec{other.rows[1]}} {} + row_type{other.rows[0]}, + row_type{other.rows[1]}} {} constexpr explicit mat_base( const mat_base& other) : rows{ - vec{other.rows[0]}, - vec{other.rows[1]}} {} + row_type{other.rows[0]}, + row_type{other.rows[1]}} {} }; template < typename T > class mat_base { public: - vec rows[3]; + using row_type = vec; + row_type rows[3]; public: constexpr mat_base() : rows{ - {1, 0, 0}, - {0, 1, 0}, - {0, 0, 1}, + row_type{1, 0, 0}, + row_type{0, 1, 0}, + row_type{0, 0, 1}, } {} constexpr explicit mat_base(T v) : rows{ - {v, 0, 0}, - {0, v, 0}, - {0, 0, v}} {} + row_type{v, 0, 0}, + row_type{0, v, 0}, + row_type{0, 0, v}} {} constexpr mat_base( T m11, T m12, T m13, T m21, T m22, T m23, T m31, T m32, T m33) : rows{ - {m11, m12, m13}, - {m21, m22, m23}, - {m31, m32, m33}} {} + row_type{m11, m12, m13}, + row_type{m21, m22, m23}, + row_type{m31, m32, m33}} {} constexpr mat_base( - const vec& row0, - const vec& row1, - const vec& row2) + const row_type& row0, + const row_type& row1, + const row_type& row2) : rows{row0, row1, row2} {} constexpr explicit mat_base( const mat_base& other) : rows{ - {other.rows[0], 0}, - {other.rows[1], 0}, - {0, 0, 1}} {} + row_type{other.rows[0], 0}, + row_type{other.rows[1], 0}, + row_type{0, 0, 1}} {} constexpr explicit mat_base( const mat_base& other) : rows{ - vec{other.rows[0]}, - vec{other.rows[1]}, - vec{other.rows[2]}} {} + row_type{other.rows[0]}, + row_type{other.rows[1]}, + row_type{other.rows[2]}} {} }; template < typename T > class mat_base { public: - vec rows[4]; + using row_type = vec; + row_type rows[4]; public: constexpr mat_base() : rows{ - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, + row_type{1, 0, 0, 0}, + row_type{0, 1, 0, 0}, + row_type{0, 0, 1, 0}, + row_type{0, 0, 0, 1}, } {} constexpr explicit mat_base(T v) : rows{ - {v, 0, 0, 0}, - {0, v, 0, 0}, - {0, 0, v, 0}, - {0, 0, 0, v}} {} + row_type{v, 0, 0, 0}, + row_type{0, v, 0, 0}, + row_type{0, 0, v, 0}, + row_type{0, 0, 0, v}} {} constexpr mat_base( T m11, T m12, T m13, T m14, @@ -128,33 +131,33 @@ namespace vmath_hpp::detail T m31, T m32, T m33, T m34, T m41, T m42, T m43, T m44) : rows{ - {m11, m12, m13, m14}, - {m21, m22, m23, m24}, - {m31, m32, m33, m34}, - {m41, m42, m43, m44}} {} + row_type{m11, m12, m13, m14}, + row_type{m21, m22, m23, m24}, + row_type{m31, m32, m33, m34}, + row_type{m41, m42, m43, m44}} {} constexpr mat_base( - const vec& row0, - const vec& row1, - const vec& row2, - const vec& row3) + const row_type& row0, + const row_type& row1, + const row_type& row2, + const row_type& row3) : rows{row0, row1, row2, row3} {} constexpr explicit mat_base( const mat_base& other) : rows{ - {other.rows[0], 0, 0}, - {other.rows[1], 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}} {} + row_type{other.rows[0], 0, 0}, + row_type{other.rows[1], 0, 0}, + row_type{0, 0, 1, 0}, + row_type{0, 0, 0, 1}} {} constexpr explicit mat_base( const mat_base& other) : rows{ - {other.rows[0], 0}, - {other.rows[1], 0}, - {other.rows[2], 0}, - {0, 0, 0, 1}} {} + row_type{other.rows[0], 0}, + row_type{other.rows[1], 0}, + row_type{other.rows[2], 0}, + row_type{0, 0, 0, 1}} {} }; } @@ -166,18 +169,18 @@ namespace vmath_hpp using self_type = mat; using base_type = detail::mat_base; public: - using value_type = vec; + using row_type = vec; - using pointer = value_type*; - using const_pointer = const value_type*; + using pointer = row_type*; + using const_pointer = const row_type*; - using reference = value_type&; - using const_reference = const value_type&; + using reference = row_type&; + using const_reference = const row_type&; static constexpr std::size_t size = Size; public: - using base_type::rows; using base_type::mat_base; + using base_type::rows; mat() = default; @@ -190,7 +193,7 @@ namespace vmath_hpp void swap(mat& other) noexcept(std::is_nothrow_swappable_v) { for ( std::size_t i = 0; i < Size; ++i ) { using std::swap; - swap(rows[i], other.rows[i]); + swap((*this)[i], other[i]); } } diff --git a/headers/vmath.hpp/vmath_mat_fun.hpp b/headers/vmath.hpp/vmath_mat_fun.hpp index c194f7a..0f06091 100644 --- a/headers/vmath.hpp/vmath_mat_fun.hpp +++ b/headers/vmath.hpp/vmath_mat_fun.hpp @@ -11,34 +11,247 @@ #include "vmath_fun.hpp" #include "vmath_mat.hpp" +namespace vmath_hpp::detail +{ + namespace impl + { + template < typename A, std::size_t Size, typename F, std::size_t... Is > + constexpr auto map_impl(F&& f, const mat& a, std::index_sequence) + -> mat>::value_type, Size> + { + return { f(a[Is])... }; + } + + template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > + constexpr auto zip_impl(F&& f, const mat& a, const mat& b, std::index_sequence) + -> mat, vec>::value_type, Size> + { + return { f(a[Is], b[Is])... }; + } + + template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > + constexpr auto zip_impl(F&& f, const mat& a, const mat& b, const mat& c, std::index_sequence) + -> mat, vec, vec>::value_type, Size> + { + return { f(a[Is], b[Is], c[Is])... }; + } + + template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > + constexpr auto fold_impl(F&& f, A init, const mat& b, std::index_sequence) + -> A + { + return ((init = f(std::move(init), b[Is])), ...); + } + + template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > + constexpr auto fold_impl(F&& f, A init, const mat& b, const mat& c, std::index_sequence) + -> A + { + return ((init = f(std::move(init), b[Is], c[Is])), ...); + } + } + + template < typename A, std::size_t Size, typename F > + constexpr auto map(F&& f, const mat& a) { + return impl::map_impl(std::forward(f), a, std::make_index_sequence{}); + } + + template < typename A, typename B, std::size_t Size, typename F > + constexpr auto zip(F&& f, const mat& a, const mat& b) { + return impl::zip_impl(std::forward(f), a, b, std::make_index_sequence{}); + } + + template < typename A, typename B, typename C, std::size_t Size, typename F > + constexpr auto zip(F&& f, const mat& a, const mat& b, const mat& c) { + return impl::zip_impl(std::forward(f), a, b, c, std::make_index_sequence{}); + } + + template < typename A, typename B, std::size_t Size, typename F > + constexpr auto fold(F&& f, A init, const mat& b) { + return impl::fold_impl(std::forward(f), std::move(init), b, std::make_index_sequence{}); + } + + template < typename A, typename B, typename C, std::size_t Size, typename F > + constexpr auto fold(F&& f, A init, const mat& b, const mat& c) { + return impl::fold_impl(std::forward(f), std::move(init), b, c, std::make_index_sequence{}); + } +} + // // Operators // namespace vmath_hpp { + // -operator + template < typename T, std::size_t Size > - constexpr bool operator==(const mat& l, const mat& r) { - for ( std::size_t i = 0; i < Size; ++i ) { - if ( !(l[i] == r[i]) ) { - return false; - } - } - return true; + constexpr mat operator-(const mat& xs) { + return map(std::negate<>(), xs); + } + + // operator+ + + template < typename T, std::size_t Size > + constexpr mat operator+(const mat& xs, T y) { + return map([y](const vec& x){ return x + y; }, xs); } template < typename T, std::size_t Size > - constexpr bool operator!=(const mat& l, const mat& r) { - return !(l == r); + constexpr mat operator+(T x, const mat& ys) { + return map([x](const vec& y){ return x + y; }, ys); } template < typename T, std::size_t Size > - constexpr bool operator<(const mat& l, const mat& r) { + constexpr mat operator+(const mat& xs, const mat& ys) { + return zip(std::plus<>(), xs, ys); + } + + // operator- + + template < typename T, std::size_t Size > + constexpr mat operator-(const mat& xs, T y) { + return map([y](const vec& x){ return x - y; }, xs); + } + + template < typename T, std::size_t Size > + constexpr mat operator-(T x, const mat& ys) { + return map([x](const vec& y){ return x - y; }, ys); + } + + template < typename T, std::size_t Size > + constexpr mat operator-(const mat& xs, const mat& ys) { + return zip(std::minus<>(), xs, ys); + } + + // operator* + + template < typename T, std::size_t Size > + constexpr mat operator*(const mat& xs, T y) { + return map([y](const vec& x){ return x * y; }, xs); + } + + template < typename T, std::size_t Size > + constexpr mat operator*(T x, const mat& ys) { + return map([x](const vec& y){ return x * y; }, ys); + } + + template < typename T > + constexpr vec operator*(const vec& xs, const mat& ys) { + return { + xs.x * ys[0][0] + xs.y * ys[1][0], + xs.x * ys[0][1] + xs.y * ys[1][1]}; + } + + template < typename T > + constexpr mat operator*(const mat& xs, const mat& ys) { + return { + xs[0][0] * ys[0][0] + xs[0][1] * ys[1][0], + xs[0][0] * ys[0][1] + xs[0][1] * ys[1][1], + + xs[1][0] * ys[0][0] + xs[1][1] * ys[1][0], + xs[1][0] * ys[0][1] + xs[1][1] * ys[1][1]}; + } + + template < typename T > + constexpr vec operator*(const vec& xs, const mat& ys) { + return { + xs.x * ys[0][0] + xs.y * ys[1][0] + xs.z * ys[2][0], + xs.x * ys[0][1] + xs.y * ys[1][1] + xs.z * ys[2][1], + xs.x * ys[0][2] + xs.y * ys[1][2] + xs.z * ys[2][2]}; + } + + template < typename T > + constexpr mat operator*(const mat& xs, const mat& ys) { + return { + xs[0][0] * ys[0][0] + xs[0][1] * ys[1][0] + xs[0][2] * ys[2][0], + xs[0][0] * ys[0][1] + xs[0][1] * ys[1][1] + xs[0][2] * ys[2][1], + xs[0][0] * ys[0][2] + xs[0][1] * ys[1][2] + xs[0][2] * ys[2][2], + + xs[1][0] * ys[0][0] + xs[1][1] * ys[1][0] + xs[1][2] * ys[2][0], + xs[1][0] * ys[0][1] + xs[1][1] * ys[1][1] + xs[1][2] * ys[2][1], + xs[1][0] * ys[0][2] + xs[1][1] * ys[1][2] + xs[1][2] * ys[2][2], + + xs[2][0] * ys[0][0] + xs[2][1] * ys[1][0] + xs[2][2] * ys[2][0], + xs[2][0] * ys[0][1] + xs[2][1] * ys[1][1] + xs[2][2] * ys[2][1], + xs[2][0] * ys[0][2] + xs[2][1] * ys[1][2] + xs[2][2] * ys[2][2]}; + } + + template < typename T > + constexpr vec operator*(const vec& xs, const mat& ys) { + return { + xs.x * ys[0][0] + xs.y * ys[1][0] + xs.z * ys[2][0] + xs.w * ys[3][0], + xs.x * ys[0][1] + xs.y * ys[1][1] + xs.z * ys[2][1] + xs.w * ys[3][1], + xs.x * ys[0][2] + xs.y * ys[1][2] + xs.z * ys[2][2] + xs.w * ys[3][2], + xs.x * ys[0][3] + xs.y * ys[1][3] + xs.z * ys[2][3] + xs.w * ys[3][3]}; + } + + template < typename T > + constexpr mat operator*(const mat& xs, const mat& ys) { + return { + xs[0][0] * ys[0][0] + xs[0][1] * ys[1][0] + xs[0][2] * ys[2][0] + xs[0][3] * ys[3][0], + xs[0][0] * ys[0][1] + xs[0][1] * ys[1][1] + xs[0][2] * ys[2][1] + xs[0][3] * ys[3][1], + xs[0][0] * ys[0][2] + xs[0][1] * ys[1][2] + xs[0][2] * ys[2][2] + xs[0][3] * ys[3][2], + xs[0][0] * ys[0][3] + xs[0][1] * ys[1][3] + xs[0][2] * ys[2][3] + xs[0][3] * ys[3][3], + + xs[1][0] * ys[0][0] + xs[1][1] * ys[1][0] + xs[1][2] * ys[2][0] + xs[1][3] * ys[3][0], + xs[1][0] * ys[0][1] + xs[1][1] * ys[1][1] + xs[1][2] * ys[2][1] + xs[1][3] * ys[3][1], + xs[1][0] * ys[0][2] + xs[1][1] * ys[1][2] + xs[1][2] * ys[2][2] + xs[1][3] * ys[3][2], + xs[1][0] * ys[0][3] + xs[1][1] * ys[1][3] + xs[1][2] * ys[2][3] + xs[1][3] * ys[3][3], + + xs[2][0] * ys[0][0] + xs[2][1] * ys[1][0] + xs[2][2] * ys[2][0] + xs[2][3] * ys[3][0], + xs[2][0] * ys[0][1] + xs[2][1] * ys[1][1] + xs[2][2] * ys[2][1] + xs[2][3] * ys[3][1], + xs[2][0] * ys[0][2] + xs[2][1] * ys[1][2] + xs[2][2] * ys[2][2] + xs[2][3] * ys[3][2], + xs[2][0] * ys[0][3] + xs[2][1] * ys[1][3] + xs[2][2] * ys[2][3] + xs[2][3] * ys[3][3], + + xs[3][0] * ys[0][0] + xs[3][1] * ys[1][0] + xs[3][2] * ys[2][0] + xs[3][3] * ys[3][0], + xs[3][0] * ys[0][1] + xs[3][1] * ys[1][1] + xs[3][2] * ys[2][1] + xs[3][3] * ys[3][1], + xs[3][0] * ys[0][2] + xs[3][1] * ys[1][2] + xs[3][2] * ys[2][2] + xs[3][3] * ys[3][2], + xs[3][0] * ys[0][3] + xs[3][1] * ys[1][3] + xs[3][2] * ys[2][3] + xs[3][3] * ys[3][3]}; + } + + // operator/ + + template < typename T, std::size_t Size > + constexpr mat operator/(const mat& xs, T y) { + return map([y](const vec& x){ return x / y; }, xs); + } + + template < typename T, std::size_t Size > + constexpr mat operator/(T x, const mat& ys) { + return map([x](const vec& y){ return x / y; }, ys); + } + + template < typename T, std::size_t Size > + constexpr mat operator/(const mat& xs, const mat& ys) { + return zip(std::divides<>(), xs, ys); + } + + // operator== + + template < typename T, std::size_t Size > + constexpr bool operator==(const mat& xs, const mat& ys) { + return fold([](bool acc, const vec& x, const vec& y){ + return acc && (x == y); + }, true, xs, ys); + } + + template < typename T, std::size_t Size > + constexpr bool operator!=(const mat& xs, const mat& ys) { + return fold([](bool acc, const vec& x, const vec& y){ + return acc || (x != y); + }, false, xs, ys); + } + + // operator< + + template < typename T, std::size_t Size > + constexpr bool operator<(const mat& xs, const mat& ys) { for ( std::size_t i = 0; i < Size; ++i ) { - if ( l[i] < r[i] ) { + if ( xs[i] < ys[i] ) { return true; } - if ( r[i] < l[i] ) { + if ( ys[i] < xs[i] ) { return false; } } diff --git a/untests/vmath_mat_fun_tests.cpp b/untests/vmath_mat_fun_tests.cpp index 603955d..ad5ff2c 100644 --- a/untests/vmath_mat_fun_tests.cpp +++ b/untests/vmath_mat_fun_tests.cpp @@ -11,8 +11,32 @@ namespace { + using namespace vmath_hpp; } TEST_CASE("vmath/mat_fun") { - using namespace vmath_hpp; + SECTION("Operators") { + STATIC_REQUIRE(-mat2i(1,2,3,4) == mat2i(-1,-2,-3,-4)); + + STATIC_REQUIRE(mat2i(1,2,3,4) + 2 == mat2i(3,4,5,6)); + STATIC_REQUIRE(mat2i(1,2,3,4) - 2 == mat2i(-1,0,1,2)); + STATIC_REQUIRE(mat2i(1,2,3,4) * 2 == mat2i(2,4,6,8)); + STATIC_REQUIRE(mat2i(1,2,3,4) / 2 == mat2i(0,1,1,2)); + + STATIC_REQUIRE(4 + mat2i(1,2,3,4) == mat2i(5,6,7,8)); + STATIC_REQUIRE(4 - mat2i(1,2,3,4) == mat2i(3,2,1,0)); + STATIC_REQUIRE(4 * mat2i(1,2,3,4) == mat2i(4,8,12,16)); + STATIC_REQUIRE(4 / mat2i(1,2,3,4) == mat2i(4,2,1,1)); + + STATIC_REQUIRE(mat2i(1,2,3,4) + mat2i(5,6,7,8) == mat2i(6,8,10,12)); + STATIC_REQUIRE(mat2i(1,2,3,4) - mat2i(5,6,7,8) == mat2i(-4,-4,-4,-4)); + STATIC_REQUIRE(mat2i(5,6,7,8) / mat2i(1,2,3,4) == mat2i(5,3,2,2)); + + STATIC_REQUIRE(mat2i() * mat2i() == mat2i()); + STATIC_REQUIRE(mat3i() * mat3i() == mat3i()); + + STATIC_REQUIRE(vec2i(1,2) * mat2i() == vec2i(1,2)); + STATIC_REQUIRE(vec3i(1,2,3) * mat3i() == vec3i(1,2,3)); + STATIC_REQUIRE(vec4i(1,2,3,4) * mat4i() == vec4i(1,2,3,4)); + } } From caf6ba65b4683dd91bc12044549477f2e530082e Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 24 Nov 2020 19:23:55 +0700 Subject: [PATCH 16/53] transpose and determinant matrix functions --- headers/vmath.hpp/vmath_mat_fun.hpp | 134 ++++++++++++++++++++++++++++ untests/vmath_mat_fun_tests.cpp | 67 ++++++++++++++ 2 files changed, 201 insertions(+) diff --git a/headers/vmath.hpp/vmath_mat_fun.hpp b/headers/vmath.hpp/vmath_mat_fun.hpp index 0f06091..ae03300 100644 --- a/headers/vmath.hpp/vmath_mat_fun.hpp +++ b/headers/vmath.hpp/vmath_mat_fun.hpp @@ -258,3 +258,137 @@ namespace vmath_hpp return false; } } + +// +// Matrix Functions +// + +namespace vmath_hpp +{ + namespace impl + { + template < typename T > + constexpr mat transpose_2x2_impl( + T a, T c, + T b, T d) + { + return { + a, b, + c, d}; + } + + template < typename T > + constexpr mat transpose_3x3_impl( + T a, T d, T g, + T b, T e, T h, + T c, T f, T i) + { + return { + a, b, c, + d, e, f, + g, h, i}; + } + + template < typename T > + constexpr mat transpose_4x4_impl( + T a, T e, T i, T m, + T b, T f, T j, T n, + T c, T g, T k, T o, + T d, T h, T l, T p) + { + return { + a, b, c, d, + e, f, g, h, + i, j, k, l, + m, n, o, p}; + } + } + + template < typename T > + constexpr mat transpose(const mat& m) { + return impl::transpose_2x2_impl( + m[0][0], m[0][1], + m[1][0], m[1][1]); + } + + template < typename T > + constexpr mat transpose(const mat& m) { + return impl::transpose_3x3_impl( + m[0][0], m[0][1], m[0][2], + m[1][0], m[1][1], m[1][2], + m[2][0], m[2][1], m[2][2]); + } + + template < typename T > + constexpr mat transpose(const mat& m) { + return impl::transpose_4x4_impl( + m[0][0], m[0][1], m[0][2], m[0][3], + m[1][0], m[1][1], m[1][2], m[1][3], + m[2][0], m[2][1], m[2][2], m[2][3], + m[3][0], m[3][1], m[3][2], m[3][3]); + } + + namespace impl + { + template < typename T > + constexpr T determinant_2x2_impl( + T a, T b, + T c, T d) + { + return + + a * d + - b * c; + } + + template < typename T > + constexpr T determinant_3x3_impl( + T a, T b, T c, + T d, T e, T f, + T g, T h, T i) + { + return + + a * determinant_2x2_impl(e, f, h, i) + - b * determinant_2x2_impl(d, f, g, i) + + c * determinant_2x2_impl(d, e, g, h); + + } + + template < typename T > + constexpr T determinant_4x4_impl( + T a, T b, T c, T d, + T e, T f, T g, T h, + T i, T j, T k, T l, + T m, T n, T o, T p) + { + 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) + + c * determinant_3x3_impl(e, f, h, i, j, l, m, n, p) + - d * determinant_3x3_impl(e, f, g, i, j, k, m, n, o); + } + } + + template < typename T > + constexpr T determinant(const mat& m) { + return impl::determinant_2x2_impl( + m[0][0], m[0][1], + m[1][0], m[1][1]); + } + + template < typename T > + constexpr T determinant(const mat& m) { + return impl::determinant_3x3_impl( + m[0][0], m[0][1], m[0][2], + m[1][0], m[1][1], m[1][2], + m[2][0], m[2][1], m[2][2]); + } + + template < typename T > + constexpr T determinant(const mat& m) { + return impl::determinant_4x4_impl( + m[0][0], m[0][1], m[0][2], m[0][3], + m[1][0], m[1][1], m[1][2], m[1][3], + m[2][0], m[2][1], m[2][2], m[2][3], + m[3][0], m[3][1], m[3][2], m[3][3]); + } +} diff --git a/untests/vmath_mat_fun_tests.cpp b/untests/vmath_mat_fun_tests.cpp index ad5ff2c..7fa61e0 100644 --- a/untests/vmath_mat_fun_tests.cpp +++ b/untests/vmath_mat_fun_tests.cpp @@ -12,6 +12,23 @@ namespace { using namespace vmath_hpp; + + template < typename T, int Size > + constexpr mat generate_frank_matrix() { + mat m; + for ( int i = 1; i <= Size; ++i ) { + for ( int j = 1; j <= Size; ++j ) { + if ( j < i - Size ) { + m[i - 1][j - 1] = 0; + } else if ( j == (i - 1) ) { + m[i - 1][j - 1] = Size + 1 - i; + } else { + m[i - 1][j - 1] = Size + 1 - j; + } + } + } + return m; + } } TEST_CASE("vmath/mat_fun") { @@ -39,4 +56,54 @@ TEST_CASE("vmath/mat_fun") { STATIC_REQUIRE(vec3i(1,2,3) * mat3i() == vec3i(1,2,3)); STATIC_REQUIRE(vec4i(1,2,3,4) * mat4i() == vec4i(1,2,3,4)); } + + SECTION("Matrix Functions") { + { + STATIC_REQUIRE(transpose(mat2i( + 1, 2, + 3, 4 + )) == mat2i( + 1, 3, + 2, 4 + )); + + STATIC_REQUIRE(transpose(mat3i( + 1, 2, 3, + 4, 5, 6, + 7, 8, 9 + )) == mat3i( + 1, 4, 7, + 2, 5, 8, + 3, 6, 9 + )); + + STATIC_REQUIRE(transpose(mat4i( + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16 + )) == mat4i( + 1, 5, 9, 13, + 2, 6, 10, 14, + 3, 7, 11, 15, + 4, 8, 12, 16 + )); + } + { + constexpr mat2i m2{1,2,3,4}; + constexpr mat3i m3{1,2,3,4,5,6,7,8,9}; + constexpr mat4i 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_REQUIRE(determinant(generate_frank_matrix()) == 1); + STATIC_REQUIRE(determinant(generate_frank_matrix()) == 1); + STATIC_REQUIRE(determinant(generate_frank_matrix()) == 1); + + STATIC_REQUIRE(determinant(transpose(generate_frank_matrix())) == 1); + STATIC_REQUIRE(determinant(transpose(generate_frank_matrix())) == 1); + STATIC_REQUIRE(determinant(transpose(generate_frank_matrix())) == 1); + } + } } From d1aa48bd4e632f734e6778e2e15a982a3f720764 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 24 Nov 2020 21:51:27 +0700 Subject: [PATCH 17/53] translate/rotate/scale matrix functions --- headers/vmath.hpp/vmath_mat_ext.hpp | 120 ++++++++++++++++++++++++++++ untests/vmath_mat_ext_tests.cpp | 103 ++++++++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 headers/vmath.hpp/vmath_mat_ext.hpp create mode 100644 untests/vmath_mat_ext_tests.cpp diff --git a/headers/vmath.hpp/vmath_mat_ext.hpp b/headers/vmath.hpp/vmath_mat_ext.hpp new file mode 100644 index 0000000..9771b31 --- /dev/null +++ b/headers/vmath.hpp/vmath_mat_ext.hpp @@ -0,0 +1,120 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "vmath_fwd.hpp" + +#include "vmath_fun.hpp" +#include "vmath_mat.hpp" +#include "vmath_mat_fun.hpp" + +namespace vmath_hpp +{ + // identity + + template < typename T > + mat identity() { + return { + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}}; + } + + // translate + + template < typename T > + mat translate(T x, T y, T z) { + return { + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {x, y, z, 1}}; + } + + template < typename T > + mat translate(const vec& xyz) { + return translate(xyz.x, xyz.y, xyz.z); + } + + template < typename T > + mat translate(const mat& m, T x, T y, T z) { + return m * translate(x, y, z); + } + + template < typename T > + mat translate(const mat& m, const vec& xyz) { + return m * translate(xyz); + } + + // rotate + + template < typename T > + mat rotate(T angle, T axis_x, T axis_y, T axis_z) { + const T x = axis_x; + const T y = axis_y; + const T z = axis_z; + const T px = x * x; + const T py = y * y; + const T pz = z * z; + const T cs = cos(angle); + const T sn = sin(angle); + const T ics = T(1) - cs; + const T xym = x * y * ics; + const T xzm = x * z * ics; + const T yzm = y * z * ics; + const T xsn = x * sn; + const T ysn = y * sn; + const T zsn = z * sn; + return { + px * ics + cs, xym + zsn, xzm - ysn, 0, + xym - zsn, py * ics + cs, yzm + xsn, 0, + xzm + ysn, yzm - xsn, pz * ics + cs, 0, + 0, 0, 0, 1}; + } + + template < typename T > + mat rotate(T angle, const vec& axis) { + return rotate(angle, axis.x, axis.y, axis.z); + } + + template < typename T > + mat rotate(const mat& m, T angle, T axis_x, T axis_y, T axis_z) { + return m * rotate(angle, axis_x, axis_y, axis_z); + } + + template < typename T > + mat rotate(const mat& m, T angle, const vec& axis) { + return m * rotate(angle, axis); + } + + // scale + + template < typename T > + mat scale(T x, T y, T z) { + return { + {x, 0, 0, 0}, + {0, y, 0, 0}, + {0, 0, z, 0}, + {0, 0, 0, 1}}; + } + + template < typename T > + mat scale(const vec& xyz) { + return scale(xyz.x, xyz.y, xyz.z); + } + + template < typename T > + mat scale(const mat& m, T x, T y, T z) { + return m * scale(x, y, z); + } + + template < typename T > + mat scale(const mat& m, const vec& xyz) { + return m * scale(xyz); + } +} diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp new file mode 100644 index 0000000..3a3ceb0 --- /dev/null +++ b/untests/vmath_mat_ext_tests.cpp @@ -0,0 +1,103 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include + +#define CATCH_CONFIG_FAST_COMPILE +#include + +namespace +{ + using namespace vmath_hpp; + + template < typename T > + class approx2 { + public: + constexpr explicit approx2(T v) : value_(v) {} + constexpr explicit approx2(T x, T y) : value_(x, y) {} + + friend constexpr bool operator==(const vec& l, const approx2& r) { + return (r.value_.x < l.x + epsilon) + && (l.x < r.value_.x + epsilon) + && (r.value_.y < l.y + epsilon) + && (l.y < r.value_.y + epsilon); + } + private: + vec value_; + static constexpr T epsilon = std::numeric_limits::epsilon() * 100; + }; + + template < typename T > + class approx3 { + public: + constexpr explicit approx3(T v) : value_(v) {} + constexpr explicit approx3(T x, T y, T z) : value_(x, y, z) {} + + friend constexpr bool operator==(const vec& l, const approx3& r) { + return (r.value_.x < l.x + epsilon) + && (l.x < r.value_.x + epsilon) + && (r.value_.y < l.y + epsilon) + && (l.y < r.value_.y + epsilon) + && (r.value_.z < l.z + epsilon) + && (l.z < r.value_.z + epsilon); + } + private: + vec value_; + static constexpr T epsilon = std::numeric_limits::epsilon() * 100; + }; + + template < typename T > + class approx4 { + public: + constexpr explicit approx4(T v) : value_(v) {} + constexpr explicit approx4(T x, T y, T z, T w) : value_(x, y, z, w) {} + + friend constexpr bool operator==(const vec& l, const approx4& r) { + return (r.value_.x < l.x + epsilon) + && (l.x < r.value_.x + epsilon) + && (r.value_.y < l.y + epsilon) + && (l.y < r.value_.y + epsilon) + && (r.value_.z < l.z + epsilon) + && (l.z < r.value_.z + epsilon) + && (r.value_.w < l.w + epsilon) + && (l.w < r.value_.w + epsilon); + } + private: + vec value_; + static constexpr T epsilon = std::numeric_limits::epsilon() * 100; + }; +} + +TEST_CASE("vmath/mat_ext") { + SECTION("identity") { + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); + } + + SECTION("translate") { + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(1.f,2.f,3.f) == approx4(3.f,5.f,7.f,1.f)); + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(vec3f{1.f,2.f,3.f}) == approx4(3.f,5.f,7.f,1.f)); + + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), 1.f,2.f,3.f) == approx4(4.f,7.f,10.f,1.f)); + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), vec3f{1.f,2.f,3.f}) == approx4(4.f,7.f,10.f,1.f)); + } + + SECTION("rotate") { + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(float(M_PI),0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(float(M_PI),vec3f{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); + + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(rotate(float(M_PI_2),0.f,0.f,1.f),float(M_PI_2),0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(rotate(float(M_PI_2),0.f,0.f,1.f),float(M_PI_2),vec3f{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); + } + + SECTION("scale") { + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(2.f,3.f,4.f) == approx4(4.f,9.f,16.f,1.f)); + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(vec3f{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f)); + + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), 2.f,3.f,4.f) == approx4(8.f,18.f,32.f,1.f)); + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), vec3f{2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); + } +} From 75aed0e28237bc3341c30986e61e757d38c55266 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 24 Nov 2020 22:20:20 +0700 Subject: [PATCH 18/53] matrix inverse --- headers/vmath.hpp/vmath_mat_fun.hpp | 102 ++++++++++++++++++++++++ untests/vmath_mat_fun_tests.cpp | 118 ++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+) diff --git a/headers/vmath.hpp/vmath_mat_fun.hpp b/headers/vmath.hpp/vmath_mat_fun.hpp index ae03300..aa71d47 100644 --- a/headers/vmath.hpp/vmath_mat_fun.hpp +++ b/headers/vmath.hpp/vmath_mat_fun.hpp @@ -391,4 +391,106 @@ namespace vmath_hpp m[2][0], m[2][1], m[2][2], m[2][3], m[3][0], m[3][1], m[3][2], m[3][3]); } + + namespace impl + { + template < typename T > + constexpr mat inverse_2x2_impl( + T a, T b, + T c, T d) + { + const T inv_det = T(1) / determinant_2x2_impl( + a, b, + c, d); + + const mat inv_m( + d, -b, + -c, a); + + return inv_m * inv_det; + } + + template < typename T > + constexpr mat inverse_3x3_impl( + T a, T b, T c, + T d, T e, T f, + T g, T h, T i) + { + const T inv_det = T(1) / determinant_3x3_impl( + a, b, c, + d, e, f, + g, h, i); + + const mat inv_m( + e * i - f * h, + c * h - b * i, + b * f - c * e, + f * g - d * i, + a * i - c * g, + c * d - a * f, + d * h - e * g, + b * g - a * h, + a * e - b * d); + + return inv_m * inv_det; + } + + template < typename T > + constexpr mat inverse_4x4_impl( + T a, T b, T c, T d, + T e, T f, T g, T h, + T i, T j, T k, T l, + T m, T n, T o, T p) + { + const T inv_det = T(1) / determinant_4x4_impl( + a, b, c, d, + e, f, g, h, + i, j, k, l, + m, n, o, p); + + 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)), + (b * (h * k - g * l) + c * (f * l - h * j) + d * (g * j - f * k)), + (g * (i * p - l * m) + h * (k * m - i * o) + e * (l * o - k * p)), + (k * (a * p - d * m) + l * (c * m - a * o) + i * (d * o - c * p)), + (o * (a * h - d * e) + p * (c * e - a * g) + m * (d * g - c * h)), + (c * (h * i - e * l) + d * (e * k - g * i) + a * (g * l - h * k)), + (h * (i * n - j * m) + e * (j * p - l * n) + f * (l * m - i * p)), + (l * (a * n - b * m) + i * (b * p - d * n) + j * (d * m - a * p)), + (p * (a * f - b * e) + m * (b * h - d * f) + n * (d * e - a * h)), + (d * (f * i - e * j) + a * (h * j - f * l) + b * (e * l - h * i)), + (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))); + + return inv_m * inv_det; + } + } + + template < typename T > + constexpr mat inverse(const mat& m) { + return impl::inverse_2x2_impl( + m[0][0], m[0][1], + m[1][0], m[1][1]); + } + + template < typename T > + constexpr matinverse(const mat& m) { + return impl::inverse_3x3_impl( + m[0][0], m[0][1], m[0][2], + m[1][0], m[1][1], m[1][2], + m[2][0], m[2][1], m[2][2]); + } + + template < typename T > + constexpr matinverse(const mat& m) { + return impl::inverse_4x4_impl( + m[0][0], m[0][1], m[0][2], m[0][3], + m[1][0], m[1][1], m[1][2], m[1][3], + m[2][0], m[2][1], m[2][2], m[2][3], + m[3][0], m[3][1], m[3][2], m[3][3]); + } } diff --git a/untests/vmath_mat_fun_tests.cpp b/untests/vmath_mat_fun_tests.cpp index 7fa61e0..b0fd699 100644 --- a/untests/vmath_mat_fun_tests.cpp +++ b/untests/vmath_mat_fun_tests.cpp @@ -5,6 +5,7 @@ ******************************************************************************/ #include +#include #define CATCH_CONFIG_FAST_COMPILE #include @@ -29,6 +30,108 @@ namespace } return m; } + + template < typename T > + class approx2 { + public: + constexpr explicit approx2(T v) : value_(v) {} + constexpr explicit approx2(const vec& v) : value_(v) {} + constexpr explicit approx2(T x, T y) : value_(x, y) {} + + friend constexpr bool operator==(const vec& l, const approx2& r) { + return (r.value_.x < l.x + epsilon) + && (l.x < r.value_.x + epsilon) + && (r.value_.y < l.y + epsilon) + && (l.y < r.value_.y + epsilon); + } + private: + vec value_; + static constexpr T epsilon = std::numeric_limits::epsilon() * 100; + }; + + template < typename T > + class approx3 { + public: + constexpr explicit approx3(T v) : value_(v) {} + constexpr explicit approx3(const vec& v) : value_(v) {} + constexpr explicit approx3(T x, T y, T z) : value_(x, y, z) {} + + friend constexpr bool operator==(const vec& l, const approx3& r) { + return (r.value_.x < l.x + epsilon) + && (l.x < r.value_.x + epsilon) + && (r.value_.y < l.y + epsilon) + && (l.y < r.value_.y + epsilon) + && (r.value_.z < l.z + epsilon) + && (l.z < r.value_.z + epsilon); + } + private: + vec value_; + static constexpr T epsilon = std::numeric_limits::epsilon() * 100; + }; + + template < typename T > + class approx4 { + public: + constexpr explicit approx4(T v) : value_(v) {} + constexpr explicit approx4(const vec& v) : value_(v) {} + constexpr explicit approx4(T x, T y, T z, T w) : value_(x, y, z, w) {} + + friend constexpr bool operator==(const vec& l, const approx4& r) { + return (r.value_.x < l.x + epsilon) + && (l.x < r.value_.x + epsilon) + && (r.value_.y < l.y + epsilon) + && (l.y < r.value_.y + epsilon) + && (r.value_.z < l.z + epsilon) + && (l.z < r.value_.z + epsilon) + && (r.value_.w < l.w + epsilon) + && (l.w < r.value_.w + epsilon); + } + private: + vec value_; + static constexpr T epsilon = std::numeric_limits::epsilon() * 100; + }; + + template < typename T > + class approx2x2 { + public: + constexpr explicit approx2x2(const mat& v) : value_(v) {} + + friend constexpr bool operator==(const mat& l, const approx2x2& r) { + return l[0] == approx2(r.value_[0]) + && l[1] == approx2(r.value_[1]); + } + private: + mat value_; + }; + + template < typename T > + class approx3x3 { + public: + constexpr explicit approx3x3(const mat& v) : value_(v) {} + + friend constexpr bool operator==(const mat& l, const approx3x3& r) { + return l[0] == approx3(r.value_[0]) + && l[1] == approx3(r.value_[1]) + && l[2] == approx3(r.value_[2]); + } + private: + mat value_; + }; + + template < typename T > + class approx4x4 { + public: + constexpr explicit approx4x4(const mat& v) : value_(v) {} + + friend constexpr bool operator==(const mat& l, const approx4x4& r) { + return l[0] == approx4(r.value_[0]) + && l[1] == approx4(r.value_[1]) + && l[2] == approx4(r.value_[2]) + && l[3] == approx4(r.value_[3]); + } + private: + mat value_; + }; } TEST_CASE("vmath/mat_fun") { @@ -105,5 +208,20 @@ TEST_CASE("vmath/mat_fun") { STATIC_REQUIRE(determinant(transpose(generate_frank_matrix())) == 1); STATIC_REQUIRE(determinant(transpose(generate_frank_matrix())) == 1); } + { + STATIC_REQUIRE(inverse(mat2i()) == mat2i()); + STATIC_REQUIRE(inverse(mat3i()) == mat3i()); + STATIC_REQUIRE(inverse(mat4i()) == mat4i()); + + REQUIRE(inverse(mat2f(0.5)) == mat2f(2.f)); + REQUIRE(inverse(mat3f(0.5)) == mat3f(2.f)); + REQUIRE(inverse(mat4f(0.5)) == mat4f(2.f)); + + REQUIRE(inverse(translate(1.f,2.f,3.f)) == approx4x4(translate(-1.f,-2.f,-3.f))); + + REQUIRE(inverse(rotate(0.5f,normalize(vec3f{1.f,2.f,3.f}))) == approx4x4(rotate(-0.5f,normalize(vec3f{1.f,2.f,3.f})))); + REQUIRE(inverse(mat3f(rotate(0.5f,normalize(vec3f{1.f,2.f,3.f})))) == approx3x3(mat3f(rotate(-0.5f,normalize(vec3f{1.f,2.f,3.f}))))); + REQUIRE(inverse(mat2f(rotate(0.5f,vec3f{0,0,1}))) == approx2x2(mat2f(rotate(-0.5f,vec3f{0,0,1})))); + } } } From 0a26d1824e3e2dac8652c709ceece475e48a6904 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 24 Nov 2020 22:27:22 +0700 Subject: [PATCH 19/53] more constexpr --- headers/vmath.hpp/vmath_mat_ext.hpp | 18 +++++++++--------- untests/vmath_mat_ext_tests.cpp | 20 ++++++++++---------- untests/vmath_mat_fun_tests.cpp | 8 ++++---- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/headers/vmath.hpp/vmath_mat_ext.hpp b/headers/vmath.hpp/vmath_mat_ext.hpp index 9771b31..bd431d7 100644 --- a/headers/vmath.hpp/vmath_mat_ext.hpp +++ b/headers/vmath.hpp/vmath_mat_ext.hpp @@ -17,7 +17,7 @@ namespace vmath_hpp // identity template < typename T > - mat identity() { + constexpr mat identity() { return { {1, 0, 0, 0}, {0, 1, 0, 0}, @@ -28,7 +28,7 @@ namespace vmath_hpp // translate template < typename T > - mat translate(T x, T y, T z) { + constexpr mat translate(T x, T y, T z) { return { {1, 0, 0, 0}, {0, 1, 0, 0}, @@ -37,17 +37,17 @@ namespace vmath_hpp } template < typename T > - mat translate(const vec& xyz) { + constexpr mat translate(const vec& xyz) { return translate(xyz.x, xyz.y, xyz.z); } template < typename T > - mat translate(const mat& m, T x, T y, T z) { + constexpr mat translate(const mat& m, T x, T y, T z) { return m * translate(x, y, z); } template < typename T > - mat translate(const mat& m, const vec& xyz) { + constexpr mat translate(const mat& m, const vec& xyz) { return m * translate(xyz); } @@ -95,7 +95,7 @@ namespace vmath_hpp // scale template < typename T > - mat scale(T x, T y, T z) { + constexpr mat scale(T x, T y, T z) { return { {x, 0, 0, 0}, {0, y, 0, 0}, @@ -104,17 +104,17 @@ namespace vmath_hpp } template < typename T > - mat scale(const vec& xyz) { + constexpr mat scale(const vec& xyz) { return scale(xyz.x, xyz.y, xyz.z); } template < typename T > - mat scale(const mat& m, T x, T y, T z) { + constexpr mat scale(const mat& m, T x, T y, T z) { return m * scale(x, y, z); } template < typename T > - mat scale(const mat& m, const vec& xyz) { + constexpr mat scale(const mat& m, const vec& xyz) { return m * scale(xyz); } } diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp index 3a3ceb0..4e2e74a 100644 --- a/untests/vmath_mat_ext_tests.cpp +++ b/untests/vmath_mat_ext_tests.cpp @@ -73,16 +73,16 @@ namespace TEST_CASE("vmath/mat_ext") { SECTION("identity") { - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); + STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); + STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); } SECTION("translate") { - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(1.f,2.f,3.f) == approx4(3.f,5.f,7.f,1.f)); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(vec3f{1.f,2.f,3.f}) == approx4(3.f,5.f,7.f,1.f)); + STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(1.f,2.f,3.f) == approx4(3.f,5.f,7.f,1.f)); + STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(vec3f{1.f,2.f,3.f}) == approx4(3.f,5.f,7.f,1.f)); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), 1.f,2.f,3.f) == approx4(4.f,7.f,10.f,1.f)); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), vec3f{1.f,2.f,3.f}) == approx4(4.f,7.f,10.f,1.f)); + STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), 1.f,2.f,3.f) == approx4(4.f,7.f,10.f,1.f)); + STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), vec3f{1.f,2.f,3.f}) == approx4(4.f,7.f,10.f,1.f)); } SECTION("rotate") { @@ -94,10 +94,10 @@ TEST_CASE("vmath/mat_ext") { } SECTION("scale") { - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(2.f,3.f,4.f) == approx4(4.f,9.f,16.f,1.f)); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(vec3f{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f)); + STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(2.f,3.f,4.f) == approx4(4.f,9.f,16.f,1.f)); + STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(vec3f{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f)); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), 2.f,3.f,4.f) == approx4(8.f,18.f,32.f,1.f)); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), vec3f{2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); + STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), 2.f,3.f,4.f) == approx4(8.f,18.f,32.f,1.f)); + STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), vec3f{2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); } } diff --git a/untests/vmath_mat_fun_tests.cpp b/untests/vmath_mat_fun_tests.cpp index b0fd699..a2d1f97 100644 --- a/untests/vmath_mat_fun_tests.cpp +++ b/untests/vmath_mat_fun_tests.cpp @@ -213,11 +213,11 @@ TEST_CASE("vmath/mat_fun") { STATIC_REQUIRE(inverse(mat3i()) == mat3i()); STATIC_REQUIRE(inverse(mat4i()) == mat4i()); - REQUIRE(inverse(mat2f(0.5)) == mat2f(2.f)); - REQUIRE(inverse(mat3f(0.5)) == mat3f(2.f)); - REQUIRE(inverse(mat4f(0.5)) == mat4f(2.f)); + STATIC_REQUIRE(inverse(mat2f(0.5)) == mat2f(2.f)); + STATIC_REQUIRE(inverse(mat3f(0.5)) == mat3f(2.f)); + STATIC_REQUIRE(inverse(mat4f(0.5)) == mat4f(2.f)); - REQUIRE(inverse(translate(1.f,2.f,3.f)) == approx4x4(translate(-1.f,-2.f,-3.f))); + STATIC_REQUIRE(inverse(translate(1.f,2.f,3.f)) == approx4x4(translate(-1.f,-2.f,-3.f))); REQUIRE(inverse(rotate(0.5f,normalize(vec3f{1.f,2.f,3.f}))) == approx4x4(rotate(-0.5f,normalize(vec3f{1.f,2.f,3.f})))); REQUIRE(inverse(mat3f(rotate(0.5f,normalize(vec3f{1.f,2.f,3.f})))) == approx3x3(mat3f(rotate(-0.5f,normalize(vec3f{1.f,2.f,3.f}))))); From 6f132b0be3d82a04cdc7eead6eb90b5786d098b5 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 24 Nov 2020 22:38:00 +0700 Subject: [PATCH 20/53] fix msvc compilation --- untests/vmath_mat_ext_tests.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp index 4e2e74a..d44afa9 100644 --- a/untests/vmath_mat_ext_tests.cpp +++ b/untests/vmath_mat_ext_tests.cpp @@ -86,11 +86,14 @@ TEST_CASE("vmath/mat_ext") { } SECTION("rotate") { - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(float(M_PI),0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(float(M_PI),vec3f{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); + constexpr float pi = radians(180.f); + constexpr float pi_2 = radians(90.f); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(rotate(float(M_PI_2),0.f,0.f,1.f),float(M_PI_2),0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(rotate(float(M_PI_2),0.f,0.f,1.f),float(M_PI_2),vec3f{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(pi,0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(pi,vec3f{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); + + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,0.f,0.f,1.f),pi_2,0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,0.f,0.f,1.f),pi_2,vec3f{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); } SECTION("scale") { From 545bbf6c3e4308bd63153eacd5dcac08bb81efd9 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 24 Nov 2020 23:58:30 +0700 Subject: [PATCH 21/53] operator += -= *= /= operators --- headers/vmath.hpp/vmath_mat_fun.hpp | 53 +++++++++++++++++++++++++++++ headers/vmath.hpp/vmath_vec_fun.hpp | 48 ++++++++++++++++++++++++++ untests/vmath_mat_fun_tests.cpp | 48 ++++++++++++++++++++++++++ untests/vmath_vec_fun_tests.cpp | 29 ++++++++++++++++ 4 files changed, 178 insertions(+) diff --git a/headers/vmath.hpp/vmath_mat_fun.hpp b/headers/vmath.hpp/vmath_mat_fun.hpp index aa71d47..1039cb6 100644 --- a/headers/vmath.hpp/vmath_mat_fun.hpp +++ b/headers/vmath.hpp/vmath_mat_fun.hpp @@ -107,6 +107,18 @@ namespace vmath_hpp return zip(std::plus<>(), xs, ys); } + // operator+= + + template < typename T, std::size_t Size > + constexpr mat& operator+=(mat& xs, T y) { + return (xs = xs + y); + } + + template < typename T, std::size_t Size > + constexpr mat& operator+=(mat& xs, const mat& ys) { + return (xs = xs + ys); + } + // operator- template < typename T, std::size_t Size > @@ -124,6 +136,18 @@ namespace vmath_hpp return zip(std::minus<>(), xs, ys); } + // operator-= + + template < typename T, std::size_t Size > + constexpr mat& operator-=(mat& xs, T y) { + return (xs = xs - y); + } + + template < typename T, std::size_t Size > + constexpr mat& operator-=(mat& xs, const mat& ys) { + return (xs = xs - ys); + } + // operator* template < typename T, std::size_t Size > @@ -210,6 +234,23 @@ namespace vmath_hpp xs[3][0] * ys[0][3] + xs[3][1] * ys[1][3] + xs[3][2] * ys[2][3] + xs[3][3] * ys[3][3]}; } + // operator*= + + template < typename T, std::size_t Size > + constexpr mat& operator*=(mat& xs, T y) { + return (xs = xs * y); + } + + template < typename T, std::size_t Size > + constexpr vec& operator*=(vec& xs, const mat& ys) { + return (xs = xs * ys); + } + + template < typename T, std::size_t Size > + constexpr mat& operator*=(mat& xs, const mat& ys) { + return (xs = xs * ys); + } + // operator/ template < typename T, std::size_t Size > @@ -227,6 +268,18 @@ namespace vmath_hpp return zip(std::divides<>(), xs, ys); } + // operator/= + + template < typename T, std::size_t Size > + constexpr mat& operator/=(mat& xs, T y) { + return (xs = xs / y); + } + + template < typename T, std::size_t Size > + constexpr mat& operator/=(mat& xs, const mat& ys) { + return (xs = xs / ys); + } + // operator== template < typename T, std::size_t Size > diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index bc77b64..e5a17ac 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -107,6 +107,18 @@ namespace vmath_hpp return zip(std::plus<>(), xs, ys); } + // operator+= + + template < typename T, std::size_t Size > + constexpr vec& operator+=(vec& xs, T y) { + return (xs = xs + y); + } + + template < typename T, std::size_t Size > + constexpr vec& operator+=(vec& xs, const vec& ys) { + return (xs = xs + ys); + } + // operator- template < typename T, std::size_t Size > @@ -124,6 +136,18 @@ namespace vmath_hpp return zip(std::minus<>(), xs, ys); } + // operator-= + + template < typename T, std::size_t Size > + constexpr vec& operator-=(vec& xs, T y) { + return (xs = xs - y); + } + + template < typename T, std::size_t Size > + constexpr vec& operator-=(vec& xs, const vec& ys) { + return (xs = xs - ys); + } + // operator* template < typename T, std::size_t Size > @@ -141,6 +165,18 @@ namespace vmath_hpp return zip(std::multiplies<>(), xs, ys); } + // operator*= + + template < typename T, std::size_t Size > + constexpr vec& operator*=(vec& xs, T y) { + return (xs = xs * y); + } + + template < typename T, std::size_t Size > + constexpr vec& operator*=(vec& xs, const vec& ys) { + return (xs = xs * ys); + } + // operator/ template < typename T, std::size_t Size > @@ -158,6 +194,18 @@ namespace vmath_hpp return zip(std::divides<>(), xs, ys); } + // operator/= + + template < typename T, std::size_t Size > + constexpr vec& operator/=(vec& xs, T y) { + return (xs = xs / y); + } + + template < typename T, std::size_t Size > + constexpr vec& operator/=(vec& xs, const vec& ys) { + return (xs = xs / ys); + } + // operator== template < typename T, std::size_t Size > diff --git a/untests/vmath_mat_fun_tests.cpp b/untests/vmath_mat_fun_tests.cpp index a2d1f97..98e482b 100644 --- a/untests/vmath_mat_fun_tests.cpp +++ b/untests/vmath_mat_fun_tests.cpp @@ -158,6 +158,54 @@ TEST_CASE("vmath/mat_fun") { STATIC_REQUIRE(vec2i(1,2) * mat2i() == vec2i(1,2)); STATIC_REQUIRE(vec3i(1,2,3) * mat3i() == vec3i(1,2,3)); STATIC_REQUIRE(vec4i(1,2,3,4) * mat4i() == vec4i(1,2,3,4)); + + { + mat2i v{1,2,3,4}; + REQUIRE(&v == &(v += 3)); + REQUIRE(v == mat2i{4,5,6,7}); + REQUIRE(&v == &(v += mat2i{1,2,3,4})); + REQUIRE(v == mat2i{5,7,9,11}); + } + { + mat2i v{4,5,6,7}; + REQUIRE(&v == &(v -= 3)); + REQUIRE(v == mat2i{1,2,3,4}); + REQUIRE(&v == &(v -= mat2i{2,4,6,8})); + REQUIRE(v == mat2i{-1,-2,-3,-4}); + } + { + mat2i v{1,2,3,4}; + REQUIRE(&v == &(v *= 3)); + REQUIRE(v == mat2i{3,6,9,12}); + } + { + mat2i v{6,18,36,60}; + REQUIRE(&v == &(v /= 2)); + REQUIRE(v == mat2i{3,9,18,30}); + REQUIRE(&v == &(v /= mat2i{3,4,3,10})); + REQUIRE(v == mat2i{1,2,6,3}); + } + + { + vec4f v{0.f, 0.f, 0.f, 1.f}; + REQUIRE(&v == &(v *= translate(1.f,2.f,3.f))); + REQUIRE(v == approx4(1.f,2.f,3.f,1.f)); + } + { + vec3f v{1.f, 2.f, 3.f}; + REQUIRE(&v == &(v *= mat3f(scale(2.f,3.f,4.f)))); + REQUIRE(v == approx3(2.f,6.f,12.f)); + } + { + mat4f v = translate(1.f, 2.f, 3.f); + REQUIRE(&v == &(v *= translate(1.f,2.f,3.f))); + REQUIRE(v == approx4x4(translate(2.f,4.f,6.f))); + } + { + mat3f v = mat3f(scale(1.f, 2.f, 3.f)); + REQUIRE(&v == &(v *= mat3f(scale(2.f,3.f,4.f)))); + REQUIRE(v == approx3x3(mat3f(scale(2.f,6.f,12.f)))); + } } SECTION("Matrix Functions") { diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index c90660d..2994c6c 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -68,6 +68,35 @@ TEST_CASE("vmath/vec_fun") { STATIC_REQUIRE(vec2i(1,2) - vec2i(3,4) == vec2i(-2,-2)); STATIC_REQUIRE(vec2i(1,2) * vec2i(3,4) == vec2i(3,8)); STATIC_REQUIRE(vec2i(3,4) / vec2i(1,2) == vec2i(3,2)); + + { + vec2i v{1,2}; + REQUIRE(&v == &(v += 3)); + REQUIRE(v == vec2i{4,5}); + REQUIRE(&v == &(v += vec2i{1,2})); + REQUIRE(v == vec2i{5,7}); + } + { + vec2i v{4,5}; + REQUIRE(&v == &(v -= 3)); + REQUIRE(v == vec2i{1,2}); + REQUIRE(&v == &(v -= vec2i{2,4})); + REQUIRE(v == vec2i{-1,-2}); + } + { + vec2i v{1,2}; + REQUIRE(&v == &(v *= 3)); + REQUIRE(v == vec2i{3,6}); + REQUIRE(&v == &(v *= vec2i{2,3})); + REQUIRE(v == vec2i{6,18}); + } + { + vec2i v{6,18}; + REQUIRE(&v == &(v /= 2)); + REQUIRE(v == vec2i{3,9}); + REQUIRE(&v == &(v /= vec2i{3,4})); + REQUIRE(v == vec2i{1,2}); + } } SECTION("Angle and Trigonometry Functions") { From 2b9a6d4951da3fb27ecc1f58b969b5c17bc0f73f Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 25 Nov 2020 18:33:11 +0700 Subject: [PATCH 22/53] move common tests code --- untests/vmath_fun_tests.cpp | 19 ++---- untests/vmath_mat_ext_tests.cpp | 60 +----------------- untests/vmath_mat_fun_tests.cpp | 105 +------------------------------ untests/vmath_mat_tests.cpp | 6 +- untests/vmath_tests.hpp | 107 ++++++++++++++++++++++++++++++++ untests/vmath_vec_fun_tests.cpp | 39 +----------- untests/vmath_vec_tests.cpp | 6 +- 7 files changed, 128 insertions(+), 214 deletions(-) create mode 100644 untests/vmath_tests.hpp diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index ca23017..11da4ac 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -9,26 +9,15 @@ #define CATCH_CONFIG_FAST_COMPILE #include +#include "vmath_tests.hpp" + namespace { - template < typename T > - class approx { - public: - explicit constexpr approx(T v) : value_(v) {} - - friend constexpr bool operator==(const T& l, const approx& r) { - return (r.value_ < l + epsilon) - && (l < r.value_ + epsilon); - } - private: - T value_; - static constexpr T epsilon = std::numeric_limits::epsilon() * 100; - }; + using namespace vmath_hpp; + using namespace vmath_tests; } TEST_CASE("vmath/fun") { - using namespace vmath_hpp; - SECTION("Angle and Trigonometry Functions") { STATIC_REQUIRE(radians(degrees(12.13f)) == approx(12.13f)); STATIC_REQUIRE(degrees(radians(12.13f)) == approx(12.13f)); diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp index d44afa9..0c7b716 100644 --- a/untests/vmath_mat_ext_tests.cpp +++ b/untests/vmath_mat_ext_tests.cpp @@ -9,66 +9,12 @@ #define CATCH_CONFIG_FAST_COMPILE #include +#include "vmath_tests.hpp" + namespace { using namespace vmath_hpp; - - template < typename T > - class approx2 { - public: - constexpr explicit approx2(T v) : value_(v) {} - constexpr explicit approx2(T x, T y) : value_(x, y) {} - - friend constexpr bool operator==(const vec& l, const approx2& r) { - return (r.value_.x < l.x + epsilon) - && (l.x < r.value_.x + epsilon) - && (r.value_.y < l.y + epsilon) - && (l.y < r.value_.y + epsilon); - } - private: - vec value_; - static constexpr T epsilon = std::numeric_limits::epsilon() * 100; - }; - - template < typename T > - class approx3 { - public: - constexpr explicit approx3(T v) : value_(v) {} - constexpr explicit approx3(T x, T y, T z) : value_(x, y, z) {} - - friend constexpr bool operator==(const vec& l, const approx3& r) { - return (r.value_.x < l.x + epsilon) - && (l.x < r.value_.x + epsilon) - && (r.value_.y < l.y + epsilon) - && (l.y < r.value_.y + epsilon) - && (r.value_.z < l.z + epsilon) - && (l.z < r.value_.z + epsilon); - } - private: - vec value_; - static constexpr T epsilon = std::numeric_limits::epsilon() * 100; - }; - - template < typename T > - class approx4 { - public: - constexpr explicit approx4(T v) : value_(v) {} - constexpr explicit approx4(T x, T y, T z, T w) : value_(x, y, z, w) {} - - friend constexpr bool operator==(const vec& l, const approx4& r) { - return (r.value_.x < l.x + epsilon) - && (l.x < r.value_.x + epsilon) - && (r.value_.y < l.y + epsilon) - && (l.y < r.value_.y + epsilon) - && (r.value_.z < l.z + epsilon) - && (l.z < r.value_.z + epsilon) - && (r.value_.w < l.w + epsilon) - && (l.w < r.value_.w + epsilon); - } - private: - vec value_; - static constexpr T epsilon = std::numeric_limits::epsilon() * 100; - }; + using namespace vmath_tests; } TEST_CASE("vmath/mat_ext") { diff --git a/untests/vmath_mat_fun_tests.cpp b/untests/vmath_mat_fun_tests.cpp index 98e482b..068ab4a 100644 --- a/untests/vmath_mat_fun_tests.cpp +++ b/untests/vmath_mat_fun_tests.cpp @@ -10,9 +10,12 @@ #define CATCH_CONFIG_FAST_COMPILE #include +#include "vmath_tests.hpp" + namespace { using namespace vmath_hpp; + using namespace vmath_tests; template < typename T, int Size > constexpr mat generate_frank_matrix() { @@ -30,108 +33,6 @@ namespace } return m; } - - template < typename T > - class approx2 { - public: - constexpr explicit approx2(T v) : value_(v) {} - constexpr explicit approx2(const vec& v) : value_(v) {} - constexpr explicit approx2(T x, T y) : value_(x, y) {} - - friend constexpr bool operator==(const vec& l, const approx2& r) { - return (r.value_.x < l.x + epsilon) - && (l.x < r.value_.x + epsilon) - && (r.value_.y < l.y + epsilon) - && (l.y < r.value_.y + epsilon); - } - private: - vec value_; - static constexpr T epsilon = std::numeric_limits::epsilon() * 100; - }; - - template < typename T > - class approx3 { - public: - constexpr explicit approx3(T v) : value_(v) {} - constexpr explicit approx3(const vec& v) : value_(v) {} - constexpr explicit approx3(T x, T y, T z) : value_(x, y, z) {} - - friend constexpr bool operator==(const vec& l, const approx3& r) { - return (r.value_.x < l.x + epsilon) - && (l.x < r.value_.x + epsilon) - && (r.value_.y < l.y + epsilon) - && (l.y < r.value_.y + epsilon) - && (r.value_.z < l.z + epsilon) - && (l.z < r.value_.z + epsilon); - } - private: - vec value_; - static constexpr T epsilon = std::numeric_limits::epsilon() * 100; - }; - - template < typename T > - class approx4 { - public: - constexpr explicit approx4(T v) : value_(v) {} - constexpr explicit approx4(const vec& v) : value_(v) {} - constexpr explicit approx4(T x, T y, T z, T w) : value_(x, y, z, w) {} - - friend constexpr bool operator==(const vec& l, const approx4& r) { - return (r.value_.x < l.x + epsilon) - && (l.x < r.value_.x + epsilon) - && (r.value_.y < l.y + epsilon) - && (l.y < r.value_.y + epsilon) - && (r.value_.z < l.z + epsilon) - && (l.z < r.value_.z + epsilon) - && (r.value_.w < l.w + epsilon) - && (l.w < r.value_.w + epsilon); - } - private: - vec value_; - static constexpr T epsilon = std::numeric_limits::epsilon() * 100; - }; - - template < typename T > - class approx2x2 { - public: - constexpr explicit approx2x2(const mat& v) : value_(v) {} - - friend constexpr bool operator==(const mat& l, const approx2x2& r) { - return l[0] == approx2(r.value_[0]) - && l[1] == approx2(r.value_[1]); - } - private: - mat value_; - }; - - template < typename T > - class approx3x3 { - public: - constexpr explicit approx3x3(const mat& v) : value_(v) {} - - friend constexpr bool operator==(const mat& l, const approx3x3& r) { - return l[0] == approx3(r.value_[0]) - && l[1] == approx3(r.value_[1]) - && l[2] == approx3(r.value_[2]); - } - private: - mat value_; - }; - - template < typename T > - class approx4x4 { - public: - constexpr explicit approx4x4(const mat& v) : value_(v) {} - - friend constexpr bool operator==(const mat& l, const approx4x4& r) { - return l[0] == approx4(r.value_[0]) - && l[1] == approx4(r.value_[1]) - && l[2] == approx4(r.value_[2]) - && l[3] == approx4(r.value_[3]); - } - private: - mat value_; - }; } TEST_CASE("vmath/mat_fun") { diff --git a/untests/vmath_mat_tests.cpp b/untests/vmath_mat_tests.cpp index 06860b9..1682855 100644 --- a/untests/vmath_mat_tests.cpp +++ b/untests/vmath_mat_tests.cpp @@ -10,13 +10,15 @@ #define CATCH_CONFIG_FAST_COMPILE #include +#include "vmath_tests.hpp" + namespace { + using namespace vmath_hpp; + using namespace vmath_tests; } TEST_CASE("vmath/mat") { - using namespace vmath_hpp; - SECTION("size/sizeof") { STATIC_REQUIRE(mat2i{}.size == 2); STATIC_REQUIRE(mat3i{}.size == 3); diff --git a/untests/vmath_tests.hpp b/untests/vmath_tests.hpp new file mode 100644 index 0000000..5c50b21 --- /dev/null +++ b/untests/vmath_tests.hpp @@ -0,0 +1,107 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include +#include + +#include + +namespace vmath_tests +{ + using namespace vmath_hpp; + + template < typename T > + inline constexpr T epsilon = std::numeric_limits::epsilon() * 100; + + template < typename T > + struct approx { + T value; + explicit constexpr approx(T v) : value(v) {} + + friend constexpr bool operator==(const T& l, const approx& r) { + return (r.value < l + epsilon) + && (l < r.value + epsilon); + } + }; + + template < typename T > + struct approx2 { + vec value; + constexpr explicit approx2(T v) : value(v) {} + constexpr explicit approx2(T x, T y) : value(x, y) {} + constexpr explicit approx2(const vec& v) : value(v) {} + + friend constexpr bool operator==(const vec& l, const approx2& r) { + return l[0] == approx(r.value[0]) + && l[1] == approx(r.value[1]); + } + }; + + template < typename T > + struct approx3 { + vec value; + constexpr explicit approx3(T v) : value(v) {} + constexpr explicit approx3(T x, T y, T z) : value(x, y, z) {} + constexpr explicit approx3(const vec& v) : value(v) {} + + friend constexpr bool operator==(const vec& l, const approx3& r) { + return l[0] == approx(r.value[0]) + && l[1] == approx(r.value[1]) + && l[2] == approx(r.value[2]); + } + }; + + template < typename T > + struct approx4 { + vec value; + constexpr explicit approx4(T v) : value(v) {} + constexpr explicit approx4(T x, T y, T z, T w) : value(x, y, z, w) {} + constexpr explicit approx4(const vec& v) : value(v) {} + + friend constexpr bool operator==(const vec& l, const approx4& r) { + return l[0] == approx(r.value[0]) + && l[1] == approx(r.value[1]) + && l[2] == approx(r.value[2]) + && l[3] == approx(r.value[3]); + } + }; + + template < typename T > + struct approx2x2 { + mat value; + constexpr explicit approx2x2(const mat& v) : value(v) {} + + friend constexpr bool operator==(const mat& l, const approx2x2& r) { + return l[0] == approx2(r.value[0]) + && l[1] == approx2(r.value[1]); + } + }; + + template < typename T > + struct approx3x3 { + mat value; + constexpr explicit approx3x3(const mat& v) : value(v) {} + + friend constexpr bool operator==(const mat& l, const approx3x3& r) { + return l[0] == approx3(r.value[0]) + && l[1] == approx3(r.value[1]) + && l[2] == approx3(r.value[2]); + } + }; + + template < typename T > + struct approx4x4 { + mat value; + constexpr explicit approx4x4(const mat& v) : value(v) {} + + friend constexpr bool operator==(const mat& l, const approx4x4& r) { + return l[0] == approx4(r.value[0]) + && l[1] == approx4(r.value[1]) + && l[2] == approx4(r.value[2]) + && l[3] == approx4(r.value[3]); + } + }; +} diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 2994c6c..612d01b 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -9,45 +9,12 @@ #define CATCH_CONFIG_FAST_COMPILE #include +#include "vmath_tests.hpp" + namespace { using namespace vmath_hpp; - - template < typename T > - class approx2 { - public: - constexpr explicit approx2(T v) : value_(v) {} - constexpr explicit approx2(T x, T y) : value_(x, y) {} - - friend constexpr bool operator==(const vec& l, const approx2& r) { - return (r.value_.x < l.x + epsilon) - && (l.x < r.value_.x + epsilon) - && (r.value_.y < l.y + epsilon) - && (l.y < r.value_.y + epsilon); - } - private: - vec value_; - static constexpr T epsilon = std::numeric_limits::epsilon() * 100; - }; - - template < typename T > - class approx3 { - public: - constexpr explicit approx3(T v) : value_(v) {} - constexpr explicit approx3(T x, T y, T z) : value_(x, y, z) {} - - friend constexpr bool operator==(const vec& l, const approx3& r) { - return (r.value_.x < l.x + epsilon) - && (l.x < r.value_.x + epsilon) - && (r.value_.y < l.y + epsilon) - && (l.y < r.value_.y + epsilon) - && (r.value_.z < l.z + epsilon) - && (l.z < r.value_.z + epsilon); - } - private: - vec value_; - static constexpr T epsilon = std::numeric_limits::epsilon() * 100; - }; + using namespace vmath_tests; } TEST_CASE("vmath/vec_fun") { diff --git a/untests/vmath_vec_tests.cpp b/untests/vmath_vec_tests.cpp index 5129d58..3c9f84c 100644 --- a/untests/vmath_vec_tests.cpp +++ b/untests/vmath_vec_tests.cpp @@ -10,13 +10,15 @@ #define CATCH_CONFIG_FAST_COMPILE #include +#include "vmath_tests.hpp" + namespace { + using namespace vmath_hpp; + using namespace vmath_tests; } TEST_CASE("vmath/vec") { - using namespace vmath_hpp; - SECTION("size/sizeof") { STATIC_REQUIRE(vec2i{}.size == 2); STATIC_REQUIRE(vec3i{}.size == 3); From 7cf4059e32850d30e54692d03a7b3065a2c1fba3 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 25 Nov 2020 18:43:29 +0700 Subject: [PATCH 23/53] saturate function --- headers/vmath.hpp/vmath_fun.hpp | 5 +++++ headers/vmath.hpp/vmath_vec_fun.hpp | 5 +++++ untests/vmath_fun_tests.cpp | 4 ++++ untests/vmath_vec_fun_tests.cpp | 2 ++ 4 files changed, 16 insertions(+) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index 3ea4c4a..3018e8c 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -95,6 +95,11 @@ namespace vmath_hpp return min(max(x, min_x), max_x); } + template < typename T > + constexpr T saturate(T x) noexcept { + return clamp(x, T(0), T(1)); + } + template < typename T > constexpr T mix(T x, T y, T a) noexcept { return x * (T(1) - a) + y * a; diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index e5a17ac..0dbd7ae 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -456,6 +456,11 @@ namespace vmath_hpp return zip([](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 > + constexpr vec saturate(const vec& xs) { + return map([](T x) { return saturate(x); }, xs); + } + template < typename T, std::size_t Size > constexpr vec mix(const vec& xs, const vec& ys, T a) { return zip([a](T x, T y) { return mix(x, y, a); }, xs, ys); diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index 11da4ac..a935a00 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -86,6 +86,10 @@ TEST_CASE("vmath/fun") { STATIC_REQUIRE(clamp(2.5f, 2.f, 3.f) == approx(2.5f)); STATIC_REQUIRE(clamp(3.5f, 2.f, 3.f) == approx(3.0f)); + STATIC_REQUIRE(saturate(-0.5f) == approx(0.f)); + STATIC_REQUIRE(saturate(0.5f) == approx(0.5f)); + STATIC_REQUIRE(saturate(1.5f) == approx(1.f)); + STATIC_REQUIRE(mix(0.f, 10.f, 0.5f) == approx(5.f)); STATIC_REQUIRE(mix(0.f, 10.f, false) == approx(0.f)); STATIC_REQUIRE(mix(0.f, 10.f, true) == approx(10.f)); diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 612d01b..d84e6b9 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -126,6 +126,8 @@ TEST_CASE("vmath/vec_fun") { STATIC_REQUIRE(clamp(vec2i(1,2), 0, 1) == vec2i(1,1)); STATIC_REQUIRE(clamp(vec2i(1,2), vec2i(0), vec2i(1)) == vec2i(1,1)); + STATIC_REQUIRE(saturate(vec3f(-1.f,0.5,1.5f)) == approx3(0.f,0.5f,1.f)); + STATIC_REQUIRE(mix(vec2f(0.f), vec2f(10.f), 0.5f) == approx2(5.f)); STATIC_REQUIRE(mix(vec2f(0.f), vec2f(10.f), vec2f(0.5f)) == approx2(5.f)); From e589c03c538426294c4ba6c2a4cf34f87d1e5fe9 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 25 Nov 2020 18:47:44 +0700 Subject: [PATCH 24/53] isfinite function --- headers/vmath.hpp/vmath_fun.hpp | 3 ++- headers/vmath.hpp/vmath_vec_fun.hpp | 5 +++++ untests/vmath_fun_tests.cpp | 1 + untests/vmath_vec_fun_tests.cpp | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index 3018e8c..e1059d9 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -123,8 +123,9 @@ namespace vmath_hpp using ::std::isnan; using ::std::isinf; - using ::std::fma; + using ::std::isfinite; + using ::std::fma; using ::std::frexp; using ::std::ldexp; } diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index 0dbd7ae..c79cc1e 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -511,6 +511,11 @@ namespace vmath_hpp return map([](T x) { return isinf(x); }, xs); } + template < typename T, std::size_t Size > + vec isfinite(const vec& xs) { + return map([](T x) { return isfinite(x); }, xs); + } + template < typename T, std::size_t Size > vec fma(const vec& as, const vec& bs, const vec& cs) { return zip([](T a, T b, T c) { return fma(a, b, c); }, as, bs, cs); diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index a935a00..2db00a1 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -99,6 +99,7 @@ TEST_CASE("vmath/fun") { REQUIRE_FALSE(isnan(1.f)); REQUIRE_FALSE(isinf(1.f)); + REQUIRE(isfinite(1.f)); REQUIRE(fma(2.f, 3.f, 4.f) == approx(10.f)); diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index d84e6b9..247716d 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -147,6 +147,7 @@ TEST_CASE("vmath/vec_fun") { REQUIRE_FALSE(isnan(vec2f(1.f)).x); REQUIRE_FALSE(isinf(vec2f(1.f)).x); + REQUIRE(isfinite(vec2f(1.f)).x); REQUIRE_FALSE(fma(vec2f(2.f), vec2f(3.f), vec2f(4.f)).x == Approx(12.f)); From 8dd4ccc08b8236e2622e41b504d2153d3cf3cc4a Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 25 Nov 2020 18:55:41 +0700 Subject: [PATCH 25/53] lerp instead mix --- headers/vmath.hpp/vmath_fun.hpp | 7 +------ headers/vmath.hpp/vmath_vec_fun.hpp | 18 ++++-------------- untests/vmath_fun_tests.cpp | 4 +--- untests/vmath_vec_fun_tests.cpp | 10 ++-------- 4 files changed, 8 insertions(+), 31 deletions(-) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index e1059d9..d317b20 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -101,15 +101,10 @@ namespace vmath_hpp } template < typename T > - constexpr T mix(T x, T y, T a) noexcept { + constexpr T lerp(T x, T y, T a) noexcept { return x * (T(1) - a) + y * a; } - template < typename T > - constexpr T mix(T x, T y, bool a) noexcept { - return a ? y : x; - } - template < typename T > constexpr T step(T edge, T x) noexcept { return x < edge ? T(0) : T(1); diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index c79cc1e..7429762 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -462,23 +462,13 @@ namespace vmath_hpp } template < typename T, std::size_t Size > - constexpr vec mix(const vec& xs, const vec& ys, T a) { - return zip([a](T x, T y) { return mix(x, y, a); }, xs, ys); + constexpr vec lerp(const vec& xs, const vec& ys, T a) { + return zip([a](T x, T y) { return lerp(x, y, a); }, xs, ys); } template < typename T, std::size_t Size > - constexpr vec mix(const vec& xs, const vec& ys, bool a) { - return zip([a](T x, T y) { return mix(x, y, a); }, xs, ys); - } - - template < typename T, std::size_t Size > - constexpr vec mix(const vec& xs, const vec& ys, const vec& as) { - return zip([](T x, T y, T a) { return mix(x, y, a); }, xs, ys, as); - } - - template < typename T, std::size_t Size > - constexpr vec mix(const vec& xs, const vec& ys, const vec& as) { - return zip([](T x, T y, bool a) { return mix(x, y, a); }, xs, ys, as); + constexpr vec lerp(const vec& xs, const vec& ys, const vec& as) { + return zip([](T x, T y, T a) { return lerp(x, y, a); }, xs, ys, as); } template < typename T, std::size_t Size > diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index 2db00a1..419a4f3 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -90,9 +90,7 @@ TEST_CASE("vmath/fun") { STATIC_REQUIRE(saturate(0.5f) == approx(0.5f)); STATIC_REQUIRE(saturate(1.5f) == approx(1.f)); - STATIC_REQUIRE(mix(0.f, 10.f, 0.5f) == approx(5.f)); - STATIC_REQUIRE(mix(0.f, 10.f, false) == approx(0.f)); - STATIC_REQUIRE(mix(0.f, 10.f, true) == approx(10.f)); + STATIC_REQUIRE(lerp(0.f, 10.f, 0.5f) == approx(5.f)); STATIC_REQUIRE(step(0.5f, 0.4f) == approx(0.f)); STATIC_REQUIRE(step(0.5f, 0.6f) == approx(1.f)); STATIC_REQUIRE(smoothstep(0.f, 1.f, 0.1f) == approx(0.028f)); diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 247716d..6cd0631 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -128,14 +128,8 @@ TEST_CASE("vmath/vec_fun") { STATIC_REQUIRE(saturate(vec3f(-1.f,0.5,1.5f)) == approx3(0.f,0.5f,1.f)); - STATIC_REQUIRE(mix(vec2f(0.f), vec2f(10.f), 0.5f) == approx2(5.f)); - STATIC_REQUIRE(mix(vec2f(0.f), vec2f(10.f), vec2f(0.5f)) == approx2(5.f)); - - STATIC_REQUIRE(mix(vec2f(0.f), vec2f(10.f), true) == approx2(10.f)); - STATIC_REQUIRE(mix(vec2f(0.f), vec2f(10.f), false) == approx2(0.f)); - - STATIC_REQUIRE(mix(vec2f(0.f,5.f), vec2f(10.f,20.f), vec2f(true,false)) == approx2(10.f, 5.f)); - STATIC_REQUIRE(mix(vec2f(0.f,5.f), vec2f(10.f,20.f), vec2f(true,false)) == approx2(10.f, 5.f)); + STATIC_REQUIRE(lerp(vec2f(0.f), vec2f(10.f), 0.5f) == approx2(5.f)); + STATIC_REQUIRE(lerp(vec2f(0.f), vec2f(10.f), vec2f(0.5f)) == approx2(5.f)); STATIC_REQUIRE(step(0.5f, vec2f(0.4f)) == approx2(0.f)); STATIC_REQUIRE(step(0.5f, vec2f(0.6f)) == approx2(1.f)); From ba60d415443b3e95b272e7facb21523caeb3d9be Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 25 Nov 2020 18:56:13 +0700 Subject: [PATCH 26/53] vecNz and matNz typedefs --- headers/vmath.hpp/vmath_fwd.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/headers/vmath.hpp/vmath_fwd.hpp b/headers/vmath.hpp/vmath_fwd.hpp index be41369..6121c00 100644 --- a/headers/vmath.hpp/vmath_fwd.hpp +++ b/headers/vmath.hpp/vmath_fwd.hpp @@ -41,6 +41,10 @@ namespace vmath_hpp using vec2u = vec; using vec3u = vec; using vec4u = vec; + + using vec2z = vec; + using vec3z = vec; + using vec4z = vec; } namespace vmath_hpp @@ -67,4 +71,8 @@ namespace vmath_hpp using mat2u = mat; using mat3u = mat; using mat4u = mat; + + using mat2z = mat; + using mat3z = mat; + using mat4z = mat; } From a8e34285eee8091ce55d7d90063b3d02907eead6 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 25 Nov 2020 20:13:02 +0700 Subject: [PATCH 27/53] length2 and distance2 --- headers/vmath.hpp/vmath_fun.hpp | 22 ++++++++++++++++------ headers/vmath.hpp/vmath_vec_fun.hpp | 24 ++++++++++++++++++------ untests/vmath_fun_tests.cpp | 10 ++++++++-- untests/vmath_vec_fun_tests.cpp | 10 ++++++++-- 4 files changed, 50 insertions(+), 16 deletions(-) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index d317b20..aca7938 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -131,19 +131,29 @@ namespace vmath_hpp namespace vmath_hpp { + template < typename T > + constexpr T dot(T x, T y) noexcept { + return x * y; + } + template < typename T > T length(T x) noexcept { return abs(x); } template < typename T > - T distance(T x, T y) noexcept { - return length(x - y); + constexpr T length2(T x) noexcept { + return dot(x, x); } template < typename T > - T dot(T x, T y) noexcept { - return x * y; + T distance(T x, T y) noexcept { + return length(y - x); + } + + template < typename T > + constexpr T distance2(T x, T y) noexcept { + return length2(y - x); } template < typename T > @@ -152,12 +162,12 @@ namespace vmath_hpp } template < typename T > - T faceforward(T n, T i, T nref) noexcept { + constexpr T faceforward(T n, T i, T nref) noexcept { return dot(nref, i) < T(0) ? n : -n; } template < typename T > - T reflect(T i, T n) noexcept { + constexpr T reflect(T i, T n) noexcept { return i - n * dot(n, i) * T(2); } diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index 7429762..9e914a1 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -536,19 +536,31 @@ namespace vmath_hpp namespace vmath_hpp { + template < typename T, std::size_t Size > + constexpr T dot(const vec& xs, const vec& ys) { + return fold([](T acc, T x, T y){ + return acc + (x * y); + }, T(0), xs, ys); + } + template < typename T, std::size_t Size > T length(const vec& xs) { return sqrt(dot(xs, xs)); } template < typename T, std::size_t Size > - T distance(const vec& xs, const vec& ys) { - return length(xs - ys); + constexpr T length2(const vec& xs) { + return dot(xs, xs); } template < typename T, std::size_t Size > - constexpr T dot(const vec& xs, const vec& ys) { - return fold(std::plus<>(), T(0), zip(std::multiplies<>(), xs, ys)); + T distance(const vec& xs, const vec& ys) { + return length(ys - xs); + } + + template < typename T, std::size_t Size > + constexpr T distance2(const vec& xs, const vec& ys) { + return length2(ys - xs); } template < typename T > @@ -565,12 +577,12 @@ namespace vmath_hpp } template < typename T, std::size_t Size > - vec faceforward(const vec& n, const vec& i, const vec& nref) { + constexpr vec faceforward(const vec& n, const vec& i, const vec& nref) { return dot(nref, i) < T(0) ? n : -n; } template < typename T, std::size_t Size > - vec reflect(const vec& i, const vec& n) { + constexpr vec reflect(const vec& i, const vec& n) { return i - n * dot(n, i) * T(2); } diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index 419a4f3..72ed18c 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -114,14 +114,20 @@ TEST_CASE("vmath/fun") { REQUIRE(length(10.f) == approx(10.f)); REQUIRE(length(-10.f) == approx(10.f)); + STATIC_REQUIRE(length2(10.f) == approx(100.f)); + STATIC_REQUIRE(length2(-10.f) == approx(100.f)); + REQUIRE(distance(5.f, 10.f) == approx(5.f)); REQUIRE(distance(-5.f, -10.f) == approx(5.f)); + STATIC_REQUIRE(distance2(5.f, 10.f) == approx(25.f)); + STATIC_REQUIRE(distance2(-5.f, -10.f) == approx(25.f)); + REQUIRE(dot(2.f, 5.f) == approx(10.f)); REQUIRE(normalize(0.5f) == approx(1.f)); - REQUIRE(faceforward(1.f, 2.f, 3.f) == approx(-1.f)); - REQUIRE(reflect(1.f, 2.f) == approx(-7.f)); + STATIC_REQUIRE(faceforward(1.f, 2.f, 3.f) == approx(-1.f)); + STATIC_REQUIRE(reflect(1.f, 2.f) == approx(-7.f)); REQUIRE(refract(1.f, 2.f, 1.f) == approx(-7.f)); } } diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 6cd0631..11f4221 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -158,15 +158,21 @@ TEST_CASE("vmath/vec_fun") { REQUIRE(length(vec2f(10.f,0.f)) == Approx(10.f)); REQUIRE(length(vec2f(-10.f,0.f)) == Approx(10.f)); + STATIC_REQUIRE(length2(vec2f(10.f,0.f)) == approx(100.f)); + STATIC_REQUIRE(length2(vec2f(-10.f,0.f)) == approx(100.f)); + REQUIRE(distance(vec2f(5.f,0.f), vec2f(10.f,0.f)) == Approx(5.f)); REQUIRE(distance(vec2f(-5.f,0.f), vec2f(-10.f,0.f)) == Approx(5.f)); + STATIC_REQUIRE(distance2(vec2f(5.f,0.f), vec2f(10.f,0.f)) == approx(25.f)); + STATIC_REQUIRE(distance2(vec2f(-5.f,0.f), vec2f(-10.f,0.f)) == approx(25.f)); + STATIC_REQUIRE(dot(vec2i(1,2),vec2i(3,4)) == 11); STATIC_REQUIRE(cross(vec3i(1,0,0),vec3i(0,1,0)) == vec3i(0,0,1)); REQUIRE(normalize(vec2f(0.5f,0.f)).x == Approx(1.f)); - REQUIRE(faceforward(vec2f(1.f), vec2f(2.f), vec2f(3.f)).x == Approx(-1.f)); - REQUIRE(reflect(vec2f(1.f), vec2f(2.f)).x == Approx(-15.f)); + STATIC_REQUIRE(faceforward(vec2f(1.f), vec2f(2.f), vec2f(3.f)).x == approx(-1.f)); + STATIC_REQUIRE(reflect(vec2f(1.f), vec2f(2.f)).x == approx(-15.f)); REQUIRE(refract(vec2f(1.f), vec2f(2.f), 1.f).x == Approx(-15.f)); } From bf3baf9c64d917d29a97e3301635be25ebf792e5 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 25 Nov 2020 20:32:27 +0700 Subject: [PATCH 28/53] cast_to --- headers/vmath.hpp/vmath.hpp | 2 ++ headers/vmath.hpp/vmath_ext.hpp | 19 +++++++++++++++++++ headers/vmath.hpp/vmath_mat_ext.hpp | 14 ++++++++++++++ headers/vmath.hpp/vmath_vec_ext.hpp | 23 +++++++++++++++++++++++ untests/vmath_ext_tests.cpp | 26 ++++++++++++++++++++++++++ untests/vmath_mat_ext_tests.cpp | 6 ++++++ untests/vmath_vec_ext_tests.cpp | 26 ++++++++++++++++++++++++++ 7 files changed, 116 insertions(+) create mode 100644 headers/vmath.hpp/vmath_ext.hpp create mode 100644 headers/vmath.hpp/vmath_vec_ext.hpp create mode 100644 untests/vmath_ext_tests.cpp create mode 100644 untests/vmath_vec_ext_tests.cpp diff --git a/headers/vmath.hpp/vmath.hpp b/headers/vmath.hpp/vmath.hpp index 770ce34..5353745 100644 --- a/headers/vmath.hpp/vmath.hpp +++ b/headers/vmath.hpp/vmath.hpp @@ -9,5 +9,7 @@ #include "vmath_fun.hpp" #include "vmath_mat.hpp" #include "vmath_mat_fun.hpp" +#include "vmath_mat_ext.hpp" #include "vmath_vec.hpp" #include "vmath_vec_fun.hpp" +#include "vmath_vec_ext.hpp" diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp new file mode 100644 index 0000000..1dd9b72 --- /dev/null +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -0,0 +1,19 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "vmath_fwd.hpp" + +#include "vmath_fun.hpp" + +namespace vmath_hpp +{ + template < typename To, typename From > + constexpr To cast_to(From x) noexcept { + return static_cast(x); + } +} diff --git a/headers/vmath.hpp/vmath_mat_ext.hpp b/headers/vmath.hpp/vmath_mat_ext.hpp index bd431d7..11974e7 100644 --- a/headers/vmath.hpp/vmath_mat_ext.hpp +++ b/headers/vmath.hpp/vmath_mat_ext.hpp @@ -8,10 +8,24 @@ #include "vmath_fwd.hpp" +#include "vmath_ext.hpp" #include "vmath_fun.hpp" + +#include "vmath_vec.hpp" +#include "vmath_vec_fun.hpp" +#include "vmath_vec_ext.hpp" + #include "vmath_mat.hpp" #include "vmath_mat_fun.hpp" +namespace vmath_hpp +{ + template < typename To, typename From, std::size_t Size > + constexpr mat cast_to(const mat& xs) { + return detail::map([](const vec& x){ return cast_to(x); }, xs); + } +} + namespace vmath_hpp { // identity diff --git a/headers/vmath.hpp/vmath_vec_ext.hpp b/headers/vmath.hpp/vmath_vec_ext.hpp new file mode 100644 index 0000000..31095bc --- /dev/null +++ b/headers/vmath.hpp/vmath_vec_ext.hpp @@ -0,0 +1,23 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "vmath_fwd.hpp" + +#include "vmath_ext.hpp" +#include "vmath_fun.hpp" + +#include "vmath_vec.hpp" +#include "vmath_vec_fun.hpp" + +namespace vmath_hpp +{ + template < typename To, typename From, std::size_t Size > + constexpr vec cast_to(const vec& xs) { + return detail::map([](From x){ return cast_to(x); }, xs); + } +} diff --git a/untests/vmath_ext_tests.cpp b/untests/vmath_ext_tests.cpp new file mode 100644 index 0000000..8a30350 --- /dev/null +++ b/untests/vmath_ext_tests.cpp @@ -0,0 +1,26 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include + +#define CATCH_CONFIG_FAST_COMPILE +#include + +#include "vmath_tests.hpp" + +namespace +{ + using namespace vmath_hpp; + using namespace vmath_tests; +} + +TEST_CASE("vmath/ext") { + SECTION("cast_to") { + constexpr auto i = cast_to(1.5f); + STATIC_REQUIRE(i == 1); + STATIC_REQUIRE(std::is_same_v); + } +} diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp index 0c7b716..403ee2f 100644 --- a/untests/vmath_mat_ext_tests.cpp +++ b/untests/vmath_mat_ext_tests.cpp @@ -18,6 +18,12 @@ namespace } TEST_CASE("vmath/mat_ext") { + SECTION("cast_to") { + constexpr auto m = cast_to(mat2f{1.5f}); + STATIC_REQUIRE(m == mat2i(1)); + STATIC_REQUIRE(std::is_same_v); + } + SECTION("identity") { STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); diff --git a/untests/vmath_vec_ext_tests.cpp b/untests/vmath_vec_ext_tests.cpp new file mode 100644 index 0000000..fa1f794 --- /dev/null +++ b/untests/vmath_vec_ext_tests.cpp @@ -0,0 +1,26 @@ +/******************************************************************************* + * 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, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include + +#define CATCH_CONFIG_FAST_COMPILE +#include + +#include "vmath_tests.hpp" + +namespace +{ + using namespace vmath_hpp; + using namespace vmath_tests; +} + +TEST_CASE("vmath/vec_ext") { + SECTION("cast_to") { + constexpr auto v = cast_to(vec2f{1.5f}); + STATIC_REQUIRE(v == vec2i(1)); + STATIC_REQUIRE(std::is_same_v); + } +} From 65699f6b0f0ddeb0678af33658233599e062e23a Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 25 Nov 2020 22:30:17 +0700 Subject: [PATCH 29/53] row, column, component --- headers/vmath.hpp/vmath_mat_ext.hpp | 44 +++++++++++++++++++++++++++-- headers/vmath.hpp/vmath_vec_ext.hpp | 19 +++++++++++-- untests/vmath_mat_ext_tests.cpp | 16 +++++++++++ untests/vmath_vec_ext_tests.cpp | 8 ++++++ 4 files changed, 83 insertions(+), 4 deletions(-) diff --git a/headers/vmath.hpp/vmath_mat_ext.hpp b/headers/vmath.hpp/vmath_mat_ext.hpp index 11974e7..6639501 100644 --- a/headers/vmath.hpp/vmath_mat_ext.hpp +++ b/headers/vmath.hpp/vmath_mat_ext.hpp @@ -20,9 +20,49 @@ namespace vmath_hpp { + // cast_to + template < typename To, typename From, std::size_t Size > - constexpr mat cast_to(const mat& xs) { - return detail::map([](const vec& x){ return cast_to(x); }, xs); + constexpr mat cast_to(const mat& m) { + return detail::map([](const vec& v){ return cast_to(v); }, m); + } + + // row + + template < typename T, std::size_t Size > + constexpr vec row(const mat& m, std::size_t index) { + return m.rows[index]; + } + + template < typename T, std::size_t Size > + constexpr mat row(mat m, std::size_t index, const vec& v) { + m.rows[index] = v; + return m; + } + + // column + + namespace impl + { + template < typename T, std::size_t Size, std::size_t... Is > + constexpr vec column_impl(const mat& m, std::size_t index, std::index_sequence) { + return { m[Is][index]... }; + } + + template < typename T, std::size_t Size, std::size_t... Is > + constexpr mat column_impl(const mat& m, std::size_t index, const vec& v, std::index_sequence) { + return { component(m[Is], index, v[Is])... }; + } + } + + template < typename T, std::size_t Size > + constexpr vec column(const mat& m, std::size_t index) { + return impl::column_impl(m, index, std::make_index_sequence{}); + } + + template < typename T, std::size_t Size > + constexpr mat column(const mat& m, std::size_t index, const vec& v) { + return impl::column_impl(m, index, v, std::make_index_sequence{}); } } diff --git a/headers/vmath.hpp/vmath_vec_ext.hpp b/headers/vmath.hpp/vmath_vec_ext.hpp index 31095bc..84dd79d 100644 --- a/headers/vmath.hpp/vmath_vec_ext.hpp +++ b/headers/vmath.hpp/vmath_vec_ext.hpp @@ -16,8 +16,23 @@ namespace vmath_hpp { + // cast_to + template < typename To, typename From, std::size_t Size > - constexpr vec cast_to(const vec& xs) { - return detail::map([](From x){ return cast_to(x); }, xs); + constexpr vec cast_to(const vec& v) { + return detail::map([](From x){ return cast_to(x); }, v); + } + + // component + + template < typename T, std::size_t Size > + constexpr T component(const vec& v, std::size_t index) { + return v[index]; + } + + template < typename T, std::size_t Size > + constexpr vec component(vec v, std::size_t index, T x) { + v[index] = x; + return v; } } diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp index 403ee2f..342ffd3 100644 --- a/untests/vmath_mat_ext_tests.cpp +++ b/untests/vmath_mat_ext_tests.cpp @@ -24,6 +24,22 @@ TEST_CASE("vmath/mat_ext") { STATIC_REQUIRE(std::is_same_v); } + SECTION("row") { + STATIC_REQUIRE(row(mat2i(1,2,3,4), 0) == vec2i(1,2)); + STATIC_REQUIRE(row(mat2i(1,2,3,4), 1) == vec2i(3,4)); + + STATIC_REQUIRE(row(mat2i(), 0, {1,2}) == mat2i(1,2,0,1)); + STATIC_REQUIRE(row(mat2i(), 1, {3,4}) == mat2i(1,0,3,4)); + } + + SECTION("column") { + STATIC_REQUIRE(column(mat2i(1,2,3,4), 0) == vec2i(1,3)); + STATIC_REQUIRE(column(mat2i(1,2,3,4), 1) == vec2i(2,4)); + + STATIC_REQUIRE(column(mat2i(), 0, {2,3}) == mat2i(2,0,3,1)); + STATIC_REQUIRE(column(mat2i(), 1, {3,4}) == mat2i(1,3,0,4)); + } + SECTION("identity") { STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); diff --git a/untests/vmath_vec_ext_tests.cpp b/untests/vmath_vec_ext_tests.cpp index fa1f794..a013df2 100644 --- a/untests/vmath_vec_ext_tests.cpp +++ b/untests/vmath_vec_ext_tests.cpp @@ -23,4 +23,12 @@ TEST_CASE("vmath/vec_ext") { STATIC_REQUIRE(v == vec2i(1)); STATIC_REQUIRE(std::is_same_v); } + + SECTION("component") { + STATIC_REQUIRE(component(vec2i{1,2}, 0) == 1); + STATIC_REQUIRE(component(vec2i{1,2}, 1) == 2); + + STATIC_REQUIRE(component(vec2i{0,0}, 0, 1) == vec2i{1,0}); + STATIC_REQUIRE(component(vec2i{0,0}, 1, 2) == vec2i{0,2}); + } } From 88f1ca95fd7509cc07b2e99f93cb149713f72134 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 25 Nov 2020 23:10:52 +0700 Subject: [PATCH 30/53] std hash support --- headers/vmath.hpp/vmath_ext.hpp | 10 ++++++++++ headers/vmath.hpp/vmath_mat_ext.hpp | 10 ++++++++++ headers/vmath.hpp/vmath_vec_ext.hpp | 10 ++++++++++ untests/vmath_mat_ext_tests.cpp | 5 +++++ untests/vmath_vec_ext_tests.cpp | 11 +++++++++++ 5 files changed, 46 insertions(+) diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index 1dd9b72..a5a0c02 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -10,6 +10,16 @@ #include "vmath_fun.hpp" +namespace vmath_hpp::detail +{ + struct hash_combiner { + template < typename T > + std::size_t operator()(std::size_t seed, const T& x) noexcept { + return (seed ^= std::hash{}(x) + 0x9e3779b9 + (seed << 6) + ( seed >> 2)); + } + }; +} + namespace vmath_hpp { template < typename To, typename From > diff --git a/headers/vmath.hpp/vmath_mat_ext.hpp b/headers/vmath.hpp/vmath_mat_ext.hpp index 6639501..bf6494d 100644 --- a/headers/vmath.hpp/vmath_mat_ext.hpp +++ b/headers/vmath.hpp/vmath_mat_ext.hpp @@ -18,6 +18,16 @@ #include "vmath_mat.hpp" #include "vmath_mat_fun.hpp" +namespace std +{ + template < typename T, size_t Size > + struct hash> { + size_t operator()(const vmath_hpp::mat& m) const noexcept { + return vmath_hpp::detail::fold(vmath_hpp::detail::hash_combiner{}, size_t{}, m); + } + }; +} + namespace vmath_hpp { // cast_to diff --git a/headers/vmath.hpp/vmath_vec_ext.hpp b/headers/vmath.hpp/vmath_vec_ext.hpp index 84dd79d..75b3019 100644 --- a/headers/vmath.hpp/vmath_vec_ext.hpp +++ b/headers/vmath.hpp/vmath_vec_ext.hpp @@ -14,6 +14,16 @@ #include "vmath_vec.hpp" #include "vmath_vec_fun.hpp" +namespace std +{ + template < typename T, size_t Size > + struct hash> { + size_t operator()(const vmath_hpp::vec& v) const noexcept { + return vmath_hpp::detail::fold(vmath_hpp::detail::hash_combiner{}, size_t{}, v); + } + }; +} + namespace vmath_hpp { // cast_to diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp index 342ffd3..9cceae5 100644 --- a/untests/vmath_mat_ext_tests.cpp +++ b/untests/vmath_mat_ext_tests.cpp @@ -18,6 +18,11 @@ namespace } TEST_CASE("vmath/mat_ext") { + SECTION("hash") { + REQUIRE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,3,4})); + REQUIRE_FALSE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,4,3})); + } + SECTION("cast_to") { constexpr auto m = cast_to(mat2f{1.5f}); STATIC_REQUIRE(m == mat2i(1)); diff --git a/untests/vmath_vec_ext_tests.cpp b/untests/vmath_vec_ext_tests.cpp index a013df2..0db5f33 100644 --- a/untests/vmath_vec_ext_tests.cpp +++ b/untests/vmath_vec_ext_tests.cpp @@ -18,6 +18,17 @@ namespace } TEST_CASE("vmath/vec_ext") { + SECTION("hash") { + REQUIRE(std::hash{}({1,2}) == std::hash{}({1,2})); + REQUIRE_FALSE(std::hash{}({1,2}) == std::hash{}({2,1})); + + REQUIRE(std::hash{}({1,2,3}) == std::hash{}({1,2,3})); + REQUIRE_FALSE(std::hash{}({1,2,3}) == std::hash{}({3,2,1})); + + REQUIRE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,3,4})); + REQUIRE_FALSE(std::hash{}({1,2,3,4}) == std::hash{}({3,2,1,4})); + } + SECTION("cast_to") { constexpr auto v = cast_to(vec2f{1.5f}); STATIC_REQUIRE(v == vec2i(1)); From bccb1f60f10764bce74c9d233f21c3e65850f33b Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 25 Nov 2020 23:46:58 +0700 Subject: [PATCH 31/53] vector and matrix predef units --- headers/vmath.hpp/vmath_mat_ext.hpp | 15 +++++++++++++++ headers/vmath.hpp/vmath_vec_ext.hpp | 23 +++++++++++++++++++++++ untests/vmath_mat_ext_tests.cpp | 14 ++++++++++++++ untests/vmath_vec_ext_tests.cpp | 21 +++++++++++++++++++++ 4 files changed, 73 insertions(+) diff --git a/headers/vmath.hpp/vmath_mat_ext.hpp b/headers/vmath.hpp/vmath_mat_ext.hpp index bf6494d..ae33bf1 100644 --- a/headers/vmath.hpp/vmath_mat_ext.hpp +++ b/headers/vmath.hpp/vmath_mat_ext.hpp @@ -18,6 +18,21 @@ #include "vmath_mat.hpp" #include "vmath_mat_fun.hpp" +namespace vmath_hpp +{ + template < typename T > constexpr mat zero2x2() { return {0, 0, 0, 0}; } + template < typename T > constexpr mat zero3x3() { return {0, 0, 0, 0, 0, 0, 0, 0, 0}; } + template < typename T > constexpr mat zero4x4() { return {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; } + + template < typename T > constexpr mat unit2x2() { return {1, 1, 1, 1}; } + template < typename T > constexpr mat unit3x3() { return {1, 1, 1, 1, 1, 1, 1, 1, 1}; } + template < typename T > constexpr mat unit4x4() { return {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; } + + template < typename T > constexpr mat identity2x2() { return {1, 0, 0, 1}; } + template < typename T > constexpr mat identity3x3() { return {1, 0, 0, 0, 1, 0, 0, 0, 1}; } + template < typename T > constexpr mat identity4x4() { return {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; } +} + namespace std { template < typename T, size_t Size > diff --git a/headers/vmath.hpp/vmath_vec_ext.hpp b/headers/vmath.hpp/vmath_vec_ext.hpp index 75b3019..f47069e 100644 --- a/headers/vmath.hpp/vmath_vec_ext.hpp +++ b/headers/vmath.hpp/vmath_vec_ext.hpp @@ -14,6 +14,29 @@ #include "vmath_vec.hpp" #include "vmath_vec_fun.hpp" +namespace vmath_hpp +{ + template < typename T > constexpr vec zero2() { return {0, 0}; } + template < typename T > constexpr vec zero3() { return {0, 0, 0}; } + template < typename T > constexpr vec zero4() { return {0, 0, 0, 0}; } + + template < typename T > constexpr vec unit2() { return {1, 1}; } + template < typename T > constexpr vec unit3() { return {1, 1, 1}; } + template < typename T > constexpr vec unit4() { return {1, 1, 1, 1}; } + + template < typename T > constexpr vec unit2_x() { return {1, 0}; } + template < typename T > constexpr vec unit2_y() { return {0, 1}; } + + template < typename T > constexpr vec unit3_x() { return {1, 0, 0}; } + template < typename T > constexpr vec unit3_y() { return {0, 1, 0}; } + template < typename T > constexpr vec unit3_z() { return {0, 0, 1}; } + + template < typename T > constexpr vec unit4_x() { return {1, 0, 0, 0}; } + template < typename T > constexpr vec unit4_y() { return {0, 1, 0, 0}; } + template < typename T > constexpr vec unit4_z() { return {0, 0, 1, 0}; } + template < typename T > constexpr vec unit4_w() { return {0, 0, 0, 1}; } +} + namespace std { template < typename T, size_t Size > diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp index 9cceae5..cb09f10 100644 --- a/untests/vmath_mat_ext_tests.cpp +++ b/untests/vmath_mat_ext_tests.cpp @@ -18,6 +18,20 @@ namespace } TEST_CASE("vmath/mat_ext") { + SECTION("units") { + STATIC_REQUIRE(zero2x2() == mat2i(0,0,0,0)); + STATIC_REQUIRE(zero3x3() == mat3i(0,0,0,0,0,0,0,0,0)); + STATIC_REQUIRE(zero4x4() == mat4i(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)); + + STATIC_REQUIRE(unit2x2() == mat2i(1,1,1,1)); + STATIC_REQUIRE(unit3x3() == mat3i(1,1,1,1,1,1,1,1,1)); + STATIC_REQUIRE(unit4x4() == mat4i(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)); + + STATIC_REQUIRE(identity2x2() == mat2i()); + STATIC_REQUIRE(identity3x3() == mat3i()); + STATIC_REQUIRE(identity4x4() == mat4i()); + } + SECTION("hash") { REQUIRE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,3,4})); REQUIRE_FALSE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,4,3})); diff --git a/untests/vmath_vec_ext_tests.cpp b/untests/vmath_vec_ext_tests.cpp index 0db5f33..0fcdbb5 100644 --- a/untests/vmath_vec_ext_tests.cpp +++ b/untests/vmath_vec_ext_tests.cpp @@ -18,6 +18,27 @@ namespace } TEST_CASE("vmath/vec_ext") { + SECTION("units") { + STATIC_REQUIRE(zero2() == vec2i(0,0)); + STATIC_REQUIRE(zero3() == vec3i(0,0,0)); + STATIC_REQUIRE(zero4() == vec4i(0,0,0,0)); + + STATIC_REQUIRE(unit2() == vec2i(1,1)); + STATIC_REQUIRE(unit2_x() == vec2i(1,0)); + STATIC_REQUIRE(unit2_y() == vec2i(0,1)); + + STATIC_REQUIRE(unit3() == vec3i(1,1,1)); + STATIC_REQUIRE(unit3_x() == vec3i(1,0,0)); + STATIC_REQUIRE(unit3_y() == vec3i(0,1,0)); + STATIC_REQUIRE(unit3_z() == vec3i(0,0,1)); + + STATIC_REQUIRE(unit4() == vec4i(1,1,1,1)); + STATIC_REQUIRE(unit4_x() == vec4i(1,0,0,0)); + STATIC_REQUIRE(unit4_y() == vec4i(0,1,0,0)); + STATIC_REQUIRE(unit4_z() == vec4i(0,0,1,0)); + STATIC_REQUIRE(unit4_w() == vec4i(0,0,0,1)); + } + SECTION("hash") { REQUIRE(std::hash{}({1,2}) == std::hash{}({1,2})); REQUIRE_FALSE(std::hash{}({1,2}) == std::hash{}({2,1})); From 7805d57ba7b13fbbfd4772279db9c21012e82c6b Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 25 Nov 2020 23:49:18 +0700 Subject: [PATCH 32/53] vec2 cross --- headers/vmath.hpp/vmath_vec_fun.hpp | 5 +++++ untests/vmath_vec_fun_tests.cpp | 1 + 2 files changed, 6 insertions(+) diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index 9e914a1..eb4ac90 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -563,6 +563,11 @@ namespace vmath_hpp return length2(ys - xs); } + template < typename T > + constexpr T cross(const vec& xs, const vec& ys) { + return xs.x * ys.y - xs.y * ys.x; + } + template < typename T > constexpr vec cross(const vec& xs, const vec& ys) { return { diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 11f4221..a7217a6 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -168,6 +168,7 @@ TEST_CASE("vmath/vec_fun") { STATIC_REQUIRE(distance2(vec2f(-5.f,0.f), vec2f(-10.f,0.f)) == approx(25.f)); STATIC_REQUIRE(dot(vec2i(1,2),vec2i(3,4)) == 11); + STATIC_REQUIRE(cross(vec2i(1,0),vec2i(0,1)) == 1); STATIC_REQUIRE(cross(vec3i(1,0,0),vec3i(0,1,0)) == vec3i(0,0,1)); REQUIRE(normalize(vec2f(0.5f,0.f)).x == Approx(1.f)); From db848a7964b8eb82094d64f4b07e66383bcf903c Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 00:01:27 +0700 Subject: [PATCH 33/53] min/max for vector components --- headers/vmath.hpp/vmath_vec_fun.hpp | 23 +++++++++++++++++++++++ untests/vmath_vec_fun_tests.cpp | 2 ++ 2 files changed, 25 insertions(+) diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index eb4ac90..edb14d6 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -49,6 +49,14 @@ namespace vmath_hpp::detail { return ((init = f(std::move(init), b[Is], c[Is])), ...); } + + template < typename A, std::size_t Size, typename F, std::size_t I, std::size_t... Is > + constexpr auto fold1_impl(F&& f, const vec& a, std::index_sequence) + -> A + { + A init = a[I]; + return ((init = f(std::move(init), a[Is])), ...); + } } template < typename A, std::size_t Size, typename F > @@ -75,6 +83,11 @@ namespace vmath_hpp::detail constexpr auto fold(F&& f, A init, const vec& b, const vec& c) { return impl::fold_impl(std::forward(f), std::move(init), b, c, std::make_index_sequence{}); } + + template < typename A, std::size_t Size, typename F > + constexpr auto fold1(F&& f, const vec& a) { + return impl::fold1_impl(std::forward(f), a, std::make_index_sequence{}); + } } // @@ -426,6 +439,11 @@ namespace vmath_hpp return impl::modf_impl(xs, is, std::make_index_sequence{}); } + template < typename T, std::size_t Size > + constexpr T min(const vec& xs) { + return fold1([](T acc, T x){ return min(acc, x); }, xs); + } + template < typename T, std::size_t Size > constexpr vec min(const vec& xs, T y) { return map([y](T x) { return min(x, y); }, xs); @@ -436,6 +454,11 @@ namespace vmath_hpp return zip([](T x, T y) { return min(x, y); }, xs, ys); } + template < typename T, std::size_t Size > + constexpr T max(const vec& xs) { + return fold1([](T acc, T x){ return max(acc, x); }, xs); + } + template < typename T, std::size_t Size > constexpr vec max(const vec& xs, T y) { return map([y](T x) { return max(x, y); }, xs); diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index a7217a6..9977afb 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -117,9 +117,11 @@ TEST_CASE("vmath/vec_fun") { REQUIRE(out_i.x == Approx(1.f)); } + STATIC_REQUIRE(min(vec2i(1,2)) == 1); STATIC_REQUIRE(min(vec2i(1,2), 1) == vec2i(1,1)); STATIC_REQUIRE(min(vec2i(1,1), vec2i(0,2)) == vec2i(0,1)); + STATIC_REQUIRE(max(vec2i(1,2)) == 2); STATIC_REQUIRE(max(vec2i(1,2), 1) == vec2i(1,2)); STATIC_REQUIRE(max(vec2i(1,1), vec2i(0,2)) == vec2i(1,2)); From 163afb6c9819a00c3b954882a269603b88825d6c Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 00:28:00 +0700 Subject: [PATCH 34/53] unnecessary code --- headers/vmath.hpp/vmath_mat_ext.hpp | 11 ----------- untests/vmath_mat_ext_tests.cpp | 5 ----- 2 files changed, 16 deletions(-) diff --git a/headers/vmath.hpp/vmath_mat_ext.hpp b/headers/vmath.hpp/vmath_mat_ext.hpp index ae33bf1..059680c 100644 --- a/headers/vmath.hpp/vmath_mat_ext.hpp +++ b/headers/vmath.hpp/vmath_mat_ext.hpp @@ -93,17 +93,6 @@ namespace vmath_hpp namespace vmath_hpp { - // identity - - template < typename T > - constexpr mat identity() { - return { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}}; - } - // translate template < typename T > diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp index cb09f10..5bd85e2 100644 --- a/untests/vmath_mat_ext_tests.cpp +++ b/untests/vmath_mat_ext_tests.cpp @@ -59,11 +59,6 @@ TEST_CASE("vmath/mat_ext") { STATIC_REQUIRE(column(mat2i(), 1, {3,4}) == mat2i(1,3,0,4)); } - SECTION("identity") { - STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); - STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * identity() == approx4(2.f,3.f,4.f,1.f)); - } - SECTION("translate") { STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(1.f,2.f,3.f) == approx4(3.f,5.f,7.f,1.f)); STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(vec3f{1.f,2.f,3.f}) == approx4(3.f,5.f,7.f,1.f)); From 8dc6878f5cc3a690d35930651206b7839f7b065b Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 00:40:47 +0700 Subject: [PATCH 35/53] hlsl typedefs style instead glsl --- headers/vmath.hpp/vmath_fwd.hpp | 72 +++++----- untests/vmath_mat_ext_tests.cpp | 68 ++++----- untests/vmath_mat_fun_tests.cpp | 112 +++++++-------- untests/vmath_mat_tests.cpp | 182 ++++++++++++------------ untests/vmath_vec_ext_tests.cpp | 54 +++---- untests/vmath_vec_fun_tests.cpp | 240 ++++++++++++++++---------------- untests/vmath_vec_tests.cpp | 164 +++++++++++----------- 7 files changed, 446 insertions(+), 446 deletions(-) diff --git a/headers/vmath.hpp/vmath_fwd.hpp b/headers/vmath.hpp/vmath_fwd.hpp index 6121c00..c9e2bad 100644 --- a/headers/vmath.hpp/vmath_fwd.hpp +++ b/headers/vmath.hpp/vmath_fwd.hpp @@ -22,29 +22,29 @@ namespace vmath_hpp template < typename T, std::size_t Size > class vec; - using vec2i = vec; - using vec3i = vec; - using vec4i = vec; + using bool2 = vec; + using bool3 = vec; + using bool4 = vec; - using vec2b = vec; - using vec3b = vec; - using vec4b = vec; + using int2 = vec; + using int3 = vec; + using int4 = vec; - using vec2f = vec; - using vec3f = vec; - using vec4f = vec; + using uint2 = vec; + using uint3 = vec; + using uint4 = vec; - using vec2d = vec; - using vec3d = vec; - using vec4d = vec; + using float2 = vec; + using float3 = vec; + using float4 = vec; - using vec2u = vec; - using vec3u = vec; - using vec4u = vec; + using double2 = vec; + using double3 = vec; + using double4 = vec; - using vec2z = vec; - using vec3z = vec; - using vec4z = vec; + using size2 = vec; + using size3 = vec; + using size4 = vec; } namespace vmath_hpp @@ -52,27 +52,27 @@ namespace vmath_hpp template < typename T, std::size_t Size > class mat; - using mat2i = mat; - using mat3i = mat; - using mat4i = mat; + using bool2x2 = mat; + using bool3x3 = mat; + using bool4x4 = mat; - using mat2b = mat; - using mat3b = mat; - using mat4b = mat; + using int2x2 = mat; + using int3x3 = mat; + using int4x4 = mat; - using mat2f = mat; - using mat3f = mat; - using mat4f = mat; + using uint2x2 = mat; + using uint3x3 = mat; + using uint4x4 = mat; - using mat2d = mat; - using mat3d = mat; - using mat4d = mat; + using float2x2 = mat; + using float3x3 = mat; + using float4x4 = mat; - using mat2u = mat; - using mat3u = mat; - using mat4u = mat; + using double2x2 = mat; + using double3x3 = mat; + using double4x4 = mat; - using mat2z = mat; - using mat3z = mat; - using mat4z = mat; + using size2x2 = mat; + using size3x3 = mat; + using size4x4 = mat; } diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp index 5bd85e2..05f6221 100644 --- a/untests/vmath_mat_ext_tests.cpp +++ b/untests/vmath_mat_ext_tests.cpp @@ -19,70 +19,70 @@ namespace TEST_CASE("vmath/mat_ext") { SECTION("units") { - STATIC_REQUIRE(zero2x2() == mat2i(0,0,0,0)); - STATIC_REQUIRE(zero3x3() == mat3i(0,0,0,0,0,0,0,0,0)); - STATIC_REQUIRE(zero4x4() == mat4i(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)); + STATIC_REQUIRE(zero2x2() == int2x2(0,0,0,0)); + STATIC_REQUIRE(zero3x3() == int3x3(0,0,0,0,0,0,0,0,0)); + STATIC_REQUIRE(zero4x4() == int4x4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)); - STATIC_REQUIRE(unit2x2() == mat2i(1,1,1,1)); - STATIC_REQUIRE(unit3x3() == mat3i(1,1,1,1,1,1,1,1,1)); - STATIC_REQUIRE(unit4x4() == mat4i(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)); + STATIC_REQUIRE(unit2x2() == int2x2(1,1,1,1)); + STATIC_REQUIRE(unit3x3() == int3x3(1,1,1,1,1,1,1,1,1)); + STATIC_REQUIRE(unit4x4() == int4x4(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)); - STATIC_REQUIRE(identity2x2() == mat2i()); - STATIC_REQUIRE(identity3x3() == mat3i()); - STATIC_REQUIRE(identity4x4() == mat4i()); + STATIC_REQUIRE(identity2x2() == int2x2()); + STATIC_REQUIRE(identity3x3() == int3x3()); + STATIC_REQUIRE(identity4x4() == int4x4()); } SECTION("hash") { - REQUIRE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,3,4})); - REQUIRE_FALSE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,4,3})); + REQUIRE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,3,4})); + REQUIRE_FALSE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,4,3})); } SECTION("cast_to") { - constexpr auto m = cast_to(mat2f{1.5f}); - STATIC_REQUIRE(m == mat2i(1)); - STATIC_REQUIRE(std::is_same_v); + constexpr auto m = cast_to(float2x2{1.5f}); + STATIC_REQUIRE(m == int2x2(1)); + STATIC_REQUIRE(std::is_same_v); } SECTION("row") { - STATIC_REQUIRE(row(mat2i(1,2,3,4), 0) == vec2i(1,2)); - STATIC_REQUIRE(row(mat2i(1,2,3,4), 1) == vec2i(3,4)); + 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_REQUIRE(row(mat2i(), 0, {1,2}) == mat2i(1,2,0,1)); - STATIC_REQUIRE(row(mat2i(), 1, {3,4}) == mat2i(1,0,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)); } SECTION("column") { - STATIC_REQUIRE(column(mat2i(1,2,3,4), 0) == vec2i(1,3)); - STATIC_REQUIRE(column(mat2i(1,2,3,4), 1) == vec2i(2,4)); + 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_REQUIRE(column(mat2i(), 0, {2,3}) == mat2i(2,0,3,1)); - STATIC_REQUIRE(column(mat2i(), 1, {3,4}) == mat2i(1,3,0,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)); } SECTION("translate") { - STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(1.f,2.f,3.f) == approx4(3.f,5.f,7.f,1.f)); - STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(vec3f{1.f,2.f,3.f}) == approx4(3.f,5.f,7.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(1.f,2.f,3.f) == approx4(3.f,5.f,7.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(float3{1.f,2.f,3.f}) == approx4(3.f,5.f,7.f,1.f)); - STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), 1.f,2.f,3.f) == approx4(4.f,7.f,10.f,1.f)); - STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), vec3f{1.f,2.f,3.f}) == approx4(4.f,7.f,10.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), 1.f,2.f,3.f) == approx4(4.f,7.f,10.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), float3{1.f,2.f,3.f}) == approx4(4.f,7.f,10.f,1.f)); } SECTION("rotate") { constexpr float pi = radians(180.f); constexpr float pi_2 = radians(90.f); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(pi,0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(pi,vec3f{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,0.f,0.f,1.f),pi_2,0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); - REQUIRE(vec4f(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,0.f,0.f,1.f),pi_2,vec3f{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,0.f,0.f,1.f),pi_2,0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,0.f,0.f,1.f),pi_2,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); } SECTION("scale") { - STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(2.f,3.f,4.f) == approx4(4.f,9.f,16.f,1.f)); - STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(vec3f{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(2.f,3.f,4.f) == approx4(4.f,9.f,16.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f)); - STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), 2.f,3.f,4.f) == approx4(8.f,18.f,32.f,1.f)); - STATIC_REQUIRE(vec4f(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), vec3f{2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), 2.f,3.f,4.f) == approx4(8.f,18.f,32.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), float3{2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); } } diff --git a/untests/vmath_mat_fun_tests.cpp b/untests/vmath_mat_fun_tests.cpp index 068ab4a..f220f4d 100644 --- a/untests/vmath_mat_fun_tests.cpp +++ b/untests/vmath_mat_fun_tests.cpp @@ -37,104 +37,104 @@ namespace TEST_CASE("vmath/mat_fun") { SECTION("Operators") { - STATIC_REQUIRE(-mat2i(1,2,3,4) == mat2i(-1,-2,-3,-4)); + STATIC_REQUIRE(-int2x2(1,2,3,4) == int2x2(-1,-2,-3,-4)); - STATIC_REQUIRE(mat2i(1,2,3,4) + 2 == mat2i(3,4,5,6)); - STATIC_REQUIRE(mat2i(1,2,3,4) - 2 == mat2i(-1,0,1,2)); - STATIC_REQUIRE(mat2i(1,2,3,4) * 2 == mat2i(2,4,6,8)); - STATIC_REQUIRE(mat2i(1,2,3,4) / 2 == mat2i(0,1,1,2)); + 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(4 + mat2i(1,2,3,4) == mat2i(5,6,7,8)); - STATIC_REQUIRE(4 - mat2i(1,2,3,4) == mat2i(3,2,1,0)); - STATIC_REQUIRE(4 * mat2i(1,2,3,4) == mat2i(4,8,12,16)); - STATIC_REQUIRE(4 / mat2i(1,2,3,4) == mat2i(4,2,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(mat2i(1,2,3,4) + mat2i(5,6,7,8) == mat2i(6,8,10,12)); - STATIC_REQUIRE(mat2i(1,2,3,4) - mat2i(5,6,7,8) == mat2i(-4,-4,-4,-4)); - STATIC_REQUIRE(mat2i(5,6,7,8) / mat2i(1,2,3,4) == mat2i(5,3,2,2)); + STATIC_REQUIRE(int2x2(1,2,3,4) + int2x2(5,6,7,8) == int2x2(6,8,10,12)); + STATIC_REQUIRE(int2x2(1,2,3,4) - int2x2(5,6,7,8) == int2x2(-4,-4,-4,-4)); + STATIC_REQUIRE(int2x2(5,6,7,8) / int2x2(1,2,3,4) == int2x2(5,3,2,2)); - STATIC_REQUIRE(mat2i() * mat2i() == mat2i()); - STATIC_REQUIRE(mat3i() * mat3i() == mat3i()); + STATIC_REQUIRE(int2x2() * int2x2() == int2x2()); + STATIC_REQUIRE(int3x3() * int3x3() == int3x3()); - STATIC_REQUIRE(vec2i(1,2) * mat2i() == vec2i(1,2)); - STATIC_REQUIRE(vec3i(1,2,3) * mat3i() == vec3i(1,2,3)); - STATIC_REQUIRE(vec4i(1,2,3,4) * mat4i() == vec4i(1,2,3,4)); + 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)); { - mat2i v{1,2,3,4}; + int2x2 v{1,2,3,4}; REQUIRE(&v == &(v += 3)); - REQUIRE(v == mat2i{4,5,6,7}); - REQUIRE(&v == &(v += mat2i{1,2,3,4})); - REQUIRE(v == mat2i{5,7,9,11}); + REQUIRE(v == int2x2{4,5,6,7}); + REQUIRE(&v == &(v += int2x2{1,2,3,4})); + REQUIRE(v == int2x2{5,7,9,11}); } { - mat2i v{4,5,6,7}; + int2x2 v{4,5,6,7}; REQUIRE(&v == &(v -= 3)); - REQUIRE(v == mat2i{1,2,3,4}); - REQUIRE(&v == &(v -= mat2i{2,4,6,8})); - REQUIRE(v == mat2i{-1,-2,-3,-4}); + REQUIRE(v == int2x2{1,2,3,4}); + REQUIRE(&v == &(v -= int2x2{2,4,6,8})); + REQUIRE(v == int2x2{-1,-2,-3,-4}); } { - mat2i v{1,2,3,4}; + int2x2 v{1,2,3,4}; REQUIRE(&v == &(v *= 3)); - REQUIRE(v == mat2i{3,6,9,12}); + REQUIRE(v == int2x2{3,6,9,12}); } { - mat2i v{6,18,36,60}; + int2x2 v{6,18,36,60}; REQUIRE(&v == &(v /= 2)); - REQUIRE(v == mat2i{3,9,18,30}); - REQUIRE(&v == &(v /= mat2i{3,4,3,10})); - REQUIRE(v == mat2i{1,2,6,3}); + REQUIRE(v == int2x2{3,9,18,30}); + REQUIRE(&v == &(v /= int2x2{3,4,3,10})); + REQUIRE(v == int2x2{1,2,6,3}); } { - vec4f v{0.f, 0.f, 0.f, 1.f}; + float4 v{0.f, 0.f, 0.f, 1.f}; REQUIRE(&v == &(v *= translate(1.f,2.f,3.f))); REQUIRE(v == approx4(1.f,2.f,3.f,1.f)); } { - vec3f v{1.f, 2.f, 3.f}; - REQUIRE(&v == &(v *= mat3f(scale(2.f,3.f,4.f)))); + float3 v{1.f, 2.f, 3.f}; + REQUIRE(&v == &(v *= float3x3(scale(2.f,3.f,4.f)))); REQUIRE(v == approx3(2.f,6.f,12.f)); } { - mat4f v = translate(1.f, 2.f, 3.f); + float4x4 v = translate(1.f, 2.f, 3.f); REQUIRE(&v == &(v *= translate(1.f,2.f,3.f))); REQUIRE(v == approx4x4(translate(2.f,4.f,6.f))); } { - mat3f v = mat3f(scale(1.f, 2.f, 3.f)); - REQUIRE(&v == &(v *= mat3f(scale(2.f,3.f,4.f)))); - REQUIRE(v == approx3x3(mat3f(scale(2.f,6.f,12.f)))); + float3x3 v = float3x3(scale(1.f, 2.f, 3.f)); + REQUIRE(&v == &(v *= float3x3(scale(2.f,3.f,4.f)))); + REQUIRE(v == approx3x3(float3x3(scale(2.f,6.f,12.f)))); } } SECTION("Matrix Functions") { { - STATIC_REQUIRE(transpose(mat2i( + STATIC_REQUIRE(transpose(int2x2( 1, 2, 3, 4 - )) == mat2i( + )) == int2x2( 1, 3, 2, 4 )); - STATIC_REQUIRE(transpose(mat3i( + STATIC_REQUIRE(transpose(int3x3( 1, 2, 3, 4, 5, 6, 7, 8, 9 - )) == mat3i( + )) == int3x3( 1, 4, 7, 2, 5, 8, 3, 6, 9 )); - STATIC_REQUIRE(transpose(mat4i( + STATIC_REQUIRE(transpose(int4x4( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 - )) == mat4i( + )) == int4x4( 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, @@ -142,9 +142,9 @@ TEST_CASE("vmath/mat_fun") { )); } { - constexpr mat2i m2{1,2,3,4}; - constexpr mat3i m3{1,2,3,4,5,6,7,8,9}; - constexpr mat4i m4{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; + 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))); @@ -158,19 +158,19 @@ TEST_CASE("vmath/mat_fun") { STATIC_REQUIRE(determinant(transpose(generate_frank_matrix())) == 1); } { - STATIC_REQUIRE(inverse(mat2i()) == mat2i()); - STATIC_REQUIRE(inverse(mat3i()) == mat3i()); - STATIC_REQUIRE(inverse(mat4i()) == mat4i()); + STATIC_REQUIRE(inverse(int2x2()) == int2x2()); + STATIC_REQUIRE(inverse(int3x3()) == int3x3()); + STATIC_REQUIRE(inverse(int4x4()) == int4x4()); - STATIC_REQUIRE(inverse(mat2f(0.5)) == mat2f(2.f)); - STATIC_REQUIRE(inverse(mat3f(0.5)) == mat3f(2.f)); - STATIC_REQUIRE(inverse(mat4f(0.5)) == mat4f(2.f)); + 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_REQUIRE(inverse(translate(1.f,2.f,3.f)) == approx4x4(translate(-1.f,-2.f,-3.f))); - REQUIRE(inverse(rotate(0.5f,normalize(vec3f{1.f,2.f,3.f}))) == approx4x4(rotate(-0.5f,normalize(vec3f{1.f,2.f,3.f})))); - REQUIRE(inverse(mat3f(rotate(0.5f,normalize(vec3f{1.f,2.f,3.f})))) == approx3x3(mat3f(rotate(-0.5f,normalize(vec3f{1.f,2.f,3.f}))))); - REQUIRE(inverse(mat2f(rotate(0.5f,vec3f{0,0,1}))) == approx2x2(mat2f(rotate(-0.5f,vec3f{0,0,1})))); + REQUIRE(inverse(rotate(0.5f,normalize(float3{1.f,2.f,3.f}))) == approx4x4(rotate(-0.5f,normalize(float3{1.f,2.f,3.f})))); + REQUIRE(inverse(float3x3(rotate(0.5f,normalize(float3{1.f,2.f,3.f})))) == approx3x3(float3x3(rotate(-0.5f,normalize(float3{1.f,2.f,3.f}))))); + REQUIRE(inverse(float2x2(rotate(0.5f,float3{0,0,1}))) == approx2x2(float2x2(rotate(-0.5f,float3{0,0,1})))); } } } diff --git a/untests/vmath_mat_tests.cpp b/untests/vmath_mat_tests.cpp index 1682855..b48fde8 100644 --- a/untests/vmath_mat_tests.cpp +++ b/untests/vmath_mat_tests.cpp @@ -20,155 +20,155 @@ namespace TEST_CASE("vmath/mat") { SECTION("size/sizeof") { - STATIC_REQUIRE(mat2i{}.size == 2); - STATIC_REQUIRE(mat3i{}.size == 3); - STATIC_REQUIRE(mat4i{}.size == 4); + STATIC_REQUIRE(int2x2{}.size == 2); + STATIC_REQUIRE(int3x3{}.size == 3); + STATIC_REQUIRE(int4x4{}.size == 4); - STATIC_REQUIRE(sizeof(mat2i{}) == sizeof(int) * 2 * 2); - STATIC_REQUIRE(sizeof(mat3i{}) == sizeof(int) * 3 * 3); - STATIC_REQUIRE(sizeof(mat4i{}) == sizeof(int) * 4 * 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); } SECTION("ctors") { { - STATIC_REQUIRE(mat2i()[0] == vec2i(1,0)); - STATIC_REQUIRE(mat2i()[1] == vec2i(0,1)); + STATIC_REQUIRE(int2x2()[0] == int2(1,0)); + STATIC_REQUIRE(int2x2()[1] == int2(0,1)); - STATIC_REQUIRE(mat2i(1,2,3,4)[0] == vec2i(1,2)); - STATIC_REQUIRE(mat2i(1,2,3,4)[1] == vec2i(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_REQUIRE(mat2i({1,2},{3,4})[0] == vec2i(1,2)); - STATIC_REQUIRE(mat2i({1,2},{3,4})[1] == vec2i(3,4)); + STATIC_REQUIRE(int2x2({1,2},{3,4})[0] == int2(1,2)); + STATIC_REQUIRE(int2x2({1,2},{3,4})[1] == int2(3,4)); } { - constexpr mat2i v(1,2,3,4); - constexpr mat2i v2 = v; - STATIC_REQUIRE(v2 == mat2i(1,2,3,4)); + constexpr int2x2 v(1,2,3,4); + constexpr int2x2 v2 = v; + STATIC_REQUIRE(v2 == int2x2(1,2,3,4)); } { - constexpr mat2i v(1,2,3,4); - constexpr mat2i v2 = std::move(v); - STATIC_REQUIRE(v2 == mat2i(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_REQUIRE(mat2i() == mat2i(1,0,0,1)); - STATIC_REQUIRE(mat2i(2) == mat2i(2,0,0,2)); - STATIC_REQUIRE(mat2i(1,2,3,4) == mat2i(1,2,3,4)); - STATIC_REQUIRE(mat2i({1,2},{3,4}) == mat2i(1,2,3,4)); - STATIC_REQUIRE(mat2i(mat2i({1,2},{3,4})) == mat2i(1,2,3,4)); - STATIC_REQUIRE(mat2i(mat3i({1,2,3},{4,5,6},{7,8,9})) == mat2i(1,2,4,5)); - STATIC_REQUIRE(mat2i(mat4i({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == mat2i(1,2,5,6)); + STATIC_REQUIRE(int2x2() == int2x2(1,0,0,1)); + STATIC_REQUIRE(int2x2(2) == int2x2(2,0,0,2)); + 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_REQUIRE(mat3i() == mat3i(1,0,0,0,1,0,0,0,1)); - STATIC_REQUIRE(mat3i(2) == mat3i(2,0,0,0,2,0,0,0,2)); - STATIC_REQUIRE(mat3i(1,2,3,4,5,6,7,8,9) == mat3i(1,2,3,4,5,6,7,8,9)); - STATIC_REQUIRE(mat3i({1,2,3},{4,5,6},{7,8,9}) == mat3i(1,2,3,4,5,6,7,8,9)); - STATIC_REQUIRE(mat3i(mat3i({1,2,3},{4,5,6},{7,8,9})) == mat3i(1,2,3,4,5,6,7,8,9)); - STATIC_REQUIRE(mat3i(mat2i({1,2},{3,4})) == mat3i(1,2,0,3,4,0,0,0,1)); - STATIC_REQUIRE(mat3i(mat4i({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == mat3i(1,2,3,5,6,7,9,10,11)); + 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(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(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_REQUIRE(mat4i() == mat4i(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)); - STATIC_REQUIRE(mat4i(2) == mat4i(2,0,0,0,0,2,0,0,0,0,2,0,0,0,0,2)); - STATIC_REQUIRE(mat4i(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) == mat4i(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)); - STATIC_REQUIRE(mat4i({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}) == mat4i(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)); - STATIC_REQUIRE(mat4i(mat4i({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == mat4i(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)); - STATIC_REQUIRE(mat4i(mat2i({1,2},{3,4})) == mat4i(1,2,0,0,3,4,0,0,0,0,1,0,0,0,0,1)); - STATIC_REQUIRE(mat4i(mat3i({1,2,3},{4,5,6},{7,8,9})) == mat4i(1,2,3,0,4,5,6,0,7,8,9,0,0,0,0,1)); + 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(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(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)); } } SECTION("operator=") { { - mat2i v(1,2,3,4); - mat2i v2; + int2x2 v(1,2,3,4); + int2x2 v2; v2 = v; - REQUIRE(v2 == mat2i(1,2,3,4)); + REQUIRE(v2 == int2x2(1,2,3,4)); } { - mat2i v(1,2,3,4); - mat2i v2; + int2x2 v(1,2,3,4); + int2x2 v2; v2 = std::move(v); - REQUIRE(v2 == mat2i(1,2,3,4)); + REQUIRE(v2 == int2x2(1,2,3,4)); } } SECTION("swap") { { - mat2i v1(1,2,3,4); - mat2i v2(4,5,6,7); + int2x2 v1(1,2,3,4); + int2x2 v2(4,5,6,7); v1.swap(v2); - REQUIRE(v1 == mat2i(4,5,6,7)); - REQUIRE(v2 == mat2i(1,2,3,4)); + REQUIRE(v1 == int2x2(4,5,6,7)); + REQUIRE(v2 == int2x2(1,2,3,4)); } { - mat2i v1(1,2,3,4); - mat2i v2(4,5,6,7); + int2x2 v1(1,2,3,4); + int2x2 v2(4,5,6,7); swap(v1, v2); - REQUIRE(v1 == mat2i(4,5,6,7)); - REQUIRE(v2 == mat2i(1,2,3,4)); + REQUIRE(v1 == int2x2(4,5,6,7)); + REQUIRE(v2 == int2x2(1,2,3,4)); } } SECTION("operator[]") { { - STATIC_REQUIRE(mat2i()[0] == vec2i(1,0)); - STATIC_REQUIRE(mat2i()[1] == vec2i(0,1)); + STATIC_REQUIRE(int2x2()[0] == int2(1,0)); + STATIC_REQUIRE(int2x2()[1] == int2(0,1)); - STATIC_REQUIRE(mat3i()[0] == vec3i(1,0,0)); - STATIC_REQUIRE(mat3i()[1] == vec3i(0,1,0)); - STATIC_REQUIRE(mat3i()[2] == vec3i(0,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_REQUIRE(mat4i()[0] == vec4i(1,0,0,0)); - STATIC_REQUIRE(mat4i()[1] == vec4i(0,1,0,0)); - STATIC_REQUIRE(mat4i()[2] == vec4i(0,0,1,0)); - STATIC_REQUIRE(mat4i()[3] == vec4i(0,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)); } { - mat2i v; - v[0] = vec2i(1,2); - v[1] = vec2i(3,4); - REQUIRE(v == mat2i(1,2,3,4)); + int2x2 v; + v[0] = int2(1,2); + v[1] = int2(3,4); + REQUIRE(v == int2x2(1,2,3,4)); } { - mat3i v; - v[0] = vec3i(1,2,3); - v[1] = vec3i(4,5,6); - v[2] = vec3i(7,8,9); - REQUIRE(v == mat3i(1,2,3,4,5,6,7,8,9)); + 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)); } { - mat4i v; - v[0] = vec4i(1,2,3,4); - v[1] = vec4i(5,6,7,8); - v[2] = vec4i(9,10,11,12); - v[3] = vec4i(13,14,15,16); - REQUIRE(v == mat4i(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)); + int4x4 v; + v[0] = int4(1,2,3,4); + 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)); } } SECTION("at") { - STATIC_REQUIRE(mat2i(1,2,3,4).at(0) == vec2i(1,2)); - STATIC_REQUIRE(mat2i(1,2,3,4).at(1) == vec2i(3,4)); - REQUIRE_THROWS_AS(mat2i(1,2,3,4).at(2), std::out_of_range); + 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(int2x2(1,2,3,4).at(2), std::out_of_range); } SECTION("operator==/operator!=") { - STATIC_REQUIRE(mat2i(1,2,3,4) == mat2i(1,2,3,4)); - STATIC_REQUIRE_FALSE(mat2i(1,2,3,4) == mat2i(2,2,3,4)); - STATIC_REQUIRE_FALSE(mat2i(1,2,3,4) == mat2i(1,3,3,4)); + 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_REQUIRE_FALSE(mat2i(1,2,3,4) != mat2i(1,2,3,4)); - STATIC_REQUIRE(mat2i(1,2,3,4) != mat2i(2,2,3,4)); - STATIC_REQUIRE(mat2i(1,2,3,4) != mat2i(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)); } SECTION("operator<") { - STATIC_REQUIRE_FALSE(mat2i(1,2,3,4) < mat2i(1,2,3,4)); + STATIC_REQUIRE_FALSE(int2x2(1,2,3,4) < int2x2(1,2,3,4)); - STATIC_REQUIRE(mat2i(1,1,3,4) < mat2i(1,2,3,4)); - STATIC_REQUIRE_FALSE(mat2i(1,2,3,4) < mat2i(1,1,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_REQUIRE(mat2i(0,3,3,4) < mat2i(1,2,3,4)); - STATIC_REQUIRE_FALSE(mat2i(1,2,3,4) < mat2i(0,3,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)); } } diff --git a/untests/vmath_vec_ext_tests.cpp b/untests/vmath_vec_ext_tests.cpp index 0fcdbb5..4c204e6 100644 --- a/untests/vmath_vec_ext_tests.cpp +++ b/untests/vmath_vec_ext_tests.cpp @@ -19,48 +19,48 @@ namespace TEST_CASE("vmath/vec_ext") { SECTION("units") { - STATIC_REQUIRE(zero2() == vec2i(0,0)); - STATIC_REQUIRE(zero3() == vec3i(0,0,0)); - STATIC_REQUIRE(zero4() == vec4i(0,0,0,0)); + STATIC_REQUIRE(zero2() == int2(0,0)); + STATIC_REQUIRE(zero3() == int3(0,0,0)); + STATIC_REQUIRE(zero4() == int4(0,0,0,0)); - STATIC_REQUIRE(unit2() == vec2i(1,1)); - STATIC_REQUIRE(unit2_x() == vec2i(1,0)); - STATIC_REQUIRE(unit2_y() == vec2i(0,1)); + STATIC_REQUIRE(unit2() == int2(1,1)); + STATIC_REQUIRE(unit2_x() == int2(1,0)); + STATIC_REQUIRE(unit2_y() == int2(0,1)); - STATIC_REQUIRE(unit3() == vec3i(1,1,1)); - STATIC_REQUIRE(unit3_x() == vec3i(1,0,0)); - STATIC_REQUIRE(unit3_y() == vec3i(0,1,0)); - STATIC_REQUIRE(unit3_z() == vec3i(0,0,1)); + STATIC_REQUIRE(unit3() == int3(1,1,1)); + STATIC_REQUIRE(unit3_x() == int3(1,0,0)); + STATIC_REQUIRE(unit3_y() == int3(0,1,0)); + STATIC_REQUIRE(unit3_z() == int3(0,0,1)); - STATIC_REQUIRE(unit4() == vec4i(1,1,1,1)); - STATIC_REQUIRE(unit4_x() == vec4i(1,0,0,0)); - STATIC_REQUIRE(unit4_y() == vec4i(0,1,0,0)); - STATIC_REQUIRE(unit4_z() == vec4i(0,0,1,0)); - STATIC_REQUIRE(unit4_w() == vec4i(0,0,0,1)); + STATIC_REQUIRE(unit4() == int4(1,1,1,1)); + STATIC_REQUIRE(unit4_x() == int4(1,0,0,0)); + STATIC_REQUIRE(unit4_y() == int4(0,1,0,0)); + STATIC_REQUIRE(unit4_z() == int4(0,0,1,0)); + STATIC_REQUIRE(unit4_w() == int4(0,0,0,1)); } SECTION("hash") { - REQUIRE(std::hash{}({1,2}) == std::hash{}({1,2})); - REQUIRE_FALSE(std::hash{}({1,2}) == std::hash{}({2,1})); + REQUIRE(std::hash{}({1,2}) == std::hash{}({1,2})); + REQUIRE_FALSE(std::hash{}({1,2}) == std::hash{}({2,1})); - REQUIRE(std::hash{}({1,2,3}) == std::hash{}({1,2,3})); - REQUIRE_FALSE(std::hash{}({1,2,3}) == std::hash{}({3,2,1})); + REQUIRE(std::hash{}({1,2,3}) == std::hash{}({1,2,3})); + REQUIRE_FALSE(std::hash{}({1,2,3}) == std::hash{}({3,2,1})); - REQUIRE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,3,4})); - REQUIRE_FALSE(std::hash{}({1,2,3,4}) == std::hash{}({3,2,1,4})); + REQUIRE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,3,4})); + REQUIRE_FALSE(std::hash{}({1,2,3,4}) == std::hash{}({3,2,1,4})); } SECTION("cast_to") { - constexpr auto v = cast_to(vec2f{1.5f}); - STATIC_REQUIRE(v == vec2i(1)); + constexpr auto v = cast_to(float2{1.5f}); + STATIC_REQUIRE(v == int2(1)); STATIC_REQUIRE(std::is_same_v); } SECTION("component") { - STATIC_REQUIRE(component(vec2i{1,2}, 0) == 1); - STATIC_REQUIRE(component(vec2i{1,2}, 1) == 2); + STATIC_REQUIRE(component(int2{1,2}, 0) == 1); + STATIC_REQUIRE(component(int2{1,2}, 1) == 2); - STATIC_REQUIRE(component(vec2i{0,0}, 0, 1) == vec2i{1,0}); - STATIC_REQUIRE(component(vec2i{0,0}, 1, 2) == vec2i{0,2}); + STATIC_REQUIRE(component(int2{0,0}, 0, 1) == int2{1,0}); + STATIC_REQUIRE(component(int2{0,0}, 1, 2) == int2{0,2}); } } diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 9977afb..7daf195 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -19,189 +19,189 @@ namespace TEST_CASE("vmath/vec_fun") { SECTION("Operators") { - STATIC_REQUIRE(-vec2i(1,-2) == vec2i(-1,2)); + STATIC_REQUIRE(-int2(1,-2) == int2(-1,2)); - STATIC_REQUIRE(vec2i(1,2) + 3 == vec2i(4,5)); - STATIC_REQUIRE(vec2i(1,2) - 3 == vec2i(-2,-1)); - STATIC_REQUIRE(vec2i(1,2) * 3 == vec2i(3,6)); - STATIC_REQUIRE(vec2i(2,4) / 2 == vec2i(1,2)); + 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(3 + vec2i(1,2) == vec2i(4,5)); - STATIC_REQUIRE(3 - vec2i(1,2) == vec2i(2,1)); - STATIC_REQUIRE(3 * vec2i(1,2) == vec2i(3,6)); - STATIC_REQUIRE(4 / vec2i(2,4) == vec2i(2,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(vec2i(1,2) + vec2i(3,4) == vec2i(4,6)); - STATIC_REQUIRE(vec2i(1,2) - vec2i(3,4) == vec2i(-2,-2)); - STATIC_REQUIRE(vec2i(1,2) * vec2i(3,4) == vec2i(3,8)); - STATIC_REQUIRE(vec2i(3,4) / vec2i(1,2) == vec2i(3,2)); + 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)); { - vec2i v{1,2}; + int2 v{1,2}; REQUIRE(&v == &(v += 3)); - REQUIRE(v == vec2i{4,5}); - REQUIRE(&v == &(v += vec2i{1,2})); - REQUIRE(v == vec2i{5,7}); + REQUIRE(v == int2{4,5}); + REQUIRE(&v == &(v += int2{1,2})); + REQUIRE(v == int2{5,7}); } { - vec2i v{4,5}; + int2 v{4,5}; REQUIRE(&v == &(v -= 3)); - REQUIRE(v == vec2i{1,2}); - REQUIRE(&v == &(v -= vec2i{2,4})); - REQUIRE(v == vec2i{-1,-2}); + REQUIRE(v == int2{1,2}); + REQUIRE(&v == &(v -= int2{2,4})); + REQUIRE(v == int2{-1,-2}); } { - vec2i v{1,2}; + int2 v{1,2}; REQUIRE(&v == &(v *= 3)); - REQUIRE(v == vec2i{3,6}); - REQUIRE(&v == &(v *= vec2i{2,3})); - REQUIRE(v == vec2i{6,18}); + REQUIRE(v == int2{3,6}); + REQUIRE(&v == &(v *= int2{2,3})); + REQUIRE(v == int2{6,18}); } { - vec2i v{6,18}; + int2 v{6,18}; REQUIRE(&v == &(v /= 2)); - REQUIRE(v == vec2i{3,9}); - REQUIRE(&v == &(v /= vec2i{3,4})); - REQUIRE(v == vec2i{1,2}); + REQUIRE(v == int2{3,9}); + REQUIRE(&v == &(v /= int2{3,4})); + REQUIRE(v == int2{1,2}); } } SECTION("Angle and Trigonometry Functions") { - STATIC_REQUIRE(radians(degrees(vec2f(12.13f))) == approx2(12.13f)); - STATIC_REQUIRE(degrees(radians(vec2f(12.13f))) == approx2(12.13f)); + STATIC_REQUIRE(radians(degrees(float2(12.13f))) == approx2(12.13f)); + STATIC_REQUIRE(degrees(radians(float2(12.13f))) == approx2(12.13f)); - (void)sin(vec2f(1.f)); - (void)cos(vec2f(1.f)); - (void)tan(vec2f(1.f)); + (void)sin(float2(1.f)); + (void)cos(float2(1.f)); + (void)tan(float2(1.f)); - (void)asin(vec2f(1.f)); - (void)acos(vec2f(1.f)); - (void)atan(vec2f(1.f)); - (void)atan2(vec2f(1.f), vec2f(1.f)); + (void)asin(float2(1.f)); + (void)acos(float2(1.f)); + (void)atan(float2(1.f)); + (void)atan2(float2(1.f), float2(1.f)); - (void)sinh(vec2f(1.f)); - (void)cosh(vec2f(1.f)); - (void)tanh(vec2f(1.f)); + (void)sinh(float2(1.f)); + (void)cosh(float2(1.f)); + (void)tanh(float2(1.f)); - (void)asinh(vec2f(1.f)); - (void)acosh(vec2f(1.f)); - (void)atanh(vec2f(1.f)); + (void)asinh(float2(1.f)); + (void)acosh(float2(1.f)); + (void)atanh(float2(1.f)); } SECTION("Exponential Functions") { - (void)pow(vec2f(1.f), vec2f(2.f)); - (void)exp(vec2f(1.f)); - (void)log(vec2f(1.f)); - (void)exp2(vec2f(1.f)); - (void)log2(vec2f(1.f)); - (void)sqrt(vec2f(1.f)); - (void)invsqrt(vec2f(1.f)); + (void)pow(float2(1.f), float2(2.f)); + (void)exp(float2(1.f)); + (void)log(float2(1.f)); + (void)exp2(float2(1.f)); + (void)log2(float2(1.f)); + (void)sqrt(float2(1.f)); + (void)invsqrt(float2(1.f)); } SECTION("Common Functions") { - REQUIRE(abs(vec2f(1.f, -1.f)) == approx2(1.f,1.f)); - REQUIRE(sign(vec3f(1.f, -1.f, 0.f)) == approx3(1.f,-1.f,0.f)); + REQUIRE(abs(float2(1.f, -1.f)) == approx2(1.f,1.f)); + REQUIRE(sign(float3(1.f, -1.f, 0.f)) == approx3(1.f,-1.f,0.f)); - (void)floor(vec2f(1.f, -1.f)); - (void)trunc(vec2f(1.f, -1.f)); - (void)round(vec2f(1.f, -1.f)); - (void)ceil(vec2f(1.f, -1.f)); - (void)fract(vec2f(1.f, -1.f)); + (void)floor(float2(1.f, -1.f)); + (void)trunc(float2(1.f, -1.f)); + (void)round(float2(1.f, -1.f)); + (void)ceil(float2(1.f, -1.f)); + (void)fract(float2(1.f, -1.f)); - REQUIRE(fmod(vec2f(1.7f), 1.2f) == approx2(0.5f)); - REQUIRE(fmod(vec2f(1.7f), vec2f(1.2f)) == approx2(0.5f)); + REQUIRE(fmod(float2(1.7f), 1.2f) == approx2(0.5f)); + REQUIRE(fmod(float2(1.7f), float2(1.2f)) == approx2(0.5f)); { - vec2f out_i{}; - REQUIRE(modf(vec2f(1.7f), &out_i) == approx2(0.7f)); + float2 out_i{}; + REQUIRE(modf(float2(1.7f), &out_i) == approx2(0.7f)); REQUIRE(out_i.x == Approx(1.f)); } - STATIC_REQUIRE(min(vec2i(1,2)) == 1); - STATIC_REQUIRE(min(vec2i(1,2), 1) == vec2i(1,1)); - STATIC_REQUIRE(min(vec2i(1,1), vec2i(0,2)) == vec2i(0,1)); + 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_REQUIRE(max(vec2i(1,2)) == 2); - STATIC_REQUIRE(max(vec2i(1,2), 1) == vec2i(1,2)); - STATIC_REQUIRE(max(vec2i(1,1), vec2i(0,2)) == vec2i(1,2)); + 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_REQUIRE(clamp(vec2i(1,2), 0, 1) == vec2i(1,1)); - STATIC_REQUIRE(clamp(vec2i(1,2), vec2i(0), vec2i(1)) == vec2i(1,1)); + STATIC_REQUIRE(clamp(int2(1,2), 0, 1) == int2(1,1)); + STATIC_REQUIRE(clamp(int2(1,2), int2(0), int2(1)) == int2(1,1)); - STATIC_REQUIRE(saturate(vec3f(-1.f,0.5,1.5f)) == approx3(0.f,0.5f,1.f)); + STATIC_REQUIRE(saturate(float3(-1.f,0.5,1.5f)) == approx3(0.f,0.5f,1.f)); - STATIC_REQUIRE(lerp(vec2f(0.f), vec2f(10.f), 0.5f) == approx2(5.f)); - STATIC_REQUIRE(lerp(vec2f(0.f), vec2f(10.f), vec2f(0.5f)) == approx2(5.f)); + STATIC_REQUIRE(lerp(float2(0.f), float2(10.f), 0.5f) == approx2(5.f)); + STATIC_REQUIRE(lerp(float2(0.f), float2(10.f), float2(0.5f)) == approx2(5.f)); - STATIC_REQUIRE(step(0.5f, vec2f(0.4f)) == approx2(0.f)); - STATIC_REQUIRE(step(0.5f, vec2f(0.6f)) == approx2(1.f)); - STATIC_REQUIRE(step(vec2f(0.5f), vec2f(0.4f)) == approx2(0.f)); - STATIC_REQUIRE(step(vec2f(0.5f), vec2f(0.6f)) == approx2(1.f)); + STATIC_REQUIRE(step(0.5f, float2(0.4f)) == approx2(0.f)); + STATIC_REQUIRE(step(0.5f, float2(0.6f)) == approx2(1.f)); + STATIC_REQUIRE(step(float2(0.5f), float2(0.4f)) == approx2(0.f)); + STATIC_REQUIRE(step(float2(0.5f), float2(0.6f)) == approx2(1.f)); - STATIC_REQUIRE(smoothstep(0.f, 1.f, vec2f(0.1f)) == approx2(0.028f)); - STATIC_REQUIRE(smoothstep(vec2f(0.f), vec2f(1.f), vec2f(0.1f)) == approx2(0.028f)); + STATIC_REQUIRE(smoothstep(0.f, 1.f, float2(0.1f)) == approx2(0.028f)); + STATIC_REQUIRE(smoothstep(float2(0.f), float2(1.f), float2(0.1f)) == approx2(0.028f)); - REQUIRE_FALSE(isnan(vec2f(1.f)).x); - REQUIRE_FALSE(isinf(vec2f(1.f)).x); - REQUIRE(isfinite(vec2f(1.f)).x); + REQUIRE_FALSE(isnan(float2(1.f)).x); + REQUIRE_FALSE(isinf(float2(1.f)).x); + REQUIRE(isfinite(float2(1.f)).x); - REQUIRE_FALSE(fma(vec2f(2.f), vec2f(3.f), vec2f(4.f)).x == Approx(12.f)); + REQUIRE_FALSE(fma(float2(2.f), float2(3.f), float2(4.f)).x == Approx(12.f)); { - vec2i out_exp{}; - REQUIRE(frexp(vec2f(1.7f), &out_exp).x == Approx(0.85f)); - REQUIRE(out_exp == vec2i(1)); + int2 out_exp{}; + REQUIRE(frexp(float2(1.7f), &out_exp).x == Approx(0.85f)); + REQUIRE(out_exp == int2(1)); } - REQUIRE(ldexp(vec2f(0.85f), vec2i(1)).x == Approx(1.7f)); + REQUIRE(ldexp(float2(0.85f), int2(1)).x == Approx(1.7f)); } SECTION("Geometric Functions") { - REQUIRE(length(vec2f(10.f,0.f)) == Approx(10.f)); - REQUIRE(length(vec2f(-10.f,0.f)) == Approx(10.f)); + REQUIRE(length(float2(10.f,0.f)) == Approx(10.f)); + REQUIRE(length(float2(-10.f,0.f)) == Approx(10.f)); - STATIC_REQUIRE(length2(vec2f(10.f,0.f)) == approx(100.f)); - STATIC_REQUIRE(length2(vec2f(-10.f,0.f)) == approx(100.f)); + STATIC_REQUIRE(length2(float2(10.f,0.f)) == approx(100.f)); + STATIC_REQUIRE(length2(float2(-10.f,0.f)) == approx(100.f)); - REQUIRE(distance(vec2f(5.f,0.f), vec2f(10.f,0.f)) == Approx(5.f)); - REQUIRE(distance(vec2f(-5.f,0.f), vec2f(-10.f,0.f)) == Approx(5.f)); + REQUIRE(distance(float2(5.f,0.f), float2(10.f,0.f)) == Approx(5.f)); + REQUIRE(distance(float2(-5.f,0.f), float2(-10.f,0.f)) == Approx(5.f)); - STATIC_REQUIRE(distance2(vec2f(5.f,0.f), vec2f(10.f,0.f)) == approx(25.f)); - STATIC_REQUIRE(distance2(vec2f(-5.f,0.f), vec2f(-10.f,0.f)) == approx(25.f)); + STATIC_REQUIRE(distance2(float2(5.f,0.f), float2(10.f,0.f)) == approx(25.f)); + STATIC_REQUIRE(distance2(float2(-5.f,0.f), float2(-10.f,0.f)) == approx(25.f)); - STATIC_REQUIRE(dot(vec2i(1,2),vec2i(3,4)) == 11); - STATIC_REQUIRE(cross(vec2i(1,0),vec2i(0,1)) == 1); - STATIC_REQUIRE(cross(vec3i(1,0,0),vec3i(0,1,0)) == vec3i(0,0,1)); - REQUIRE(normalize(vec2f(0.5f,0.f)).x == Approx(1.f)); + STATIC_REQUIRE(dot(int2(1,2),int2(3,4)) == 11); + STATIC_REQUIRE(cross(int2(1,0),int2(0,1)) == 1); + STATIC_REQUIRE(cross(int3(1,0,0),int3(0,1,0)) == int3(0,0,1)); + REQUIRE(normalize(float2(0.5f,0.f)).x == Approx(1.f)); - STATIC_REQUIRE(faceforward(vec2f(1.f), vec2f(2.f), vec2f(3.f)).x == approx(-1.f)); - STATIC_REQUIRE(reflect(vec2f(1.f), vec2f(2.f)).x == approx(-15.f)); - REQUIRE(refract(vec2f(1.f), vec2f(2.f), 1.f).x == Approx(-15.f)); + STATIC_REQUIRE(faceforward(float2(1.f), float2(2.f), float2(3.f)).x == approx(-1.f)); + STATIC_REQUIRE(reflect(float2(1.f), float2(2.f)).x == approx(-15.f)); + REQUIRE(refract(float2(1.f), float2(2.f), 1.f).x == Approx(-15.f)); } SECTION("Vector Relational Functions") { - STATIC_REQUIRE(less(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(false, false, true)); - STATIC_REQUIRE(less_equal(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(false, true, true)); + STATIC_REQUIRE(less(int3(1,1,1), int3(0,1,2)) == bool3(false, false, true)); + STATIC_REQUIRE(less_equal(int3(1,1,1), int3(0,1,2)) == bool3(false, true, true)); - STATIC_REQUIRE(greater(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(true, false, false)); - STATIC_REQUIRE(greater_equal(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(true, true, false)); + STATIC_REQUIRE(greater(int3(1,1,1), int3(0,1,2)) == bool3(true, false, false)); + STATIC_REQUIRE(greater_equal(int3(1,1,1), int3(0,1,2)) == bool3(true, true, false)); - STATIC_REQUIRE(equal_to(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(false, true, false)); - STATIC_REQUIRE(not_equal_to(vec3i(1,1,1), vec3i(0,1,2)) == vec3b(true, false, true)); + STATIC_REQUIRE(equal_to(int3(1,1,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_FALSE(any(vec2b(false, false))); - STATIC_REQUIRE(any(vec2b(true, false))); - STATIC_REQUIRE(any(vec2b(false, true))); - STATIC_REQUIRE(any(vec2b(true, true))); + 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_REQUIRE_FALSE(all(vec2b(false, false))); - STATIC_REQUIRE_FALSE(all(vec2b(true, false))); - STATIC_REQUIRE_FALSE(all(vec2b(false, true))); - STATIC_REQUIRE(all(vec2b(true, true))); + 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_REQUIRE(not_(vec2b(false, false)) == vec2b(true, true)); - STATIC_REQUIRE(not_(vec2b(true, false)) == vec2b(false, true)); - STATIC_REQUIRE(not_(vec2b(false, true)) == vec2b(true, false)); - STATIC_REQUIRE(not_(vec2b(true, true)) == vec2b(false, false)); + STATIC_REQUIRE(not_(bool2(false, false)) == bool2(true, true)); + STATIC_REQUIRE(not_(bool2(true, false)) == bool2(false, true)); + STATIC_REQUIRE(not_(bool2(false, true)) == bool2(true, false)); + STATIC_REQUIRE(not_(bool2(true, true)) == bool2(false, false)); } } diff --git a/untests/vmath_vec_tests.cpp b/untests/vmath_vec_tests.cpp index 3c9f84c..9d75355 100644 --- a/untests/vmath_vec_tests.cpp +++ b/untests/vmath_vec_tests.cpp @@ -20,157 +20,157 @@ namespace TEST_CASE("vmath/vec") { SECTION("size/sizeof") { - STATIC_REQUIRE(vec2i{}.size == 2); - STATIC_REQUIRE(vec3i{}.size == 3); - STATIC_REQUIRE(vec4i{}.size == 4); + STATIC_REQUIRE(int2{}.size == 2); + STATIC_REQUIRE(int3{}.size == 3); + STATIC_REQUIRE(int4{}.size == 4); - STATIC_REQUIRE(sizeof(vec2i{}) == sizeof(int) * 2); - STATIC_REQUIRE(sizeof(vec3i{}) == sizeof(int) * 3); - STATIC_REQUIRE(sizeof(vec4i{}) == sizeof(int) * 4); + STATIC_REQUIRE(sizeof(int2{}) == sizeof(int) * 2); + STATIC_REQUIRE(sizeof(int3{}) == sizeof(int) * 3); + STATIC_REQUIRE(sizeof(int4{}) == sizeof(int) * 4); } SECTION("ctors") { { - STATIC_REQUIRE(vec2i().x == 0); - STATIC_REQUIRE(vec2i().y == 0); + STATIC_REQUIRE(int2().x == 0); + STATIC_REQUIRE(int2().y == 0); - STATIC_REQUIRE(vec2i(1).x == 1); - STATIC_REQUIRE(vec2i(1).y == 1); + STATIC_REQUIRE(int2(1).x == 1); + STATIC_REQUIRE(int2(1).y == 1); - STATIC_REQUIRE(vec2i(1,2).x == 1); - STATIC_REQUIRE(vec2i(1,2).y == 2); + STATIC_REQUIRE(int2(1,2).x == 1); + STATIC_REQUIRE(int2(1,2).y == 2); } { - constexpr vec2i v(1,2); - constexpr vec2i v2 = v; - STATIC_REQUIRE(v2 == vec2i(1,2)); + constexpr int2 v(1,2); + constexpr int2 v2 = v; + STATIC_REQUIRE(v2 == int2(1,2)); } { - constexpr vec2i v(1,2); - constexpr vec2i v2 = std::move(v); - STATIC_REQUIRE(v2 == vec2i(1,2)); + constexpr int2 v(1,2); + constexpr int2 v2 = std::move(v); + STATIC_REQUIRE(v2 == int2(1,2)); } { - STATIC_REQUIRE(vec2i(1) == vec2i(1,1)); - STATIC_REQUIRE(vec2i(1,2) == vec2i(1,2)); - STATIC_REQUIRE(vec2i(vec2i(1,2)) == vec2i(1,2)); - STATIC_REQUIRE(vec2i(vec3i(1,2,3)) == vec2i(1,2)); - STATIC_REQUIRE(vec2i(vec4i(1,2,3,4)) == vec2i(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_REQUIRE(vec3i(1) == vec3i(1,1,1)); - STATIC_REQUIRE(vec3i(1,2,3) == vec3i(1,2,3)); - STATIC_REQUIRE(vec3i(vec2i(1,2),3) == vec3i(1,2,3)); - STATIC_REQUIRE(vec3i(1,vec2i(2,3)) == vec3i(1,2,3)); - STATIC_REQUIRE(vec3i(vec3i(1,2,3)) == vec3i(1,2,3)); - STATIC_REQUIRE(vec3i(vec4i(1,2,3,4)) == vec3i(1,2,3)); + 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_REQUIRE(vec4i(1) == vec4i(1,1,1,1)); - STATIC_REQUIRE(vec4i(1,2,3,4) == vec4i(1,2,3,4)); - STATIC_REQUIRE(vec4i(vec2i(1,2),3,4) == vec4i(1,2,3,4)); - STATIC_REQUIRE(vec4i(1,vec2i(2,3),4) == vec4i(1,2,3,4)); - STATIC_REQUIRE(vec4i(1,2,vec2i(3,4)) == vec4i(1,2,3,4)); - STATIC_REQUIRE(vec4i(vec2i(1,2),vec2i(3,4)) == vec4i(1,2,3,4)); - STATIC_REQUIRE(vec4i(vec3i(1,2,3),4) == vec4i(1,2,3,4)); - STATIC_REQUIRE(vec4i(1,vec3i(2,3,4)) == vec4i(1,2,3,4)); + 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)); } } SECTION("operator=") { { - vec2i v(1,2); - vec2i v2; + int2 v(1,2); + int2 v2; v2 = v; - REQUIRE(v2 == vec2i(1,2)); + REQUIRE(v2 == int2(1,2)); } { - vec2i v(1,2); - vec2i v2; + int2 v(1,2); + int2 v2; v2 = std::move(v); - REQUIRE(v2 == vec2i(1,2)); + REQUIRE(v2 == int2(1,2)); } } SECTION("swap") { { - vec2i v1(1,2); - vec2i v2(4,5); + int2 v1(1,2); + int2 v2(4,5); v1.swap(v2); - REQUIRE(v1 == vec2i(4,5)); - REQUIRE(v2 == vec2i(1,2)); + REQUIRE(v1 == int2(4,5)); + REQUIRE(v2 == int2(1,2)); } { - vec2i v1(1,2); - vec2i v2(4,5); + int2 v1(1,2); + int2 v2(4,5); swap(v1, v2); - REQUIRE(v1 == vec2i(4,5)); - REQUIRE(v2 == vec2i(1,2)); + REQUIRE(v1 == int2(4,5)); + REQUIRE(v2 == int2(1,2)); } } SECTION("operator[]") { { - STATIC_REQUIRE(vec2i(1,2).x == 1); - STATIC_REQUIRE(vec2i(1,2).y == 2); + STATIC_REQUIRE(int2(1,2).x == 1); + STATIC_REQUIRE(int2(1,2).y == 2); - STATIC_REQUIRE(vec3i(1,2,3).x == 1); - STATIC_REQUIRE(vec3i(1,2,3).y == 2); - STATIC_REQUIRE(vec3i(1,2,3).z == 3); + 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_REQUIRE(vec4i(1,2,3,4).x == 1); - STATIC_REQUIRE(vec4i(1,2,3,4).y == 2); - STATIC_REQUIRE(vec4i(1,2,3,4).z == 3); - STATIC_REQUIRE(vec4i(1,2,3,4).w == 4); + 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_REQUIRE(vec2i(1,2)[0] == 1); - STATIC_REQUIRE(vec2i(1,2)[1] == 2); + STATIC_REQUIRE(int2(1,2)[0] == 1); + STATIC_REQUIRE(int2(1,2)[1] == 2); } { - vec2i v; + int2 v; v.x = 1; v.y = 2; - REQUIRE(v == vec2i(1,2)); + REQUIRE(v == int2(1,2)); } { - vec3i v; + int3 v; v.x = 1; v.y = 2; v.z = 3; - REQUIRE(v == vec3i(1,2,3)); + REQUIRE(v == int3(1,2,3)); } { - vec4i v; + int4 v; v.x = 1; v.y = 2; v.z = 3; v.w = 4; - REQUIRE(v == vec4i(1,2,3,4)); + REQUIRE(v == int4(1,2,3,4)); } } SECTION("at") { - STATIC_REQUIRE(vec2i(1,2).at(0) == 1); - STATIC_REQUIRE(vec2i(1,2).at(1) == 2); - REQUIRE_THROWS_AS(vec2i(1,2).at(2), std::out_of_range); + STATIC_REQUIRE(int2(1,2).at(0) == 1); + STATIC_REQUIRE(int2(1,2).at(1) == 2); + REQUIRE_THROWS_AS(int2(1,2).at(2), std::out_of_range); } SECTION("operator==/operator!=") { - STATIC_REQUIRE(vec2i(1,2) == vec2i(1,2)); - STATIC_REQUIRE_FALSE(vec2i(1,2) == vec2i(2,2)); - STATIC_REQUIRE_FALSE(vec2i(1,2) == vec2i(1,3)); + 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_REQUIRE_FALSE(vec2i(1,2) != vec2i(1,2)); - STATIC_REQUIRE(vec2i(1,2) != vec2i(2,2)); - STATIC_REQUIRE(vec2i(1,2) != vec2i(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)); } SECTION("operator<") { - STATIC_REQUIRE_FALSE(vec2i(1,2) < vec2i(1,2)); + STATIC_REQUIRE_FALSE(int2(1,2) < int2(1,2)); - STATIC_REQUIRE(vec2i(1,1) < vec2i(1,2)); - STATIC_REQUIRE_FALSE(vec2i(1,2) < vec2i(1,1)); + STATIC_REQUIRE(int2(1,1) < int2(1,2)); + STATIC_REQUIRE_FALSE(int2(1,2) < int2(1,1)); - STATIC_REQUIRE(vec2i(0,3) < vec2i(1,2)); - STATIC_REQUIRE_FALSE(vec2i(1,2) < vec2i(0,3)); + STATIC_REQUIRE(int2(0,3) < int2(1,2)); + STATIC_REQUIRE_FALSE(int2(1,2) < int2(0,3)); } } From 4505a5899ba710bf9e77b455cff4aa64d2158dbf Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 01:52:24 +0700 Subject: [PATCH 36/53] scalar relational functions --- headers/vmath.hpp/vmath_fun.hpp | 49 +++++++++++++++++++++++++++++++++ untests/vmath_fun_tests.cpp | 27 ++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index aca7938..fca4d6f 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -178,3 +178,52 @@ namespace vmath_hpp return T(k >= T(0)) * (eta * i - (eta * d + sqrt(k)) * n); } } + +// +// Scalar Relational Functions +// + +namespace vmath_hpp +{ + template < typename T > + constexpr bool less(const T& x, const T& y) { + return x < y; + } + + template < typename T > + constexpr bool less_equal(const T& x, const T& y) { + return x <= y; + } + + template < typename T > + constexpr bool greater(const T& x, const T& y) { + return x > y; + } + + template < typename T > + constexpr bool greater_equal(const T& x, const T& y) { + return x >= y; + } + + template < typename T > + constexpr bool equal_to(const T& x, const T& y) { + return x == y; + } + + template < typename T > + constexpr bool not_equal_to(const T& x, const T& y) { + return x != y; + } + + constexpr bool any(bool x) noexcept { + return x; + } + + constexpr bool all(bool x) noexcept { + return x; + } + + constexpr bool not_(bool x) noexcept { + return !x; + } +} diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index 72ed18c..ce93c22 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -130,4 +130,31 @@ TEST_CASE("vmath/fun") { STATIC_REQUIRE(reflect(1.f, 2.f) == approx(-7.f)); REQUIRE(refract(1.f, 2.f, 1.f) == approx(-7.f)); } + + SECTION("Scalar Relational Functions") { + STATIC_REQUIRE(less(0, 1)); + STATIC_REQUIRE(less_equal(0, 1)); + STATIC_REQUIRE_FALSE(less(1, 1)); + STATIC_REQUIRE(less_equal(1, 1)); + + STATIC_REQUIRE(greater(1, 0)); + STATIC_REQUIRE(greater_equal(1, 0)); + STATIC_REQUIRE_FALSE(greater(1, 1)); + STATIC_REQUIRE(greater_equal(1, 1)); + + STATIC_REQUIRE_FALSE(equal_to(0, 1)); + STATIC_REQUIRE(equal_to(1, 1)); + + STATIC_REQUIRE(not_equal_to(0, 1)); + STATIC_REQUIRE_FALSE(not_equal_to(1, 1)); + + STATIC_REQUIRE_FALSE(any(false)); + STATIC_REQUIRE(any(true)); + + STATIC_REQUIRE_FALSE(all(false)); + STATIC_REQUIRE(all(true)); + + STATIC_REQUIRE_FALSE(not_(true)); + STATIC_REQUIRE(not_(false)); + } } From ed8e530accb70823b6a4e65441642ba70860569d Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 01:58:27 +0700 Subject: [PATCH 37/53] isnormal, issubnormal --- headers/vmath.hpp/vmath_fun.hpp | 6 ++++++ headers/vmath.hpp/vmath_vec_fun.hpp | 10 ++++++++++ untests/vmath_fun_tests.cpp | 2 ++ untests/vmath_vec_fun_tests.cpp | 2 ++ 4 files changed, 20 insertions(+) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index fca4d6f..602d2e5 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -119,6 +119,12 @@ namespace vmath_hpp using ::std::isnan; using ::std::isinf; using ::std::isfinite; + using ::std::isnormal; + + template < typename T > + bool issubnormal(T x) noexcept { + return std::fpclassify(x) == FP_SUBNORMAL; + } using ::std::fma; using ::std::frexp; diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index edb14d6..eec79c1 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -529,6 +529,16 @@ namespace vmath_hpp return map([](T x) { return isfinite(x); }, xs); } + template < typename T, std::size_t Size > + vec isnormal(const vec& xs) { + return map([](T x) { return isnormal(x); }, xs); + } + + template < typename T, std::size_t Size > + vec issubnormal(const vec& xs) { + return map([](T x) { return issubnormal(x); }, xs); + } + template < typename T, std::size_t Size > vec fma(const vec& as, const vec& bs, const vec& cs) { return zip([](T a, T b, T c) { return fma(a, b, c); }, as, bs, cs); diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index ce93c22..02a281d 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -98,6 +98,8 @@ TEST_CASE("vmath/fun") { REQUIRE_FALSE(isnan(1.f)); REQUIRE_FALSE(isinf(1.f)); REQUIRE(isfinite(1.f)); + REQUIRE(isnormal(1.f)); + REQUIRE_FALSE(issubnormal(1.f)); REQUIRE(fma(2.f, 3.f, 4.f) == approx(10.f)); diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 7daf195..53aa7e7 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -144,6 +144,8 @@ TEST_CASE("vmath/vec_fun") { REQUIRE_FALSE(isnan(float2(1.f)).x); REQUIRE_FALSE(isinf(float2(1.f)).x); REQUIRE(isfinite(float2(1.f)).x); + REQUIRE(isnormal(float2(1.f)).x); + REQUIRE(issubnormal(float2(1.f)).x); REQUIRE_FALSE(fma(float2(2.f), float2(3.f), float2(4.f)).x == Approx(12.f)); From bd156d8af997b5d89268b1d8fd4561534366c488 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 02:27:47 +0700 Subject: [PATCH 38/53] equal_to with epsilon --- headers/vmath.hpp/vmath_fun.hpp | 24 ++++++++++++++++++++++-- headers/vmath.hpp/vmath_vec_fun.hpp | 28 +++++++++++++++++++--------- untests/vmath_fun_tests.cpp | 8 +++++++- untests/vmath_vec_fun_tests.cpp | 7 +++++++ 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index 602d2e5..8baed1d 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -67,10 +67,20 @@ namespace vmath_hpp namespace vmath_hpp { - using ::std::abs; + template < typename T > + std::enable_if_t, T> + constexpr abs(T x) noexcept { + return x; + } template < typename T > - T sign(T x) noexcept { + std::enable_if_t, T> + constexpr abs(T x) noexcept { + return x >= T(0) ? x : -x; + } + + template < typename T > + constexpr T sign(T x) noexcept { return static_cast((T(0) < x) - (x < T(0))); } @@ -216,11 +226,21 @@ namespace vmath_hpp return x == y; } + template < typename T > + constexpr bool equal_to(const T& x, const T& y, const T& epsilon) { + return abs(x - y) <= epsilon; + } + template < typename T > constexpr bool not_equal_to(const T& x, const T& y) { return x != y; } + template < typename T > + constexpr bool not_equal_to(const T& x, const T& y, const T& epsilon) { + return abs(x - y) > epsilon; + } + constexpr bool any(bool x) noexcept { return x; } diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index eec79c1..7700c13 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -640,46 +640,56 @@ namespace vmath_hpp { template < typename T, std::size_t Size > constexpr vec less(const vec& xs, const vec& ys) { - return zip(std::less<>(), xs, ys); + return zip([](T x, T y){ return less(x, y); }, xs, ys); } template < typename T, std::size_t Size > constexpr vec less_equal(const vec& xs, const vec& ys) { - return zip(std::less_equal<>(), xs, ys); + return zip([](T x, T y){ return less_equal(x, y); }, xs, ys); } template < typename T, std::size_t Size > constexpr vec greater(const vec& xs, const vec& ys) { - return zip(std::greater<>(), xs, ys); + return zip([](T x, T y){ return greater(x, y); }, xs, ys); } template < typename T, std::size_t Size > constexpr vec greater_equal(const vec& xs, const vec& ys) { - return zip(std::greater_equal<>(), xs, ys); + return zip([](T x, T y){ return greater_equal(x, y); }, xs, ys); } template < typename T, std::size_t Size > constexpr vec equal_to(const vec& xs, const vec& ys) { - return zip(std::equal_to<>(), xs, ys); + return zip([](T x, T y){ return equal_to(x, y); }, xs, ys); + } + + template < typename T, std::size_t Size > + constexpr vec equal_to(const vec& xs, const vec& ys, const T& epsilon) { + return zip([epsilon](T x, T y){ return equal_to(x, y, epsilon); }, xs, ys); } template < typename T, std::size_t Size > constexpr vec not_equal_to(const vec& xs, const vec& ys) { - return zip(std::not_equal_to<>(), xs, ys); + return zip([](T x, T y){ return not_equal_to(x, y); }, xs, ys); + } + + template < typename T, std::size_t Size > + constexpr vec not_equal_to(const vec& xs, const vec& ys, const T& epsilon) { + return zip([epsilon](T x, T y){ return not_equal_to(x, y, epsilon); }, xs, ys); } template < std::size_t Size > constexpr bool any(const vec& xs) { - return fold(std::logical_or<>(), false, xs); + return fold([](bool x, bool y){ return x || y; }, false, xs); } template < std::size_t Size > constexpr bool all(const vec& xs) { - return fold(std::logical_and<>(), true, xs); + return fold([](bool x, bool y){ return x && y; }, true, xs); } template < std::size_t Size > constexpr vec not_(const vec& xs) { - return map(std::logical_not<>(), xs); + return map([](bool x){ return not_(x); }, xs); } } diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index 02a281d..c32ab7b 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -144,11 +144,17 @@ TEST_CASE("vmath/fun") { STATIC_REQUIRE_FALSE(greater(1, 1)); STATIC_REQUIRE(greater_equal(1, 1)); - STATIC_REQUIRE_FALSE(equal_to(0, 1)); STATIC_REQUIRE(equal_to(1, 1)); + STATIC_REQUIRE_FALSE(equal_to(0, 1)); + STATIC_REQUIRE_FALSE(equal_to(0, 1, 0)); + STATIC_REQUIRE(equal_to(0, 1, 1)); STATIC_REQUIRE(not_equal_to(0, 1)); + STATIC_REQUIRE(not_equal_to(0, 1, 0)); + STATIC_REQUIRE_FALSE(not_equal_to(0, 1, 1)); STATIC_REQUIRE_FALSE(not_equal_to(1, 1)); + STATIC_REQUIRE_FALSE(not_equal_to(1, 1, 0)); + STATIC_REQUIRE_FALSE(not_equal_to(1, 1, 1)); STATIC_REQUIRE_FALSE(any(false)); STATIC_REQUIRE(any(true)); diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 53aa7e7..8b4cb5b 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -189,7 +189,14 @@ TEST_CASE("vmath/vec_fun") { STATIC_REQUIRE(greater_equal(int3(1,1,1), int3(0,1,2)) == bool3(true, true, false)); STATIC_REQUIRE(equal_to(int3(1,1,1), int3(0,1,2)) == bool3(false, true, false)); + STATIC_REQUIRE(equal_to(int4(1,1,1,1), int4(0,1,2,3), 0) == bool4(false, true, false, false)); + STATIC_REQUIRE(equal_to(int4(1,1,1,1), int4(0,1,2,3), 1) == bool4(true, true, true, false)); + STATIC_REQUIRE(equal_to(int4(1,1,1,1), int4(0,1,2,3), 2) == bool4(true, true, true, true)); + STATIC_REQUIRE(not_equal_to(int3(1,1,1), int3(0,1,2)) == bool3(true, false, true)); + STATIC_REQUIRE(not_equal_to(int4(1,1,1,1), int4(0,1,2,3), 0) == bool4(true, false, true, true)); + STATIC_REQUIRE(not_equal_to(int4(1,1,1,1), int4(0,1,2,3), 1) == bool4(false, false, false, true)); + STATIC_REQUIRE(not_equal_to(int4(1,1,1,1), int4(0,1,2,3), 2) == bool4(false, false, false, false)); STATIC_REQUIRE_FALSE(any(bool2(false, false))); STATIC_REQUIRE(any(bool2(true, false))); From 87e4233383777e3f5950cda2019cfa2639ea1298 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 02:39:04 +0700 Subject: [PATCH 39/53] fix tests --- untests/vmath_tests.hpp | 15 ++++----------- untests/vmath_vec_fun_tests.cpp | 2 +- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/untests/vmath_tests.hpp b/untests/vmath_tests.hpp index 5c50b21..c57ce5f 100644 --- a/untests/vmath_tests.hpp +++ b/untests/vmath_tests.hpp @@ -22,8 +22,7 @@ namespace vmath_tests explicit constexpr approx(T v) : value(v) {} friend constexpr bool operator==(const T& l, const approx& r) { - return (r.value < l + epsilon) - && (l < r.value + epsilon); + return equal_to(l, r.value, epsilon); } }; @@ -35,8 +34,7 @@ namespace vmath_tests constexpr explicit approx2(const vec& v) : value(v) {} friend constexpr bool operator==(const vec& l, const approx2& r) { - return l[0] == approx(r.value[0]) - && l[1] == approx(r.value[1]); + return all(equal_to(l, r.value, epsilon)); } }; @@ -48,9 +46,7 @@ namespace vmath_tests constexpr explicit approx3(const vec& v) : value(v) {} friend constexpr bool operator==(const vec& l, const approx3& r) { - return l[0] == approx(r.value[0]) - && l[1] == approx(r.value[1]) - && l[2] == approx(r.value[2]); + return all(equal_to(l, r.value, epsilon)); } }; @@ -62,10 +58,7 @@ namespace vmath_tests constexpr explicit approx4(const vec& v) : value(v) {} friend constexpr bool operator==(const vec& l, const approx4& r) { - return l[0] == approx(r.value[0]) - && l[1] == approx(r.value[1]) - && l[2] == approx(r.value[2]) - && l[3] == approx(r.value[3]); + return all(equal_to(l, r.value, epsilon)); } }; diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 8b4cb5b..3991383 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -145,7 +145,7 @@ TEST_CASE("vmath/vec_fun") { REQUIRE_FALSE(isinf(float2(1.f)).x); REQUIRE(isfinite(float2(1.f)).x); REQUIRE(isnormal(float2(1.f)).x); - REQUIRE(issubnormal(float2(1.f)).x); + REQUIRE_FALSE(issubnormal(float2(1.f)).x); REQUIRE_FALSE(fma(float2(2.f), float2(3.f), float2(4.f)).x == Approx(12.f)); From f1e56a2c8a1dab6344c64e65848ffc515c0dafd7 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 03:03:52 +0700 Subject: [PATCH 40/53] vector angle function --- headers/vmath.hpp/vmath_mat_ext.hpp | 18 ++++++------- headers/vmath.hpp/vmath_vec_ext.hpp | 38 +++++++++++++++++----------- untests/vmath_mat_ext_tests.cpp | 18 ++++++------- untests/vmath_vec_ext_tests.cpp | 39 ++++++++++++++++++----------- 4 files changed, 65 insertions(+), 48 deletions(-) diff --git a/headers/vmath.hpp/vmath_mat_ext.hpp b/headers/vmath.hpp/vmath_mat_ext.hpp index 059680c..0fab15e 100644 --- a/headers/vmath.hpp/vmath_mat_ext.hpp +++ b/headers/vmath.hpp/vmath_mat_ext.hpp @@ -20,17 +20,17 @@ namespace vmath_hpp { - template < typename T > constexpr mat zero2x2() { return {0, 0, 0, 0}; } - template < typename T > constexpr mat zero3x3() { return {0, 0, 0, 0, 0, 0, 0, 0, 0}; } - template < typename T > constexpr mat zero4x4() { return {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; } + template < typename T > inline constexpr mat zero2x2{0, 0, 0, 0}; + template < typename T > inline constexpr mat zero3x3{0, 0, 0, 0, 0, 0, 0, 0, 0}; + template < typename T > inline constexpr mat zero4x4{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - template < typename T > constexpr mat unit2x2() { return {1, 1, 1, 1}; } - template < typename T > constexpr mat unit3x3() { return {1, 1, 1, 1, 1, 1, 1, 1, 1}; } - template < typename T > constexpr mat unit4x4() { return {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; } + template < typename T > inline constexpr mat unit2x2{1, 1, 1, 1}; + template < typename T > inline constexpr mat unit3x3{1, 1, 1, 1, 1, 1, 1, 1, 1}; + template < typename T > inline constexpr mat unit4x4{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - template < typename T > constexpr mat identity2x2() { return {1, 0, 0, 1}; } - template < typename T > constexpr mat identity3x3() { return {1, 0, 0, 0, 1, 0, 0, 0, 1}; } - template < typename T > constexpr mat identity4x4() { return {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; } + template < typename T > inline constexpr mat identity2x2{1, 0, 0, 1}; + template < typename T > inline constexpr mat identity3x3{1, 0, 0, 0, 1, 0, 0, 0, 1}; + template < typename T > inline constexpr mat identity4x4{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; } namespace std diff --git a/headers/vmath.hpp/vmath_vec_ext.hpp b/headers/vmath.hpp/vmath_vec_ext.hpp index f47069e..e62c142 100644 --- a/headers/vmath.hpp/vmath_vec_ext.hpp +++ b/headers/vmath.hpp/vmath_vec_ext.hpp @@ -16,25 +16,25 @@ namespace vmath_hpp { - template < typename T > constexpr vec zero2() { return {0, 0}; } - template < typename T > constexpr vec zero3() { return {0, 0, 0}; } - template < typename T > constexpr vec zero4() { return {0, 0, 0, 0}; } + template < typename T > inline constexpr vec zero2{0, 0}; + template < typename T > inline constexpr vec zero3{0, 0, 0}; + template < typename T > inline constexpr vec zero4{0, 0, 0, 0}; - template < typename T > constexpr vec unit2() { return {1, 1}; } - template < typename T > constexpr vec unit3() { return {1, 1, 1}; } - template < typename T > constexpr vec unit4() { return {1, 1, 1, 1}; } + template < typename T > inline constexpr vec unit2{1, 1}; + template < typename T > inline constexpr vec unit3{1, 1, 1}; + template < typename T > inline constexpr vec unit4{1, 1, 1, 1}; - template < typename T > constexpr vec unit2_x() { return {1, 0}; } - template < typename T > constexpr vec unit2_y() { return {0, 1}; } + template < typename T > inline constexpr vec unit2_x{1, 0}; + template < typename T > inline constexpr vec unit2_y{0, 1}; - template < typename T > constexpr vec unit3_x() { return {1, 0, 0}; } - template < typename T > constexpr vec unit3_y() { return {0, 1, 0}; } - template < typename T > constexpr vec unit3_z() { return {0, 0, 1}; } + template < typename T > inline constexpr vec unit3_x{1, 0, 0}; + template < typename T > inline constexpr vec unit3_y{0, 1, 0}; + template < typename T > inline constexpr vec unit3_z{0, 0, 1}; - template < typename T > constexpr vec unit4_x() { return {1, 0, 0, 0}; } - template < typename T > constexpr vec unit4_y() { return {0, 1, 0, 0}; } - template < typename T > constexpr vec unit4_z() { return {0, 0, 1, 0}; } - template < typename T > constexpr vec unit4_w() { return {0, 0, 0, 1}; } + template < typename T > inline constexpr vec unit4_x{1, 0, 0, 0}; + template < typename T > inline constexpr vec unit4_y{0, 1, 0, 0}; + template < typename T > inline constexpr vec unit4_z{0, 0, 1, 0}; + template < typename T > inline constexpr vec unit4_w{0, 0, 0, 1}; } namespace std @@ -69,3 +69,11 @@ namespace vmath_hpp return v; } } + +namespace vmath_hpp +{ + template < typename T, std::size_t Size > + T angle(const vec& x, const vec& y) { + return acos(dot(x, y) * invsqrt(length2(x) * length2(y))); + } +} diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp index 05f6221..36fbc95 100644 --- a/untests/vmath_mat_ext_tests.cpp +++ b/untests/vmath_mat_ext_tests.cpp @@ -19,17 +19,17 @@ namespace TEST_CASE("vmath/mat_ext") { SECTION("units") { - STATIC_REQUIRE(zero2x2() == int2x2(0,0,0,0)); - STATIC_REQUIRE(zero3x3() == int3x3(0,0,0,0,0,0,0,0,0)); - STATIC_REQUIRE(zero4x4() == int4x4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)); + STATIC_REQUIRE(zero2x2 == int2x2(0,0,0,0)); + STATIC_REQUIRE(zero3x3 == int3x3(0,0,0,0,0,0,0,0,0)); + STATIC_REQUIRE(zero4x4 == int4x4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)); - STATIC_REQUIRE(unit2x2() == int2x2(1,1,1,1)); - STATIC_REQUIRE(unit3x3() == int3x3(1,1,1,1,1,1,1,1,1)); - STATIC_REQUIRE(unit4x4() == int4x4(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)); + STATIC_REQUIRE(unit2x2 == int2x2(1,1,1,1)); + STATIC_REQUIRE(unit3x3 == int3x3(1,1,1,1,1,1,1,1,1)); + STATIC_REQUIRE(unit4x4 == int4x4(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)); - STATIC_REQUIRE(identity2x2() == int2x2()); - STATIC_REQUIRE(identity3x3() == int3x3()); - STATIC_REQUIRE(identity4x4() == int4x4()); + STATIC_REQUIRE(identity2x2 == int2x2()); + STATIC_REQUIRE(identity3x3 == int3x3()); + STATIC_REQUIRE(identity4x4 == int4x4()); } SECTION("hash") { diff --git a/untests/vmath_vec_ext_tests.cpp b/untests/vmath_vec_ext_tests.cpp index 4c204e6..a72c2e5 100644 --- a/untests/vmath_vec_ext_tests.cpp +++ b/untests/vmath_vec_ext_tests.cpp @@ -19,24 +19,24 @@ namespace TEST_CASE("vmath/vec_ext") { SECTION("units") { - STATIC_REQUIRE(zero2() == int2(0,0)); - STATIC_REQUIRE(zero3() == int3(0,0,0)); - STATIC_REQUIRE(zero4() == int4(0,0,0,0)); + STATIC_REQUIRE(zero2 == int2(0,0)); + STATIC_REQUIRE(zero3 == int3(0,0,0)); + STATIC_REQUIRE(zero4 == int4(0,0,0,0)); - STATIC_REQUIRE(unit2() == int2(1,1)); - STATIC_REQUIRE(unit2_x() == int2(1,0)); - STATIC_REQUIRE(unit2_y() == int2(0,1)); + STATIC_REQUIRE(unit2 == int2(1,1)); + STATIC_REQUIRE(unit2_x == int2(1,0)); + STATIC_REQUIRE(unit2_y == int2(0,1)); - STATIC_REQUIRE(unit3() == int3(1,1,1)); - STATIC_REQUIRE(unit3_x() == int3(1,0,0)); - STATIC_REQUIRE(unit3_y() == int3(0,1,0)); - STATIC_REQUIRE(unit3_z() == int3(0,0,1)); + STATIC_REQUIRE(unit3 == int3(1,1,1)); + STATIC_REQUIRE(unit3_x == int3(1,0,0)); + STATIC_REQUIRE(unit3_y == int3(0,1,0)); + STATIC_REQUIRE(unit3_z == int3(0,0,1)); - STATIC_REQUIRE(unit4() == int4(1,1,1,1)); - STATIC_REQUIRE(unit4_x() == int4(1,0,0,0)); - STATIC_REQUIRE(unit4_y() == int4(0,1,0,0)); - STATIC_REQUIRE(unit4_z() == int4(0,0,1,0)); - STATIC_REQUIRE(unit4_w() == int4(0,0,0,1)); + STATIC_REQUIRE(unit4 == int4(1,1,1,1)); + STATIC_REQUIRE(unit4_x == int4(1,0,0,0)); + STATIC_REQUIRE(unit4_y == int4(0,1,0,0)); + STATIC_REQUIRE(unit4_z == int4(0,0,1,0)); + STATIC_REQUIRE(unit4_w == int4(0,0,0,1)); } SECTION("hash") { @@ -63,4 +63,13 @@ TEST_CASE("vmath/vec_ext") { STATIC_REQUIRE(component(int2{0,0}, 0, 1) == int2{1,0}); STATIC_REQUIRE(component(int2{0,0}, 1, 2) == int2{0,2}); } + + SECTION("angle") { + REQUIRE(angle(float2(2.f,0.f), float2(0.f,1.f)) == Approx(radians(90.f))); + REQUIRE(angle(float2(0.f,3.f), float2(1.f,0.f)) == Approx(radians(90.f))); + REQUIRE(angle(float2(0.5f,0.f), float2(-1.f,0.f)) == Approx(radians(180.f))); + REQUIRE(angle(float2(-0.2f,0.f), float2(1.f,0.f)) == Approx(radians(180.f))); + REQUIRE(angle(float3(0.f,2.f,0.f), float3(0.f,0.f,1.f)) == Approx(radians(90.f))); + REQUIRE(angle(float3(0.f,0.f,3.f), float3(0.f,1.f,0.f)) == Approx(radians(90.f))); + } } From bf258a00ac36060a4cd268d5a258ae67ad6c05fc Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 05:07:42 +0700 Subject: [PATCH 41/53] vector rotate functions --- headers/vmath.hpp/vmath.hpp | 7 +- headers/vmath.hpp/vmath_ext.hpp | 279 ++++++++++++++++++++++++++++ headers/vmath.hpp/vmath_mat_ext.hpp | 188 ------------------- headers/vmath.hpp/vmath_vec_ext.hpp | 79 -------- untests/vmath_ext_tests.cpp | 133 ++++++++++++- untests/vmath_mat_ext_tests.cpp | 88 --------- untests/vmath_mat_fun_tests.cpp | 3 +- untests/vmath_vec_ext_tests.cpp | 75 -------- untests/vmath_vec_fun_tests.cpp | 2 +- 9 files changed, 416 insertions(+), 438 deletions(-) delete mode 100644 headers/vmath.hpp/vmath_mat_ext.hpp delete mode 100644 headers/vmath.hpp/vmath_vec_ext.hpp delete mode 100644 untests/vmath_mat_ext_tests.cpp delete mode 100644 untests/vmath_vec_ext_tests.cpp diff --git a/headers/vmath.hpp/vmath.hpp b/headers/vmath.hpp/vmath.hpp index 5353745..4151a03 100644 --- a/headers/vmath.hpp/vmath.hpp +++ b/headers/vmath.hpp/vmath.hpp @@ -6,10 +6,13 @@ #pragma once +#include "vmath_fwd.hpp" + #include "vmath_fun.hpp" +#include "vmath_ext.hpp" + #include "vmath_mat.hpp" #include "vmath_mat_fun.hpp" -#include "vmath_mat_ext.hpp" + #include "vmath_vec.hpp" #include "vmath_vec_fun.hpp" -#include "vmath_vec_ext.hpp" diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index a5a0c02..652a448 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -9,6 +9,51 @@ #include "vmath_fwd.hpp" #include "vmath_fun.hpp" +#include "vmath_vec_fun.hpp" +#include "vmath_mat_fun.hpp" + +// +// Units +// + +namespace vmath_hpp +{ + template < typename T > inline constexpr vec zero2{0, 0}; + template < typename T > inline constexpr vec zero3{0, 0, 0}; + template < typename T > inline constexpr vec zero4{0, 0, 0, 0}; + + template < typename T > inline constexpr vec unit2{1, 1}; + template < typename T > inline constexpr vec unit3{1, 1, 1}; + template < typename T > inline constexpr vec unit4{1, 1, 1, 1}; + + template < typename T > inline constexpr vec unit2_x{1, 0}; + template < typename T > inline constexpr vec unit2_y{0, 1}; + + template < typename T > inline constexpr vec unit3_x{1, 0, 0}; + template < typename T > inline constexpr vec unit3_y{0, 1, 0}; + template < typename T > inline constexpr vec unit3_z{0, 0, 1}; + + template < typename T > inline constexpr vec unit4_x{1, 0, 0, 0}; + template < typename T > inline constexpr vec unit4_y{0, 1, 0, 0}; + template < typename T > inline constexpr vec unit4_z{0, 0, 1, 0}; + template < typename T > inline constexpr vec unit4_w{0, 0, 0, 1}; + + template < typename T > inline constexpr mat zero2x2{0, 0, 0, 0}; + template < typename T > inline constexpr mat zero3x3{0, 0, 0, 0, 0, 0, 0, 0, 0}; + template < typename T > inline constexpr mat zero4x4{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + template < typename T > inline constexpr mat unit2x2{1, 1, 1, 1}; + template < typename T > inline constexpr mat unit3x3{1, 1, 1, 1, 1, 1, 1, 1, 1}; + template < typename T > inline constexpr mat unit4x4{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + + template < typename T > inline constexpr mat identity2x2{1, 0, 0, 1}; + template < typename T > inline constexpr mat identity3x3{1, 0, 0, 0, 1, 0, 0, 0, 1}; + template < typename T > inline constexpr mat identity4x4{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; +} + +// +// Hash +// namespace vmath_hpp::detail { @@ -18,12 +63,246 @@ namespace vmath_hpp::detail return (seed ^= std::hash{}(x) + 0x9e3779b9 + (seed << 6) + ( seed >> 2)); } }; + + template < typename T, size_t Size > + std::size_t hash(const vec& v) noexcept { + return fold(hash_combiner{}, std::size_t{}, v); + } + + template < typename T, size_t Size > + std::size_t hash(const mat& m) noexcept { + return fold(hash_combiner{}, std::size_t{}, m); + } } +namespace std +{ + template < typename T, size_t Size > + struct hash> { + size_t operator()(const vmath_hpp::vec& v) const noexcept { + return vmath_hpp::detail::hash(v); + } + }; + + template < typename T, size_t Size > + struct hash> { + size_t operator()(const vmath_hpp::mat& m) const noexcept { + return vmath_hpp::detail::hash(m); + } + }; +} + +// +// Cast +// + namespace vmath_hpp { template < typename To, typename From > constexpr To cast_to(From x) noexcept { return static_cast(x); } + + template < typename To, typename From, std::size_t Size > + constexpr vec cast_to(const vec& v) { + return detail::map([](From x){ return cast_to(x); }, v); + } + + template < typename To, typename From, std::size_t Size > + constexpr mat cast_to(const mat& m) { + return detail::map([](const vec& v){ return cast_to(v); }, m); + } +} + +// +// Access +// + +namespace vmath_hpp +{ + // component + + template < typename T, std::size_t Size > + constexpr T component(const vec& v, std::size_t index) { + return v[index]; + } + + template < typename T, std::size_t Size > + constexpr vec component(vec v, std::size_t index, T x) { + v[index] = x; + return v; + } + + // row + + template < typename T, std::size_t Size > + constexpr vec row(const mat& m, std::size_t index) { + return m.rows[index]; + } + + template < typename T, std::size_t Size > + constexpr mat row(mat m, std::size_t index, const vec& v) { + m.rows[index] = v; + return m; + } + + // column + + namespace impl + { + template < typename T, std::size_t Size, std::size_t... Is > + constexpr vec column_impl(const mat& m, std::size_t index, std::index_sequence) { + return { m[Is][index]... }; + } + + template < typename T, std::size_t Size, std::size_t... Is > + constexpr mat column_impl(const mat& m, std::size_t index, const vec& v, std::index_sequence) { + return { component(m[Is], index, v[Is])... }; + } + } + + template < typename T, std::size_t Size > + constexpr vec column(const mat& m, std::size_t index) { + return impl::column_impl(m, index, std::make_index_sequence{}); + } + + template < typename T, std::size_t Size > + constexpr mat column(const mat& m, std::size_t index, const vec& v) { + return impl::column_impl(m, index, v, std::make_index_sequence{}); + } +} + +// +// Matrix Transform +// + +namespace vmath_hpp +{ + // translate + + template < typename T > + constexpr mat translate(T x, T y, T z) { + return { + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {x, y, z, 1}}; + } + + template < typename T > + constexpr mat translate(const vec& xyz) { + return translate(xyz.x, xyz.y, xyz.z); + } + + template < typename T > + constexpr mat translate(const mat& m, T x, T y, T z) { + return m * translate(x, y, z); + } + + template < typename T > + constexpr mat translate(const mat& m, const vec& xyz) { + return m * translate(xyz); + } + + // rotate + + template < typename T > + mat rotate(T angle, T axis_x, T axis_y, T axis_z) { + const T x = axis_x; + const T y = axis_y; + const T z = axis_z; + const T px = x * x; + const T py = y * y; + const T pz = z * z; + const T cs = cos(angle); + const T sn = sin(angle); + const T ics = T(1) - cs; + const T xym = x * y * ics; + const T xzm = x * z * ics; + const T yzm = y * z * ics; + const T xsn = x * sn; + const T ysn = y * sn; + const T zsn = z * sn; + return { + px * ics + cs, xym + zsn, xzm - ysn, 0, + xym - zsn, py * ics + cs, yzm + xsn, 0, + xzm + ysn, yzm - xsn, pz * ics + cs, 0, + 0, 0, 0, 1}; + } + + template < typename T > + mat rotate(T angle, const vec& axis) { + return rotate(angle, axis.x, axis.y, axis.z); + } + + template < typename T > + mat rotate(const mat& m, T angle, T axis_x, T axis_y, T axis_z) { + return m * rotate(angle, axis_x, axis_y, axis_z); + } + + template < typename T > + mat rotate(const mat& m, T angle, const vec& axis) { + return m * rotate(angle, axis); + } + + // scale + + template < typename T > + constexpr mat scale(T x, T y, T z) { + return { + {x, 0, 0, 0}, + {0, y, 0, 0}, + {0, 0, z, 0}, + {0, 0, 0, 1}}; + } + + template < typename T > + constexpr mat scale(const vec& xyz) { + return scale(xyz.x, xyz.y, xyz.z); + } + + template < typename T > + constexpr mat scale(const mat& m, T x, T y, T z) { + return m * scale(x, y, z); + } + + template < typename T > + constexpr mat scale(const mat& m, const vec& xyz) { + return m * scale(xyz); + } +} + +// +// Vector Transform +// + +namespace vmath_hpp +{ + // angle + + template < typename T, std::size_t Size > + T angle(const vec& x, const vec& y) { + return acos(dot(x, y) * invsqrt(length2(x) * length2(y))); + } + + // rotate + + template < typename T > + vec rotate(const vec& v, T angle) { + const T cs = cos(angle); + const T sn = sin(angle); + return { + v.x * cs - v.y * sn, + v.x * sn + v.y * cs}; + } + + template < typename T > + vec rotate(const vec& v, T angle, const vec& normal) { + return v * mat(rotate(angle, normal)); + } + + template < typename T > + vec rotate(const vec& v, T angle, const vec& normal) { + return v * rotate(angle, normal); + } } diff --git a/headers/vmath.hpp/vmath_mat_ext.hpp b/headers/vmath.hpp/vmath_mat_ext.hpp deleted file mode 100644 index 0fab15e..0000000 --- a/headers/vmath.hpp/vmath_mat_ext.hpp +++ /dev/null @@ -1,188 +0,0 @@ -/******************************************************************************* - * 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, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "vmath_fwd.hpp" - -#include "vmath_ext.hpp" -#include "vmath_fun.hpp" - -#include "vmath_vec.hpp" -#include "vmath_vec_fun.hpp" -#include "vmath_vec_ext.hpp" - -#include "vmath_mat.hpp" -#include "vmath_mat_fun.hpp" - -namespace vmath_hpp -{ - template < typename T > inline constexpr mat zero2x2{0, 0, 0, 0}; - template < typename T > inline constexpr mat zero3x3{0, 0, 0, 0, 0, 0, 0, 0, 0}; - template < typename T > inline constexpr mat zero4x4{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - template < typename T > inline constexpr mat unit2x2{1, 1, 1, 1}; - template < typename T > inline constexpr mat unit3x3{1, 1, 1, 1, 1, 1, 1, 1, 1}; - template < typename T > inline constexpr mat unit4x4{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - - template < typename T > inline constexpr mat identity2x2{1, 0, 0, 1}; - template < typename T > inline constexpr mat identity3x3{1, 0, 0, 0, 1, 0, 0, 0, 1}; - template < typename T > inline constexpr mat identity4x4{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; -} - -namespace std -{ - template < typename T, size_t Size > - struct hash> { - size_t operator()(const vmath_hpp::mat& m) const noexcept { - return vmath_hpp::detail::fold(vmath_hpp::detail::hash_combiner{}, size_t{}, m); - } - }; -} - -namespace vmath_hpp -{ - // cast_to - - template < typename To, typename From, std::size_t Size > - constexpr mat cast_to(const mat& m) { - return detail::map([](const vec& v){ return cast_to(v); }, m); - } - - // row - - template < typename T, std::size_t Size > - constexpr vec row(const mat& m, std::size_t index) { - return m.rows[index]; - } - - template < typename T, std::size_t Size > - constexpr mat row(mat m, std::size_t index, const vec& v) { - m.rows[index] = v; - return m; - } - - // column - - namespace impl - { - template < typename T, std::size_t Size, std::size_t... Is > - constexpr vec column_impl(const mat& m, std::size_t index, std::index_sequence) { - return { m[Is][index]... }; - } - - template < typename T, std::size_t Size, std::size_t... Is > - constexpr mat column_impl(const mat& m, std::size_t index, const vec& v, std::index_sequence) { - return { component(m[Is], index, v[Is])... }; - } - } - - template < typename T, std::size_t Size > - constexpr vec column(const mat& m, std::size_t index) { - return impl::column_impl(m, index, std::make_index_sequence{}); - } - - template < typename T, std::size_t Size > - constexpr mat column(const mat& m, std::size_t index, const vec& v) { - return impl::column_impl(m, index, v, std::make_index_sequence{}); - } -} - -namespace vmath_hpp -{ - // translate - - template < typename T > - constexpr mat translate(T x, T y, T z) { - return { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {x, y, z, 1}}; - } - - template < typename T > - constexpr mat translate(const vec& xyz) { - return translate(xyz.x, xyz.y, xyz.z); - } - - template < typename T > - constexpr mat translate(const mat& m, T x, T y, T z) { - return m * translate(x, y, z); - } - - template < typename T > - constexpr mat translate(const mat& m, const vec& xyz) { - return m * translate(xyz); - } - - // rotate - - template < typename T > - mat rotate(T angle, T axis_x, T axis_y, T axis_z) { - const T x = axis_x; - const T y = axis_y; - const T z = axis_z; - const T px = x * x; - const T py = y * y; - const T pz = z * z; - const T cs = cos(angle); - const T sn = sin(angle); - const T ics = T(1) - cs; - const T xym = x * y * ics; - const T xzm = x * z * ics; - const T yzm = y * z * ics; - const T xsn = x * sn; - const T ysn = y * sn; - const T zsn = z * sn; - return { - px * ics + cs, xym + zsn, xzm - ysn, 0, - xym - zsn, py * ics + cs, yzm + xsn, 0, - xzm + ysn, yzm - xsn, pz * ics + cs, 0, - 0, 0, 0, 1}; - } - - template < typename T > - mat rotate(T angle, const vec& axis) { - return rotate(angle, axis.x, axis.y, axis.z); - } - - template < typename T > - mat rotate(const mat& m, T angle, T axis_x, T axis_y, T axis_z) { - return m * rotate(angle, axis_x, axis_y, axis_z); - } - - template < typename T > - mat rotate(const mat& m, T angle, const vec& axis) { - return m * rotate(angle, axis); - } - - // scale - - template < typename T > - constexpr mat scale(T x, T y, T z) { - return { - {x, 0, 0, 0}, - {0, y, 0, 0}, - {0, 0, z, 0}, - {0, 0, 0, 1}}; - } - - template < typename T > - constexpr mat scale(const vec& xyz) { - return scale(xyz.x, xyz.y, xyz.z); - } - - template < typename T > - constexpr mat scale(const mat& m, T x, T y, T z) { - return m * scale(x, y, z); - } - - template < typename T > - constexpr mat scale(const mat& m, const vec& xyz) { - return m * scale(xyz); - } -} diff --git a/headers/vmath.hpp/vmath_vec_ext.hpp b/headers/vmath.hpp/vmath_vec_ext.hpp deleted file mode 100644 index e62c142..0000000 --- a/headers/vmath.hpp/vmath_vec_ext.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * 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, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "vmath_fwd.hpp" - -#include "vmath_ext.hpp" -#include "vmath_fun.hpp" - -#include "vmath_vec.hpp" -#include "vmath_vec_fun.hpp" - -namespace vmath_hpp -{ - template < typename T > inline constexpr vec zero2{0, 0}; - template < typename T > inline constexpr vec zero3{0, 0, 0}; - template < typename T > inline constexpr vec zero4{0, 0, 0, 0}; - - template < typename T > inline constexpr vec unit2{1, 1}; - template < typename T > inline constexpr vec unit3{1, 1, 1}; - template < typename T > inline constexpr vec unit4{1, 1, 1, 1}; - - template < typename T > inline constexpr vec unit2_x{1, 0}; - template < typename T > inline constexpr vec unit2_y{0, 1}; - - template < typename T > inline constexpr vec unit3_x{1, 0, 0}; - template < typename T > inline constexpr vec unit3_y{0, 1, 0}; - template < typename T > inline constexpr vec unit3_z{0, 0, 1}; - - template < typename T > inline constexpr vec unit4_x{1, 0, 0, 0}; - template < typename T > inline constexpr vec unit4_y{0, 1, 0, 0}; - template < typename T > inline constexpr vec unit4_z{0, 0, 1, 0}; - template < typename T > inline constexpr vec unit4_w{0, 0, 0, 1}; -} - -namespace std -{ - template < typename T, size_t Size > - struct hash> { - size_t operator()(const vmath_hpp::vec& v) const noexcept { - return vmath_hpp::detail::fold(vmath_hpp::detail::hash_combiner{}, size_t{}, v); - } - }; -} - -namespace vmath_hpp -{ - // cast_to - - template < typename To, typename From, std::size_t Size > - constexpr vec cast_to(const vec& v) { - return detail::map([](From x){ return cast_to(x); }, v); - } - - // component - - template < typename T, std::size_t Size > - constexpr T component(const vec& v, std::size_t index) { - return v[index]; - } - - template < typename T, std::size_t Size > - constexpr vec component(vec v, std::size_t index, T x) { - v[index] = x; - return v; - } -} - -namespace vmath_hpp -{ - template < typename T, std::size_t Size > - T angle(const vec& x, const vec& y) { - return acos(dot(x, y) * invsqrt(length2(x) * length2(y))); - } -} diff --git a/untests/vmath_ext_tests.cpp b/untests/vmath_ext_tests.cpp index 8a30350..1944be6 100644 --- a/untests/vmath_ext_tests.cpp +++ b/untests/vmath_ext_tests.cpp @@ -18,9 +18,136 @@ namespace } TEST_CASE("vmath/ext") { + SECTION("units") { + STATIC_REQUIRE(zero2 == int2(0,0)); + STATIC_REQUIRE(zero3 == int3(0,0,0)); + STATIC_REQUIRE(zero4 == int4(0,0,0,0)); + + STATIC_REQUIRE(unit2 == int2(1,1)); + STATIC_REQUIRE(unit2_x == int2(1,0)); + STATIC_REQUIRE(unit2_y == int2(0,1)); + + STATIC_REQUIRE(unit3 == int3(1,1,1)); + STATIC_REQUIRE(unit3_x == int3(1,0,0)); + STATIC_REQUIRE(unit3_y == int3(0,1,0)); + STATIC_REQUIRE(unit3_z == int3(0,0,1)); + + STATIC_REQUIRE(unit4 == int4(1,1,1,1)); + STATIC_REQUIRE(unit4_x == int4(1,0,0,0)); + STATIC_REQUIRE(unit4_y == int4(0,1,0,0)); + STATIC_REQUIRE(unit4_z == int4(0,0,1,0)); + STATIC_REQUIRE(unit4_w == int4(0,0,0,1)); + + STATIC_REQUIRE(zero2x2 == int2x2(0,0,0,0)); + STATIC_REQUIRE(zero3x3 == int3x3(0,0,0,0,0,0,0,0,0)); + STATIC_REQUIRE(zero4x4 == int4x4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)); + + STATIC_REQUIRE(unit2x2 == int2x2(1,1,1,1)); + STATIC_REQUIRE(unit3x3 == int3x3(1,1,1,1,1,1,1,1,1)); + STATIC_REQUIRE(unit4x4 == int4x4(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)); + + STATIC_REQUIRE(identity2x2 == int2x2()); + STATIC_REQUIRE(identity3x3 == int3x3()); + STATIC_REQUIRE(identity4x4 == int4x4()); + } + + SECTION("hash") { + REQUIRE(std::hash{}({1,2}) == std::hash{}({1,2})); + REQUIRE_FALSE(std::hash{}({1,2}) == std::hash{}({2,1})); + + REQUIRE(std::hash{}({1,2,3}) == std::hash{}({1,2,3})); + REQUIRE_FALSE(std::hash{}({1,2,3}) == std::hash{}({3,2,1})); + + REQUIRE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,3,4})); + REQUIRE_FALSE(std::hash{}({1,2,3,4}) == std::hash{}({3,2,1,4})); + + REQUIRE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,3,4})); + REQUIRE_FALSE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,4,3})); + } + SECTION("cast_to") { - constexpr auto i = cast_to(1.5f); - STATIC_REQUIRE(i == 1); - STATIC_REQUIRE(std::is_same_v); + { + constexpr auto i = cast_to(1.5f); + STATIC_REQUIRE(i == 1); + STATIC_REQUIRE(std::is_same_v); + } + { + constexpr auto v = cast_to(float2{1.5f}); + STATIC_REQUIRE(v == int2(1)); + STATIC_REQUIRE(std::is_same_v); + } + { + constexpr auto m = cast_to(float2x2{1.5f}); + STATIC_REQUIRE(m == int2x2(1)); + STATIC_REQUIRE(std::is_same_v); + } + } + + SECTION("component") { + STATIC_REQUIRE(component(int2{1,2}, 0) == 1); + STATIC_REQUIRE(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}); + } + + SECTION("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_REQUIRE(row(int2x2(), 0, {1,2}) == int2x2(1,2,0,1)); + STATIC_REQUIRE(row(int2x2(), 1, {3,4}) == int2x2(1,0,3,4)); + } + + SECTION("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_REQUIRE(column(int2x2(), 0, {2,3}) == int2x2(2,0,3,1)); + STATIC_REQUIRE(column(int2x2(), 1, {3,4}) == int2x2(1,3,0,4)); + } + + SECTION("matrix translate") { + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(1.f,2.f,3.f) == approx4(3.f,5.f,7.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(float3{1.f,2.f,3.f}) == approx4(3.f,5.f,7.f,1.f)); + + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), 1.f,2.f,3.f) == approx4(4.f,7.f,10.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), float3{1.f,2.f,3.f}) == approx4(4.f,7.f,10.f,1.f)); + } + + SECTION("matrix rotate") { + constexpr float pi = radians(180.f); + constexpr float pi_2 = radians(90.f); + + REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); + + REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,0.f,0.f,1.f),pi_2,0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,0.f,0.f,1.f),pi_2,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); + } + + SECTION("matrix scale") { + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(2.f,3.f,4.f) == approx4(4.f,9.f,16.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f)); + + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), 2.f,3.f,4.f) == approx4(8.f,18.f,32.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), float3{2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); + } + + SECTION("vector angle") { + REQUIRE(angle(float2(2.f,0.f), float2(0.f,1.f)) == Approx(radians(90.f))); + REQUIRE(angle(float2(0.f,3.f), float2(1.f,0.f)) == Approx(radians(90.f))); + REQUIRE(angle(float2(0.5f,0.f), float2(-1.f,0.f)) == Approx(radians(180.f))); + REQUIRE(angle(float2(-0.2f,0.f), float2(1.f,0.f)) == Approx(radians(180.f))); + REQUIRE(angle(float3(0.f,2.f,0.f), float3(0.f,0.f,1.f)) == Approx(radians(90.f))); + REQUIRE(angle(float3(0.f,0.f,3.f), float3(0.f,1.f,0.f)) == Approx(radians(90.f))); + } + + SECTION("vector rotate") { + REQUIRE(rotate(float2(2.f,0.f), radians(90.f)) == approx2(0.f,2.f)); + REQUIRE(rotate(float2(1.5f,0.f), radians(-90.f)) == approx2(0.f,-1.5f)); + + REQUIRE(rotate(float3(1.5f,0.f,0.f), radians(90.f), float3(0,0,1)) == approx3(0.f,1.5f,0.f)); + REQUIRE(rotate(float4(1.5f,0.f,0.f,1.f), radians(90.f), float3(0,0,1)) == approx4(0.f,1.5f,0.f,1.f)); } } diff --git a/untests/vmath_mat_ext_tests.cpp b/untests/vmath_mat_ext_tests.cpp deleted file mode 100644 index 36fbc95..0000000 --- a/untests/vmath_mat_ext_tests.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/******************************************************************************* - * 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, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#include - -#define CATCH_CONFIG_FAST_COMPILE -#include - -#include "vmath_tests.hpp" - -namespace -{ - using namespace vmath_hpp; - using namespace vmath_tests; -} - -TEST_CASE("vmath/mat_ext") { - SECTION("units") { - STATIC_REQUIRE(zero2x2 == int2x2(0,0,0,0)); - STATIC_REQUIRE(zero3x3 == int3x3(0,0,0,0,0,0,0,0,0)); - STATIC_REQUIRE(zero4x4 == int4x4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)); - - STATIC_REQUIRE(unit2x2 == int2x2(1,1,1,1)); - STATIC_REQUIRE(unit3x3 == int3x3(1,1,1,1,1,1,1,1,1)); - STATIC_REQUIRE(unit4x4 == int4x4(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)); - - STATIC_REQUIRE(identity2x2 == int2x2()); - STATIC_REQUIRE(identity3x3 == int3x3()); - STATIC_REQUIRE(identity4x4 == int4x4()); - } - - SECTION("hash") { - REQUIRE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,3,4})); - REQUIRE_FALSE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,4,3})); - } - - SECTION("cast_to") { - constexpr auto m = cast_to(float2x2{1.5f}); - STATIC_REQUIRE(m == int2x2(1)); - STATIC_REQUIRE(std::is_same_v); - } - - SECTION("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_REQUIRE(row(int2x2(), 0, {1,2}) == int2x2(1,2,0,1)); - STATIC_REQUIRE(row(int2x2(), 1, {3,4}) == int2x2(1,0,3,4)); - } - - SECTION("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_REQUIRE(column(int2x2(), 0, {2,3}) == int2x2(2,0,3,1)); - STATIC_REQUIRE(column(int2x2(), 1, {3,4}) == int2x2(1,3,0,4)); - } - - SECTION("translate") { - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(1.f,2.f,3.f) == approx4(3.f,5.f,7.f,1.f)); - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(float3{1.f,2.f,3.f}) == approx4(3.f,5.f,7.f,1.f)); - - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), 1.f,2.f,3.f) == approx4(4.f,7.f,10.f,1.f)); - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), float3{1.f,2.f,3.f}) == approx4(4.f,7.f,10.f,1.f)); - } - - SECTION("rotate") { - constexpr float pi = radians(180.f); - constexpr float pi_2 = radians(90.f); - - REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); - REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); - - REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,0.f,0.f,1.f),pi_2,0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); - REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,0.f,0.f,1.f),pi_2,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); - } - - SECTION("scale") { - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(2.f,3.f,4.f) == approx4(4.f,9.f,16.f,1.f)); - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f)); - - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), 2.f,3.f,4.f) == approx4(8.f,18.f,32.f,1.f)); - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), float3{2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); - } -} diff --git a/untests/vmath_mat_fun_tests.cpp b/untests/vmath_mat_fun_tests.cpp index f220f4d..f1b19bb 100644 --- a/untests/vmath_mat_fun_tests.cpp +++ b/untests/vmath_mat_fun_tests.cpp @@ -4,8 +4,7 @@ * Copyright (C) 2020, by Matvey Cherevko (blackmatov@gmail.com) ******************************************************************************/ -#include -#include +#include #define CATCH_CONFIG_FAST_COMPILE #include diff --git a/untests/vmath_vec_ext_tests.cpp b/untests/vmath_vec_ext_tests.cpp deleted file mode 100644 index a72c2e5..0000000 --- a/untests/vmath_vec_ext_tests.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * 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, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#include - -#define CATCH_CONFIG_FAST_COMPILE -#include - -#include "vmath_tests.hpp" - -namespace -{ - using namespace vmath_hpp; - using namespace vmath_tests; -} - -TEST_CASE("vmath/vec_ext") { - SECTION("units") { - STATIC_REQUIRE(zero2 == int2(0,0)); - STATIC_REQUIRE(zero3 == int3(0,0,0)); - STATIC_REQUIRE(zero4 == int4(0,0,0,0)); - - STATIC_REQUIRE(unit2 == int2(1,1)); - STATIC_REQUIRE(unit2_x == int2(1,0)); - STATIC_REQUIRE(unit2_y == int2(0,1)); - - STATIC_REQUIRE(unit3 == int3(1,1,1)); - STATIC_REQUIRE(unit3_x == int3(1,0,0)); - STATIC_REQUIRE(unit3_y == int3(0,1,0)); - STATIC_REQUIRE(unit3_z == int3(0,0,1)); - - STATIC_REQUIRE(unit4 == int4(1,1,1,1)); - STATIC_REQUIRE(unit4_x == int4(1,0,0,0)); - STATIC_REQUIRE(unit4_y == int4(0,1,0,0)); - STATIC_REQUIRE(unit4_z == int4(0,0,1,0)); - STATIC_REQUIRE(unit4_w == int4(0,0,0,1)); - } - - SECTION("hash") { - REQUIRE(std::hash{}({1,2}) == std::hash{}({1,2})); - REQUIRE_FALSE(std::hash{}({1,2}) == std::hash{}({2,1})); - - REQUIRE(std::hash{}({1,2,3}) == std::hash{}({1,2,3})); - REQUIRE_FALSE(std::hash{}({1,2,3}) == std::hash{}({3,2,1})); - - REQUIRE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,3,4})); - REQUIRE_FALSE(std::hash{}({1,2,3,4}) == std::hash{}({3,2,1,4})); - } - - SECTION("cast_to") { - constexpr auto v = cast_to(float2{1.5f}); - STATIC_REQUIRE(v == int2(1)); - STATIC_REQUIRE(std::is_same_v); - } - - SECTION("component") { - STATIC_REQUIRE(component(int2{1,2}, 0) == 1); - STATIC_REQUIRE(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}); - } - - SECTION("angle") { - REQUIRE(angle(float2(2.f,0.f), float2(0.f,1.f)) == Approx(radians(90.f))); - REQUIRE(angle(float2(0.f,3.f), float2(1.f,0.f)) == Approx(radians(90.f))); - REQUIRE(angle(float2(0.5f,0.f), float2(-1.f,0.f)) == Approx(radians(180.f))); - REQUIRE(angle(float2(-0.2f,0.f), float2(1.f,0.f)) == Approx(radians(180.f))); - REQUIRE(angle(float3(0.f,2.f,0.f), float3(0.f,0.f,1.f)) == Approx(radians(90.f))); - REQUIRE(angle(float3(0.f,0.f,3.f), float3(0.f,1.f,0.f)) == Approx(radians(90.f))); - } -} diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 3991383..18584d4 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -4,7 +4,7 @@ * Copyright (C) 2020, by Matvey Cherevko (blackmatov@gmail.com) ******************************************************************************/ -#include +#include #define CATCH_CONFIG_FAST_COMPILE #include From 6c4a1f64f5db086218f021a18dfec96bf09169d2 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 05:49:35 +0700 Subject: [PATCH 42/53] look_at matrix functions --- headers/vmath.hpp/vmath_ext.hpp | 92 +++++++++++++++++---------------- untests/vmath_ext_tests.cpp | 22 ++++---- untests/vmath_mat_fun_tests.cpp | 18 +++---- 3 files changed, 68 insertions(+), 64 deletions(-) diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index 652a448..3a911ef 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -181,36 +181,26 @@ namespace vmath_hpp // translate template < typename T > - constexpr mat translate(T x, T y, T z) { + constexpr mat translate(const vec& v) { return { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {x, y, z, 1}}; + { 1, 0, 0, 0}, + { 0, 1, 0, 0}, + { 0, 0, 1, 0}, + {v.x, v.y, v.z, 1}}; } template < typename T > - constexpr mat translate(const vec& xyz) { - return translate(xyz.x, xyz.y, xyz.z); - } - - template < typename T > - constexpr mat translate(const mat& m, T x, T y, T z) { - return m * translate(x, y, z); - } - - template < typename T > - constexpr mat translate(const mat& m, const vec& xyz) { - return m * translate(xyz); + constexpr mat translate(const mat& m, const vec& v) { + return m * translate(v); } // rotate template < typename T > - mat rotate(T angle, T axis_x, T axis_y, T axis_z) { - const T x = axis_x; - const T y = axis_y; - const T z = axis_z; + mat rotate(T angle, const vec& axis) { + const T x = axis.x; + const T y = axis.y; + const T z = axis.z; const T px = x * x; const T py = y * y; const T pz = z * z; @@ -230,16 +220,6 @@ namespace vmath_hpp 0, 0, 0, 1}; } - template < typename T > - mat rotate(T angle, const vec& axis) { - return rotate(angle, axis.x, axis.y, axis.z); - } - - template < typename T > - mat rotate(const mat& m, T angle, T axis_x, T axis_y, T axis_z) { - return m * rotate(angle, axis_x, axis_y, axis_z); - } - template < typename T > mat rotate(const mat& m, T angle, const vec& axis) { return m * rotate(angle, axis); @@ -248,27 +228,49 @@ namespace vmath_hpp // scale template < typename T > - constexpr mat scale(T x, T y, T z) { + constexpr mat scale(const vec& v) { return { - {x, 0, 0, 0}, - {0, y, 0, 0}, - {0, 0, z, 0}, - {0, 0, 0, 1}}; + {v.x, 0, 0, 0}, + { 0, v.y, 0, 0}, + { 0, 0, v.z, 0}, + { 0, 0, 0, 1}}; } template < typename T > - constexpr mat scale(const vec& xyz) { - return scale(xyz.x, xyz.y, xyz.z); + constexpr mat scale(const mat& m, const vec& v) { + return m * scale(v); + } + + // look_at + + template < typename T > + constexpr mat look_at_lh(const vec& eye, const vec& at, const vec& up) { + 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); + const T dz = dot(az, eye); + return { + ax.x, ay.x, az.x, 0, + ax.y, ay.y, az.y, 0, + ax.z, ay.z, az.z, 0, + -dx, -dy, -dz, 1}; } template < typename T > - constexpr mat scale(const mat& m, T x, T y, T z) { - return m * scale(x, y, z); - } - - template < typename T > - constexpr mat scale(const mat& m, const vec& xyz) { - return m * scale(xyz); + constexpr mat look_at_rh(const vec& eye, const vec& at, const vec& up) { + 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); + const T dz = dot(az, eye); + return { + ax.x, ay.x, az.x, 0, + ax.y, ay.y, az.y, 0, + ax.z, ay.z, az.z, 0, + -dx, -dy, -dz, 1}; } } diff --git a/untests/vmath_ext_tests.cpp b/untests/vmath_ext_tests.cpp index 1944be6..7097873 100644 --- a/untests/vmath_ext_tests.cpp +++ b/untests/vmath_ext_tests.cpp @@ -108,30 +108,32 @@ TEST_CASE("vmath/ext") { } SECTION("matrix translate") { - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(1.f,2.f,3.f) == approx4(3.f,5.f,7.f,1.f)); STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(float3{1.f,2.f,3.f}) == approx4(3.f,5.f,7.f,1.f)); - - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), 1.f,2.f,3.f) == approx4(4.f,7.f,10.f,1.f)); - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(1.f,2.f,3.f), float3{1.f,2.f,3.f}) == approx4(4.f,7.f,10.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(float3{1.f,2.f,3.f}), float3{1.f,2.f,3.f}) == approx4(4.f,7.f,10.f,1.f)); } SECTION("matrix rotate") { constexpr float pi = radians(180.f); constexpr float pi_2 = radians(90.f); - REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); - REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,0.f,0.f,1.f),pi_2,0.f,0.f,1.f) == approx4(-2.f,-3.f,4.f,1.f)); - REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,0.f,0.f,1.f),pi_2,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,{0.f,0.f,1.f}),pi_2,{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,float3{0.f,0.f,1.f}),pi_2,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); } SECTION("matrix scale") { - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(2.f,3.f,4.f) == approx4(4.f,9.f,16.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f)); STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f)); - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), 2.f,3.f,4.f) == approx4(8.f,18.f,32.f,1.f)); - STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(2.f,2.f,2.f), float3{2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), {2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), float3{2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); + } + + SECTION("matrix look_at") { + look_at_lh(float3(-10.f), float3(0.f), float3(0,-1,0)); + look_at_rh(float3(-10.f), float3(0.f), float3(0,-1,0)); } SECTION("vector angle") { diff --git a/untests/vmath_mat_fun_tests.cpp b/untests/vmath_mat_fun_tests.cpp index f1b19bb..4edfae7 100644 --- a/untests/vmath_mat_fun_tests.cpp +++ b/untests/vmath_mat_fun_tests.cpp @@ -88,23 +88,23 @@ TEST_CASE("vmath/mat_fun") { { float4 v{0.f, 0.f, 0.f, 1.f}; - REQUIRE(&v == &(v *= translate(1.f,2.f,3.f))); + REQUIRE(&v == &(v *= translate(float3{1.f,2.f,3.f}))); REQUIRE(v == approx4(1.f,2.f,3.f,1.f)); } { float3 v{1.f, 2.f, 3.f}; - REQUIRE(&v == &(v *= float3x3(scale(2.f,3.f,4.f)))); + REQUIRE(&v == &(v *= float3x3(scale(float3{2.f,3.f,4.f})))); REQUIRE(v == approx3(2.f,6.f,12.f)); } { - float4x4 v = translate(1.f, 2.f, 3.f); - REQUIRE(&v == &(v *= translate(1.f,2.f,3.f))); - REQUIRE(v == approx4x4(translate(2.f,4.f,6.f))); + float4x4 v = translate(float3{1.f, 2.f, 3.f}); + REQUIRE(&v == &(v *= translate(float3{1.f,2.f,3.f}))); + REQUIRE(v == approx4x4(translate(float3{2.f,4.f,6.f}))); } { - float3x3 v = float3x3(scale(1.f, 2.f, 3.f)); - REQUIRE(&v == &(v *= float3x3(scale(2.f,3.f,4.f)))); - REQUIRE(v == approx3x3(float3x3(scale(2.f,6.f,12.f)))); + float3x3 v = float3x3(scale(float3{1.f, 2.f, 3.f})); + REQUIRE(&v == &(v *= float3x3(scale(float3{2.f,3.f,4.f})))); + REQUIRE(v == approx3x3(float3x3(scale(float3{2.f,6.f,12.f})))); } } @@ -165,7 +165,7 @@ TEST_CASE("vmath/mat_fun") { STATIC_REQUIRE(inverse(float3x3(0.5)) == float3x3(2.f)); STATIC_REQUIRE(inverse(float4x4(0.5)) == float4x4(2.f)); - STATIC_REQUIRE(inverse(translate(1.f,2.f,3.f)) == approx4x4(translate(-1.f,-2.f,-3.f))); + STATIC_REQUIRE(inverse(translate(float3{1.f,2.f,3.f})) == approx4x4(translate(float3{-1.f,-2.f,-3.f}))); REQUIRE(inverse(rotate(0.5f,normalize(float3{1.f,2.f,3.f}))) == approx4x4(rotate(-0.5f,normalize(float3{1.f,2.f,3.f})))); REQUIRE(inverse(float3x3(rotate(0.5f,normalize(float3{1.f,2.f,3.f})))) == approx3x3(float3x3(rotate(-0.5f,normalize(float3{1.f,2.f,3.f}))))); From 15cd3a981ebd21392bc090da8c471bed68e4ac8f Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 06:21:51 +0700 Subject: [PATCH 43/53] orthographic and perspective functions --- headers/vmath.hpp/vmath_ext.hpp | 135 +++++++++++++++++++++++++++++++- untests/vmath_ext_tests.cpp | 10 +++ 2 files changed, 143 insertions(+), 2 deletions(-) diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index 3a911ef..4467307 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -244,7 +244,7 @@ namespace vmath_hpp // look_at template < typename T > - constexpr mat look_at_lh(const vec& eye, const vec& at, const vec& up) { + mat look_at_lh(const vec& eye, const vec& at, const vec& up) { const vec az = normalize(at - eye); const vec ax = normalize(cross(up, az)); const vec ay = cross(az, ax); @@ -259,7 +259,7 @@ namespace vmath_hpp } template < typename T > - constexpr mat look_at_rh(const vec& eye, const vec& at, const vec& up) { + mat look_at_rh(const vec& eye, const vec& at, const vec& up) { const vec az = normalize(eye - at); const vec ax = normalize(cross(up, az)); const vec ay = cross(az, ax); @@ -274,6 +274,137 @@ namespace vmath_hpp } } +// +// Matrix Projections +// + +namespace vmath_hpp +{ + // orthographic + + template < typename T > + mat orthographic_lh_zo(T left, T right, T bottom, T top, T znear, T zfar) { + const T sx = T(2) / (right - left); + const T sy = T(2) / (top - bottom); + const T sz = T(1) / (zfar - znear); + + const T tx = - (right + left) / (right - left); + const T ty = - (top + bottom) / (top - bottom); + const T tz = - znear / (zfar - znear); + + return { + sx, 0, 0, 0, + 0, sy, 0, 0, + 0, 0, sz, 0, + tx, ty, tz, 1}; + } + + template < typename T > + mat orthographic_lh_no(T left, T right, T bottom, T top, T znear, T zfar) { + const T sx = T(2) / (right - left); + const T sy = T(2) / (top - bottom); + const T sz = T(2) / (zfar - znear); + + const T tx = - (right + left) / (right - left); + const T ty = - (top + bottom) / (top - bottom); + const T tz = - (zfar + znear) / (zfar - znear); + + return { + sx, 0, 0, 0, + 0, sy, 0, 0, + 0, 0, sz, 0, + tx, ty, tz, 1}; + } + + template < typename T > + mat orthographic_rh_zo(T left, T right, T bottom, T top, T znear, T zfar) { + const T sx = T(2) / (right - left); + const T sy = T(2) / (top - bottom); + const T sz = -T(1) / (zfar - znear); + + const T tx = - (right + left) / (right - left); + const T ty = - (top + bottom) / (top - bottom); + const T tz = - znear / (zfar - znear); + + return { + sx, 0, 0, 0, + 0, sy, 0, 0, + 0, 0, sz, 0, + tx, ty, tz, 1}; + } + + template < typename T > + mat orthographic_rh_no(T left, T right, T bottom, T top, T znear, T zfar) { + const T sx = T(2) / (right - left); + const T sy = T(2) / (top - bottom); + const T sz = -T(2) / (zfar - znear); + + const T tx = - (right + left) / (right - left); + const T ty = - (top + bottom) / (top - bottom); + const T tz = - (zfar + znear) / (zfar - znear); + + return { + sx, 0, 0, 0, + 0, sy, 0, 0, + 0, 0, sz, 0, + tx, ty, tz, 1}; + } + + // perspective + + template < typename T > + mat perspective_lh_zo(T fov, T aspect, T znear, T zfar) { + const T sy = T(1) / tan(fov * T(0.5)); + const T sx = sy / aspect; + const T sz = zfar / (zfar - znear); + const T tz = (znear * zfar) / (znear - zfar); + return { + sx, 0, 0, 0, + 0, sy, 0, 0, + 0, 0, sz, 1, + 0, 0, tz, 0}; + } + + template < typename T > + mat perspective_lh_no(T fov, T aspect, T znear, T zfar) { + const T sy = T(1) / 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}; + } + + template < typename T > + mat perspective_rh_zo(T fov, T aspect, T znear, T zfar) { + const T sy = T(1) / tan(fov * T(0.5)); + const T sx = sy / aspect; + const T sz = zfar / (znear - zfar); + const T tz = (znear * zfar) / (znear - zfar); + return { + sx, 0, 0, 0, + 0, sy, 0, 0, + 0, 0, sz, -1, + 0, 0, tz, 0}; + } + + template < typename T > + mat perspective_rh_no(T fov, T aspect, T znear, T zfar) { + const T sy = T(1) / 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); + return { + sx, 0, 0, 0, + 0, sy, 0, 0, + 0, 0, sz, -1, + 0, 0, tz, 0}; + } +} + // // Vector Transform // diff --git a/untests/vmath_ext_tests.cpp b/untests/vmath_ext_tests.cpp index 7097873..92d0cdc 100644 --- a/untests/vmath_ext_tests.cpp +++ b/untests/vmath_ext_tests.cpp @@ -134,6 +134,16 @@ TEST_CASE("vmath/ext") { SECTION("matrix look_at") { look_at_lh(float3(-10.f), float3(0.f), float3(0,-1,0)); look_at_rh(float3(-10.f), float3(0.f), float3(0,-1,0)); + + orthographic_lh_zo(0.f, 800.f, 0.f, 640.f, 0.f, 10.f); + orthographic_lh_no(0.f, 800.f, 0.f, 640.f, 0.f, 10.f); + orthographic_rh_zo(0.f, 800.f, 0.f, 640.f, 0.f, 10.f); + orthographic_rh_no(0.f, 800.f, 0.f, 640.f, 0.f, 10.f); + + perspective_lh_zo(1.f, 1.3f, 0.f, 10.f); + perspective_lh_no(1.f, 1.3f, 0.f, 10.f); + perspective_rh_zo(1.f, 1.3f, 0.f, 10.f); + perspective_rh_no(1.f, 1.3f, 0.f, 10.f); } SECTION("vector angle") { From 29b6ec8d895b0bc21db11a64c0de18fd87decf3f Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 17:49:13 +0700 Subject: [PATCH 44/53] translate, rotate and scale for 2d --- headers/vmath.hpp/vmath_ext.hpp | 49 ++++++++++++++++++++++++++++++--- untests/vmath_ext_tests.cpp | 7 +++++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index 4467307..58c0933 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -180,6 +180,14 @@ namespace vmath_hpp { // translate + template < typename T > + constexpr mat translate(const vec& v) { + return { + { 1, 0, 0}, + { 0, 1, 0}, + {v.x, v.y, 1}}; + } + template < typename T > constexpr mat translate(const vec& v) { return { @@ -189,6 +197,11 @@ namespace vmath_hpp {v.x, v.y, v.z, 1}}; } + template < typename T > + constexpr mat translate(const mat& m, const vec& v) { + return m * translate(v); + } + template < typename T > constexpr mat translate(const mat& m, const vec& v) { return m * translate(v); @@ -196,6 +209,16 @@ namespace vmath_hpp // rotate + template < typename T > + mat rotate(T angle) { + const T cs = cos(angle); + const T sn = sin(angle); + return { + cs, sn, 0, + -sn, cs, 0, + 0, 0, 1}; + } + template < typename T > mat rotate(T angle, const vec& axis) { const T x = axis.x; @@ -220,6 +243,11 @@ namespace vmath_hpp 0, 0, 0, 1}; } + template < typename T > + mat rotate(const mat& m, T angle) { + return m * rotate(angle); + } + template < typename T > mat rotate(const mat& m, T angle, const vec& axis) { return m * rotate(angle, axis); @@ -227,13 +255,26 @@ namespace vmath_hpp // scale + template < typename T > + constexpr mat scale(const vec& v) { + return { + {v.x, 0, 0}, + { 0, v.y, 0}, + { 0, 0, 1}}; + } + template < typename T > constexpr mat scale(const vec& v) { return { - {v.x, 0, 0, 0}, - { 0, v.y, 0, 0}, - { 0, 0, v.z, 0}, - { 0, 0, 0, 1}}; + {v.x, 0, 0, 0}, + { 0, v.y, 0, 0}, + { 0, 0, v.z, 0}, + { 0, 0, 0, 1}}; + } + + template < typename T > + constexpr mat scale(const mat& m, const vec& v) { + return m * scale(v); } template < typename T > diff --git a/untests/vmath_ext_tests.cpp b/untests/vmath_ext_tests.cpp index 92d0cdc..75f42c8 100644 --- a/untests/vmath_ext_tests.cpp +++ b/untests/vmath_ext_tests.cpp @@ -108,6 +108,9 @@ TEST_CASE("vmath/ext") { } SECTION("matrix translate") { + STATIC_REQUIRE(float3(2.f,3.f,1.f) * translate(float2{1.f,2.f}) == approx3(3.f,5.f,1.f)); + STATIC_REQUIRE(float3(2.f,3.f,1.f) * translate(translate(float2{1.f,2.f}), float2{1.f,2.f}) == approx3(4.f,7.f,1.f)); + STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(float3{1.f,2.f,3.f}) == approx4(3.f,5.f,7.f,1.f)); STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * translate(translate(float3{1.f,2.f,3.f}), float3{1.f,2.f,3.f}) == approx4(4.f,7.f,10.f,1.f)); } @@ -116,17 +119,21 @@ TEST_CASE("vmath/ext") { constexpr float pi = radians(180.f); constexpr float pi_2 = radians(90.f); + REQUIRE(float3(2.f,3.f,1.f) * rotate(pi) == approx3(-2.f,-3.f,1.f)); REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(pi,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); + REQUIRE(float3(2.f,3.f,1.f) * rotate(rotate(pi_2),pi_2) == approx3(-2.f,-3.f,1.f)); REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,{0.f,0.f,1.f}),pi_2,{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); REQUIRE(float4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,float3{0.f,0.f,1.f}),pi_2,float3{0.f,0.f,1.f}) == approx4(-2.f,-3.f,4.f,1.f)); } SECTION("matrix scale") { + STATIC_REQUIRE(float3(2.f,3.f,1.f) * scale(float2{2.f,3.f}) == approx3(4.f,9.f,1.f)); STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f)); STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(float3{2.f,3.f,4.f}) == approx4(4.f,9.f,16.f,1.f)); + STATIC_REQUIRE(float3(2.f,3.f,1.f) * scale(scale(float2{2.f,2.f}), {2.f,3.f}) == approx3(8.f,18.f,1.f)); STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), {2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), float3{2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); } From 4d62fd034aee179787691401721f15ae51590458 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 18:15:31 +0700 Subject: [PATCH 45/53] shear matrix --- headers/vmath.hpp/vmath_ext.hpp | 138 ++++++++++++++++++++++---------- untests/vmath_ext_tests.cpp | 16 ++++ 2 files changed, 112 insertions(+), 42 deletions(-) diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index 58c0933..76e9d76 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -173,21 +173,13 @@ namespace vmath_hpp } // -// Matrix Transform +// Matrix Transform 3D // namespace vmath_hpp { // translate - template < typename T > - constexpr mat translate(const vec& v) { - return { - { 1, 0, 0}, - { 0, 1, 0}, - {v.x, v.y, 1}}; - } - template < typename T > constexpr mat translate(const vec& v) { return { @@ -197,11 +189,6 @@ namespace vmath_hpp {v.x, v.y, v.z, 1}}; } - template < typename T > - constexpr mat translate(const mat& m, const vec& v) { - return m * translate(v); - } - template < typename T > constexpr mat translate(const mat& m, const vec& v) { return m * translate(v); @@ -209,16 +196,6 @@ namespace vmath_hpp // rotate - template < typename T > - mat rotate(T angle) { - const T cs = cos(angle); - const T sn = sin(angle); - return { - cs, sn, 0, - -sn, cs, 0, - 0, 0, 1}; - } - template < typename T > mat rotate(T angle, const vec& axis) { const T x = axis.x; @@ -243,11 +220,6 @@ namespace vmath_hpp 0, 0, 0, 1}; } - template < typename T > - mat rotate(const mat& m, T angle) { - return m * rotate(angle); - } - template < typename T > mat rotate(const mat& m, T angle, const vec& axis) { return m * rotate(angle, axis); @@ -255,14 +227,6 @@ namespace vmath_hpp // scale - template < typename T > - constexpr mat scale(const vec& v) { - return { - {v.x, 0, 0}, - { 0, v.y, 0}, - { 0, 0, 1}}; - } - template < typename T > constexpr mat scale(const vec& v) { return { @@ -272,11 +236,6 @@ namespace vmath_hpp { 0, 0, 0, 1}}; } - template < typename T > - constexpr mat scale(const mat& m, const vec& v) { - return m * scale(v); - } - template < typename T > constexpr mat scale(const mat& m, const vec& v) { return m * scale(v); @@ -315,6 +274,101 @@ namespace vmath_hpp } } +// +// Matrix Transform 2D +// + +namespace vmath_hpp +{ + // translate + + template < typename T > + constexpr mat translate(const vec& v) { + return { + { 1, 0, 0}, + { 0, 1, 0}, + {v.x, v.y, 1}}; + } + + template < typename T > + constexpr mat translate(const mat& m, const vec& v) { + return m * translate(v); + } + + // rotate + + template < typename T > + mat rotate(T angle) { + const T cs = cos(angle); + const T sn = sin(angle); + return { + cs, sn, 0, + -sn, cs, 0, + 0, 0, 1}; + } + + template < typename T > + mat rotate(const mat& m, T angle) { + return m * rotate(angle); + } + + // scale + + template < typename T > + constexpr mat scale(const vec& v) { + return { + {v.x, 0, 0}, + { 0, v.y, 0}, + { 0, 0, 1}}; + } + + template < typename T > + constexpr mat scale(const mat& m, const vec& v) { + return m * scale(v); + } + + // shear + + template < typename T > + constexpr mat shear(const vec& v) { + return { + { 1, v.y, 0}, + {v.x, 1, 0}, + { 0, 0, 1}}; + } + + template < typename T > + constexpr mat shear_x(T y) { + return { + {1, 0, 0}, + {y, 1, 0}, + {0, 0, 1}}; + } + + template < typename T > + constexpr mat shear_y(T x) { + return { + {1, x, 0}, + {0, 1, 0}, + {0, 0, 1}}; + } + + template < typename T > + constexpr mat shear(const mat& m, const vec& v) { + return m * shear(v); + } + + template < typename T > + constexpr mat shear_x(const mat& m, T y) { + return m * shear_x(y); + } + + template < typename T > + constexpr mat shear_y(const mat& m, T x) { + return m * shear_y(x); + } +} + // // Matrix Projections // diff --git a/untests/vmath_ext_tests.cpp b/untests/vmath_ext_tests.cpp index 75f42c8..da802f2 100644 --- a/untests/vmath_ext_tests.cpp +++ b/untests/vmath_ext_tests.cpp @@ -138,6 +138,22 @@ TEST_CASE("vmath/ext") { STATIC_REQUIRE(float4(2.f,3.f,4.f,1.f) * scale(scale(float3{2.f,2.f,2.f}), float3{2.f,3.f,4.f}) == approx4(8.f,18.f,32.f,1.f)); } + SECTION("matrix shear") { + STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_x(0.f) == approx3(2.f,3.f,1.f)); + STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_x(1.f) == approx3(5.f,3.f,1.f)); + STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_x(shear_x(1.f),1.f) == approx3(8.f,3.f,1.f)); + + STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_y(0.f) == approx3(2.f,3.f,1.f)); + STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_y(1.f) == approx3(2.f,5.f,1.f)); + STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear_y(shear_y(1.f),1.f) == approx3(2.f,7.f,1.f)); + + STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(float2(0.f,0.f)) == approx3(2.f,3.f,1.f)); + STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(float2(1.f,0.f)) == approx3(5.f,3.f,1.f)); + STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(float2(0.f,1.f)) == approx3(2.f,5.f,1.f)); + STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(shear(float2(1.f,0.f)),float2(1.f,0.f)) == approx3(8.f,3.f,1.f)); + STATIC_REQUIRE(float3(2.f,3.f,1.f) * shear(shear(float2(0.f,1.f)),float2(0.f,1.f)) == approx3(2.f,7.f,1.f)); + } + SECTION("matrix look_at") { look_at_lh(float3(-10.f), float3(0.f), float3(0,-1,0)); look_at_rh(float3(-10.f), float3(0.f), float3(0,-1,0)); From bba60b0aade13f04b7b792ee63dfad65a9bbdfeb Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 20:06:57 +0700 Subject: [PATCH 46/53] type restrictions of basic math functions --- headers/vmath.hpp/vmath_ext.hpp | 2 +- headers/vmath.hpp/vmath_fun.hpp | 235 ++++++++++++++++++++++------ headers/vmath.hpp/vmath_fwd.hpp | 10 +- headers/vmath.hpp/vmath_vec_fun.hpp | 16 +- untests/vmath_fun_tests.cpp | 4 +- untests/vmath_vec_fun_tests.cpp | 4 +- 6 files changed, 204 insertions(+), 67 deletions(-) diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index 76e9d76..e13f97d 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -510,7 +510,7 @@ namespace vmath_hpp template < typename T, std::size_t Size > T angle(const vec& x, const vec& y) { - return acos(dot(x, y) * invsqrt(length2(x) * length2(y))); + return acos(dot(x, y) * rsqrt(length2(x) * length2(y))); } // rotate diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index 8baed1d..5e7e4b3 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -15,31 +15,94 @@ namespace vmath_hpp { template < typename T > - constexpr T radians(T degrees) noexcept { + std::enable_if_t, T> + constexpr radians(T degrees) noexcept { return degrees * T(0.01745329251994329576923690768489); } template < typename T > - constexpr T degrees(T radians) noexcept { + std::enable_if_t, T> + constexpr degrees(T radians) noexcept { return radians * T(57.295779513082320876798154814105); } - using ::std::sin; - using ::std::cos; - using ::std::tan; + template < typename T > + std::enable_if_t, T> + sin(T x) noexcept { + return std::sin(x); + } - using ::std::asin; - using ::std::acos; - using ::std::atan; - using ::std::atan2; + template < typename T > + std::enable_if_t, T> + cos(T x) noexcept { + return std::cos(x); + } - using ::std::sinh; - using ::std::cosh; - using ::std::tanh; + template < typename T > + std::enable_if_t, T> + tan(T x) noexcept { + return std::tan(x); + } - using ::std::asinh; - using ::std::acosh; - using ::std::atanh; + template < typename T > + std::enable_if_t, T> + asin(T x) noexcept { + return std::asin(x); + } + + template < typename T > + std::enable_if_t, T> + acos(T x) noexcept { + return std::acos(x); + } + + template < typename T > + std::enable_if_t, T> + atan(T x) noexcept { + return std::atan(x); + } + + template < typename T > + std::enable_if_t, T> + atan2(T y, T x) noexcept { + return std::atan2(y, x); + } + + template < typename T > + std::enable_if_t, T> + sinh(T x) noexcept { + return std::sinh(x); + } + + template < typename T > + std::enable_if_t, T> + cosh(T x) noexcept { + return std::cosh(x); + } + + template < typename T > + std::enable_if_t, T> + tanh(T x) noexcept { + return std::tanh(x); + } + + template < typename T > + std::enable_if_t, T> + asinh(T x) noexcept { + return std::asinh(x); + } + + template < typename T > + std::enable_if_t, T> + acosh(T x) noexcept { + return std::acosh(x); + } + + template < typename T > + std::enable_if_t, T> + atanh(T x) noexcept { + return std::atanh(x); + } } // @@ -48,15 +111,45 @@ namespace vmath_hpp namespace vmath_hpp { - using ::std::pow; - using ::std::exp; - using ::std::log; - using ::std::exp2; - using ::std::log2; - using ::std::sqrt; + template < typename T > + std::enable_if_t, T> + pow(T x, T y) noexcept { + return std::pow(x, y); + } template < typename T > - T invsqrt(T x) noexcept { + std::enable_if_t, T> + exp(T x) noexcept { + return std::exp(x); + } + + template < typename T > + std::enable_if_t, T> + log(T x) noexcept { + return std::log(x); + } + + template < typename T > + std::enable_if_t, T> + exp2(T x) noexcept { + return std::exp2(x); + } + + template < typename T > + std::enable_if_t, T> + log2(T x) noexcept { + return std::log2(x); + } + + template < typename T > + std::enable_if_t, T> + sqrt(T x) noexcept { + return std::sqrt(x); + } + + template < typename T > + std::enable_if_t, T> + rsqrt(T x) noexcept { return T(1) / sqrt(x); } } @@ -80,48 +173,92 @@ namespace vmath_hpp } template < typename T > - constexpr T sign(T x) noexcept { + std::enable_if_t, T> + constexpr sign(T x) noexcept { return static_cast((T(0) < x) - (x < T(0))); } - using ::std::floor; - using ::std::trunc; - using ::std::round; - using ::std::ceil; + template < typename T > + std::enable_if_t, T> + floor(T x) noexcept { + return std::floor(x); + } template < typename T > - T fract(T x) noexcept { + std::enable_if_t, T> + trunc(T x) noexcept { + return std::trunc(x); + } + + template < typename T > + std::enable_if_t, T> + round(T x) noexcept { + return std::round(x); + } + + template < typename T > + std::enable_if_t, T> + ceil(T x) noexcept { + return std::ceil(x); + } + + template < typename T > + std::enable_if_t, T> + fract(T x) noexcept { return x - floor(x); } - using ::std::fmod; - using ::std::modf; - - using ::std::min; - using ::std::max; + template < typename T > + std::enable_if_t, T> + fmod(T x, T y) noexcept { + return std::fmod(x, y); + } template < typename T > - constexpr T clamp(T x, T min_x, T max_x) noexcept { + std::enable_if_t, T> + modf(T x, T* y) noexcept { + return std::modf(x, y); + } + + template < typename T > + std::enable_if_t, T> + constexpr min(T x, T y) noexcept { + return std::min(x, y); + } + + template < typename T > + std::enable_if_t, T> + constexpr max(T x, T y) noexcept { + return std::max(x, y); + } + + template < typename T > + std::enable_if_t, T> + constexpr clamp(T x, T min_x, T max_x) noexcept { return min(max(x, min_x), max_x); } template < typename T > - constexpr T saturate(T x) noexcept { + std::enable_if_t, T> + constexpr saturate(T x) noexcept { return clamp(x, T(0), T(1)); } template < typename T > - constexpr T lerp(T x, T y, T a) noexcept { + std::enable_if_t, T> + constexpr lerp(T x, T y, T a) noexcept { return x * (T(1) - a) + y * a; } template < typename T > - constexpr T step(T edge, T x) noexcept { + std::enable_if_t, T> + constexpr step(T edge, T x) noexcept { return x < edge ? T(0) : T(1); } template < typename T > - constexpr T smoothstep(T edge0, T edge1, T x) noexcept { + std::enable_if_t, T> + constexpr smoothstep(T edge0, T edge1, T x) noexcept { const T t = clamp((x - edge0) / (edge1 - edge0), T(0), T(1)); return t * t * (T(3) - T(2) * t); } @@ -129,16 +266,24 @@ namespace vmath_hpp using ::std::isnan; using ::std::isinf; using ::std::isfinite; - using ::std::isnormal; template < typename T > - bool issubnormal(T x) noexcept { - return std::fpclassify(x) == FP_SUBNORMAL; + std::enable_if_t, T> + fma(T x, T y, T z) noexcept { + return std::fma(x, y, z); } - using ::std::fma; - using ::std::frexp; - using ::std::ldexp; + template < typename T > + std::enable_if_t, T> + frexp(T x, int* exp) noexcept { + return std::frexp(x, exp); + } + + template < typename T > + std::enable_if_t, T> + ldexp(T x, int exp) noexcept { + return std::ldexp(x, exp); + } } // @@ -174,7 +319,7 @@ namespace vmath_hpp template < typename T > T normalize(T x) noexcept { - return x * invsqrt(dot(x, x)); + return x * rsqrt(dot(x, x)); } template < typename T > diff --git a/headers/vmath.hpp/vmath_fwd.hpp b/headers/vmath.hpp/vmath_fwd.hpp index c9e2bad..01f8ea6 100644 --- a/headers/vmath.hpp/vmath_fwd.hpp +++ b/headers/vmath.hpp/vmath_fwd.hpp @@ -6,13 +6,11 @@ #pragma once -#include #include #include #include #include -#include #include #include #include @@ -45,6 +43,10 @@ namespace vmath_hpp using size2 = vec; using size3 = vec; using size4 = vec; + + using ptrdiff2 = vec; + using ptrdiff3 = vec; + using ptrdiff4 = vec; } namespace vmath_hpp @@ -75,4 +77,8 @@ namespace vmath_hpp using size2x2 = mat; using size3x3 = mat; using size4x4 = mat; + + using ptrdiff2x2 = mat; + using ptrdiff3x3 = mat; + using ptrdiff4x4 = mat; } diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index 7700c13..6212191 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -370,8 +370,8 @@ namespace vmath_hpp } template < typename T, std::size_t Size > - vec invsqrt(const vec& xs) { - return map([](T x) { return invsqrt(x); }, xs); + vec rsqrt(const vec& xs) { + return map([](T x) { return rsqrt(x); }, xs); } } @@ -529,16 +529,6 @@ namespace vmath_hpp return map([](T x) { return isfinite(x); }, xs); } - template < typename T, std::size_t Size > - vec isnormal(const vec& xs) { - return map([](T x) { return isnormal(x); }, xs); - } - - template < typename T, std::size_t Size > - vec issubnormal(const vec& xs) { - return map([](T x) { return issubnormal(x); }, xs); - } - template < typename T, std::size_t Size > vec fma(const vec& as, const vec& bs, const vec& cs) { return zip([](T a, T b, T c) { return fma(a, b, c); }, as, bs, cs); @@ -611,7 +601,7 @@ namespace vmath_hpp template < typename T, std::size_t Size > vec normalize(const vec& xs) { - return xs * invsqrt(dot(xs, xs)); + return xs * rsqrt(dot(xs, xs)); } template < typename T, std::size_t Size > diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index c32ab7b..96c2769 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -47,7 +47,7 @@ TEST_CASE("vmath/fun") { (void)exp2(2.f); (void)log2(2.f); (void)sqrt(2.f); - (void)invsqrt(2.f); + (void)rsqrt(2.f); } SECTION("Common Functions") { @@ -98,8 +98,6 @@ TEST_CASE("vmath/fun") { REQUIRE_FALSE(isnan(1.f)); REQUIRE_FALSE(isinf(1.f)); REQUIRE(isfinite(1.f)); - REQUIRE(isnormal(1.f)); - REQUIRE_FALSE(issubnormal(1.f)); REQUIRE(fma(2.f, 3.f, 4.f) == approx(10.f)); diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 18584d4..19a574f 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -95,7 +95,7 @@ TEST_CASE("vmath/vec_fun") { (void)exp2(float2(1.f)); (void)log2(float2(1.f)); (void)sqrt(float2(1.f)); - (void)invsqrt(float2(1.f)); + (void)rsqrt(float2(1.f)); } SECTION("Common Functions") { @@ -144,8 +144,6 @@ TEST_CASE("vmath/vec_fun") { REQUIRE_FALSE(isnan(float2(1.f)).x); REQUIRE_FALSE(isinf(float2(1.f)).x); REQUIRE(isfinite(float2(1.f)).x); - REQUIRE(isnormal(float2(1.f)).x); - REQUIRE_FALSE(issubnormal(float2(1.f)).x); REQUIRE_FALSE(fma(float2(2.f), float2(3.f), float2(4.f)).x == Approx(12.f)); From dcdb54a4f175bff0ff9815fcb3e46773628d4efa Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 20:37:14 +0700 Subject: [PATCH 47/53] more restrictions of basic math functions and nodiscard --- headers/vmath.hpp/vmath_fun.hpp | 155 +++++++++++++++------------- headers/vmath.hpp/vmath_vec_fun.hpp | 5 - untests/vmath_fun_tests.cpp | 17 +-- untests/vmath_vec_fun_tests.cpp | 13 ++- 4 files changed, 104 insertions(+), 86 deletions(-) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index 5e7e4b3..3bb07a3 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -15,91 +15,91 @@ namespace vmath_hpp { template < typename T > - std::enable_if_t, T> - constexpr radians(T degrees) noexcept { + [[nodiscard]] constexpr std::enable_if_t, T> + radians(T degrees) noexcept { return degrees * T(0.01745329251994329576923690768489); } template < typename T > - std::enable_if_t, T> - constexpr degrees(T radians) noexcept { + [[nodiscard]] constexpr std::enable_if_t, T> + degrees(T radians) noexcept { return radians * T(57.295779513082320876798154814105); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> sin(T x) noexcept { return std::sin(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> cos(T x) noexcept { return std::cos(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> tan(T x) noexcept { return std::tan(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> asin(T x) noexcept { return std::asin(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> acos(T x) noexcept { return std::acos(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> atan(T x) noexcept { return std::atan(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> atan2(T y, T x) noexcept { return std::atan2(y, x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> sinh(T x) noexcept { return std::sinh(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> cosh(T x) noexcept { return std::cosh(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> tanh(T x) noexcept { return std::tanh(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> asinh(T x) noexcept { return std::asinh(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> acosh(T x) noexcept { return std::acosh(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> atanh(T x) noexcept { return std::atanh(x); } @@ -112,43 +112,43 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> pow(T x, T y) noexcept { return std::pow(x, y); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> exp(T x) noexcept { return std::exp(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> log(T x) noexcept { return std::log(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> exp2(T x) noexcept { return std::exp2(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> log2(T x) noexcept { return std::log2(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> sqrt(T x) noexcept { return std::sqrt(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> rsqrt(T x) noexcept { return T(1) / sqrt(x); } @@ -161,103 +161,103 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> constexpr abs(T x) noexcept { return x; } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> constexpr abs(T x) noexcept { return x >= T(0) ? x : -x; } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> constexpr sign(T x) noexcept { return static_cast((T(0) < x) - (x < T(0))); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> floor(T x) noexcept { return std::floor(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> trunc(T x) noexcept { return std::trunc(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> round(T x) noexcept { return std::round(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> ceil(T x) noexcept { return std::ceil(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> fract(T x) noexcept { return x - floor(x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> fmod(T x, T y) noexcept { return std::fmod(x, y); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> modf(T x, T* y) noexcept { return std::modf(x, y); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> constexpr min(T x, T y) noexcept { return std::min(x, y); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> constexpr max(T x, T y) noexcept { return std::max(x, y); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> constexpr clamp(T x, T min_x, T max_x) noexcept { return min(max(x, min_x), max_x); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> constexpr saturate(T x) noexcept { return clamp(x, T(0), T(1)); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> constexpr lerp(T x, T y, T a) noexcept { return x * (T(1) - a) + y * a; } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> constexpr step(T edge, T x) noexcept { return x < edge ? T(0) : T(1); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> constexpr smoothstep(T edge0, T edge1, T x) noexcept { const T t = clamp((x - edge0) / (edge1 - edge0), T(0), T(1)); return t * t * (T(3) - T(2) * t); @@ -268,19 +268,19 @@ namespace vmath_hpp using ::std::isfinite; template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> fma(T x, T y, T z) noexcept { return std::fma(x, y, z); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> frexp(T x, int* exp) noexcept { return std::frexp(x, exp); } template < typename T > - std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> ldexp(T x, int exp) noexcept { return std::ldexp(x, exp); } @@ -293,47 +293,56 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T > - constexpr T dot(T x, T y) noexcept { + [[nodiscard]] constexpr std::enable_if_t, T> + dot(T x, T y) noexcept { return x * y; } template < typename T > - T length(T x) noexcept { + [[nodiscard]] constexpr std::enable_if_t, T> + length(T x) noexcept { return abs(x); } template < typename T > - constexpr T length2(T x) noexcept { + [[nodiscard]] constexpr std::enable_if_t, T> + length2(T x) noexcept { return dot(x, x); } template < typename T > - T distance(T x, T y) noexcept { + [[nodiscard]] constexpr std::enable_if_t, T> + distance(T x, T y) noexcept { return length(y - x); } template < typename T > - constexpr T distance2(T x, T y) noexcept { + [[nodiscard]] constexpr std::enable_if_t, T> + distance2(T x, T y) noexcept { return length2(y - x); } template < typename T > - T normalize(T x) noexcept { + [[nodiscard]] std::enable_if_t, T> + normalize(T x) noexcept { return x * rsqrt(dot(x, x)); } template < typename T > - constexpr T faceforward(T n, T i, T nref) noexcept { + [[nodiscard]] constexpr std::enable_if_t, T> + faceforward(T n, T i, T nref) noexcept { return dot(nref, i) < T(0) ? n : -n; } template < typename T > - constexpr T reflect(T i, T n) noexcept { + [[nodiscard]] constexpr std::enable_if_t, T> + reflect(T i, T n) noexcept { return i - n * dot(n, i) * T(2); } template < typename T > - T refract(T i, T n, T eta) noexcept { + [[nodiscard]] std::enable_if_t, T> + refract(T i, T n, T eta) noexcept { const T d = dot(n, i); const T k = T(1) - eta * eta * (T(1) - d * d); return T(k >= T(0)) * (eta * i - (eta * d + sqrt(k)) * n); @@ -347,54 +356,62 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T > - constexpr bool less(const T& x, const T& y) { + [[nodiscard]] constexpr std::enable_if_t, bool> + less(T x, T y) noexcept { return x < y; } template < typename T > - constexpr bool less_equal(const T& x, const T& y) { + [[nodiscard]] constexpr std::enable_if_t, bool> + less_equal(T x, T y) noexcept { return x <= y; } template < typename T > - constexpr bool greater(const T& x, const T& y) { + [[nodiscard]] constexpr std::enable_if_t, bool> + greater(T x, T y) noexcept { return x > y; } template < typename T > - constexpr bool greater_equal(const T& x, const T& y) { + [[nodiscard]] constexpr std::enable_if_t, bool> + greater_equal(T x, T y) noexcept { return x >= y; } template < typename T > - constexpr bool equal_to(const T& x, const T& y) { + [[nodiscard]] constexpr std::enable_if_t, bool> + equal_to(T x, T y) noexcept { return x == y; } template < typename T > - constexpr bool equal_to(const T& x, const T& y, const T& epsilon) { + [[nodiscard]] constexpr std::enable_if_t, bool> + equal_to(T x, T y, T epsilon) noexcept { return abs(x - y) <= epsilon; } template < typename T > - constexpr bool not_equal_to(const T& x, const T& y) { + [[nodiscard]] constexpr std::enable_if_t, bool> + not_equal_to(T x, T y) noexcept { return x != y; } template < typename T > - constexpr bool not_equal_to(const T& x, const T& y, const T& epsilon) { + [[nodiscard]] constexpr std::enable_if_t, bool> + not_equal_to(T x, T y, T epsilon) noexcept { return abs(x - y) > epsilon; } - constexpr bool any(bool x) noexcept { - return x; + template < typename T > + [[nodiscard]] constexpr std::enable_if_t, bool> + any(T x) noexcept { + return !!x; } - constexpr bool all(bool x) noexcept { - return x; - } - - constexpr bool not_(bool x) noexcept { - return !x; + template < typename T > + [[nodiscard]] constexpr std::enable_if_t, bool> + all(T x) noexcept { + return !!x; } } diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index 6212191..fe28c40 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -677,9 +677,4 @@ namespace vmath_hpp constexpr bool all(const vec& xs) { return fold([](bool x, bool y){ return x && y; }, true, xs); } - - template < std::size_t Size > - constexpr vec not_(const vec& xs) { - return map([](bool x){ return not_(x); }, xs); - } } diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index 96c2769..40d34bc 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -111,19 +111,19 @@ TEST_CASE("vmath/fun") { } SECTION("Geometric Functions") { - REQUIRE(length(10.f) == approx(10.f)); - REQUIRE(length(-10.f) == approx(10.f)); + STATIC_REQUIRE(length(10.f) == approx(10.f)); + STATIC_REQUIRE(length(-10.f) == approx(10.f)); STATIC_REQUIRE(length2(10.f) == approx(100.f)); STATIC_REQUIRE(length2(-10.f) == approx(100.f)); - REQUIRE(distance(5.f, 10.f) == approx(5.f)); - REQUIRE(distance(-5.f, -10.f) == approx(5.f)); + STATIC_REQUIRE(distance(5.f, 10.f) == approx(5.f)); + STATIC_REQUIRE(distance(-5.f, -10.f) == approx(5.f)); STATIC_REQUIRE(distance2(5.f, 10.f) == approx(25.f)); STATIC_REQUIRE(distance2(-5.f, -10.f) == approx(25.f)); - REQUIRE(dot(2.f, 5.f) == approx(10.f)); + STATIC_REQUIRE(dot(2.f, 5.f) == approx(10.f)); REQUIRE(normalize(0.5f) == approx(1.f)); STATIC_REQUIRE(faceforward(1.f, 2.f, 3.f) == approx(-1.f)); @@ -155,12 +155,13 @@ TEST_CASE("vmath/fun") { STATIC_REQUIRE_FALSE(not_equal_to(1, 1, 1)); STATIC_REQUIRE_FALSE(any(false)); + STATIC_REQUIRE_FALSE(any(0)); STATIC_REQUIRE(any(true)); + STATIC_REQUIRE(any(1)); STATIC_REQUIRE_FALSE(all(false)); + STATIC_REQUIRE_FALSE(all(0)); STATIC_REQUIRE(all(true)); - - STATIC_REQUIRE_FALSE(not_(true)); - STATIC_REQUIRE(not_(false)); + STATIC_REQUIRE(all(1)); } } diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 19a574f..1fdb10a 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -201,14 +201,19 @@ TEST_CASE("vmath/vec_fun") { STATIC_REQUIRE(any(bool2(false, true))); STATIC_REQUIRE(any(bool2(true, true))); + STATIC_REQUIRE_FALSE(any(bool2(0, 0))); + STATIC_REQUIRE(any(bool2(1, 0))); + STATIC_REQUIRE(any(bool2(0, 1))); + STATIC_REQUIRE(any(bool2(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_REQUIRE(not_(bool2(false, false)) == bool2(true, true)); - STATIC_REQUIRE(not_(bool2(true, false)) == bool2(false, true)); - STATIC_REQUIRE(not_(bool2(false, true)) == bool2(true, false)); - STATIC_REQUIRE(not_(bool2(true, true)) == bool2(false, false)); + STATIC_REQUIRE_FALSE(all(bool2(0, 0))); + STATIC_REQUIRE_FALSE(all(bool2(1, 0))); + STATIC_REQUIRE_FALSE(all(bool2(0, 1))); + STATIC_REQUIRE(all(bool2(1, 1))); } } From 7861cc69cf9993351adfdee441947de30630556f Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 22:14:08 +0700 Subject: [PATCH 48/53] nodiscard for vector and matrix funcs --- headers/vmath.hpp/vmath_fun.hpp | 82 ++++++----- headers/vmath.hpp/vmath_mat.hpp | 8 +- headers/vmath.hpp/vmath_mat_fun.hpp | 134 +++++++++-------- headers/vmath.hpp/vmath_vec.hpp | 16 +- headers/vmath.hpp/vmath_vec_fun.hpp | 220 ++++++++++++++-------------- untests/vmath_mat_fun_tests.cpp | 32 +++- untests/vmath_vec_fun_tests.cpp | 46 ++++-- 7 files changed, 306 insertions(+), 232 deletions(-) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index 3bb07a3..c25d1e3 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -15,14 +15,14 @@ namespace vmath_hpp { template < typename T > - [[nodiscard]] constexpr std::enable_if_t, T> - radians(T degrees) noexcept { + [[nodiscard]] std::enable_if_t, T> + constexpr radians(T degrees) noexcept { return degrees * T(0.01745329251994329576923690768489); } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, T> - degrees(T radians) noexcept { + [[nodiscard]] std::enable_if_t, T> + constexpr degrees(T radians) noexcept { return radians * T(57.295779513082320876798154814105); } @@ -178,6 +178,12 @@ namespace vmath_hpp return static_cast((T(0) < x) - (x < T(0))); } + template < typename T > + [[nodiscard]] std::enable_if_t, T> + constexpr reciprocal(T x) noexcept { + return T(1) / x; + } + template < typename T > [[nodiscard]] std::enable_if_t, T> floor(T x) noexcept { @@ -293,32 +299,32 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T > - [[nodiscard]] constexpr std::enable_if_t, T> - dot(T x, T y) noexcept { + [[nodiscard]] std::enable_if_t, T> + constexpr dot(T x, T y) noexcept { return x * y; } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, T> - length(T x) noexcept { + [[nodiscard]] std::enable_if_t, T> + constexpr length(T x) noexcept { return abs(x); } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, T> - length2(T x) noexcept { + [[nodiscard]] std::enable_if_t, T> + constexpr length2(T x) noexcept { return dot(x, x); } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, T> - distance(T x, T y) noexcept { + [[nodiscard]] std::enable_if_t, T> + constexpr distance(T x, T y) noexcept { return length(y - x); } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, T> - distance2(T x, T y) noexcept { + [[nodiscard]] std::enable_if_t, T> + constexpr distance2(T x, T y) noexcept { return length2(y - x); } @@ -329,14 +335,14 @@ namespace vmath_hpp } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, T> - faceforward(T n, T i, T nref) noexcept { + [[nodiscard]] std::enable_if_t, T> + constexpr faceforward(T n, T i, T nref) noexcept { return dot(nref, i) < T(0) ? n : -n; } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, T> - reflect(T i, T n) noexcept { + [[nodiscard]] std::enable_if_t, T> + constexpr reflect(T i, T n) noexcept { return i - n * dot(n, i) * T(2); } @@ -356,62 +362,62 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T > - [[nodiscard]] constexpr std::enable_if_t, bool> - less(T x, T y) noexcept { + [[nodiscard]] std::enable_if_t, bool> + constexpr less(T x, T y) noexcept { return x < y; } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, bool> - less_equal(T x, T y) noexcept { + [[nodiscard]] std::enable_if_t, bool> + constexpr less_equal(T x, T y) noexcept { return x <= y; } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, bool> - greater(T x, T y) noexcept { + [[nodiscard]] std::enable_if_t, bool> + constexpr greater(T x, T y) noexcept { return x > y; } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, bool> - greater_equal(T x, T y) noexcept { + [[nodiscard]] std::enable_if_t, bool> + constexpr greater_equal(T x, T y) noexcept { return x >= y; } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, bool> - equal_to(T x, T y) noexcept { + [[nodiscard]] std::enable_if_t, bool> + constexpr equal_to(T x, T y) noexcept { return x == y; } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, bool> - equal_to(T x, T y, T epsilon) noexcept { + [[nodiscard]] std::enable_if_t, bool> + constexpr equal_to(T x, T y, T epsilon) noexcept { return abs(x - y) <= epsilon; } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, bool> - not_equal_to(T x, T y) noexcept { + [[nodiscard]] std::enable_if_t, bool> + constexpr not_equal_to(T x, T y) noexcept { return x != y; } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, bool> - not_equal_to(T x, T y, T epsilon) noexcept { + [[nodiscard]] std::enable_if_t, bool> + constexpr not_equal_to(T x, T y, T epsilon) noexcept { return abs(x - y) > epsilon; } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, bool> - any(T x) noexcept { + [[nodiscard]] std::enable_if_t, bool> + constexpr any(T x) noexcept { return !!x; } template < typename T > - [[nodiscard]] constexpr std::enable_if_t, bool> - all(T x) noexcept { + [[nodiscard]] std::enable_if_t, bool> + constexpr all(T x) noexcept { return !!x; } } diff --git a/headers/vmath.hpp/vmath_mat.hpp b/headers/vmath.hpp/vmath_mat.hpp index 004cb89..ee45b27 100644 --- a/headers/vmath.hpp/vmath_mat.hpp +++ b/headers/vmath.hpp/vmath_mat.hpp @@ -197,22 +197,22 @@ namespace vmath_hpp } } - constexpr reference operator[](std::size_t index) noexcept { + [[nodiscard]] constexpr reference operator[](std::size_t index) noexcept { return rows[index]; } - constexpr const_reference operator[](std::size_t index) const noexcept { + [[nodiscard]] constexpr const_reference operator[](std::size_t index) const noexcept { return rows[index]; } - constexpr reference at(std::size_t index) { + [[nodiscard]] constexpr reference at(std::size_t index) { if ( index >= Size ) { throw std::out_of_range("mat::at"); } return rows[index]; } - constexpr const_reference at(std::size_t index) const { + [[nodiscard]] constexpr const_reference at(std::size_t index) const { if ( index >= Size ) { throw std::out_of_range("mat::at"); } diff --git a/headers/vmath.hpp/vmath_mat_fun.hpp b/headers/vmath.hpp/vmath_mat_fun.hpp index 1039cb6..273295d 100644 --- a/headers/vmath.hpp/vmath_mat_fun.hpp +++ b/headers/vmath.hpp/vmath_mat_fun.hpp @@ -11,70 +11,86 @@ #include "vmath_fun.hpp" #include "vmath_mat.hpp" +#include "vmath_vec.hpp" +#include "vmath_vec_fun.hpp" + namespace vmath_hpp::detail { namespace impl { template < typename A, std::size_t Size, typename F, std::size_t... Is > - constexpr auto map_impl(F&& f, const mat& a, std::index_sequence) + [[nodiscard]] constexpr auto map_impl(F&& f, const mat& a, std::index_sequence) -> mat>::value_type, Size> { return { f(a[Is])... }; } template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > - constexpr auto zip_impl(F&& f, const mat& a, const mat& b, std::index_sequence) + [[nodiscard]] constexpr auto zip_impl(F&& f, const mat& a, const mat& b, std::index_sequence) -> mat, vec>::value_type, Size> { return { f(a[Is], b[Is])... }; } template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > - constexpr auto zip_impl(F&& f, const mat& a, const mat& b, const mat& c, std::index_sequence) + [[nodiscard]] constexpr auto zip_impl(F&& f, const mat& a, const mat& b, const mat& c, std::index_sequence) -> mat, vec, vec>::value_type, Size> { return { f(a[Is], b[Is], c[Is])... }; } template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > - constexpr auto fold_impl(F&& f, A init, const mat& b, std::index_sequence) - -> A - { + [[nodiscard]] constexpr A fold_impl(F&& f, A init, const mat& b, std::index_sequence) { return ((init = f(std::move(init), b[Is])), ...); } template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > - constexpr auto fold_impl(F&& f, A init, const mat& b, const mat& c, std::index_sequence) - -> A - { + [[nodiscard]] constexpr A fold_impl(F&& f, A init, const mat& b, const mat& c, std::index_sequence) { return ((init = f(std::move(init), b[Is], c[Is])), ...); } + + template < typename A, std::size_t Size, typename F, std::size_t I, std::size_t... Is > + [[nodiscard]] constexpr vec fold1_impl(F&& f, const mat& a, std::index_sequence) { + vec init = a[I]; + return ((init = f(std::move(init), a[Is])), ...); + } } template < typename A, std::size_t Size, typename F > - constexpr auto map(F&& f, const mat& a) { + [[nodiscard]] constexpr auto map(F&& f, const mat& a) + -> mat>::value_type, Size> + { return impl::map_impl(std::forward(f), a, std::make_index_sequence{}); } template < typename A, typename B, std::size_t Size, typename F > - constexpr auto zip(F&& f, const mat& a, const mat& b) { + [[nodiscard]] constexpr auto zip(F&& f, const mat& a, const mat& b) + -> mat, vec>::value_type, Size> + { return impl::zip_impl(std::forward(f), a, b, std::make_index_sequence{}); } template < typename A, typename B, typename C, std::size_t Size, typename F > - constexpr auto zip(F&& f, const mat& a, const mat& b, const mat& c) { + [[nodiscard]] constexpr auto zip(F&& f, const mat& a, const mat& b, const mat& c) + -> mat, vec, vec>::value_type, Size> + { return impl::zip_impl(std::forward(f), a, b, c, std::make_index_sequence{}); } template < typename A, typename B, std::size_t Size, typename F > - constexpr auto fold(F&& f, A init, const mat& b) { + [[nodiscard]] constexpr A fold(F&& f, A init, const mat& b) { return impl::fold_impl(std::forward(f), std::move(init), b, std::make_index_sequence{}); } template < typename A, typename B, typename C, std::size_t Size, typename F > - constexpr auto fold(F&& f, A init, const mat& b, const mat& c) { + [[nodiscard]] constexpr A fold(F&& f, A init, const mat& b, const mat& c) { return impl::fold_impl(std::forward(f), std::move(init), b, c, std::make_index_sequence{}); } + + template < typename A, std::size_t Size, typename F > + [[nodiscard]] constexpr vec fold1(F&& f, const mat& a) { + return impl::fold1_impl(std::forward(f), a, std::make_index_sequence{}); + } } // @@ -86,24 +102,24 @@ namespace vmath_hpp // -operator template < typename T, std::size_t Size > - constexpr mat operator-(const mat& xs) { + [[nodiscard]] constexpr mat operator-(const mat& xs) { return map(std::negate<>(), xs); } // operator+ template < typename T, std::size_t Size > - constexpr mat operator+(const mat& xs, T y) { + [[nodiscard]] constexpr mat operator+(const mat& xs, T y) { return map([y](const vec& x){ return x + y; }, xs); } template < typename T, std::size_t Size > - constexpr mat operator+(T x, const mat& ys) { + [[nodiscard]] constexpr mat operator+(T x, const mat& ys) { return map([x](const vec& y){ return x + y; }, ys); } template < typename T, std::size_t Size > - constexpr mat operator+(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr mat operator+(const mat& xs, const mat& ys) { return zip(std::plus<>(), xs, ys); } @@ -122,17 +138,17 @@ namespace vmath_hpp // operator- template < typename T, std::size_t Size > - constexpr mat operator-(const mat& xs, T y) { + [[nodiscard]] constexpr mat operator-(const mat& xs, T y) { return map([y](const vec& x){ return x - y; }, xs); } template < typename T, std::size_t Size > - constexpr mat operator-(T x, const mat& ys) { + [[nodiscard]] constexpr mat operator-(T x, const mat& ys) { return map([x](const vec& y){ return x - y; }, ys); } template < typename T, std::size_t Size > - constexpr mat operator-(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr mat operator-(const mat& xs, const mat& ys) { return zip(std::minus<>(), xs, ys); } @@ -151,24 +167,24 @@ namespace vmath_hpp // operator* template < typename T, std::size_t Size > - constexpr mat operator*(const mat& xs, T y) { + [[nodiscard]] constexpr mat operator*(const mat& xs, T y) { return map([y](const vec& x){ return x * y; }, xs); } template < typename T, std::size_t Size > - constexpr mat operator*(T x, const mat& ys) { + [[nodiscard]] constexpr mat operator*(T x, const mat& ys) { return map([x](const vec& y){ return x * y; }, ys); } template < typename T > - constexpr vec operator*(const vec& xs, const mat& ys) { + [[nodiscard]] constexpr vec operator*(const vec& xs, const mat& ys) { return { xs.x * ys[0][0] + xs.y * ys[1][0], xs.x * ys[0][1] + xs.y * ys[1][1]}; } template < typename T > - constexpr mat operator*(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr mat operator*(const mat& xs, const mat& ys) { return { xs[0][0] * ys[0][0] + xs[0][1] * ys[1][0], xs[0][0] * ys[0][1] + xs[0][1] * ys[1][1], @@ -178,7 +194,7 @@ namespace vmath_hpp } template < typename T > - constexpr vec operator*(const vec& xs, const mat& ys) { + [[nodiscard]] constexpr vec operator*(const vec& xs, const mat& ys) { return { xs.x * ys[0][0] + xs.y * ys[1][0] + xs.z * ys[2][0], xs.x * ys[0][1] + xs.y * ys[1][1] + xs.z * ys[2][1], @@ -186,7 +202,7 @@ namespace vmath_hpp } template < typename T > - constexpr mat operator*(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr mat operator*(const mat& xs, const mat& ys) { return { xs[0][0] * ys[0][0] + xs[0][1] * ys[1][0] + xs[0][2] * ys[2][0], xs[0][0] * ys[0][1] + xs[0][1] * ys[1][1] + xs[0][2] * ys[2][1], @@ -202,7 +218,7 @@ namespace vmath_hpp } template < typename T > - constexpr vec operator*(const vec& xs, const mat& ys) { + [[nodiscard]] constexpr vec operator*(const vec& xs, const mat& ys) { return { xs.x * ys[0][0] + xs.y * ys[1][0] + xs.z * ys[2][0] + xs.w * ys[3][0], xs.x * ys[0][1] + xs.y * ys[1][1] + xs.z * ys[2][1] + xs.w * ys[3][1], @@ -211,7 +227,7 @@ namespace vmath_hpp } template < typename T > - constexpr mat operator*(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr mat operator*(const mat& xs, const mat& ys) { return { xs[0][0] * ys[0][0] + xs[0][1] * ys[1][0] + xs[0][2] * ys[2][0] + xs[0][3] * ys[3][0], xs[0][0] * ys[0][1] + xs[0][1] * ys[1][1] + xs[0][2] * ys[2][1] + xs[0][3] * ys[3][1], @@ -254,17 +270,17 @@ namespace vmath_hpp // operator/ template < typename T, std::size_t Size > - constexpr mat operator/(const mat& xs, T y) { + [[nodiscard]] constexpr mat operator/(const mat& xs, T y) { return map([y](const vec& x){ return x / y; }, xs); } template < typename T, std::size_t Size > - constexpr mat operator/(T x, const mat& ys) { + [[nodiscard]] constexpr mat operator/(T x, const mat& ys) { return map([x](const vec& y){ return x / y; }, ys); } template < typename T, std::size_t Size > - constexpr mat operator/(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr mat operator/(const mat& xs, const mat& ys) { return zip(std::divides<>(), xs, ys); } @@ -283,14 +299,14 @@ namespace vmath_hpp // operator== template < typename T, std::size_t Size > - constexpr bool operator==(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr bool operator==(const mat& xs, const mat& ys) { return fold([](bool acc, const vec& x, const vec& y){ return acc && (x == y); }, true, xs, ys); } template < typename T, std::size_t Size > - constexpr bool operator!=(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr bool operator!=(const mat& xs, const mat& ys) { return fold([](bool acc, const vec& x, const vec& y){ return acc || (x != y); }, false, xs, ys); @@ -299,7 +315,7 @@ namespace vmath_hpp // operator< template < typename T, std::size_t Size > - constexpr bool operator<(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr bool operator<(const mat& xs, const mat& ys) { for ( std::size_t i = 0; i < Size; ++i ) { if ( xs[i] < ys[i] ) { return true; @@ -321,7 +337,7 @@ namespace vmath_hpp namespace impl { template < typename T > - constexpr mat transpose_2x2_impl( + [[nodiscard]] constexpr mat transpose_2x2_impl( T a, T c, T b, T d) { @@ -331,7 +347,7 @@ namespace vmath_hpp } template < typename T > - constexpr mat transpose_3x3_impl( + [[nodiscard]] constexpr mat transpose_3x3_impl( T a, T d, T g, T b, T e, T h, T c, T f, T i) @@ -343,7 +359,7 @@ namespace vmath_hpp } template < typename T > - constexpr mat transpose_4x4_impl( + [[nodiscard]] constexpr mat transpose_4x4_impl( T a, T e, T i, T m, T b, T f, T j, T n, T c, T g, T k, T o, @@ -358,14 +374,14 @@ namespace vmath_hpp } template < typename T > - constexpr mat transpose(const mat& m) { + [[nodiscard]] constexpr mat transpose(const mat& m) { return impl::transpose_2x2_impl( m[0][0], m[0][1], m[1][0], m[1][1]); } template < typename T > - constexpr mat transpose(const mat& m) { + [[nodiscard]] constexpr mat transpose(const mat& m) { return impl::transpose_3x3_impl( m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], @@ -373,7 +389,7 @@ namespace vmath_hpp } template < typename T > - constexpr mat transpose(const mat& m) { + [[nodiscard]] constexpr mat transpose(const mat& m) { return impl::transpose_4x4_impl( m[0][0], m[0][1], m[0][2], m[0][3], m[1][0], m[1][1], m[1][2], m[1][3], @@ -384,7 +400,7 @@ namespace vmath_hpp namespace impl { template < typename T > - constexpr T determinant_2x2_impl( + [[nodiscard]] constexpr T determinant_2x2_impl( T a, T b, T c, T d) { @@ -394,7 +410,7 @@ namespace vmath_hpp } template < typename T > - constexpr T determinant_3x3_impl( + [[nodiscard]] constexpr T determinant_3x3_impl( T a, T b, T c, T d, T e, T f, T g, T h, T i) @@ -407,7 +423,7 @@ namespace vmath_hpp } template < typename T > - constexpr T determinant_4x4_impl( + [[nodiscard]] constexpr T determinant_4x4_impl( T a, T b, T c, T d, T e, T f, T g, T h, T i, T j, T k, T l, @@ -422,14 +438,14 @@ namespace vmath_hpp } template < typename T > - constexpr T determinant(const mat& m) { + [[nodiscard]] constexpr T determinant(const mat& m) { return impl::determinant_2x2_impl( m[0][0], m[0][1], m[1][0], m[1][1]); } template < typename T > - constexpr T determinant(const mat& m) { + [[nodiscard]] constexpr T determinant(const mat& m) { return impl::determinant_3x3_impl( m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], @@ -437,7 +453,7 @@ namespace vmath_hpp } template < typename T > - constexpr T determinant(const mat& m) { + [[nodiscard]] constexpr T determinant(const mat& m) { return impl::determinant_4x4_impl( m[0][0], m[0][1], m[0][2], m[0][3], m[1][0], m[1][1], m[1][2], m[1][3], @@ -448,13 +464,13 @@ namespace vmath_hpp namespace impl { template < typename T > - constexpr mat inverse_2x2_impl( + [[nodiscard]] constexpr mat inverse_2x2_impl( T a, T b, T c, T d) { - const T inv_det = T(1) / determinant_2x2_impl( + const T inv_det = reciprocal(determinant_2x2_impl( a, b, - c, d); + c, d)); const mat inv_m( d, -b, @@ -464,15 +480,15 @@ namespace vmath_hpp } template < typename T > - constexpr mat inverse_3x3_impl( + [[nodiscard]] constexpr mat inverse_3x3_impl( T a, T b, T c, T d, T e, T f, T g, T h, T i) { - const T inv_det = T(1) / determinant_3x3_impl( + const T inv_det = reciprocal(determinant_3x3_impl( a, b, c, d, e, f, - g, h, i); + g, h, i)); const mat inv_m( e * i - f * h, @@ -489,17 +505,17 @@ namespace vmath_hpp } template < typename T > - constexpr mat inverse_4x4_impl( + [[nodiscard]] constexpr mat inverse_4x4_impl( T a, T b, T c, T d, T e, T f, T g, T h, T i, T j, T k, T l, T m, T n, T o, T p) { - const T inv_det = T(1) / determinant_4x4_impl( + const T inv_det = reciprocal(determinant_4x4_impl( a, b, c, d, e, f, g, h, i, j, k, l, - m, n, o, p); + m, n, o, p)); const mat inv_m( (f * (k * p - l * o) + g * (l * n - j * p) + h * (j * o - k * n)), @@ -524,14 +540,14 @@ namespace vmath_hpp } template < typename T > - constexpr mat inverse(const mat& m) { + [[nodiscard]] constexpr mat inverse(const mat& m) { return impl::inverse_2x2_impl( m[0][0], m[0][1], m[1][0], m[1][1]); } template < typename T > - constexpr matinverse(const mat& m) { + [[nodiscard]] constexpr mat inverse(const mat& m) { return impl::inverse_3x3_impl( m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], @@ -539,7 +555,7 @@ namespace vmath_hpp } template < typename T > - constexpr matinverse(const mat& m) { + [[nodiscard]] constexpr mat inverse(const mat& m) { return impl::inverse_4x4_impl( m[0][0], m[0][1], m[0][2], m[0][3], m[1][0], m[1][1], m[1][2], m[1][3], diff --git a/headers/vmath.hpp/vmath_vec.hpp b/headers/vmath.hpp/vmath_vec.hpp index 5f14307..cd80289 100644 --- a/headers/vmath.hpp/vmath_vec.hpp +++ b/headers/vmath.hpp/vmath_vec.hpp @@ -32,7 +32,7 @@ namespace vmath_hpp::detail constexpr explicit vec_base(const vec_base& xy) : x{xy[0]}, y{xy[1]} {} - constexpr T& operator[](std::size_t index) noexcept { + [[nodiscard]] constexpr T& operator[](std::size_t index) noexcept { switch ( index ) { default: case 0: return x; @@ -40,7 +40,7 @@ namespace vmath_hpp::detail } } - constexpr const T& operator[](std::size_t index) const noexcept { + [[nodiscard]] constexpr const T& operator[](std::size_t index) const noexcept { switch ( index ) { default: case 0: return x; @@ -71,7 +71,7 @@ namespace vmath_hpp::detail constexpr explicit vec_base(const vec_base& xyz) : x{xyz[0]}, y{xyz[1]}, z{xyz[2]} {} - constexpr T& operator[](std::size_t index) noexcept { + [[nodiscard]] constexpr T& operator[](std::size_t index) noexcept { switch ( index ) { default: case 0: return x; @@ -80,7 +80,7 @@ namespace vmath_hpp::detail } } - constexpr const T& operator[](std::size_t index) const noexcept { + [[nodiscard]] constexpr const T& operator[](std::size_t index) const noexcept { switch ( index ) { default: case 0: return x; @@ -121,7 +121,7 @@ namespace vmath_hpp::detail constexpr vec_base(T x, const vec_base& yzw) : x{x}, y{yzw[0]}, z{yzw[1]}, w{yzw[2]} {} - constexpr T& operator[](std::size_t index) noexcept { + [[nodiscard]] constexpr T& operator[](std::size_t index) noexcept { switch ( index ) { default: case 0: return x; @@ -131,7 +131,7 @@ namespace vmath_hpp::detail } } - constexpr const T& operator[](std::size_t index) const noexcept { + [[nodiscard]] constexpr const T& operator[](std::size_t index) const noexcept { switch ( index ) { default: case 0: return x; @@ -179,14 +179,14 @@ namespace vmath_hpp } } - constexpr reference at(std::size_t index) { + [[nodiscard]] constexpr reference at(std::size_t index) { if ( index >= Size ) { throw std::out_of_range("vec::at"); } return (*this)[index]; } - constexpr const_reference at(std::size_t index) const { + [[nodiscard]] constexpr const_reference at(std::size_t index) const { if ( index >= Size ) { throw std::out_of_range("vec::at"); } diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index fe28c40..8efb19e 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -16,76 +16,76 @@ namespace vmath_hpp::detail namespace impl { template < typename A, std::size_t Size, typename F, std::size_t... Is > - constexpr auto map_impl(F&& f, const vec& a, std::index_sequence) + [[nodiscard]] constexpr auto map_impl(F&& f, const vec& a, std::index_sequence) -> vec, Size> { return { f(a[Is])... }; } template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > - constexpr auto zip_impl(F&& f, const vec& a, const vec& b, std::index_sequence) + [[nodiscard]] constexpr auto zip_impl(F&& f, const vec& a, const vec& b, std::index_sequence) -> vec, Size> { return { f(a[Is], b[Is])... }; } template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > - constexpr auto zip_impl(F&& f, const vec& a, const vec& b, const vec& c, std::index_sequence) + [[nodiscard]] constexpr auto zip_impl(F&& f, const vec& a, const vec& b, const vec& c, std::index_sequence) -> vec, Size> { return { f(a[Is], b[Is], c[Is])... }; } template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > - constexpr auto fold_impl(F&& f, A init, const vec& b, std::index_sequence) - -> A - { + [[nodiscard]] constexpr A fold_impl(F&& f, A init, const vec& b, std::index_sequence) { return ((init = f(std::move(init), b[Is])), ...); } template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > - constexpr auto fold_impl(F&& f, A init, const vec& b, const vec& c, std::index_sequence) - -> A - { + [[nodiscard]] constexpr A fold_impl(F&& f, A init, const vec& b, const vec& c, std::index_sequence) { return ((init = f(std::move(init), b[Is], c[Is])), ...); } template < typename A, std::size_t Size, typename F, std::size_t I, std::size_t... Is > - constexpr auto fold1_impl(F&& f, const vec& a, std::index_sequence) - -> A - { + [[nodiscard]] constexpr A fold1_impl(F&& f, const vec& a, std::index_sequence) { A init = a[I]; return ((init = f(std::move(init), a[Is])), ...); } } template < typename A, std::size_t Size, typename F > - constexpr auto map(F&& f, const vec& a) { + [[nodiscard]] constexpr auto map(F&& f, const vec& a) + -> vec, Size> + { return impl::map_impl(std::forward(f), a, std::make_index_sequence{}); } template < typename A, typename B, std::size_t Size, typename F > - constexpr auto zip(F&& f, const vec& a, const vec& b) { + [[nodiscard]] constexpr auto zip(F&& f, const vec& a, const vec& b) + -> vec, Size> + { return impl::zip_impl(std::forward(f), a, b, std::make_index_sequence{}); } template < typename A, typename B, typename C, std::size_t Size, typename F > - constexpr auto zip(F&& f, const vec& a, const vec& b, const vec& c) { + [[nodiscard]] constexpr auto zip(F&& f, const vec& a, const vec& b, const vec& c) + -> vec, Size> + { return impl::zip_impl(std::forward(f), a, b, c, std::make_index_sequence{}); } template < typename A, typename B, std::size_t Size, typename F > - constexpr auto fold(F&& f, A init, const vec& b) { + [[nodiscard]] constexpr A fold(F&& f, A init, const vec& b) { return impl::fold_impl(std::forward(f), std::move(init), b, std::make_index_sequence{}); } template < typename A, typename B, typename C, std::size_t Size, typename F > - constexpr auto fold(F&& f, A init, const vec& b, const vec& c) { + [[nodiscard]] constexpr A fold(F&& f, A init, const vec& b, const vec& c) { return impl::fold_impl(std::forward(f), std::move(init), b, c, std::make_index_sequence{}); } template < typename A, std::size_t Size, typename F > - constexpr auto fold1(F&& f, const vec& a) { + [[nodiscard]] constexpr A fold1(F&& f, const vec& a) { return impl::fold1_impl(std::forward(f), a, std::make_index_sequence{}); } } @@ -99,24 +99,24 @@ namespace vmath_hpp // -operator template < typename T, std::size_t Size > - constexpr vec operator-(const vec& xs) { + [[nodiscard]] constexpr vec operator-(const vec& xs) { return map(std::negate<>(), xs); } // operator+ template < typename T, std::size_t Size > - constexpr vec operator+(const vec& xs, T y) { + [[nodiscard]] constexpr vec operator+(const vec& xs, T y) { return map([y](T x){ return x + y; }, xs); } template < typename T, std::size_t Size > - constexpr vec operator+(T x, const vec& ys) { + [[nodiscard]] constexpr vec operator+(T x, const vec& ys) { return map([x](T y){ return x + y; }, ys); } template < typename T, std::size_t Size > - constexpr vec operator+(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec operator+(const vec& xs, const vec& ys) { return zip(std::plus<>(), xs, ys); } @@ -135,17 +135,17 @@ namespace vmath_hpp // operator- template < typename T, std::size_t Size > - constexpr vec operator-(const vec& xs, T y) { + [[nodiscard]] constexpr vec operator-(const vec& xs, T y) { return map([y](T x){ return x - y; }, xs); } template < typename T, std::size_t Size > - constexpr vec operator-(T x, const vec& ys) { + [[nodiscard]] constexpr vec operator-(T x, const vec& ys) { return map([x](T y){ return x - y; }, ys); } template < typename T, std::size_t Size > - constexpr vec operator-(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec operator-(const vec& xs, const vec& ys) { return zip(std::minus<>(), xs, ys); } @@ -164,17 +164,17 @@ namespace vmath_hpp // operator* template < typename T, std::size_t Size > - constexpr vec operator*(const vec& xs, T y) { + [[nodiscard]] constexpr vec operator*(const vec& xs, T y) { return map([y](T x){ return x * y; }, xs); } template < typename T, std::size_t Size > - constexpr vec operator*(T x, const vec& ys) { + [[nodiscard]] constexpr vec operator*(T x, const vec& ys) { return map([x](T y){ return x * y; }, ys); } template < typename T, std::size_t Size > - constexpr vec operator*(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec operator*(const vec& xs, const vec& ys) { return zip(std::multiplies<>(), xs, ys); } @@ -193,17 +193,17 @@ namespace vmath_hpp // operator/ template < typename T, std::size_t Size > - constexpr vec operator/(const vec& xs, T y) { + [[nodiscard]] constexpr vec operator/(const vec& xs, T y) { return map([y](T x){ return x / y; }, xs); } template < typename T, std::size_t Size > - constexpr vec operator/(T x, const vec& ys) { + [[nodiscard]] constexpr vec operator/(T x, const vec& ys) { return map([x](T y){ return x / y; }, ys); } template < typename T, std::size_t Size > - constexpr vec operator/(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec operator/(const vec& xs, const vec& ys) { return zip(std::divides<>(), xs, ys); } @@ -222,14 +222,14 @@ namespace vmath_hpp // operator== template < typename T, std::size_t Size > - constexpr bool operator==(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr bool operator==(const vec& xs, const vec& ys) { return fold([](bool acc, T x, T y){ return acc && (x == y); }, true, xs, ys); } template < typename T, std::size_t Size > - constexpr bool operator!=(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr bool operator!=(const vec& xs, const vec& ys) { return fold([](bool acc, T x, T y){ return acc || (x != y); }, false, xs, ys); @@ -238,7 +238,7 @@ namespace vmath_hpp // operator< template < typename T, std::size_t Size > - constexpr bool operator<(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr bool operator<(const vec& xs, const vec& ys) { for ( std::size_t i = 0; i < Size; ++i ) { if ( xs[i] < ys[i] ) { return true; @@ -258,77 +258,77 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T, std::size_t Size > - constexpr vec radians(const vec& degrees) { + [[nodiscard]] constexpr vec radians(const vec& degrees) { return map([](T x) { return radians(x); }, degrees); } template < typename T, std::size_t Size > - constexpr vec degrees(const vec& radians) { + [[nodiscard]] constexpr vec degrees(const vec& radians) { return map([](T x) { return degrees(x); }, radians); } template < typename T, std::size_t Size > - vec sin(const vec& xs) { + [[nodiscard]] vec sin(const vec& xs) { return map([](T x) { return sin(x); }, xs); } template < typename T, std::size_t Size > - vec cos(const vec& xs) { + [[nodiscard]] vec cos(const vec& xs) { return map([](T x) { return cos(x); }, xs); } template < typename T, std::size_t Size > - vec tan(const vec& xs) { + [[nodiscard]] vec tan(const vec& xs) { return map([](T x) { return tan(x); }, xs); } template < typename T, std::size_t Size > - vec asin(const vec& xs) { + [[nodiscard]] vec asin(const vec& xs) { return map([](T x) { return asin(x); }, xs); } template < typename T, std::size_t Size > - vec acos(const vec& xs) { + [[nodiscard]] vec acos(const vec& xs) { return map([](T x) { return acos(x); }, xs); } template < typename T, std::size_t Size > - vec atan(const vec& xs) { + [[nodiscard]] vec atan(const vec& xs) { return map([](T x) { return atan(x); }, xs); } template < typename T, std::size_t Size > - vec atan2(const vec& ys, const vec& xs) { + [[nodiscard]] vec atan2(const vec& ys, const vec& xs) { return zip([](T y, T x) { return atan2(y, x); }, ys, xs); } template < typename T, std::size_t Size > - vec sinh(const vec& xs) { + [[nodiscard]] vec sinh(const vec& xs) { return map([](T x) { return sinh(x); }, xs); } template < typename T, std::size_t Size > - vec cosh(const vec& xs) { + [[nodiscard]] vec cosh(const vec& xs) { return map([](T x) { return cosh(x); }, xs); } template < typename T, std::size_t Size > - vec tanh(const vec& xs) { + [[nodiscard]] vec tanh(const vec& xs) { return map([](T x) { return tanh(x); }, xs); } template < typename T, std::size_t Size > - vec asinh(const vec& xs) { + [[nodiscard]] vec asinh(const vec& xs) { return map([](T x) { return asinh(x); }, xs); } template < typename T, std::size_t Size > - vec acosh(const vec& xs) { + [[nodiscard]] vec acosh(const vec& xs) { return map([](T x) { return acosh(x); }, xs); } template < typename T, std::size_t Size > - vec atanh(const vec& xs) { + [[nodiscard]] vec atanh(const vec& xs) { return map([](T x) { return atanh(x); }, xs); } } @@ -340,37 +340,37 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T, std::size_t Size > - vec pow(const vec& xs, const vec& ys) { + [[nodiscard]] vec pow(const vec& xs, const vec& ys) { return zip([](T x, T y) { return pow(x, y); }, xs, ys); } template < typename T, std::size_t Size > - vec exp(const vec& xs) { + [[nodiscard]] vec exp(const vec& xs) { return map([](T x) { return exp(x); }, xs); } template < typename T, std::size_t Size > - vec log(const vec& xs) { + [[nodiscard]] vec log(const vec& xs) { return map([](T x) { return log(x); }, xs); } template < typename T, std::size_t Size > - vec exp2(const vec& xs) { + [[nodiscard]] vec exp2(const vec& xs) { return map([](T x) { return exp2(x); }, xs); } template < typename T, std::size_t Size > - vec log2(const vec& xs) { + [[nodiscard]] vec log2(const vec& xs) { return map([](T x) { return log2(x); }, xs); } template < typename T, std::size_t Size > - vec sqrt(const vec& xs) { + [[nodiscard]] vec sqrt(const vec& xs) { return map([](T x) { return sqrt(x); }, xs); } template < typename T, std::size_t Size > - vec rsqrt(const vec& xs) { + [[nodiscard]] vec rsqrt(const vec& xs) { return map([](T x) { return rsqrt(x); }, xs); } } @@ -382,47 +382,47 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T, std::size_t Size > - vec abs(const vec& xs) { + [[nodiscard]] constexpr vec abs(const vec& xs) { return map([](T x) { return abs(x); }, xs); } template < typename T, std::size_t Size > - vec sign(const vec& xs) { + [[nodiscard]] constexpr vec sign(const vec& xs) { return map([](T x) { return sign(x); }, xs); } template < typename T, std::size_t Size > - vec floor(const vec& xs) { + [[nodiscard]] vec floor(const vec& xs) { return map([](T x) { return floor(x); }, xs); } template < typename T, std::size_t Size > - vec trunc(const vec& xs) { + [[nodiscard]] vec trunc(const vec& xs) { return map([](T x) { return trunc(x); }, xs); } template < typename T, std::size_t Size > - vec round(const vec& xs) { + [[nodiscard]] vec round(const vec& xs) { return map([](T x) { return round(x); }, xs); } template < typename T, std::size_t Size > - vec ceil(const vec& xs) { + [[nodiscard]] vec ceil(const vec& xs) { return map([](T x) { return ceil(x); }, xs); } template < typename T, std::size_t Size > - vec fract(const vec& xs) { + [[nodiscard]] vec fract(const vec& xs) { return map([](T x) { return fract(x); }, xs); } template < typename T, std::size_t Size > - vec fmod(const vec& xs, T y) { + [[nodiscard]] vec fmod(const vec& xs, T y) { return map([y](T x) { return fmod(x, y); }, xs); } template < typename T, std::size_t Size > - vec fmod(const vec& xs, const vec& ys) { + [[nodiscard]] vec fmod(const vec& xs, const vec& ys) { return zip([](T x, T y) { return fmod(x, y); }, xs, ys); } @@ -440,97 +440,97 @@ namespace vmath_hpp } template < typename T, std::size_t Size > - constexpr T min(const vec& xs) { + [[nodiscard]] constexpr T min(const vec& xs) { return fold1([](T acc, T x){ return min(acc, x); }, xs); } template < typename T, std::size_t Size > - constexpr vec min(const vec& xs, T y) { + [[nodiscard]] constexpr vec min(const vec& xs, T y) { return map([y](T x) { return min(x, y); }, xs); } template < typename T, std::size_t Size > - constexpr vec min(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec min(const vec& xs, const vec& ys) { return zip([](T x, T y) { return min(x, y); }, xs, ys); } template < typename T, std::size_t Size > - constexpr T max(const vec& xs) { + [[nodiscard]] constexpr T max(const vec& xs) { return fold1([](T acc, T x){ return max(acc, x); }, xs); } template < typename T, std::size_t Size > - constexpr vec max(const vec& xs, T y) { + [[nodiscard]] constexpr vec max(const vec& xs, T y) { return map([y](T x) { return max(x, y); }, xs); } template < typename T, std::size_t Size > - constexpr vec max(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec max(const vec& xs, const vec& ys) { return zip([](T x, T y) { return max(x, y); }, xs, ys); } template < typename T, std::size_t Size > - constexpr vec clamp(const vec& xs, T min_x, T max_x) { + [[nodiscard]] constexpr vec clamp(const vec& xs, T min_x, T max_x) { return map([min_x, max_x](T x) { return clamp(x, min_x, max_x); }, xs); } template < typename T, std::size_t Size > - constexpr vec clamp(const vec& xs, const vec& min_xs, const vec& max_xs) { + [[nodiscard]] constexpr vec clamp(const vec& xs, const vec& min_xs, const vec& max_xs) { return zip([](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 > - constexpr vec saturate(const vec& xs) { + [[nodiscard]] constexpr vec saturate(const vec& xs) { return map([](T x) { return saturate(x); }, xs); } template < typename T, std::size_t Size > - constexpr vec lerp(const vec& xs, const vec& ys, T a) { + [[nodiscard]] constexpr vec lerp(const vec& xs, const vec& ys, T a) { return zip([a](T x, T y) { return lerp(x, y, a); }, xs, ys); } template < typename T, std::size_t Size > - constexpr vec lerp(const vec& xs, const vec& ys, const vec& as) { + [[nodiscard]] constexpr vec lerp(const vec& xs, const vec& ys, const vec& as) { return zip([](T x, T y, T a) { return lerp(x, y, a); }, xs, ys, as); } template < typename T, std::size_t Size > - constexpr vec step(T edge, const vec& xs) { + [[nodiscard]] constexpr vec step(T edge, const vec& xs) { return map([edge](T x) { return step(edge, x); }, xs); } template < typename T, std::size_t Size > - constexpr vec step(const vec& edges, const vec& xs) { + [[nodiscard]] constexpr vec step(const vec& edges, const vec& xs) { return zip([](T edge, T x) { return step(edge, x); }, edges, xs); } template < typename T, std::size_t Size > - constexpr vec smoothstep(T edge0, T edge1, const vec& xs) { + [[nodiscard]] constexpr vec smoothstep(T edge0, T edge1, const vec& xs) { return map([edge0, edge1](T x) { return smoothstep(edge0, edge1, x); }, xs); } template < typename T, std::size_t Size > - constexpr vec smoothstep(const vec& edges0, const vec& edges1, const vec& xs) { + [[nodiscard]] constexpr vec smoothstep(const vec& edges0, const vec& edges1, const vec& xs) { return zip([](T edge0, T edge1, T x) { return smoothstep(edge0, edge1, x); }, edges0, edges1, xs); } template < typename T, std::size_t Size > - vec isnan(const vec& xs) { + [[nodiscard]] vec isnan(const vec& xs) { return map([](T x) { return isnan(x); }, xs); } template < typename T, std::size_t Size > - vec isinf(const vec& xs) { + [[nodiscard]] vec isinf(const vec& xs) { return map([](T x) { return isinf(x); }, xs); } template < typename T, std::size_t Size > - vec isfinite(const vec& xs) { + [[nodiscard]] vec isfinite(const vec& xs) { return map([](T x) { return isfinite(x); }, xs); } template < typename T, std::size_t Size > - vec fma(const vec& as, const vec& bs, const vec& cs) { + [[nodiscard]] vec fma(const vec& as, const vec& bs, const vec& cs) { return zip([](T a, T b, T c) { return fma(a, b, c); }, as, bs, cs); } @@ -548,7 +548,7 @@ namespace vmath_hpp } template < typename T, std::size_t Size > - vec ldexp(const vec& xs, const vec& exps) { + [[nodiscard]] vec ldexp(const vec& xs, const vec& exps) { return zip([](T x, int exp) { return ldexp(x, exp); }, xs, exps); } } @@ -560,39 +560,39 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T, std::size_t Size > - constexpr T dot(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr T dot(const vec& xs, const vec& ys) { return fold([](T acc, T x, T y){ return acc + (x * y); }, T(0), xs, ys); } template < typename T, std::size_t Size > - T length(const vec& xs) { + [[nodiscard]] T length(const vec& xs) { return sqrt(dot(xs, xs)); } template < typename T, std::size_t Size > - constexpr T length2(const vec& xs) { + [[nodiscard]] constexpr T length2(const vec& xs) { return dot(xs, xs); } template < typename T, std::size_t Size > - T distance(const vec& xs, const vec& ys) { + [[nodiscard]] T distance(const vec& xs, const vec& ys) { return length(ys - xs); } template < typename T, std::size_t Size > - constexpr T distance2(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr T distance2(const vec& xs, const vec& ys) { return length2(ys - xs); } template < typename T > - constexpr T cross(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr T cross(const vec& xs, const vec& ys) { return xs.x * ys.y - xs.y * ys.x; } template < typename T > - constexpr vec cross(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec cross(const vec& xs, const vec& ys) { return { xs.y * ys.z - xs.z * ys.y, xs.z * ys.x - xs.x * ys.z, @@ -600,22 +600,22 @@ namespace vmath_hpp } template < typename T, std::size_t Size > - vec normalize(const vec& xs) { + [[nodiscard]] vec normalize(const vec& xs) { return xs * rsqrt(dot(xs, xs)); } template < typename T, std::size_t Size > - constexpr vec faceforward(const vec& n, const vec& i, const vec& nref) { + [[nodiscard]] constexpr vec faceforward(const vec& n, const vec& i, const vec& nref) { return dot(nref, i) < T(0) ? n : -n; } template < typename T, std::size_t Size > - constexpr vec reflect(const vec& i, const vec& n) { + [[nodiscard]] constexpr vec reflect(const vec& i, const vec& n) { return i - n * dot(n, i) * T(2); } template < typename T, std::size_t Size > - vec refract(const vec& i, const vec& n, T eta) { + [[nodiscard]] vec refract(const vec& i, const vec& n, T eta) { const T d = dot(n, i); const T k = T(1) - eta * eta * (T(1) - d * d); return T(k >= T(0)) * (eta * i - (eta * d + sqrt(k)) * n); @@ -629,52 +629,52 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T, std::size_t Size > - constexpr vec less(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec less(const vec& xs, const vec& ys) { return zip([](T x, T y){ return less(x, y); }, xs, ys); } template < typename T, std::size_t Size > - constexpr vec less_equal(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec less_equal(const vec& xs, const vec& ys) { return zip([](T x, T y){ return less_equal(x, y); }, xs, ys); } template < typename T, std::size_t Size > - constexpr vec greater(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec greater(const vec& xs, const vec& ys) { return zip([](T x, T y){ return greater(x, y); }, xs, ys); } template < typename T, std::size_t Size > - constexpr vec greater_equal(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec greater_equal(const vec& xs, const vec& ys) { return zip([](T x, T y){ return greater_equal(x, y); }, xs, ys); } template < typename T, std::size_t Size > - constexpr vec equal_to(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec equal_to(const vec& xs, const vec& ys) { return zip([](T x, T y){ return equal_to(x, y); }, xs, ys); } template < typename T, std::size_t Size > - constexpr vec equal_to(const vec& xs, const vec& ys, const T& epsilon) { + [[nodiscard]] constexpr vec equal_to(const vec& xs, const vec& ys, T epsilon) { return zip([epsilon](T x, T y){ return equal_to(x, y, epsilon); }, xs, ys); } template < typename T, std::size_t Size > - constexpr vec not_equal_to(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec not_equal_to(const vec& xs, const vec& ys) { return zip([](T x, T y){ return not_equal_to(x, y); }, xs, ys); } template < typename T, std::size_t Size > - constexpr vec not_equal_to(const vec& xs, const vec& ys, const T& epsilon) { + [[nodiscard]] constexpr vec not_equal_to(const vec& xs, const vec& ys, T epsilon) { return zip([epsilon](T x, T y){ return not_equal_to(x, y, epsilon); }, xs, ys); } - template < std::size_t Size > - constexpr bool any(const vec& xs) { - return fold([](bool x, bool y){ return x || y; }, false, xs); + template < typename T, std::size_t Size > + [[nodiscard]] constexpr bool any(const vec& xs) { + return fold([](bool acc, T x){ return acc || any(x); }, false, xs); } - template < std::size_t Size > - constexpr bool all(const vec& xs) { - return fold([](bool x, bool y){ return x && y; }, true, xs); + template < typename T, std::size_t Size > + [[nodiscard]] constexpr bool all(const vec& xs) { + return fold([](bool acc, T x){ return acc && all(x); }, true, xs); } } diff --git a/untests/vmath_mat_fun_tests.cpp b/untests/vmath_mat_fun_tests.cpp index 4edfae7..d50d414 100644 --- a/untests/vmath_mat_fun_tests.cpp +++ b/untests/vmath_mat_fun_tests.cpp @@ -35,6 +35,32 @@ namespace } TEST_CASE("vmath/mat_fun") { + SECTION("Detail") { + STATIC_REQUIRE(map([](const int2& x){ + return x * 2; + }, int2x2{}) == int2x2(2,0,0,2)); + + STATIC_REQUIRE(zip([](const int2& x, const int2& y){ + return x + y; + }, int2x2{}, int2x2{}) == int2x2(2,0,0,2)); + + STATIC_REQUIRE(zip([](const int2& x, const int2& y, const int2& z){ + return x + y + z; + }, int2x2{}, int2x2{}, int2x2{}) == int2x2(3,0,0,3)); + + STATIC_REQUIRE(fold([](int acc, const int2& x){ + return acc + x.x; + }, 0, int2x2{}) == 1); + + STATIC_REQUIRE(fold([](int acc, const int2& x, const int2& y){ + return acc + x.x + y.x; + }, 0, int2x2{}, int2x2{}) == 2); + + STATIC_REQUIRE(fold1([](const int2& acc, const int2& x){ + return acc + x; + }, int2x2{}) == int2(1,1)); + } + SECTION("Operators") { STATIC_REQUIRE(-int2x2(1,2,3,4) == int2x2(-1,-2,-3,-4)); @@ -157,9 +183,9 @@ TEST_CASE("vmath/mat_fun") { STATIC_REQUIRE(determinant(transpose(generate_frank_matrix())) == 1); } { - STATIC_REQUIRE(inverse(int2x2()) == int2x2()); - STATIC_REQUIRE(inverse(int3x3()) == int3x3()); - STATIC_REQUIRE(inverse(int4x4()) == int4x4()); + STATIC_REQUIRE(inverse(float2x2()) == float2x2()); + STATIC_REQUIRE(inverse(float3x3()) == float3x3()); + STATIC_REQUIRE(inverse(float4x4()) == float4x4()); STATIC_REQUIRE(inverse(float2x2(0.5)) == float2x2(2.f)); STATIC_REQUIRE(inverse(float3x3(0.5)) == float3x3(2.f)); diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 1fdb10a..3dbfb53 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -18,6 +18,32 @@ namespace } TEST_CASE("vmath/vec_fun") { + SECTION("Detail") { + STATIC_REQUIRE(map([](const int& x){ + return x * 2; + }, int2{1}) == int2{2}); + + STATIC_REQUIRE(zip([](const int& x, const int& y){ + return x + y; + }, int2{1}, int2{1}) == int2{2}); + + STATIC_REQUIRE(zip([](const int& x, const int& y, const int& z){ + return x + y + z; + }, int2{1}, int2{1}, int2{1}) == int2(3)); + + STATIC_REQUIRE(fold([](int acc, const int& x){ + return acc + x; + }, 0, int2{1}) == 2); + + STATIC_REQUIRE(fold([](int acc, const int& x, const int& y){ + return acc + x + y; + }, 0, int2{1}, int2{1}) == 4); + + STATIC_REQUIRE(fold1([](const int& acc, const int& x){ + return acc + x; + }, int2{1}) == 2); + } + SECTION("Operators") { STATIC_REQUIRE(-int2(1,-2) == int2(-1,2)); @@ -99,8 +125,8 @@ TEST_CASE("vmath/vec_fun") { } SECTION("Common Functions") { - REQUIRE(abs(float2(1.f, -1.f)) == approx2(1.f,1.f)); - REQUIRE(sign(float3(1.f, -1.f, 0.f)) == approx3(1.f,-1.f,0.f)); + STATIC_REQUIRE(abs(float2(1.f, -1.f)) == approx2(1.f,1.f)); + STATIC_REQUIRE(sign(float3(1.f, -1.f, 0.f)) == approx3(1.f,-1.f,0.f)); (void)floor(float2(1.f, -1.f)); (void)trunc(float2(1.f, -1.f)); @@ -201,19 +227,19 @@ TEST_CASE("vmath/vec_fun") { STATIC_REQUIRE(any(bool2(false, true))); STATIC_REQUIRE(any(bool2(true, true))); - STATIC_REQUIRE_FALSE(any(bool2(0, 0))); - STATIC_REQUIRE(any(bool2(1, 0))); - STATIC_REQUIRE(any(bool2(0, 1))); - STATIC_REQUIRE(any(bool2(1, 1))); + 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_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_REQUIRE_FALSE(all(bool2(0, 0))); - STATIC_REQUIRE_FALSE(all(bool2(1, 0))); - STATIC_REQUIRE_FALSE(all(bool2(0, 1))); - STATIC_REQUIRE(all(bool2(1, 1))); + 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))); } } From a8f242acd6c8a27e027c7b9e26b26426ddad961e Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 26 Nov 2020 22:27:51 +0700 Subject: [PATCH 49/53] nodiscard for ext functions --- headers/vmath.hpp/vmath_ext.hpp | 92 ++++++++++++++++----------------- untests/vmath_ext_tests.cpp | 51 ++++++++++++++---- 2 files changed, 87 insertions(+), 56 deletions(-) diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index e13f97d..fca2e5b 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -59,18 +59,18 @@ namespace vmath_hpp::detail { struct hash_combiner { template < typename T > - std::size_t operator()(std::size_t seed, const T& x) noexcept { + [[nodiscard]] std::size_t operator()(std::size_t seed, const T& x) noexcept { return (seed ^= std::hash{}(x) + 0x9e3779b9 + (seed << 6) + ( seed >> 2)); } }; template < typename T, size_t Size > - std::size_t hash(const vec& v) noexcept { + [[nodiscard]] std::size_t hash(const vec& v) noexcept { return fold(hash_combiner{}, std::size_t{}, v); } template < typename T, size_t Size > - std::size_t hash(const mat& m) noexcept { + [[nodiscard]] std::size_t hash(const mat& m) noexcept { return fold(hash_combiner{}, std::size_t{}, m); } } @@ -99,17 +99,17 @@ namespace std namespace vmath_hpp { template < typename To, typename From > - constexpr To cast_to(From x) noexcept { + [[nodiscard]] constexpr To cast_to(From x) noexcept { return static_cast(x); } template < typename To, typename From, std::size_t Size > - constexpr vec cast_to(const vec& v) { + [[nodiscard]] constexpr vec cast_to(const vec& v) { return detail::map([](From x){ return cast_to(x); }, v); } template < typename To, typename From, std::size_t Size > - constexpr mat cast_to(const mat& m) { + [[nodiscard]] constexpr mat cast_to(const mat& m) { return detail::map([](const vec& v){ return cast_to(v); }, m); } } @@ -123,12 +123,12 @@ namespace vmath_hpp // component template < typename T, std::size_t Size > - constexpr T component(const vec& v, std::size_t index) { + [[nodiscard]] constexpr T component(const vec& v, std::size_t index) { return v[index]; } template < typename T, std::size_t Size > - constexpr vec component(vec v, std::size_t index, T x) { + [[nodiscard]] constexpr vec component(vec v, std::size_t index, T x) { v[index] = x; return v; } @@ -136,12 +136,12 @@ namespace vmath_hpp // row template < typename T, std::size_t Size > - constexpr vec row(const mat& m, std::size_t index) { + [[nodiscard]] constexpr vec row(const mat& m, std::size_t index) { return m.rows[index]; } template < typename T, std::size_t Size > - constexpr mat row(mat m, std::size_t index, const vec& v) { + [[nodiscard]] constexpr mat row(mat m, std::size_t index, const vec& v) { m.rows[index] = v; return m; } @@ -151,23 +151,23 @@ namespace vmath_hpp namespace impl { template < typename T, std::size_t Size, std::size_t... Is > - constexpr vec column_impl(const mat& m, std::size_t index, std::index_sequence) { + [[nodiscard]] constexpr vec column_impl(const mat& m, std::size_t index, std::index_sequence) { return { m[Is][index]... }; } template < typename T, std::size_t Size, std::size_t... Is > - constexpr mat column_impl(const mat& m, std::size_t index, const vec& v, std::index_sequence) { + [[nodiscard]] constexpr mat column_impl(const mat& m, std::size_t index, const vec& v, std::index_sequence) { return { component(m[Is], index, v[Is])... }; } } template < typename T, std::size_t Size > - constexpr vec column(const mat& m, std::size_t index) { + [[nodiscard]] constexpr vec column(const mat& m, std::size_t index) { return impl::column_impl(m, index, std::make_index_sequence{}); } template < typename T, std::size_t Size > - constexpr mat column(const mat& m, std::size_t index, const vec& v) { + [[nodiscard]] constexpr mat column(const mat& m, std::size_t index, const vec& v) { return impl::column_impl(m, index, v, std::make_index_sequence{}); } } @@ -181,7 +181,7 @@ namespace vmath_hpp // translate template < typename T > - constexpr mat translate(const vec& v) { + [[nodiscard]] constexpr mat translate(const vec& v) { return { { 1, 0, 0, 0}, { 0, 1, 0, 0}, @@ -190,14 +190,14 @@ namespace vmath_hpp } template < typename T > - constexpr mat translate(const mat& m, const vec& v) { + [[nodiscard]] constexpr mat translate(const mat& m, const vec& v) { return m * translate(v); } // rotate template < typename T > - mat rotate(T angle, const vec& axis) { + [[nodiscard]] mat rotate(T angle, const vec& axis) { const T x = axis.x; const T y = axis.y; const T z = axis.z; @@ -221,14 +221,14 @@ namespace vmath_hpp } template < typename T > - mat rotate(const mat& m, T angle, const vec& axis) { + [[nodiscard]] mat rotate(const mat& m, T angle, const vec& axis) { return m * rotate(angle, axis); } // scale template < typename T > - constexpr mat scale(const vec& v) { + [[nodiscard]] constexpr mat scale(const vec& v) { return { {v.x, 0, 0, 0}, { 0, v.y, 0, 0}, @@ -237,14 +237,14 @@ namespace vmath_hpp } template < typename T > - constexpr mat scale(const mat& m, const vec& v) { + [[nodiscard]] constexpr mat scale(const mat& m, const vec& v) { return m * scale(v); } // look_at template < typename T > - mat look_at_lh(const vec& eye, const vec& at, const vec& up) { + [[nodiscard]] mat look_at_lh(const vec& eye, const vec& at, const vec& up) { const vec az = normalize(at - eye); const vec ax = normalize(cross(up, az)); const vec ay = cross(az, ax); @@ -259,7 +259,7 @@ namespace vmath_hpp } template < typename T > - mat look_at_rh(const vec& eye, const vec& at, const vec& up) { + [[nodiscard]] mat look_at_rh(const vec& eye, const vec& at, const vec& up) { const vec az = normalize(eye - at); const vec ax = normalize(cross(up, az)); const vec ay = cross(az, ax); @@ -283,7 +283,7 @@ namespace vmath_hpp // translate template < typename T > - constexpr mat translate(const vec& v) { + [[nodiscard]] constexpr mat translate(const vec& v) { return { { 1, 0, 0}, { 0, 1, 0}, @@ -291,14 +291,14 @@ namespace vmath_hpp } template < typename T > - constexpr mat translate(const mat& m, const vec& v) { + [[nodiscard]] constexpr mat translate(const mat& m, const vec& v) { return m * translate(v); } // rotate template < typename T > - mat rotate(T angle) { + [[nodiscard]] mat rotate(T angle) { const T cs = cos(angle); const T sn = sin(angle); return { @@ -308,14 +308,14 @@ namespace vmath_hpp } template < typename T > - mat rotate(const mat& m, T angle) { + [[nodiscard]] mat rotate(const mat& m, T angle) { return m * rotate(angle); } // scale template < typename T > - constexpr mat scale(const vec& v) { + [[nodiscard]] constexpr mat scale(const vec& v) { return { {v.x, 0, 0}, { 0, v.y, 0}, @@ -323,14 +323,14 @@ namespace vmath_hpp } template < typename T > - constexpr mat scale(const mat& m, const vec& v) { + [[nodiscard]] constexpr mat scale(const mat& m, const vec& v) { return m * scale(v); } // shear template < typename T > - constexpr mat shear(const vec& v) { + [[nodiscard]] constexpr mat shear(const vec& v) { return { { 1, v.y, 0}, {v.x, 1, 0}, @@ -338,7 +338,7 @@ namespace vmath_hpp } template < typename T > - constexpr mat shear_x(T y) { + [[nodiscard]] constexpr mat shear_x(T y) { return { {1, 0, 0}, {y, 1, 0}, @@ -346,7 +346,7 @@ namespace vmath_hpp } template < typename T > - constexpr mat shear_y(T x) { + [[nodiscard]] constexpr mat shear_y(T x) { return { {1, x, 0}, {0, 1, 0}, @@ -354,17 +354,17 @@ namespace vmath_hpp } template < typename T > - constexpr mat shear(const mat& m, const vec& v) { + [[nodiscard]] constexpr mat shear(const mat& m, const vec& v) { return m * shear(v); } template < typename T > - constexpr mat shear_x(const mat& m, T y) { + [[nodiscard]] constexpr mat shear_x(const mat& m, T y) { return m * shear_x(y); } template < typename T > - constexpr mat shear_y(const mat& m, T x) { + [[nodiscard]] constexpr mat shear_y(const mat& m, T x) { return m * shear_y(x); } } @@ -378,7 +378,7 @@ namespace vmath_hpp // orthographic template < typename T > - mat orthographic_lh_zo(T left, T right, T bottom, T top, T znear, T zfar) { + [[nodiscard]] mat orthographic_lh_zo(T left, T right, T bottom, T top, T znear, T zfar) { const T sx = T(2) / (right - left); const T sy = T(2) / (top - bottom); const T sz = T(1) / (zfar - znear); @@ -395,7 +395,7 @@ namespace vmath_hpp } template < typename T > - mat orthographic_lh_no(T left, T right, T bottom, T top, T znear, T zfar) { + [[nodiscard]] mat orthographic_lh_no(T left, T right, T bottom, T top, T znear, T zfar) { const T sx = T(2) / (right - left); const T sy = T(2) / (top - bottom); const T sz = T(2) / (zfar - znear); @@ -412,7 +412,7 @@ namespace vmath_hpp } template < typename T > - mat orthographic_rh_zo(T left, T right, T bottom, T top, T znear, T zfar) { + [[nodiscard]] mat orthographic_rh_zo(T left, T right, T bottom, T top, T znear, T zfar) { const T sx = T(2) / (right - left); const T sy = T(2) / (top - bottom); const T sz = -T(1) / (zfar - znear); @@ -429,7 +429,7 @@ namespace vmath_hpp } template < typename T > - mat orthographic_rh_no(T left, T right, T bottom, T top, T znear, T zfar) { + [[nodiscard]] mat orthographic_rh_no(T left, T right, T bottom, T top, T znear, T zfar) { const T sx = T(2) / (right - left); const T sy = T(2) / (top - bottom); const T sz = -T(2) / (zfar - znear); @@ -448,7 +448,7 @@ namespace vmath_hpp // perspective template < typename T > - mat perspective_lh_zo(T fov, T aspect, T znear, T zfar) { + [[nodiscard]] mat perspective_lh_zo(T fov, T aspect, T znear, T zfar) { const T sy = T(1) / tan(fov * T(0.5)); const T sx = sy / aspect; const T sz = zfar / (zfar - znear); @@ -461,7 +461,7 @@ namespace vmath_hpp } template < typename T > - mat perspective_lh_no(T fov, T aspect, T znear, T zfar) { + [[nodiscard]] mat perspective_lh_no(T fov, T aspect, T znear, T zfar) { const T sy = T(1) / tan(fov * T(0.5)); const T sx = sy / aspect; const T sz = (zfar + znear) / (zfar - znear); @@ -474,7 +474,7 @@ namespace vmath_hpp } template < typename T > - mat perspective_rh_zo(T fov, T aspect, T znear, T zfar) { + [[nodiscard]] mat perspective_rh_zo(T fov, T aspect, T znear, T zfar) { const T sy = T(1) / tan(fov * T(0.5)); const T sx = sy / aspect; const T sz = zfar / (znear - zfar); @@ -487,7 +487,7 @@ namespace vmath_hpp } template < typename T > - mat perspective_rh_no(T fov, T aspect, T znear, T zfar) { + [[nodiscard]] mat perspective_rh_no(T fov, T aspect, T znear, T zfar) { const T sy = T(1) / tan(fov * T(0.5)); const T sx = sy / aspect; const T sz = (zfar + znear) / (znear - zfar); @@ -509,14 +509,14 @@ namespace vmath_hpp // angle template < typename T, std::size_t Size > - T angle(const vec& x, const vec& y) { + [[nodiscard]] T angle(const vec& x, const vec& y) { return acos(dot(x, y) * rsqrt(length2(x) * length2(y))); } // rotate template < typename T > - vec rotate(const vec& v, T angle) { + [[nodiscard]] vec rotate(const vec& v, T angle) { const T cs = cos(angle); const T sn = sin(angle); return { @@ -525,12 +525,12 @@ namespace vmath_hpp } template < typename T > - vec rotate(const vec& v, T angle, const vec& normal) { + [[nodiscard]] vec rotate(const vec& v, T angle, const vec& normal) { return v * mat(rotate(angle, normal)); } template < typename T > - vec rotate(const vec& v, T angle, const vec& normal) { + [[nodiscard]] vec rotate(const vec& v, T angle, const vec& normal) { return v * rotate(angle, normal); } } diff --git a/untests/vmath_ext_tests.cpp b/untests/vmath_ext_tests.cpp index da802f2..10e56b0 100644 --- a/untests/vmath_ext_tests.cpp +++ b/untests/vmath_ext_tests.cpp @@ -11,6 +11,11 @@ #include "vmath_tests.hpp" +#include +#include +#include +#include + namespace { using namespace vmath_hpp; @@ -63,6 +68,32 @@ TEST_CASE("vmath/ext") { REQUIRE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,3,4})); REQUIRE_FALSE(std::hash{}({1,2,3,4}) == std::hash{}({1,2,4,3})); + { + std::set s; + s.insert(int2(1,2)); + REQUIRE(s.count(int2(1,2)) > 0); + REQUIRE_FALSE(s.count(int2(1,1)) > 0); + } + { + std::map 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); + } + { + std::unordered_set s; + s.insert(int2(1,2)); + REQUIRE(s.count(int2(1,2)) > 0); + REQUIRE_FALSE(s.count(int2(1,1)) > 0); + } + { + std::unordered_map 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); + } } SECTION("cast_to") { @@ -155,18 +186,18 @@ TEST_CASE("vmath/ext") { } SECTION("matrix look_at") { - look_at_lh(float3(-10.f), float3(0.f), float3(0,-1,0)); - look_at_rh(float3(-10.f), float3(0.f), float3(0,-1,0)); + (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)); - orthographic_lh_zo(0.f, 800.f, 0.f, 640.f, 0.f, 10.f); - orthographic_lh_no(0.f, 800.f, 0.f, 640.f, 0.f, 10.f); - orthographic_rh_zo(0.f, 800.f, 0.f, 640.f, 0.f, 10.f); - orthographic_rh_no(0.f, 800.f, 0.f, 640.f, 0.f, 10.f); + (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); - perspective_lh_zo(1.f, 1.3f, 0.f, 10.f); - perspective_lh_no(1.f, 1.3f, 0.f, 10.f); - perspective_rh_zo(1.f, 1.3f, 0.f, 10.f); - perspective_rh_no(1.f, 1.3f, 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); } SECTION("vector angle") { From 20257bd41297a6b86b209ae3f4ddca5542ebbf55 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 27 Nov 2020 03:46:16 +0700 Subject: [PATCH 50/53] vector reciprocal --- headers/vmath.hpp/vmath_ext.hpp | 20 ++++++++--------- headers/vmath.hpp/vmath_mat.hpp | 33 +++++++++++++---------------- headers/vmath.hpp/vmath_vec_fun.hpp | 5 +++++ untests/vmath_fun_tests.cpp | 23 +++++++++++--------- untests/vmath_vec_fun_tests.cpp | 1 + 5 files changed, 44 insertions(+), 38 deletions(-) diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index fca2e5b..4963e6b 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -337,6 +337,11 @@ namespace vmath_hpp { 0, 0, 1}}; } + template < typename T > + [[nodiscard]] constexpr mat shear(const mat& m, const vec& v) { + return m * shear(v); + } + template < typename T > [[nodiscard]] constexpr mat shear_x(T y) { return { @@ -345,6 +350,11 @@ namespace vmath_hpp {0, 0, 1}}; } + template < typename T > + [[nodiscard]] constexpr mat shear_x(const mat& m, T y) { + return m * shear_x(y); + } + template < typename T > [[nodiscard]] constexpr mat shear_y(T x) { return { @@ -353,16 +363,6 @@ namespace vmath_hpp {0, 0, 1}}; } - template < typename T > - [[nodiscard]] constexpr mat shear(const mat& m, const vec& v) { - return m * shear(v); - } - - template < typename T > - [[nodiscard]] constexpr mat shear_x(const mat& m, T y) { - return m * shear_x(y); - } - template < typename T > [[nodiscard]] constexpr mat shear_y(const mat& m, T x) { return m * shear_y(x); diff --git a/headers/vmath.hpp/vmath_mat.hpp b/headers/vmath.hpp/vmath_mat.hpp index ee45b27..ecb7a32 100644 --- a/headers/vmath.hpp/vmath_mat.hpp +++ b/headers/vmath.hpp/vmath_mat.hpp @@ -20,12 +20,11 @@ namespace vmath_hpp::detail class mat_base { public: using row_type = vec; - row_type rows[2]; + row_type rows[2] = { + {1, 0}, + {0, 1}}; public: - constexpr mat_base() : rows{ - row_type{1, 0}, - row_type{0, 1}, - } {} + mat_base() = default; constexpr explicit mat_base(T v) : rows{ @@ -61,13 +60,12 @@ namespace vmath_hpp::detail class mat_base { public: using row_type = vec; - row_type rows[3]; + row_type rows[3] = { + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}}; public: - constexpr mat_base() : rows{ - row_type{1, 0, 0}, - row_type{0, 1, 0}, - row_type{0, 0, 1}, - } {} + mat_base() = default; constexpr explicit mat_base(T v) : rows{ @@ -109,14 +107,13 @@ namespace vmath_hpp::detail class mat_base { public: using row_type = vec; - row_type rows[4]; + row_type rows[4] = { + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}}; public: - constexpr mat_base() : rows{ - row_type{1, 0, 0, 0}, - row_type{0, 1, 0, 0}, - row_type{0, 0, 1, 0}, - row_type{0, 0, 0, 1}, - } {} + mat_base() = default; constexpr explicit mat_base(T v) : rows{ diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index 8efb19e..4227849 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -391,6 +391,11 @@ namespace vmath_hpp return map([](T x) { return sign(x); }, xs); } + template < typename T, std::size_t Size > + [[nodiscard]] constexpr vec reciprocal(const vec& xs) { + return map([](T x) { return reciprocal(x); }, xs); + } + template < typename T, std::size_t Size > [[nodiscard]] vec floor(const vec& xs) { return map([](T x) { return floor(x); }, xs); diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index 40d34bc..f2ef755 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -51,17 +51,20 @@ TEST_CASE("vmath/fun") { } SECTION("Common Functions") { - REQUIRE(abs(1) == 1); - REQUIRE(abs(-1) == 1); - REQUIRE(abs(1.f) == approx(1.f)); - REQUIRE(abs(-1.f) == approx(1.f)); + STATIC_REQUIRE(vmath_hpp::abs(1) == 1); + STATIC_REQUIRE(vmath_hpp::abs(-1) == 1); + STATIC_REQUIRE(vmath_hpp::abs(1.f) == approx(1.f)); + STATIC_REQUIRE(vmath_hpp::abs(-1.f) == approx(1.f)); - REQUIRE(sign(2) == 1); - REQUIRE(sign(-2) == -1); - REQUIRE(sign(0) == 0); - REQUIRE(sign(2.f) == approx(1.f)); - REQUIRE(sign(-2.f) == approx(-1.f)); - REQUIRE(sign(0.f) == approx(0.f)); + STATIC_REQUIRE(sign(2) == 1); + STATIC_REQUIRE(sign(-2) == -1); + STATIC_REQUIRE(sign(0) == 0); + STATIC_REQUIRE(sign(2.f) == approx(1.f)); + STATIC_REQUIRE(sign(-2.f) == approx(-1.f)); + STATIC_REQUIRE(sign(0.f) == approx(0.f)); + + STATIC_REQUIRE(reciprocal(2.f) == approx(0.5f)); + STATIC_REQUIRE(reciprocal(4.f) == approx(0.25f)); REQUIRE(floor(1.7f) == approx(1.f)); REQUIRE(trunc(1.7f) == approx(1.f)); diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index 3dbfb53..c1ce6dd 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -127,6 +127,7 @@ TEST_CASE("vmath/vec_fun") { SECTION("Common Functions") { STATIC_REQUIRE(abs(float2(1.f, -1.f)) == approx2(1.f,1.f)); STATIC_REQUIRE(sign(float3(1.f, -1.f, 0.f)) == approx3(1.f,-1.f,0.f)); + STATIC_REQUIRE(reciprocal(float2(2.f, 4.f)) == approx2(0.5f,0.25f)); (void)floor(float2(1.f, -1.f)); (void)trunc(float2(1.f, -1.f)); From 2d120327594a528a9fd6b029cb37264034f2f677 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 27 Nov 2020 04:59:26 +0700 Subject: [PATCH 51/53] cast restrictions --- headers/vmath.hpp/vmath_ext.hpp | 5 ++++- headers/vmath.hpp/vmath_fun.hpp | 22 +++++++++++++++++++--- untests/vmath_fun_tests.cpp | 6 +++--- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index 4963e6b..406e4e0 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -99,7 +99,10 @@ namespace std namespace vmath_hpp { template < typename To, typename From > - [[nodiscard]] constexpr To cast_to(From x) noexcept { + [[nodiscard]] std::enable_if_t< + std::is_arithmetic_v && std::is_arithmetic_v + , To> + constexpr cast_to(From x) noexcept { return static_cast(x); } diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index c25d1e3..7e8ba90 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -269,9 +269,25 @@ namespace vmath_hpp return t * t * (T(3) - T(2) * t); } - using ::std::isnan; - using ::std::isinf; - using ::std::isfinite; + template < typename T > + [[nodiscard]] std::enable_if_t, bool> + isnan(T x) noexcept { + return std::isnan(x); + } + + template < typename T > + [[nodiscard]] std::enable_if_t, bool> + isinf(T x) noexcept { + return std::isinf(x); + } + + template < typename T > + [[nodiscard]] std::enable_if_t, bool> + isfinite(T x) noexcept { + return std::isfinite(x); + } + + // template < typename T > [[nodiscard]] std::enable_if_t, T> diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index f2ef755..81288a5 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -98,9 +98,9 @@ TEST_CASE("vmath/fun") { STATIC_REQUIRE(step(0.5f, 0.6f) == approx(1.f)); STATIC_REQUIRE(smoothstep(0.f, 1.f, 0.1f) == approx(0.028f)); - REQUIRE_FALSE(isnan(1.f)); - REQUIRE_FALSE(isinf(1.f)); - REQUIRE(isfinite(1.f)); + REQUIRE_FALSE(vmath_hpp::isnan(1.f)); + REQUIRE_FALSE(vmath_hpp::isinf(1.f)); + REQUIRE(vmath_hpp::isfinite(1.f)); REQUIRE(fma(2.f, 3.f, 4.f) == approx(10.f)); From e3a17c0e13234a3b5d64c8217e6e7eff5a464192 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 27 Nov 2020 04:59:42 +0700 Subject: [PATCH 52/53] readme API --- README.md | 1129 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1129 insertions(+) diff --git a/README.md b/README.md index c5896c1..7388400 100644 --- a/README.md +++ b/README.md @@ -46,4 +46,1133 @@ add_subdirectory(external/vmath.hpp) target_link_libraries(your_project_target vmath.hpp) ``` +## API + +- [Vector Types](#Vector-Types) +- [Matrix Types](#Matrix-Types) +- [Vector Operators](#Vector-Operators) +- [Matrix Operators](#Matrix-Operators) +- [Angle and Trigonometry Functions](#Angle-and-Trigonometry-Functions) +- [Exponential Functions](#Exponential-Functions) +- [Common Functions](#Common-Functions) +- [Geometric Functions](#Geometric-Functions) +- [Relational Functions](#Relational-Functions) +- [Matrix Functions](#Matrix-Functions) +- [Units](#Units) +- [Cast](#Cast) +- [Access](#Access) +- [Matrix Transform 3D](#Matrix-Transform-3D) +- [Matrix Transform 2D](#Matrix-Transform-2D) +- [Matrix Projections](#Matrix-Projections) +- [Vector Transform](#Vector-Transform) + +### Vector Types + +```cpp +template < typename T, size_t Size > +class vec_base; + +template < typename T > +class vec_base { +public: + T x{}, y{}; + + vec_base() = default; + constexpr explicit vec_base(T v); + constexpr vec_base(T x, T y); + constexpr explicit vec_base(const vec_base& xy); + constexpr explicit vec_base(const vec_base& xy); +}; + +template < typename T > +class vec_base { +public: + T x{}, y{}, z{}; + + vec_base() = default; + constexpr explicit vec_base(T v); + constexpr vec_base(T x, T y, T z); + constexpr vec_base(const vec_base& xy, T z); + constexpr vec_base(T x, const vec_base& yz); + constexpr explicit vec_base(const vec_base& xyz); +}; + +template < typename T > +class vec_base { +public: + T x{}, y{}, z{}, w{}; + + vec_base() = default; + constexpr explicit vec_base(T v); + constexpr vec_base(T x, T y, T z, T w); + constexpr vec_base(const vec_base& xy, T z, T w); + constexpr vec_base(T x, const vec_base& yz, T w); + constexpr vec_base(T x, T y, const vec_base& zw); + constexpr vec_base(const vec_base& xy, const vec_base& zw); + constexpr vec_base(const vec_base& xyz, T w); + constexpr vec_base(T x, const vec_base& yzw); +}; + +template < typename T, size_t Size > +class vec final : public vec_base { +public: + using value_type = T; + + using pointer = value_type*; + using const_pointer = const value_type*; + + using reference = value_type&; + using const_reference = const value_type&; + + static constexpr size_t size = Size; + + void swap(vec& other) noexcept(is_nothrow_swappable_v); + + constexpr reference at(size_t index); + constexpr const_reference at(size_t index) const; + + constexpr reference operator[](size_t index) noexcept; + constexpr const_reference operator[](size_t index) const noexcept; +}; + +using bool2 = vec; +using bool3 = vec; +using bool4 = vec; + +using int2 = vec; +using int3 = vec; +using int4 = vec; + +using uint2 = vec; +using uint3 = vec; +using uint4 = vec; + +using float2 = vec; +using float3 = vec; +using float4 = vec; + +using double2 = vec; +using double3 = vec; +using double4 = vec; + +using size2 = vec; +using size3 = vec; +using size4 = vec; + +using ptrdiff2 = vec; +using ptrdiff3 = vec; +using ptrdiff4 = vec; +``` + +### Matrix Types + +```cpp +template < typename T, size_t Size > +class mat_base; + +template < typename T > +class mat_base { +public: + using row_type = vec; + + row_type rows[2] = { + {1, 0}, + {0, 1}}; + + mat_base() = default; + constexpr explicit mat_base(T v); + + constexpr mat_base( + T m11, T m12, + T m21, T m22); + + constexpr mat_base( + const row_type& row0, + const row_type& row1); + + constexpr explicit mat_base(const mat_base& other); + constexpr explicit mat_base(const mat_base& other); +}; + +template < typename T > +class mat_base { +public: + using row_type = vec; + + row_type rows[3] = { + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}}; + + mat_base() = default; + constexpr explicit mat_base(T v); + + constexpr mat_base( + T m11, T m12, T m13, + T m21, T m22, T m23, + T m31, T m32, T m33); + + constexpr mat_base( + const row_type& row0, + const row_type& row1, + const row_type& row2); + + constexpr explicit mat_base(const mat_base& other); + constexpr explicit mat_base(const mat_base& other); +}; + +template < typename T > +class mat_base { +public: + using row_type = vec; + + row_type rows[4] = { + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}}; + + mat_base() = default; + constexpr explicit mat_base(T v); + + constexpr mat_base( + T m11, T m12, T m13, T m14, + T m21, T m22, T m23, T m24, + T m31, T m32, T m33, T m34, + T m41, T m42, T m43, T m44); + + constexpr mat_base( + const row_type& row0, + const row_type& row1, + const row_type& row2, + const row_type& row3); + + constexpr explicit mat_base(const mat_base& other); + constexpr explicit mat_base(const mat_base& other); +}; + +template < typename T, size_t Size > +class mat final : public mat_base { +public: + using row_type = vec; + + using pointer = row_type*; + using const_pointer = const row_type*; + + using reference = row_type&; + using const_reference = const row_type&; + + static constexpr size_t size = Size; + + void swap(mat& other) noexcept(is_nothrow_swappable_v); + + constexpr reference at(size_t index); + constexpr const_reference at(size_t index) const; + + constexpr reference operator[](size_t index) noexcept; + constexpr const_reference operator[](size_t index) const noexcept; +}; + +using bool2x2 = mat; +using bool3x3 = mat; +using bool4x4 = mat; + +using int2x2 = mat; +using int3x3 = mat; +using int4x4 = mat; + +using uint2x2 = mat; +using uint3x3 = mat; +using uint4x4 = mat; + +using float2x2 = mat; +using float3x3 = mat; +using float4x4 = mat; + +using double2x2 = mat; +using double3x3 = mat; +using double4x4 = mat; + +using size2x2 = mat; +using size3x3 = mat; +using size4x4 = mat; + +using ptrdiff2x2 = mat; +using ptrdiff3x3 = mat; +using ptrdiff4x4 = mat; +``` + +### Vector Operators + +```cpp +// -operator + +template < typename T, size_t Size > +constexpr vec operator-(const vec& xs); + +// operator+ + +template < typename T, size_t Size > +constexpr vec operator+(const vec& xs, T y); + +template < typename T, size_t Size > +constexpr vec operator+(T x, const vec& ys); + +template < typename T, size_t Size > +constexpr vec operator+(const vec& xs, const vec& ys); + +// operator+= + +template < typename T, size_t Size > +constexpr vec& operator+=(vec& xs, T y); + +template < typename T, size_t Size > +constexpr vec& operator+=(vec& xs, const vec& ys); + +// operator- + +template < typename T, size_t Size > +constexpr vec operator-(const vec& xs, T y); + +template < typename T, size_t Size > +constexpr vec operator-(T x, const vec& ys); + +template < typename T, size_t Size > +constexpr vec operator-(const vec& xs, const vec& ys); + +// operator-= + +template < typename T, size_t Size > +constexpr vec& operator-=(vec& xs, T y); + +template < typename T, size_t Size > +constexpr vec& operator-=(vec& xs, const vec& ys); + +// operator* + +template < typename T, size_t Size > +constexpr vec operator*(const vec& xs, T y); + +template < typename T, size_t Size > +constexpr vec operator*(T x, const vec& ys); + +template < typename T, size_t Size > +constexpr vec operator*(const vec& xs, const vec& ys); + +// operator*= + +template < typename T, size_t Size > +constexpr vec& operator*=(vec& xs, T y); + +template < typename T, size_t Size > +constexpr vec& operator*=(vec& xs, const vec& ys); + +// operator/ + +template < typename T, size_t Size > +constexpr vec operator/(const vec& xs, T y); + +template < typename T, size_t Size > +constexpr vec operator/(T x, const vec& ys); + +template < typename T, size_t Size > +constexpr vec operator/(const vec& xs, const vec& ys); + +// operator/= + +template < typename T, size_t Size > +constexpr vec& operator/=(vec& xs, T y); + +template < typename T, size_t Size > +constexpr vec& operator/=(vec& xs, const vec& ys); + +// operator== + +template < typename T, size_t Size > +constexpr bool operator==(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +constexpr bool operator!=(const vec& xs, const vec& ys); + +// operator< + +template < typename T, size_t Size > +constexpr bool operator<(const vec& xs, const vec& ys); +``` + +### Matrix Operators + +```cpp +// -operator + +template < typename T, size_t Size > +constexpr mat operator-(const mat& xs); + +// operator+ + +template < typename T, size_t Size > +constexpr mat operator+(const mat& xs, T y); + +template < typename T, size_t Size > +constexpr mat operator+(T x, const mat& ys); + +template < typename T, size_t Size > +constexpr mat operator+(const mat& xs, const mat& ys); + +// operator+= + +template < typename T, size_t Size > +constexpr mat& operator+=(mat& xs, T y); + +template < typename T, size_t Size > +constexpr mat& operator+=(mat& xs, const mat& ys); + +// operator- + +template < typename T, size_t Size > +constexpr mat operator-(const mat& xs, T y); + +template < typename T, size_t Size > +constexpr mat operator-(T x, const mat& ys); + +template < typename T, size_t Size > +constexpr mat operator-(const mat& xs, const mat& ys); + +// operator-= + +template < typename T, size_t Size > +constexpr mat& operator-=(mat& xs, T y); + +template < typename T, size_t Size > +constexpr mat& operator-=(mat& xs, const mat& ys); + +// operator* + +template < typename T, size_t Size > +constexpr mat operator*(const mat& xs, T y); + +template < typename T, size_t Size > +constexpr mat operator*(T x, const mat& ys); + +template < typename T, size_t Size > +constexpr vec operator*(const vec& xs, const mat& ys); + +template < typename T, size_t Size > +constexpr mat operator*(const mat& xs, const mat& ys); + +// operator*= + +template < typename T, size_t Size > +constexpr mat& operator*=(mat& xs, T y); + +template < typename T, size_t Size > +constexpr vec& operator*=(vec& xs, const mat& ys); + +template < typename T, size_t Size > +constexpr mat& operator*=(mat& xs, const mat& ys); + +// operator/ + +template < typename T, size_t Size > +constexpr mat operator/(const mat& xs, T y); + +template < typename T, size_t Size > +constexpr mat operator/(T x, const mat& ys); + +template < typename T, size_t Size > +constexpr mat operator/(const mat& xs, const mat& ys); + +// operator/= + +template < typename T, size_t Size > +constexpr mat& operator/=(mat& xs, T y); + +template < typename T, size_t Size > +constexpr mat& operator/=(mat& xs, const mat& ys); + +// operator== + +template < typename T, size_t Size > +constexpr bool operator==(const mat& xs, const mat& ys); + +template < typename T, size_t Size > +constexpr bool operator!=(const mat& xs, const mat& ys); + +// operator< + +template < typename T, size_t Size > +constexpr bool operator<(const mat& xs, const mat& ys); +``` + +### Angle and Trigonometry Functions + +```cpp +// Scalar + +template < floating_point T > +constexpr T radians(T degrees) noexcept; + +template < floating_point T > +constexpr T degrees(T radians) noexcept; + +template < floating_point T > +T sin(T x) noexcept; + +template < floating_point T > +T cos(T x) noexcept; + +template < floating_point T > +T tan(T x) noexcept; + +template < floating_point T > +T asin(T x) noexcept; + +template < floating_point T > +T acos(T x) noexcept; + +template < floating_point T > +T atan(T x) noexcept; + +template < floating_point T > +T atan2(T y, T x) noexcept; + +template < floating_point T > +T sinh(T x) noexcept; + +template < floating_point T > +T cosh(T x) noexcept; + +template < floating_point T > +T tanh(T x) noexcept; + +template < floating_point T > +T asinh(T x) noexcept; + +template < floating_point T > +T acosh(T x) noexcept; + +template < floating_point T > +T atanh(T x) noexcept; + +// Vector + +template < typename T, size_t Size > +constexpr vec radians(const vec& degrees); + +template < typename T, size_t Size > +constexpr vec degrees(const vec& radians); + +template < typename T, size_t Size > +vec sin(const vec& xs); + +template < typename T, size_t Size > +vec cos(const vec& xs); + +template < typename T, size_t Size > +vec tan(const vec& xs); + +template < typename T, size_t Size > +vec asin(const vec& xs); + +template < typename T, size_t Size > +vec acos(const vec& xs); + +template < typename T, size_t Size > +vec atan(const vec& xs); + +template < typename T, size_t Size > +vec atan2(const vec& ys, const vec& xs); + +template < typename T, size_t Size > +vec sinh(const vec& xs); + +template < typename T, size_t Size > +vec cosh(const vec& xs); + +template < typename T, size_t Size > +vec tanh(const vec& xs); + +template < typename T, size_t Size > +vec asinh(const vec& xs); + +template < typename T, size_t Size > +vec acosh(const vec& xs); + +template < typename T, size_t Size > +vec atanh(const vec& xs); +``` + +### Exponential Functions + +```cpp +// Scalar + +template < floating_point T > +T pow(T x, T y) noexcept; + +template < floating_point T > +T exp(T x) noexcept; + +template < floating_point T > +T log(T x) noexcept; + +template < floating_point T > +T exp2(T x) noexcept; + +template < floating_point T > +T log2(T x) noexcept; + +template < floating_point T > +T sqrt(T x) noexcept; + +template < floating_point T > +T rsqrt(T x) noexcept; + +// Vector + +template < typename T, size_t Size > +vec pow(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +vec exp(const vec& xs); + +template < typename T, size_t Size > +vec log(const vec& xs); + +template < typename T, size_t Size > +vec exp2(const vec& xs); + +template < typename T, size_t Size > +vec log2(const vec& xs); + +template < typename T, size_t Size > +vec sqrt(const vec& xs); + +template < typename T, size_t Size > +vec rsqrt(const vec& xs); +``` + +### Common Functions + +```cpp +// Scalar + +template < arithmetic T > +constexpr T abs(T x) noexcept; + +template < arithmetic T > +constexpr T sign(T x) noexcept; + +template < floating_point T > +constexpr T reciprocal(T x) noexcept; + +template < floating_point T > +T floor(T x) noexcept; + +template < floating_point T > +T trunc(T x) noexcept; + +template < floating_point T > +T round(T x) noexcept; + +template < floating_point T > +T ceil(T x) noexcept; + +template < floating_point T > +T fract(T x) noexcept; + +template < floating_point T > +T fmod(T x, T y) noexcept; + +template < floating_point T > +T modf(T x, T* y) noexcept; + +template < arithmetic T > +constexpr T min(T x, T y) noexcept; + +template < arithmetic T > +constexpr T max(T x, T y) noexcept; + +template < arithmetic T > +constexpr T clamp(T x, T min_x, T max_x) noexcept; + +template < arithmetic T > +constexpr T saturate(T x) noexcept; + +template < floating_point T > +constexpr T lerp(T x, T y, T a) noexcept; + +template < floating_point T > +constexpr T step(T edge, T x) noexcept; + +template < floating_point T > +constexpr T smoothstep(T edge0, T edge1, T x) noexcept; + +template < arithmetic T > +bool isnan(T x) noexcept; + +template < arithmetic T > +bool isinf(T x) noexcept; + +template < arithmetic T > +bool isfinite(T x) noexcept; + +template < floating_point T > +T fma(T x, T y, T z) noexcept; + +template < floating_point T > +T frexp(T x, int* exp) noexcept; + +template < floating_point T > +T ldexp(T x, int exp) noexcept; + +// Vector + +template < typename T, size_t Size > +constexpr vec abs(const vec& xs); + +template < typename T, size_t Size > +constexpr vec sign(const vec& xs); + +template < typename T, size_t Size > +constexpr vec reciprocal(const vec& xs); + +template < typename T, size_t Size > +vec floor(const vec& xs); + +template < typename T, size_t Size > +vec trunc(const vec& xs); + +template < typename T, size_t Size > +vec round(const vec& xs); + +template < typename T, size_t Size > +vec ceil(const vec& xs); + +template < typename T, size_t Size > +vec fract(const vec& xs); + +template < typename T, size_t Size > +vec fmod(const vec& xs, T y); + +template < typename T, size_t Size > +vec fmod(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +vec modf(const vec& xs, vec* is); + +template < typename T, size_t Size > +constexpr T min(const vec& xs); + +template < typename T, size_t Size > +constexpr vec min(const vec& xs, T y); + +template < typename T, size_t Size > +constexpr vec min(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +constexpr T max(const vec& xs); + +template < typename T, size_t Size > +constexpr vec max(const vec& xs, T y); + +template < typename T, size_t Size > +constexpr vec max(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +constexpr vec clamp(const vec& xs, T min_x, T max_x); + +template < typename T, size_t Size > +constexpr vec clamp(const vec& xs, const vec& min_xs, const vec& max_xs); + +template < typename T, size_t Size > +constexpr vec saturate(const vec& xs); + +template < typename T, size_t Size > +constexpr vec lerp(const vec& xs, const vec& ys, T a); + +template < typename T, size_t Size > +constexpr vec lerp(const vec& xs, const vec& ys, const vec& as); + +template < typename T, size_t Size > +constexpr vec step(T edge, const vec& xs); + +template < typename T, size_t Size > +constexpr vec step(const vec& edges, const vec& xs); + +template < typename T, size_t Size > +constexpr vec smoothstep(T edge0, T edge1, const vec& xs); + +template < typename T, size_t Size > +constexpr vec smoothstep(const vec& edges0, const vec& edges1, const vec& xs); + +template < typename T, size_t Size > +vec isnan(const vec& xs); + +template < typename T, size_t Size > +vec isinf(const vec& xs); + +template < typename T, size_t Size > +vec isfinite(const vec& xs); + +template < typename T, size_t Size > +vec fma(const vec& as, const vec& bs, const vec& cs); + +template < typename T, size_t Size > +vec frexp(const vec& xs, vec* exps); + +template < typename T, size_t Size > +vec ldexp(const vec& xs, const vec& exps); +``` + +### Geometric Functions + +```cpp +// Scalar + +template < arithmetic T > +constexpr T dot(T x, T y) noexcept; + +template < arithmetic T > +constexpr T length(T x) noexcept; + +template < arithmetic T > +constexpr T length2(T x) noexcept; + +template < arithmetic T > +constexpr T distance(T x, T y) noexcept; + +template < arithmetic T > +constexpr T distance2(T x, T y) noexcept; + +template < floating_point T > +T normalize(T x) noexcept; + +template < floating_point T > +constexpr T faceforward(T n, T i, T nref) noexcept; + +template < floating_point T > +constexpr T reflect(T i, T n) noexcept; + +template < floating_point T > +T refract(T i, T n, T eta) noexcept; + +// Vector + +template < typename T, size_t Size > +constexpr T dot(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +T length(const vec& xs); + +template < typename T, size_t Size > +constexpr T length2(const vec& xs); + +template < typename T, size_t Size > +T distance(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +constexpr T distance2(const vec& xs, const vec& ys); + +template < typename T > +constexpr T cross(const vec& xs, const vec& ys); + +template < typename T > +constexpr vec cross(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +vec normalize(const vec& xs); + +template < typename T, size_t Size > +constexpr vec faceforward(const vec& n, const vec& i, const vec& nref); + +template < typename T, size_t Size > +constexpr vec reflect(const vec& i, const vec& n); + +template < typename T, size_t Size > +vec refract(const vec& i, const vec& n, T eta); +``` + +### Relational Functions + +```cpp +// Scalar + +template < arithmetic T > +constexpr bool less(T x, T y) noexcept; + +template < arithmetic T > +constexpr bool less_equal(T x, T y) noexcept; + +template < arithmetic T > +constexpr bool greater(T x, T y) noexcept; + +template < arithmetic T > +constexpr bool greater_equal(T x, T y) noexcept; + +template < arithmetic T > +constexpr bool equal_to(T x, T y) noexcept; + +template < arithmetic T > +constexpr bool equal_to(T x, T y, T epsilon) noexcept; + +template < arithmetic T > +constexpr bool not_equal_to(T x, T y) noexcept; + +template < arithmetic T > +constexpr bool not_equal_to(T x, T y, T epsilon) noexcept; + +template < arithmetic T > +constexpr bool any(T x) noexcept; + +template < arithmetic T > +constexpr bool all(T x) noexcept; + +// Vector + +template < typename T, size_t Size > +constexpr vec less(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +constexpr vec less_equal(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +constexpr vec greater(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +constexpr vec greater_equal(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +constexpr vec equal_to(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +constexpr vec equal_to(const vec& xs, const vec& ys, T epsilon); + +template < typename T, size_t Size > +constexpr vec not_equal_to(const vec& xs, const vec& ys); + +template < typename T, size_t Size > +constexpr vec not_equal_to(const vec& xs, const vec& ys, T epsilon); + +template < typename T, size_t Size > +constexpr bool any(const vec& xs); + +template < typename T, size_t Size > +constexpr bool all(const vec& xs); +``` + +### Matrix Functions + +```cpp +template < typename T > +constexpr mat transpose(const mat& m); + +template < typename T > +constexpr mat transpose(const mat& m); + +template < typename T > +constexpr mat transpose(const mat& m); + +template < typename T > +constexpr T determinant(const mat& m); + +template < typename T > +constexpr T determinant(const mat& m); + +template < typename T > +constexpr T determinant(const mat& m); + +template < typename T > +constexpr mat inverse(const mat& m); + +template < typename T > +constexpr mat inverse(const mat& m); + +template < typename T > +constexpr mat inverse(const mat& m); +``` + +### Units + +```cpp +template < typename T > inline constexpr vec zero2; +template < typename T > inline constexpr vec zero3; +template < typename T > inline constexpr vec zero4; + +template < typename T > inline constexpr vec unit2; +template < typename T > inline constexpr vec unit3; +template < typename T > inline constexpr vec unit4; + +template < typename T > inline constexpr vec unit2_x; +template < typename T > inline constexpr vec unit2_y; + +template < typename T > inline constexpr vec unit3_x; +template < typename T > inline constexpr vec unit3_y; +template < typename T > inline constexpr vec unit3_z; + +template < typename T > inline constexpr vec unit4_x; +template < typename T > inline constexpr vec unit4_y; +template < typename T > inline constexpr vec unit4_z; +template < typename T > inline constexpr vec unit4_w; + +template < typename T > inline constexpr mat zero2x2; +template < typename T > inline constexpr mat zero3x3; +template < typename T > inline constexpr mat zero4x4; + +template < typename T > inline constexpr mat unit2x2; +template < typename T > inline constexpr mat unit3x3; +template < typename T > inline constexpr mat unit4x4; + +template < typename T > inline constexpr mat identity2x2; +template < typename T > inline constexpr mat identity3x3; +template < typename T > inline constexpr mat identity4x4; +``` + +### Cast + +```cpp +template < arithmetic To, arithmetic From > +constexpr To cast_to(From x) noexcept; + +template < typename To, typename From, size_t Size > +constexpr vec cast_to(const vec& v); + +template < typename To, typename From, size_t Size > +constexpr mat cast_to(const mat& m); +``` + +### Access + +```cpp +template < typename T, size_t Size > +constexpr T component(const vec& v, size_t index); + +template < typename T, size_t Size > +constexpr vec component(vec v, size_t index, T x); + +template < typename T, size_t Size > +constexpr vec row(const mat& m, size_t index); + +template < typename T, size_t Size > +constexpr mat row(mat m, size_t index, const vec& v); + +template < typename T, size_t Size > +constexpr vec column(const mat& m, size_t index); + +template < typename T, size_t Size > +constexpr mat column(const mat& m, size_t index, const vec& v); +``` + +### Matrix Transform 3D + +```cpp +template < typename T > +constexpr mat translate(const vec& v); + +template < typename T > +constexpr mat translate(const mat& m, const vec& v); + +template < typename T > +mat rotate(T angle, const vec& axis); + +template < typename T > +mat rotate(const mat& m, T angle, const vec& axis); + +template < typename T > +constexpr mat scale(const vec& v); + +template < typename T > +constexpr mat scale(const mat& m, const vec& v); + +template < typename T > +mat look_at_lh(const vec& eye, const vec& at, const vec& up); + +template < typename T > +mat look_at_rh(const vec& eye, const vec& at, const vec& up); +``` + +### Matrix Transform 2D + +```cpp +template < typename T > +constexpr mat translate(const vec& v); + +template < typename T > +constexpr mat translate(const mat& m, const vec& v); + +template < typename T > +mat rotate(T angle); + +template < typename T > +mat rotate(const mat& m, T angle); + +template < typename T > +constexpr mat scale(const vec& v); + +template < typename T > +constexpr mat scale(const mat& m, const vec& v); + +template < typename T > +constexpr mat shear(const vec& v); + +template < typename T > +constexpr mat shear(const mat& m, const vec& v); + +template < typename T > +constexpr mat shear_x(T y); + +template < typename T > +constexpr mat shear_x(const mat& m, T y); + +template < typename T > +constexpr mat shear_y(T x); + +template < typename T > +constexpr mat shear_y(const mat& m, T x); +``` + +### Matrix Projections + +```cpp +template < typename T > +mat orthographic_lh_zo(T left, T right, T bottom, T top, T znear, T zfar); + +template < typename T > +mat orthographic_lh_no(T left, T right, T bottom, T top, T znear, T zfar); + +template < typename T > +mat orthographic_rh_zo(T left, T right, T bottom, T top, T znear, T zfar); + +template < typename T > +mat orthographic_rh_no(T left, T right, T bottom, T top, T znear, T zfar); + +template < typename T > +mat perspective_lh_zo(T fov, T aspect, T znear, T zfar); + +template < typename T > +mat perspective_lh_no(T fov, T aspect, T znear, T zfar); + +template < typename T > +mat perspective_rh_zo(T fov, T aspect, T znear, T zfar); + +template < typename T > +mat perspective_rh_no(T fov, T aspect, T znear, T zfar); +``` + +### Vector Transform + +```cpp +template < typename T, size_t Size > +T angle(const vec& x, const vec& y); + +template < typename T > +vec rotate(const vec& v, T angle); + +template < typename T > +vec rotate(const vec& v, T angle, const vec& normal); + +template < typename T > +vec rotate(const vec& v, T angle, const vec& normal); +``` + ## [License (MIT)](./LICENSE.md) From c349c36dbafa5831727c4ae7df48f2383667b157 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 27 Nov 2020 05:10:10 +0700 Subject: [PATCH 53/53] try to fix clang compilation --- untests/vmath_mat_fun_tests.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/untests/vmath_mat_fun_tests.cpp b/untests/vmath_mat_fun_tests.cpp index d50d414..4fcab3b 100644 --- a/untests/vmath_mat_fun_tests.cpp +++ b/untests/vmath_mat_fun_tests.cpp @@ -113,24 +113,24 @@ TEST_CASE("vmath/mat_fun") { } { - float4 v{0.f, 0.f, 0.f, 1.f}; - REQUIRE(&v == &(v *= translate(float3{1.f,2.f,3.f}))); - REQUIRE(v == approx4(1.f,2.f,3.f,1.f)); + int4 v{0, 0, 0, 1}; + REQUIRE(&v == &(v *= translate(int3{1,2,3}))); + REQUIRE(v == approx4(1,2,3,1)); } { - float3 v{1.f, 2.f, 3.f}; - REQUIRE(&v == &(v *= float3x3(scale(float3{2.f,3.f,4.f})))); - REQUIRE(v == approx3(2.f,6.f,12.f)); + int3 v{1, 2, 3}; + REQUIRE(&v == &(v *= int3x3(scale(int3{2,3,4})))); + REQUIRE(v == int3(2,6,12)); } { - float4x4 v = translate(float3{1.f, 2.f, 3.f}); - REQUIRE(&v == &(v *= translate(float3{1.f,2.f,3.f}))); - REQUIRE(v == approx4x4(translate(float3{2.f,4.f,6.f}))); + int4x4 v = translate(int3{1, 2, 3}); + REQUIRE(&v == &(v *= translate(int3{1,2,3}))); + REQUIRE(v == translate(int3{2,4,6})); } { - float3x3 v = float3x3(scale(float3{1.f, 2.f, 3.f})); - REQUIRE(&v == &(v *= float3x3(scale(float3{2.f,3.f,4.f})))); - REQUIRE(v == approx3x3(float3x3(scale(float3{2.f,6.f,12.f})))); + 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}))); } }