mirror of
https://github.com/BlackMATov/vmath.hpp.git
synced 2025-12-14 20:31:25 +07:00
73
README.md
73
README.md
@@ -122,18 +122,41 @@ public:
|
||||
template < typename T, size_t Size >
|
||||
class vec final : public vec_base<T, Size> {
|
||||
public:
|
||||
using value_type = T;
|
||||
using component_type = T;
|
||||
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using pointer = component_type*;
|
||||
using const_pointer = const component_type*;
|
||||
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using reference = component_type&;
|
||||
using const_reference = const component_type&;
|
||||
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
static constexpr size_t size = Size;
|
||||
|
||||
void swap(vec& other) noexcept(is_nothrow_swappable_v<T>);
|
||||
|
||||
iterator begin() noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
iterator end() noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
|
||||
reverse_iterator rbegin() noexcept;
|
||||
const_reverse_iterator rbegin() const noexcept;
|
||||
reverse_iterator rend() noexcept;
|
||||
const_reverse_iterator rend() const noexcept;
|
||||
|
||||
const_iterator cbegin() const noexcept;
|
||||
const_iterator cend() const noexcept;
|
||||
const_reverse_iterator crbegin() const noexcept;
|
||||
const_reverse_iterator crend() const noexcept;
|
||||
|
||||
pointer data() noexcept;
|
||||
const_pointer data() const noexcept;
|
||||
|
||||
constexpr reference at(size_t index);
|
||||
constexpr const_reference at(size_t index) const;
|
||||
|
||||
@@ -186,7 +209,8 @@ public:
|
||||
{0, 1}};
|
||||
|
||||
constexpr mat_base() = default;
|
||||
constexpr explicit mat_base(T v);
|
||||
constexpr explicit mat_base(T d);
|
||||
constexpr explicit mat_base(const row_type& d);
|
||||
|
||||
constexpr mat_base(
|
||||
T m11, T m12,
|
||||
@@ -211,7 +235,8 @@ public:
|
||||
{0, 0, 1}};
|
||||
|
||||
constexpr mat_base() = default;
|
||||
constexpr explicit mat_base(T v);
|
||||
constexpr explicit mat_base(T d);
|
||||
constexpr explicit mat_base(const row_type& d);
|
||||
|
||||
constexpr mat_base(
|
||||
T m11, T m12, T m13,
|
||||
@@ -223,6 +248,10 @@ public:
|
||||
const row_type& row1,
|
||||
const row_type& row2);
|
||||
|
||||
constexpr mat_base(
|
||||
const mat_base<T, 2>& m,
|
||||
const vec_base<T, 2>& v);
|
||||
|
||||
constexpr explicit mat_base(const mat_base<T, 2>& other);
|
||||
constexpr explicit mat_base(const mat_base<T, 4>& other);
|
||||
};
|
||||
@@ -239,7 +268,8 @@ public:
|
||||
{0, 0, 0, 1}};
|
||||
|
||||
constexpr mat_base() = default;
|
||||
constexpr explicit mat_base(T v);
|
||||
constexpr explicit mat_base(T d);
|
||||
constexpr explicit mat_base(const row_type& d);
|
||||
|
||||
constexpr mat_base(
|
||||
T m11, T m12, T m13, T m14,
|
||||
@@ -253,6 +283,10 @@ public:
|
||||
const row_type& row2,
|
||||
const row_type& row3);
|
||||
|
||||
constexpr mat_base(
|
||||
const mat_base<T, 3>& m,
|
||||
const vec_base<T, 3>& v);
|
||||
|
||||
constexpr explicit mat_base(const mat_base<T, 2>& other);
|
||||
constexpr explicit mat_base(const mat_base<T, 3>& other);
|
||||
};
|
||||
@@ -268,10 +302,33 @@ public:
|
||||
using reference = row_type&;
|
||||
using const_reference = const row_type&;
|
||||
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
static constexpr size_t size = Size;
|
||||
|
||||
void swap(mat& other) noexcept(is_nothrow_swappable_v<T>);
|
||||
|
||||
iterator begin() noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
iterator end() noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
|
||||
reverse_iterator rbegin() noexcept;
|
||||
const_reverse_iterator rbegin() const noexcept;
|
||||
reverse_iterator rend() noexcept;
|
||||
const_reverse_iterator rend() const noexcept;
|
||||
|
||||
const_iterator cbegin() const noexcept;
|
||||
const_iterator cend() const noexcept;
|
||||
const_reverse_iterator crbegin() const noexcept;
|
||||
const_reverse_iterator crend() const noexcept;
|
||||
|
||||
pointer data() noexcept;
|
||||
const_pointer data() const noexcept;
|
||||
|
||||
constexpr reference at(size_t index);
|
||||
constexpr const_reference at(size_t index) const;
|
||||
|
||||
|
||||
@@ -66,12 +66,12 @@ namespace vmath_hpp::detail
|
||||
|
||||
template < typename T, size_t Size >
|
||||
[[nodiscard]] std::size_t hash(const vec<T, Size>& v) noexcept {
|
||||
return fold(hash_combiner{}, std::size_t{}, v);
|
||||
return fold_join(hash_combiner{}, std::size_t{}, v);
|
||||
}
|
||||
|
||||
template < typename T, size_t Size >
|
||||
[[nodiscard]] std::size_t hash(const mat<T, Size>& m) noexcept {
|
||||
return fold(hash_combiner{}, std::size_t{}, m);
|
||||
return fold_join(hash_combiner{}, std::size_t{}, m);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,12 +108,12 @@ namespace vmath_hpp
|
||||
|
||||
template < typename To, typename From, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<To, Size> cast_to(const vec<From, Size>& v) {
|
||||
return detail::map([](From x){ return cast_to<To>(x); }, v);
|
||||
return detail::map_join([](From x){ return cast_to<To>(x); }, v);
|
||||
}
|
||||
|
||||
template < typename To, typename From, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<To, Size> cast_to(const mat<From, Size>& m) {
|
||||
return detail::map([](const vec<From, Size>& v){ return cast_to<To>(v); }, m);
|
||||
return detail::map_join([](const vec<From, Size>& v){ return cast_to<To>(v); }, m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
@@ -26,10 +26,15 @@ namespace vmath_hpp::detail
|
||||
public:
|
||||
constexpr mat_base() = default;
|
||||
|
||||
constexpr explicit mat_base(T v)
|
||||
constexpr explicit mat_base(T d)
|
||||
: rows{
|
||||
row_type{v, 0},
|
||||
row_type{0, v}} {}
|
||||
row_type{d, 0},
|
||||
row_type{0, d}} {}
|
||||
|
||||
constexpr explicit mat_base(const row_type& d)
|
||||
: rows{
|
||||
row_type{d[0], 0},
|
||||
row_type{0, d[1]}} {}
|
||||
|
||||
constexpr mat_base(
|
||||
T m11, T m12,
|
||||
@@ -67,11 +72,17 @@ namespace vmath_hpp::detail
|
||||
public:
|
||||
constexpr mat_base() = default;
|
||||
|
||||
constexpr explicit mat_base(T v)
|
||||
constexpr explicit mat_base(T d)
|
||||
: rows{
|
||||
row_type{v, 0, 0},
|
||||
row_type{0, v, 0},
|
||||
row_type{0, 0, v}} {}
|
||||
row_type{d, 0, 0},
|
||||
row_type{0, d, 0},
|
||||
row_type{0, 0, d}} {}
|
||||
|
||||
constexpr explicit mat_base(const row_type& d)
|
||||
: rows{
|
||||
row_type{d[0], 0, 0},
|
||||
row_type{0, d[1], 0},
|
||||
row_type{0, 0, d[2]}} {}
|
||||
|
||||
constexpr mat_base(
|
||||
T m11, T m12, T m13,
|
||||
@@ -88,6 +99,14 @@ namespace vmath_hpp::detail
|
||||
const row_type& row2)
|
||||
: rows{row0, row1, row2} {}
|
||||
|
||||
constexpr mat_base(
|
||||
const mat_base<T, 2>& m,
|
||||
const vec_base<T, 2>& v)
|
||||
: rows{
|
||||
row_type{m.rows[0], 0},
|
||||
row_type{m.rows[1], 0},
|
||||
row_type{v, 1}} {}
|
||||
|
||||
constexpr explicit mat_base(
|
||||
const mat_base<T, 2>& other)
|
||||
: rows{
|
||||
@@ -115,12 +134,19 @@ namespace vmath_hpp::detail
|
||||
public:
|
||||
constexpr mat_base() = default;
|
||||
|
||||
constexpr explicit mat_base(T v)
|
||||
constexpr explicit mat_base(T d)
|
||||
: rows{
|
||||
row_type{v, 0, 0, 0},
|
||||
row_type{0, v, 0, 0},
|
||||
row_type{0, 0, v, 0},
|
||||
row_type{0, 0, 0, v}} {}
|
||||
row_type{d, 0, 0, 0},
|
||||
row_type{0, d, 0, 0},
|
||||
row_type{0, 0, d, 0},
|
||||
row_type{0, 0, 0, d}} {}
|
||||
|
||||
constexpr explicit mat_base(const row_type& d)
|
||||
: rows{
|
||||
row_type{d[0], 0, 0, 0},
|
||||
row_type{0, d[1], 0, 0},
|
||||
row_type{0, 0, d[2], 0},
|
||||
row_type{0, 0, 0, d[3]}} {}
|
||||
|
||||
constexpr mat_base(
|
||||
T m11, T m12, T m13, T m14,
|
||||
@@ -140,6 +166,15 @@ namespace vmath_hpp::detail
|
||||
const row_type& row3)
|
||||
: rows{row0, row1, row2, row3} {}
|
||||
|
||||
constexpr mat_base(
|
||||
const mat_base<T, 3>& m,
|
||||
const vec_base<T, 3>& v)
|
||||
: rows{
|
||||
row_type{m.rows[0], 0},
|
||||
row_type{m.rows[1], 0},
|
||||
row_type{m.rows[2], 0},
|
||||
row_type{v, 1}} {}
|
||||
|
||||
constexpr explicit mat_base(
|
||||
const mat_base<T, 2>& other)
|
||||
: rows{
|
||||
@@ -174,6 +209,11 @@ namespace vmath_hpp
|
||||
using reference = row_type&;
|
||||
using const_reference = const row_type&;
|
||||
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
static constexpr std::size_t size = Size;
|
||||
public:
|
||||
using base_type::mat_base;
|
||||
@@ -186,10 +226,33 @@ namespace vmath_hpp
|
||||
void swap(mat& other) noexcept(std::is_nothrow_swappable_v<T>) {
|
||||
for ( std::size_t i = 0; i < Size; ++i ) {
|
||||
using std::swap;
|
||||
swap((*this)[i], other[i]);
|
||||
swap(rows[i], other.rows[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] iterator begin() noexcept { return iterator(data()); }
|
||||
[[nodiscard]] const_iterator begin() const noexcept { return const_iterator(data()); }
|
||||
[[nodiscard]] iterator end() noexcept { return iterator(data() + Size); }
|
||||
[[nodiscard]] const_iterator end() const noexcept { return const_iterator(data() + Size); }
|
||||
|
||||
[[nodiscard]] reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
|
||||
[[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
|
||||
[[nodiscard]] reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
|
||||
[[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
|
||||
|
||||
[[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
|
||||
[[nodiscard]] const_iterator cend() const noexcept { return end(); }
|
||||
[[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); }
|
||||
[[nodiscard]] const_reverse_iterator crend() const noexcept { return rend(); }
|
||||
|
||||
[[nodiscard]] pointer data() noexcept {
|
||||
return &rows[0];
|
||||
}
|
||||
|
||||
[[nodiscard]] const_pointer data() const noexcept {
|
||||
return &rows[0];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr reference operator[](std::size_t index) noexcept {
|
||||
return rows[index];
|
||||
}
|
||||
@@ -212,6 +275,50 @@ namespace vmath_hpp
|
||||
return rows[index];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
// mat2
|
||||
|
||||
template < typename T >
|
||||
mat(T, T, T, T) -> mat<T, 2>;
|
||||
|
||||
template < typename T >
|
||||
mat(const vec<T, 2>&, const vec<T, 2>&) -> mat<T, 2>;
|
||||
|
||||
template < typename T >
|
||||
mat(std::initializer_list<T>, std::initializer_list<T>) -> mat<T, 2>;
|
||||
|
||||
// mat3
|
||||
|
||||
template < typename T >
|
||||
mat(T, T, T, T, T, T, T, T, T) -> mat<T, 3>;
|
||||
|
||||
template < typename T >
|
||||
mat(const vec<T, 3>&, const vec<T, 3>&, const vec<T, 3>&) -> mat<T, 3>;
|
||||
|
||||
template < typename T >
|
||||
mat(const mat<T, 2>&, const vec<T, 2>&) -> mat<T, 3>;
|
||||
|
||||
template < typename T >
|
||||
mat(std::initializer_list<T>, std::initializer_list<T>, std::initializer_list<T>) -> mat<T, 3>;
|
||||
|
||||
// mat4
|
||||
|
||||
template < typename T >
|
||||
mat(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) -> mat<T, 4>;
|
||||
|
||||
template < typename T >
|
||||
mat(const vec<T, 4>&, const vec<T, 4>&, const vec<T, 4>&, const vec<T, 4>&) -> mat<T, 4>;
|
||||
|
||||
template < typename T >
|
||||
mat(const mat<T, 3>&, const vec<T, 3>&) -> mat<T, 4>;
|
||||
|
||||
template < typename T >
|
||||
mat(std::initializer_list<T>, std::initializer_list<T>, std::initializer_list<T>, std::initializer_list<T>) -> mat<T, 4>;
|
||||
|
||||
// swap
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
void swap(mat<T, Size>& l, mat<T, Size>& r) noexcept(noexcept(l.swap(r))) {
|
||||
|
||||
@@ -14,94 +14,175 @@
|
||||
#include "vmath_vec.hpp"
|
||||
#include "vmath_vec_fun.hpp"
|
||||
|
||||
namespace vmath_hpp::detail::impl
|
||||
{
|
||||
template < typename A, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
F&& f,
|
||||
const mat<A, Size>& a,
|
||||
std::index_sequence<Is...>
|
||||
) -> mat<typename decltype(f(
|
||||
std::declval<vec<A, Size>>()))::component_type, Size>
|
||||
{
|
||||
return { f(a[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
F&& f,
|
||||
const mat<A, Size>& a,
|
||||
const mat<B, Size>& b,
|
||||
std::index_sequence<Is...>
|
||||
) -> mat<typename decltype(f(
|
||||
std::declval<vec<A, Size>>(),
|
||||
std::declval<vec<B, Size>>()))::component_type, Size>
|
||||
{
|
||||
return { f(a[Is], b[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
F&& f,
|
||||
const mat<A, Size>& a,
|
||||
const mat<B, Size>& b,
|
||||
const mat<C, Size>& c,
|
||||
std::index_sequence<Is...>
|
||||
) -> mat<typename decltype(f(
|
||||
std::declval<vec<A, Size>>(),
|
||||
std::declval<vec<B, Size>>(),
|
||||
std::declval<vec<C, Size>>()))::component_type, Size>
|
||||
{
|
||||
return { f(a[Is], b[Is], c[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join_impl(
|
||||
F&& f,
|
||||
A init,
|
||||
const mat<B, Size>& b,
|
||||
std::index_sequence<Is...>
|
||||
) -> 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 >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join_impl(
|
||||
F&& f,
|
||||
A init,
|
||||
const vec<B, Size>& b,
|
||||
const mat<C, Size>& c,
|
||||
std::index_sequence<Is...>
|
||||
) -> A {
|
||||
return ((init = f(std::move(init), b[Is], c[Is])), ...);
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join_impl(
|
||||
F&& f,
|
||||
A init,
|
||||
const mat<B, Size>& b,
|
||||
const mat<C, Size>& c,
|
||||
std::index_sequence<Is...>
|
||||
) -> A {
|
||||
return ((init = f(std::move(init), b[Is], c[Is])), ...);
|
||||
}
|
||||
|
||||
template < typename A, std::size_t Size, typename F, std::size_t I, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold1_join_impl(
|
||||
F&& f,
|
||||
const mat<A, Size>& a,
|
||||
std::index_sequence<I, Is...>
|
||||
) -> vec<A, Size> {
|
||||
vec<A, Size> init = a[I];
|
||||
return ((init = f(std::move(init), a[Is])), ...);
|
||||
}
|
||||
}
|
||||
|
||||
namespace vmath_hpp::detail
|
||||
{
|
||||
namespace impl
|
||||
{
|
||||
template < typename A, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_impl(F&& f, const mat<A, Size>& a, std::index_sequence<Is...>)
|
||||
-> mat<typename std::invoke_result_t<F, vec<A, Size>>::value_type, Size>
|
||||
{
|
||||
return { f(a[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto zip_impl(F&& f, const mat<A, Size>& a, const mat<B, Size>& b, std::index_sequence<Is...>)
|
||||
-> mat<typename std::invoke_result_t<F, vec<A, Size>, vec<B, Size>>::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 >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto zip_impl(F&& f, const mat<A, Size>& a, const mat<B, Size>& b, const mat<C, Size>& c, std::index_sequence<Is...>)
|
||||
-> mat<typename std::invoke_result_t<F, vec<A, Size>, vec<B, Size>, vec<C, Size>>::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 >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
A fold_impl(F&& f, A init, const mat<B, Size>& b, std::index_sequence<Is...>) {
|
||||
return ((init = f(std::move(init), b[Is])), ...);
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
A fold_impl(F&& f, A init, const mat<B, Size>& b, const mat<C, Size>& c, std::index_sequence<Is...>) {
|
||||
return ((init = f(std::move(init), b[Is], c[Is])), ...);
|
||||
}
|
||||
|
||||
template < typename A, std::size_t Size, typename F, std::size_t I, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
vec<A, Size> fold1_impl(F&& f, const mat<A, Size>& a, std::index_sequence<I, Is...>) {
|
||||
vec<A, Size> init = a[I];
|
||||
return ((init = f(std::move(init), a[Is])), ...);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename A, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map(F&& f, const mat<A, Size>& a)
|
||||
-> mat<typename std::invoke_result_t<F, vec<A, Size>>::value_type, Size>
|
||||
{
|
||||
return impl::map_impl(std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const mat<A, Size>& a
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto zip(F&& f, const mat<A, Size>& a, const mat<B, Size>& b)
|
||||
-> mat<typename std::invoke_result_t<F, vec<A, Size>, vec<B, Size>>::value_type, Size>
|
||||
{
|
||||
return impl::zip_impl(std::forward<F>(f), a, b, std::make_index_sequence<Size>{});
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const mat<A, Size>& a,
|
||||
const mat<B, Size>& b
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, b, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto zip(F&& f, const mat<A, Size>& a, const mat<B, Size>& b, const mat<C, Size>& c)
|
||||
-> mat<typename std::invoke_result_t<F, vec<A, Size>, vec<B, Size>, vec<C, Size>>::value_type, Size>
|
||||
{
|
||||
return impl::zip_impl(std::forward<F>(f), a, b, c, std::make_index_sequence<Size>{});
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const mat<A, Size>& a,
|
||||
const mat<B, Size>& b,
|
||||
const mat<C, Size>& c
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, b, c, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
A fold(F&& f, A init, const mat<B, Size>& b) {
|
||||
return impl::fold_impl(std::forward<F>(f), std::move(init), b, std::make_index_sequence<Size>{});
|
||||
auto fold_join(
|
||||
F&& f,
|
||||
A init,
|
||||
const mat<B, Size>& b
|
||||
) {
|
||||
return impl::fold_join_impl(
|
||||
std::forward<F>(f), std::move(init), b, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
A fold(F&& f, A init, const mat<B, Size>& b, const mat<C, Size>& c) {
|
||||
return impl::fold_impl(std::forward<F>(f), std::move(init), b, c, std::make_index_sequence<Size>{});
|
||||
auto fold_join(
|
||||
F&& f,
|
||||
A init,
|
||||
const vec<B, Size>& b,
|
||||
const mat<C, Size>& c
|
||||
) {
|
||||
return impl::fold_join_impl(
|
||||
std::forward<F>(f), std::move(init), b, c, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join(
|
||||
F&& f,
|
||||
A init,
|
||||
const mat<B, Size>& b,
|
||||
const mat<C, Size>& c
|
||||
) {
|
||||
return impl::fold_join_impl(
|
||||
std::forward<F>(f), std::move(init), b, c, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
vec<A, Size> fold1(F&& f, const mat<A, Size>& a) {
|
||||
return impl::fold1_impl(std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
auto fold1_join(
|
||||
F&& f,
|
||||
const mat<A, Size>& a
|
||||
) {
|
||||
return impl::fold1_join_impl(
|
||||
std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,24 +196,24 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator-(const mat<T, Size>& xs) {
|
||||
return map([](const vec<T, Size>& x){ return -x; }, xs);
|
||||
return map_join([](const vec<T, Size>& x){ return -x; }, xs);
|
||||
}
|
||||
|
||||
// operator+
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator+(const mat<T, Size>& xs, T y) {
|
||||
return map([y](const vec<T, Size>& x){ return x + y; }, xs);
|
||||
return map_join([y](const vec<T, Size>& x){ return x + y; }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator+(T x, const mat<T, Size>& ys) {
|
||||
return map([x](const vec<T, Size>& y){ return x + y; }, ys);
|
||||
return map_join([x](const vec<T, Size>& y){ return x + y; }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator+(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return zip([](const vec<T, Size>& x, const vec<T, Size>& y){ return x + y; }, xs, ys);
|
||||
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return x + y; }, xs, ys);
|
||||
}
|
||||
|
||||
// operator+=
|
||||
@@ -151,17 +232,17 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator-(const mat<T, Size>& xs, T y) {
|
||||
return map([y](const vec<T, Size>& x){ return x - y; }, xs);
|
||||
return map_join([y](const vec<T, Size>& x){ return x - y; }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator-(T x, const mat<T, Size>& ys) {
|
||||
return map([x](const vec<T, Size>& y){ return x - y; }, ys);
|
||||
return map_join([x](const vec<T, Size>& y){ return x - y; }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator-(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return zip([](const vec<T, Size>& x, const vec<T, Size>& y){ return x - y; }, xs, ys);
|
||||
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return x - y; }, xs, ys);
|
||||
}
|
||||
|
||||
// operator-=
|
||||
@@ -180,86 +261,26 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator*(const mat<T, Size>& xs, T y) {
|
||||
return map([y](const vec<T, Size>& x){ return x * y; }, xs);
|
||||
return map_join([y](const vec<T, Size>& x){ return x * y; }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator*(T x, const mat<T, Size>& ys) {
|
||||
return map([x](const vec<T, Size>& y){ return x * y; }, ys);
|
||||
return map_join([x](const vec<T, Size>& y){ return x * y; }, ys);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr vec<T, 2> operator*(const vec<T, 2>& xs, const mat<T, 2>& 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, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator*(const vec<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return fold_join([](const vec<T, Size>& acc, T x, const vec<T, Size>& y){
|
||||
return acc + x * y;
|
||||
}, vec<T, Size>{}, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] constexpr mat<T, 2> operator*(const mat<T, 2>& xs, const mat<T, 2>& 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 >
|
||||
[[nodiscard]] constexpr vec<T, 3> operator*(const vec<T, 3>& xs, const mat<T, 3>& 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 >
|
||||
[[nodiscard]] constexpr mat<T, 3> operator*(const mat<T, 3>& xs, const mat<T, 3>& 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 >
|
||||
[[nodiscard]] constexpr vec<T, 4> operator*(const vec<T, 4>& xs, const mat<T, 4>& 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 >
|
||||
[[nodiscard]] constexpr mat<T, 4> operator*(const mat<T, 4>& xs, const mat<T, 4>& 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]};
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator*(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return map_join([&ys](const vec<T, Size>& x){
|
||||
return x * ys;
|
||||
}, xs);
|
||||
}
|
||||
|
||||
// operator*=
|
||||
@@ -283,17 +304,17 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator/(const mat<T, Size>& xs, T y) {
|
||||
return map([y](const vec<T, Size>& x){ return x / y; }, xs);
|
||||
return map_join([y](const vec<T, Size>& x){ return x / y; }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator/(T x, const mat<T, Size>& ys) {
|
||||
return map([x](const vec<T, Size>& y){ return x / y; }, ys);
|
||||
return map_join([x](const vec<T, Size>& y){ return x / y; }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr mat<T, Size> operator/(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return zip([](const vec<T, Size>& x, const vec<T, Size>& y){ return x / y; }, xs, ys);
|
||||
return map_join([](const vec<T, Size>& x, const vec<T, Size>& y){ return x / y; }, xs, ys);
|
||||
}
|
||||
|
||||
// operator/=
|
||||
@@ -312,14 +333,14 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr bool operator==(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return fold([](bool acc, const vec<T, Size>& x, const vec<T, Size>& y){
|
||||
return fold_join([](bool acc, const vec<T, Size>& x, const vec<T, Size>& y){
|
||||
return acc && (x == y);
|
||||
}, true, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr bool operator!=(const mat<T, Size>& xs, const mat<T, Size>& ys) {
|
||||
return fold([](bool acc, const vec<T, Size>& x, const vec<T, Size>& y){
|
||||
return fold_join([](bool acc, const vec<T, Size>& x, const vec<T, Size>& y){
|
||||
return acc || (x != y);
|
||||
}, false, xs, ys);
|
||||
}
|
||||
|
||||
@@ -151,13 +151,18 @@ namespace vmath_hpp
|
||||
using self_type = vec;
|
||||
using base_type = detail::vec_base<T, Size>;
|
||||
public:
|
||||
using value_type = T;
|
||||
using component_type = T;
|
||||
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using pointer = component_type*;
|
||||
using const_pointer = const component_type*;
|
||||
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using reference = component_type&;
|
||||
using const_reference = const component_type&;
|
||||
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
static constexpr std::size_t size = Size;
|
||||
public:
|
||||
@@ -175,6 +180,29 @@ namespace vmath_hpp
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] iterator begin() noexcept { return iterator(data()); }
|
||||
[[nodiscard]] const_iterator begin() const noexcept { return const_iterator(data()); }
|
||||
[[nodiscard]] iterator end() noexcept { return iterator(data() + Size); }
|
||||
[[nodiscard]] const_iterator end() const noexcept { return const_iterator(data() + Size); }
|
||||
|
||||
[[nodiscard]] reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
|
||||
[[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
|
||||
[[nodiscard]] reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
|
||||
[[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
|
||||
|
||||
[[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
|
||||
[[nodiscard]] const_iterator cend() const noexcept { return end(); }
|
||||
[[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); }
|
||||
[[nodiscard]] const_reverse_iterator crend() const noexcept { return rend(); }
|
||||
|
||||
[[nodiscard]] pointer data() noexcept {
|
||||
return &(*this)[0];
|
||||
}
|
||||
|
||||
[[nodiscard]] const_pointer data() const noexcept {
|
||||
return &(*this)[0];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr reference at(std::size_t index) {
|
||||
if ( index >= Size ) {
|
||||
throw std::out_of_range("vec::at");
|
||||
@@ -189,6 +217,50 @@ namespace vmath_hpp
|
||||
return (*this)[index];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
// vec2
|
||||
|
||||
template < typename T >
|
||||
vec(T, T) -> vec<T, 2>;
|
||||
|
||||
// vec3
|
||||
|
||||
template < typename T >
|
||||
vec(T, T, T) -> vec<T, 3>;
|
||||
|
||||
template < typename T >
|
||||
vec(const vec<T, 2>&, T) -> vec<T, 3>;
|
||||
|
||||
template < typename T >
|
||||
vec(T, const vec<T, 2>&) -> vec<T, 3>;
|
||||
|
||||
// vec4
|
||||
|
||||
template < typename T >
|
||||
vec(T, T, T, T) -> vec<T, 4>;
|
||||
|
||||
template < typename T >
|
||||
vec(const vec<T, 2>&, T, T) -> vec<T, 4>;
|
||||
|
||||
template < typename T >
|
||||
vec(T, const vec<T, 2>&, T) -> vec<T, 4>;
|
||||
|
||||
template < typename T >
|
||||
vec(T, T, const vec<T, 2>&) -> vec<T, 4>;
|
||||
|
||||
template < typename T >
|
||||
vec(const vec<T, 2>&, const vec<T, 2>&) -> vec<T, 4>;
|
||||
|
||||
template < typename T >
|
||||
vec(const vec<T, 3>&, T) -> vec<T, 4>;
|
||||
|
||||
template < typename T >
|
||||
vec(T, const vec<T, 3>&) -> vec<T, 4>;
|
||||
|
||||
// swap
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
void swap(vec<T, Size>& l, vec<T, Size>& r) noexcept(noexcept(l.swap(r))) {
|
||||
|
||||
@@ -11,94 +11,151 @@
|
||||
#include "vmath_fun.hpp"
|
||||
#include "vmath_vec.hpp"
|
||||
|
||||
namespace vmath_hpp::detail::impl
|
||||
{
|
||||
template < typename A, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
std::index_sequence<Is...>
|
||||
) -> vec<decltype(f(
|
||||
std::declval<A>())), Size>
|
||||
{
|
||||
return { f(a[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
const vec<B, Size>& b,
|
||||
std::index_sequence<Is...>
|
||||
) -> vec<decltype(f(
|
||||
std::declval<A>(),
|
||||
std::declval<B>())), Size>
|
||||
{
|
||||
return { f(a[Is], b[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_join_impl(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
const vec<B, Size>& b,
|
||||
const vec<C, Size>& c,
|
||||
std::index_sequence<Is...>
|
||||
) -> vec<decltype(f(
|
||||
std::declval<A>(),
|
||||
std::declval<B>(),
|
||||
std::declval<C>())), Size>
|
||||
{
|
||||
return { f(a[Is], b[Is], c[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join_impl(
|
||||
F&& f,
|
||||
A init,
|
||||
const vec<B, Size>& b,
|
||||
std::index_sequence<Is...>
|
||||
) -> 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 >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold_join_impl(
|
||||
F&& f,
|
||||
A init,
|
||||
const vec<B, Size>& b,
|
||||
const vec<C, Size>& c,
|
||||
std::index_sequence<Is...>
|
||||
) -> A {
|
||||
return ((init = f(std::move(init), b[Is], c[Is])), ...);
|
||||
}
|
||||
|
||||
template < typename A, std::size_t Size, typename F, std::size_t I, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto fold1_join_impl(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
std::index_sequence<I, Is...>
|
||||
) -> A {
|
||||
A init = a[I];
|
||||
return ((init = f(std::move(init), a[Is])), ...);
|
||||
}
|
||||
}
|
||||
|
||||
namespace vmath_hpp::detail
|
||||
{
|
||||
namespace impl
|
||||
{
|
||||
template < typename A, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map_impl(F&& f, const vec<A, Size>& a, std::index_sequence<Is...>)
|
||||
-> vec<std::invoke_result_t<F, A>, Size>
|
||||
{
|
||||
return { f(a[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto zip_impl(F&& f, const vec<A, Size>& a, const vec<B, Size>& b, std::index_sequence<Is...>)
|
||||
-> vec<std::invoke_result_t<F, A, B>, Size>
|
||||
{
|
||||
return { f(a[Is], b[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto zip_impl(F&& f, const vec<A, Size>& a, const vec<B, Size>& b, const vec<C, Size>& c, std::index_sequence<Is...>)
|
||||
-> vec<std::invoke_result_t<F, A, B, C>, Size>
|
||||
{
|
||||
return { f(a[Is], b[Is], c[Is])... };
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
A fold_impl(F&& f, A init, const vec<B, Size>& b, std::index_sequence<Is...>) {
|
||||
return ((init = f(std::move(init), b[Is])), ...);
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
A fold_impl(F&& f, A init, const vec<B, Size>& b, const vec<C, Size>& c, std::index_sequence<Is...>) {
|
||||
return ((init = f(std::move(init), b[Is], c[Is])), ...);
|
||||
}
|
||||
|
||||
template < typename A, std::size_t Size, typename F, std::size_t I, std::size_t... Is >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
A fold1_impl(F&& f, const vec<A, Size>& a, std::index_sequence<I, Is...>) {
|
||||
A init = a[I];
|
||||
return ((init = f(std::move(init), a[Is])), ...);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename A, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto map(F&& f, const vec<A, Size>& a)
|
||||
-> vec<std::invoke_result_t<F, A>, Size>
|
||||
{
|
||||
return impl::map_impl(std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const vec<A, Size>& a
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto zip(F&& f, const vec<A, Size>& a, const vec<B, Size>& b)
|
||||
-> vec<std::invoke_result_t<F, A, B>, Size>
|
||||
{
|
||||
return impl::zip_impl(std::forward<F>(f), a, b, std::make_index_sequence<Size>{});
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
const vec<B, Size>& b
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, b, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
auto zip(F&& f, const vec<A, Size>& a, const vec<B, Size>& b, const vec<C, Size>& c)
|
||||
-> vec<std::invoke_result_t<F, A, B, C>, Size>
|
||||
{
|
||||
return impl::zip_impl(std::forward<F>(f), a, b, c, std::make_index_sequence<Size>{});
|
||||
auto map_join(
|
||||
F&& f,
|
||||
const vec<A, Size>& a,
|
||||
const vec<B, Size>& b,
|
||||
const vec<C, Size>& c
|
||||
) {
|
||||
return impl::map_join_impl(
|
||||
std::forward<F>(f), a, b, c, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
A fold(F&& f, A init, const vec<B, Size>& b) {
|
||||
return impl::fold_impl(std::forward<F>(f), std::move(init), b, std::make_index_sequence<Size>{});
|
||||
auto fold_join(
|
||||
F&& f,
|
||||
A init,
|
||||
const vec<B, Size>& b
|
||||
) {
|
||||
return impl::fold_join_impl(
|
||||
std::forward<F>(f), std::move(init), b, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, typename B, typename C, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
A fold(F&& f, A init, const vec<B, Size>& b, const vec<C, Size>& c) {
|
||||
return impl::fold_impl(std::forward<F>(f), std::move(init), b, c, std::make_index_sequence<Size>{});
|
||||
auto fold_join(
|
||||
F&& f,
|
||||
A init,
|
||||
const vec<B, Size>& b,
|
||||
const vec<C, Size>& c
|
||||
) {
|
||||
return impl::fold_join_impl(
|
||||
std::forward<F>(f), std::move(init), b, c, std::make_index_sequence<Size>{});
|
||||
}
|
||||
|
||||
template < typename A, std::size_t Size, typename F >
|
||||
[[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE
|
||||
A fold1(F&& f, const vec<A, Size>& a) {
|
||||
return impl::fold1_impl(std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
auto fold1_join(
|
||||
F&& f,
|
||||
const vec<A, Size>& a
|
||||
) {
|
||||
return impl::fold1_join_impl(
|
||||
std::forward<F>(f), a, std::make_index_sequence<Size>{});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,24 +169,24 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator-(const vec<T, Size>& xs) {
|
||||
return map([](T x){ return -x; }, xs);
|
||||
return map_join([](T x){ return -x; }, xs);
|
||||
}
|
||||
|
||||
// operator+
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator+(const vec<T, Size>& xs, T y) {
|
||||
return map([y](T x){ return x + y; }, xs);
|
||||
return map_join([y](T x){ return x + y; }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator+(T x, const vec<T, Size>& ys) {
|
||||
return map([x](T y){ return x + y; }, ys);
|
||||
return map_join([x](T y){ return x + y; }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator+(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y){ return x + y; }, xs, ys);
|
||||
return map_join([](T x, T y){ return x + y; }, xs, ys);
|
||||
}
|
||||
|
||||
// operator+=
|
||||
@@ -148,17 +205,17 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator-(const vec<T, Size>& xs, T y) {
|
||||
return map([y](T x){ return x - y; }, xs);
|
||||
return map_join([y](T x){ return x - y; }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator-(T x, const vec<T, Size>& ys) {
|
||||
return map([x](T y){ return x - y; }, ys);
|
||||
return map_join([x](T y){ return x - y; }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator-(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y){ return x - y; }, xs, ys);
|
||||
return map_join([](T x, T y){ return x - y; }, xs, ys);
|
||||
}
|
||||
|
||||
// operator-=
|
||||
@@ -177,17 +234,17 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator*(const vec<T, Size>& xs, T y) {
|
||||
return map([y](T x){ return x * y; }, xs);
|
||||
return map_join([y](T x){ return x * y; }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator*(T x, const vec<T, Size>& ys) {
|
||||
return map([x](T y){ return x * y; }, ys);
|
||||
return map_join([x](T y){ return x * y; }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator*(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y){ return x * y; }, xs, ys);
|
||||
return map_join([](T x, T y){ return x * y; }, xs, ys);
|
||||
}
|
||||
|
||||
// operator*=
|
||||
@@ -206,17 +263,17 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator/(const vec<T, Size>& xs, T y) {
|
||||
return map([y](T x){ return x / y; }, xs);
|
||||
return map_join([y](T x){ return x / y; }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator/(T x, const vec<T, Size>& ys) {
|
||||
return map([x](T y){ return x / y; }, ys);
|
||||
return map_join([x](T y){ return x / y; }, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> operator/(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y){ return x / y; }, xs, ys);
|
||||
return map_join([](T x, T y){ return x / y; }, xs, ys);
|
||||
}
|
||||
|
||||
// operator/=
|
||||
@@ -235,14 +292,14 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr bool operator==(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return fold([](bool acc, T x, T y){
|
||||
return fold_join([](bool acc, T x, T y){
|
||||
return acc && (x == y);
|
||||
}, true, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr bool operator!=(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return fold([](bool acc, T x, T y){
|
||||
return fold_join([](bool acc, T x, T y){
|
||||
return acc || (x != y);
|
||||
}, false, xs, ys);
|
||||
}
|
||||
@@ -271,77 +328,77 @@ namespace vmath_hpp
|
||||
{
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> radians(const vec<T, Size>& degrees) {
|
||||
return map([](T x) { return radians(x); }, degrees);
|
||||
return map_join([](T x) { return radians(x); }, degrees);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> degrees(const vec<T, Size>& radians) {
|
||||
return map([](T x) { return degrees(x); }, radians);
|
||||
return map_join([](T x) { return degrees(x); }, radians);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> sin(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return sin(x); }, xs);
|
||||
return map_join([](T x) { return sin(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> cos(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return cos(x); }, xs);
|
||||
return map_join([](T x) { return cos(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> tan(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return tan(x); }, xs);
|
||||
return map_join([](T x) { return tan(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> asin(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return asin(x); }, xs);
|
||||
return map_join([](T x) { return asin(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> acos(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return acos(x); }, xs);
|
||||
return map_join([](T x) { return acos(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> atan(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return atan(x); }, xs);
|
||||
return map_join([](T x) { return atan(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> atan2(const vec<T, Size>& ys, const vec<T, Size>& xs) {
|
||||
return zip([](T y, T x) { return atan2(y, x); }, ys, xs);
|
||||
return map_join([](T y, T x) { return atan2(y, x); }, ys, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> sinh(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return sinh(x); }, xs);
|
||||
return map_join([](T x) { return sinh(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> cosh(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return cosh(x); }, xs);
|
||||
return map_join([](T x) { return cosh(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> tanh(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return tanh(x); }, xs);
|
||||
return map_join([](T x) { return tanh(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> asinh(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return asinh(x); }, xs);
|
||||
return map_join([](T x) { return asinh(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> acosh(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return acosh(x); }, xs);
|
||||
return map_join([](T x) { return acosh(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> atanh(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return atanh(x); }, xs);
|
||||
return map_join([](T x) { return atanh(x); }, xs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,37 +410,37 @@ namespace vmath_hpp
|
||||
{
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> pow(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y) { return pow(x, y); }, xs, ys);
|
||||
return map_join([](T x, T y) { return pow(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> exp(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return exp(x); }, xs);
|
||||
return map_join([](T x) { return exp(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> log(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return log(x); }, xs);
|
||||
return map_join([](T x) { return log(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> exp2(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return exp2(x); }, xs);
|
||||
return map_join([](T x) { return exp2(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> log2(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return log2(x); }, xs);
|
||||
return map_join([](T x) { return log2(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> sqrt(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return sqrt(x); }, xs);
|
||||
return map_join([](T x) { return sqrt(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> rsqrt(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return rsqrt(x); }, xs);
|
||||
return map_join([](T x) { return rsqrt(x); }, xs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,52 +452,52 @@ namespace vmath_hpp
|
||||
{
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> abs(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return abs(x); }, xs);
|
||||
return map_join([](T x) { return abs(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> sign(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return sign(x); }, xs);
|
||||
return map_join([](T x) { return sign(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> reciprocal(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return reciprocal(x); }, xs);
|
||||
return map_join([](T x) { return reciprocal(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> floor(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return floor(x); }, xs);
|
||||
return map_join([](T x) { return floor(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> trunc(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return trunc(x); }, xs);
|
||||
return map_join([](T x) { return trunc(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> round(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return round(x); }, xs);
|
||||
return map_join([](T x) { return round(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> ceil(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return ceil(x); }, xs);
|
||||
return map_join([](T x) { return ceil(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> fract(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return fract(x); }, xs);
|
||||
return map_join([](T x) { return fract(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> fmod(const vec<T, Size>& xs, T y) {
|
||||
return map([y](T x) { return fmod(x, y); }, xs);
|
||||
return map_join([y](T x) { return fmod(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> fmod(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y) { return fmod(x, y); }, xs, ys);
|
||||
return map_join([](T x, T y) { return fmod(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
namespace impl
|
||||
@@ -459,97 +516,97 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr T min(const vec<T, Size>& xs) {
|
||||
return fold1([](T acc, T x){ return min(acc, x); }, xs);
|
||||
return fold1_join([](T acc, T x){ return min(acc, x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> min(const vec<T, Size>& xs, T y) {
|
||||
return map([y](T x) { return min(x, y); }, xs);
|
||||
return map_join([y](T x) { return min(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> min(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y) { return min(x, y); }, xs, ys);
|
||||
return map_join([](T x, T y) { return min(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr T max(const vec<T, Size>& xs) {
|
||||
return fold1([](T acc, T x){ return max(acc, x); }, xs);
|
||||
return fold1_join([](T acc, T x){ return max(acc, x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> max(const vec<T, Size>& xs, T y) {
|
||||
return map([y](T x) { return max(x, y); }, xs);
|
||||
return map_join([y](T x) { return max(x, y); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> max(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y) { return max(x, y); }, xs, ys);
|
||||
return map_join([](T x, T y) { return max(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> clamp(const vec<T, Size>& xs, T min_x, T max_x) {
|
||||
return map([min_x, max_x](T x) { return clamp(x, min_x, max_x); }, xs);
|
||||
return map_join([min_x, max_x](T x) { return clamp(x, min_x, max_x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> clamp(const vec<T, Size>& xs, const vec<T, Size>& min_xs, const vec<T, Size>& max_xs) {
|
||||
return zip([](T x, T min_x, T max_x) { return clamp(x, min_x, max_x); }, xs, min_xs, max_xs);
|
||||
return map_join([](T x, T min_x, T max_x) { return clamp(x, min_x, max_x); }, xs, min_xs, max_xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> saturate(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return saturate(x); }, xs);
|
||||
return map_join([](T x) { return saturate(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> lerp(const vec<T, Size>& xs, const vec<T, Size>& ys, T a) {
|
||||
return zip([a](T x, T y) { return lerp(x, y, a); }, xs, ys);
|
||||
return map_join([a](T x, T y) { return lerp(x, y, a); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> lerp(const vec<T, Size>& xs, const vec<T, Size>& ys, const vec<T, Size>& as) {
|
||||
return zip([](T x, T y, T a) { return lerp(x, y, a); }, xs, ys, as);
|
||||
return map_join([](T x, T y, T a) { return lerp(x, y, a); }, xs, ys, as);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> step(T edge, const vec<T, Size>& xs) {
|
||||
return map([edge](T x) { return step(edge, x); }, xs);
|
||||
return map_join([edge](T x) { return step(edge, x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> step(const vec<T, Size>& edges, const vec<T, Size>& xs) {
|
||||
return zip([](T edge, T x) { return step(edge, x); }, edges, xs);
|
||||
return map_join([](T edge, T x) { return step(edge, x); }, edges, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> smoothstep(T edge0, T edge1, const vec<T, Size>& xs) {
|
||||
return map([edge0, edge1](T x) { return smoothstep(edge0, edge1, x); }, xs);
|
||||
return map_join([edge0, edge1](T x) { return smoothstep(edge0, edge1, x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<T, Size> smoothstep(const vec<T, Size>& edges0, const vec<T, Size>& edges1, const vec<T, Size>& xs) {
|
||||
return zip([](T edge0, T edge1, T x) { return smoothstep(edge0, edge1, x); }, edges0, edges1, xs);
|
||||
return map_join([](T edge0, T edge1, T x) { return smoothstep(edge0, edge1, x); }, edges0, edges1, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<bool, Size> isnan(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return isnan(x); }, xs);
|
||||
return map_join([](T x) { return isnan(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<bool, Size> isinf(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return isinf(x); }, xs);
|
||||
return map_join([](T x) { return isinf(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<bool, Size> isfinite(const vec<T, Size>& xs) {
|
||||
return map([](T x) { return isfinite(x); }, xs);
|
||||
return map_join([](T x) { return isfinite(x); }, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> fma(const vec<T, Size>& as, const vec<T, Size>& bs, const vec<T, Size>& cs) {
|
||||
return zip([](T a, T b, T c) { return fma(a, b, c); }, as, bs, cs);
|
||||
return map_join([](T a, T b, T c) { return fma(a, b, c); }, as, bs, cs);
|
||||
}
|
||||
|
||||
namespace impl
|
||||
@@ -568,7 +625,7 @@ namespace vmath_hpp
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] vec<T, Size> ldexp(const vec<T, Size>& xs, const vec<int, Size>& exps) {
|
||||
return zip([](T x, int exp) { return ldexp(x, exp); }, xs, exps);
|
||||
return map_join([](T x, int exp) { return ldexp(x, exp); }, xs, exps);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,7 +637,7 @@ namespace vmath_hpp
|
||||
{
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr T dot(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return fold([](T acc, T x, T y){
|
||||
return fold_join([](T acc, T x, T y){
|
||||
return acc + (x * y);
|
||||
}, T(0), xs, ys);
|
||||
}
|
||||
@@ -649,51 +706,51 @@ namespace vmath_hpp
|
||||
{
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> less(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y){ return less(x, y); }, xs, ys);
|
||||
return map_join([](T x, T y){ return less(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> less_equal(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y){ return less_equal(x, y); }, xs, ys);
|
||||
return map_join([](T x, T y){ return less_equal(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> greater(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y){ return greater(x, y); }, xs, ys);
|
||||
return map_join([](T x, T y){ return greater(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> greater_equal(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y){ return greater_equal(x, y); }, xs, ys);
|
||||
return map_join([](T x, T y){ return greater_equal(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y){ return equal_to(x, y); }, xs, ys);
|
||||
return map_join([](T x, T y){ return equal_to(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys, T epsilon) {
|
||||
return zip([epsilon](T x, T y){ return equal_to(x, y, epsilon); }, xs, ys);
|
||||
return map_join([epsilon](T x, T y){ return equal_to(x, y, epsilon); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> not_equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys) {
|
||||
return zip([](T x, T y){ return not_equal_to(x, y); }, xs, ys);
|
||||
return map_join([](T x, T y){ return not_equal_to(x, y); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr vec<bool, Size> not_equal_to(const vec<T, Size>& xs, const vec<T, Size>& ys, T epsilon) {
|
||||
return zip([epsilon](T x, T y){ return not_equal_to(x, y, epsilon); }, xs, ys);
|
||||
return map_join([epsilon](T x, T y){ return not_equal_to(x, y, epsilon); }, xs, ys);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr bool any(const vec<T, Size>& xs) {
|
||||
return fold([](bool acc, T x){ return acc || any(x); }, false, xs);
|
||||
return fold_join([](bool acc, T x){ return acc || any(x); }, false, xs);
|
||||
}
|
||||
|
||||
template < typename T, std::size_t Size >
|
||||
[[nodiscard]] constexpr bool all(const vec<T, Size>& xs) {
|
||||
return fold([](bool acc, T x){ return acc && all(x); }, true, xs);
|
||||
return fold_join([](bool acc, T x){ return acc && all(x); }, true, xs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ TEST_CASE("vmath/ext") {
|
||||
{
|
||||
constexpr auto v = cast_to<int>(float2{1.5f});
|
||||
STATIC_REQUIRE(v == int2(1));
|
||||
STATIC_REQUIRE(std::is_same_v<decltype(v)::value_type, int>);
|
||||
STATIC_REQUIRE(std::is_same_v<decltype(v)::component_type, int>);
|
||||
}
|
||||
{
|
||||
constexpr auto m = cast_to<int>(float2x2{1.5f});
|
||||
|
||||
@@ -32,27 +32,27 @@ namespace
|
||||
|
||||
TEST_CASE("vmath/mat_fun") {
|
||||
SUBCASE("detail") {
|
||||
STATIC_REQUIRE(map([](const int2& x){
|
||||
STATIC_REQUIRE(map_join([](const int2& x){
|
||||
return x * 2;
|
||||
}, int2x2{}) == int2x2(2,0,0,2));
|
||||
|
||||
STATIC_REQUIRE(zip([](const int2& x, const int2& y){
|
||||
STATIC_REQUIRE(map_join([](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){
|
||||
STATIC_REQUIRE(map_join([](const int2& x, const int2& y, const int2& z){
|
||||
return x + y + z;
|
||||
}, int2x2{}, int2x2{}, int2x2{}) == int2x2(3,0,0,3));
|
||||
|
||||
STATIC_REQUIRE(fold([](int acc, const int2& x){
|
||||
STATIC_REQUIRE(fold_join([](int acc, const int2& x){
|
||||
return acc + x.x;
|
||||
}, 0, int2x2{}) == 1);
|
||||
|
||||
STATIC_REQUIRE(fold([](int acc, const int2& x, const int2& y){
|
||||
STATIC_REQUIRE(fold_join([](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){
|
||||
STATIC_REQUIRE(fold1_join([](const int2& acc, const int2& x){
|
||||
return acc + x;
|
||||
}, int2x2{}) == int2(1,1));
|
||||
}
|
||||
|
||||
@@ -24,6 +24,22 @@ TEST_CASE("vmath/mat") {
|
||||
STATIC_REQUIRE(sizeof(int4x4{}) == sizeof(int) * 4 * 4);
|
||||
}
|
||||
|
||||
SUBCASE("guides") {
|
||||
STATIC_REQUIRE(mat{1,2,3,4}.size == 2);
|
||||
STATIC_REQUIRE(mat{{1,2},{3,4}}.size == 2);
|
||||
STATIC_REQUIRE(mat{vec{1,2},vec{3,4}}.size == 2);
|
||||
|
||||
STATIC_REQUIRE(mat{1,2,3,4,5,6,7,8,9}.size == 3);
|
||||
STATIC_REQUIRE(mat{{1,2,3},{4,5,6},{7,8,9}}.size == 3);
|
||||
STATIC_REQUIRE(mat{vec{1,2,3},vec{4,5,6},vec{7,8,9}}.size == 3);
|
||||
STATIC_REQUIRE(mat{mat{1,2,3,4},vec{5,6}}.size == 3);
|
||||
|
||||
STATIC_REQUIRE(mat{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}.size == 4);
|
||||
STATIC_REQUIRE(mat{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}}.size == 4);
|
||||
STATIC_REQUIRE(mat{vec{1,2,3,4},vec{5,6,7,8},vec{9,10,11,12},vec{13,14,15,16}}.size == 4);
|
||||
STATIC_REQUIRE(mat{mat{1,2,3,4,5,6,7,8,9},vec{5,6,7}}.size == 4);
|
||||
}
|
||||
|
||||
SUBCASE("ctors") {
|
||||
{
|
||||
STATIC_REQUIRE(int2x2()[0] == int2(1,0));
|
||||
@@ -48,6 +64,7 @@ TEST_CASE("vmath/mat") {
|
||||
{
|
||||
STATIC_REQUIRE(int2x2() == int2x2(1,0,0,1));
|
||||
STATIC_REQUIRE(int2x2(2) == int2x2(2,0,0,2));
|
||||
STATIC_REQUIRE(int2x2(int2{2,3}) == int2x2(2,0,0,3));
|
||||
STATIC_REQUIRE(int2x2(1,2,3,4) == int2x2(1,2,3,4));
|
||||
STATIC_REQUIRE(int2x2({1,2},{3,4}) == int2x2(1,2,3,4));
|
||||
STATIC_REQUIRE(int2x2(int2x2({1,2},{3,4})) == int2x2(1,2,3,4));
|
||||
@@ -56,16 +73,20 @@ TEST_CASE("vmath/mat") {
|
||||
|
||||
STATIC_REQUIRE(int3x3() == int3x3(1,0,0,0,1,0,0,0,1));
|
||||
STATIC_REQUIRE(int3x3(2) == int3x3(2,0,0,0,2,0,0,0,2));
|
||||
STATIC_REQUIRE(int3x3(int3{2,3,4}) == int3x3(2,0,0,0,3,0,0,0,4));
|
||||
STATIC_REQUIRE(int3x3(1,2,3,4,5,6,7,8,9) == int3x3(1,2,3,4,5,6,7,8,9));
|
||||
STATIC_REQUIRE(int3x3({1,2,3},{4,5,6},{7,8,9}) == int3x3(1,2,3,4,5,6,7,8,9));
|
||||
STATIC_REQUIRE(int3x3(int2x2({1,2},{3,4}),int2{5,6}) == int3x3(1,2,0,3,4,0,5,6,1));
|
||||
STATIC_REQUIRE(int3x3(int3x3({1,2,3},{4,5,6},{7,8,9})) == int3x3(1,2,3,4,5,6,7,8,9));
|
||||
STATIC_REQUIRE(int3x3(int2x2({1,2},{3,4})) == int3x3(1,2,0,3,4,0,0,0,1));
|
||||
STATIC_REQUIRE(int3x3(int4x4({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == int3x3(1,2,3,5,6,7,9,10,11));
|
||||
|
||||
STATIC_REQUIRE(int4x4() == int4x4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1));
|
||||
STATIC_REQUIRE(int4x4(2) == int4x4(2,0,0,0,0,2,0,0,0,0,2,0,0,0,0,2));
|
||||
STATIC_REQUIRE(int4x4(int4{2,3,4,5}) == int4x4(2,0,0,0,0,3,0,0,0,0,4,0,0,0,0,5));
|
||||
STATIC_REQUIRE(int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) == int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
|
||||
STATIC_REQUIRE(int4x4({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}) == int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
|
||||
STATIC_REQUIRE(int4x4(int3x3({1,2,3},{4,5,6},{7,8,9}),int3{10,11,12}) == int4x4(1,2,3,0,4,5,6,0,7,8,9,0,10,11,12,1));
|
||||
STATIC_REQUIRE(int4x4(int4x4({1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16})) == int4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
|
||||
STATIC_REQUIRE(int4x4(int2x2({1,2},{3,4})) == int4x4(1,2,0,0,3,4,0,0,0,0,1,0,0,0,0,1));
|
||||
STATIC_REQUIRE(int4x4(int3x3({1,2,3},{4,5,6},{7,8,9})) == int4x4(1,2,3,0,4,5,6,0,7,8,9,0,0,0,0,1));
|
||||
@@ -104,6 +125,99 @@ TEST_CASE("vmath/mat") {
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("iter") {
|
||||
{
|
||||
int2x2 m{1,2,3,4};
|
||||
|
||||
REQUIRE(*m.begin() == vec{1,2});
|
||||
REQUIRE(*(m.begin() + 1) == vec{3,4});
|
||||
REQUIRE(*(m.end() - 1) == vec{3,4});
|
||||
REQUIRE(*(m.end() - 2) == vec{1,2});
|
||||
REQUIRE(m.begin() + 2 == m.end());
|
||||
REQUIRE(m.end() - 2 == m.begin());
|
||||
|
||||
REQUIRE(*m.cbegin() == vec{1,2});
|
||||
REQUIRE(*(m.cbegin() + 1) == vec{3,4});
|
||||
REQUIRE(*(m.cend() - 1) == vec{3,4});
|
||||
REQUIRE(*(m.cend() - 2) == vec{1,2});
|
||||
REQUIRE(m.cbegin() + 2 == m.cend());
|
||||
REQUIRE(m.cend() - 2 == m.cbegin());
|
||||
|
||||
REQUIRE(*m.rbegin() == vec{3,4});
|
||||
REQUIRE(*(m.rbegin() + 1) == vec{1,2});
|
||||
REQUIRE(*(m.rend() - 1) == vec{1,2});
|
||||
REQUIRE(*(m.rend() - 2) == vec{3,4});
|
||||
REQUIRE(m.rbegin() + 2 == m.rend());
|
||||
REQUIRE(m.rend() - 2 == m.rbegin());
|
||||
|
||||
REQUIRE(*m.crbegin() == vec{3,4});
|
||||
REQUIRE(*(m.crbegin() + 1) == vec{1,2});
|
||||
REQUIRE(*(m.crend() - 1) == vec{1,2});
|
||||
REQUIRE(*(m.crend() - 2) == vec{3,4});
|
||||
REQUIRE(m.crbegin() + 2 == m.crend());
|
||||
REQUIRE(m.crend() - 2 == m.crbegin());
|
||||
|
||||
*m.begin() = {5,6};
|
||||
REQUIRE(m == int2x2{5,6,3,4});
|
||||
*m.rbegin() = {7,8};
|
||||
REQUIRE(m == int2x2{5,6,7,8});
|
||||
}
|
||||
{
|
||||
const int2x2 m{1,2,3,4};
|
||||
|
||||
REQUIRE(*m.begin() == vec{1,2});
|
||||
REQUIRE(*(m.begin() + 1) == vec{3,4});
|
||||
REQUIRE(*(m.end() - 1) == vec{3,4});
|
||||
REQUIRE(*(m.end() - 2) == vec{1,2});
|
||||
REQUIRE(m.begin() + 2 == m.end());
|
||||
REQUIRE(m.end() - 2 == m.begin());
|
||||
|
||||
REQUIRE(*m.cbegin() == vec{1,2});
|
||||
REQUIRE(*(m.cbegin() + 1) == vec{3,4});
|
||||
REQUIRE(*(m.cend() - 1) == vec{3,4});
|
||||
REQUIRE(*(m.cend() - 2) == vec{1,2});
|
||||
REQUIRE(m.cbegin() + 2 == m.cend());
|
||||
REQUIRE(m.cend() - 2 == m.cbegin());
|
||||
|
||||
REQUIRE(*m.rbegin() == vec{3,4});
|
||||
REQUIRE(*(m.rbegin() + 1) == vec{1,2});
|
||||
REQUIRE(*(m.rend() - 1) == vec{1,2});
|
||||
REQUIRE(*(m.rend() - 2) == vec{3,4});
|
||||
REQUIRE(m.rbegin() + 2 == m.rend());
|
||||
REQUIRE(m.rend() - 2 == m.rbegin());
|
||||
|
||||
REQUIRE(*m.crbegin() == vec{3,4});
|
||||
REQUIRE(*(m.crbegin() + 1) == vec{1,2});
|
||||
REQUIRE(*(m.crend() - 1) == vec{1,2});
|
||||
REQUIRE(*(m.crend() - 2) == vec{3,4});
|
||||
REQUIRE(m.crbegin() + 2 == m.crend());
|
||||
REQUIRE(m.crend() - 2 == m.crbegin());
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("data") {
|
||||
{
|
||||
int2x2 m2;
|
||||
REQUIRE(m2.data() == &m2[0]);
|
||||
|
||||
int3x3 m3;
|
||||
REQUIRE(m3.data() == &m3[0]);
|
||||
|
||||
int4x4 m4;
|
||||
REQUIRE(m4.data() == &m4[0]);
|
||||
}
|
||||
{
|
||||
const int2x2 m2;
|
||||
REQUIRE(m2.data() == &m2[0]);
|
||||
|
||||
const int3x3 m3;
|
||||
REQUIRE(m3.data() == &m3[0]);
|
||||
|
||||
const int4x4 m4;
|
||||
REQUIRE(m4.data() == &m4[0]);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("operator[]") {
|
||||
{
|
||||
STATIC_REQUIRE(int2x2()[0] == int2(1,0));
|
||||
|
||||
@@ -15,27 +15,27 @@ namespace
|
||||
|
||||
TEST_CASE("vmath/vec_fun") {
|
||||
SUBCASE("Detail") {
|
||||
STATIC_REQUIRE(map([](const int& x){
|
||||
STATIC_REQUIRE(map_join([](const int& x){
|
||||
return x * 2;
|
||||
}, int2{1}) == int2{2});
|
||||
|
||||
STATIC_REQUIRE(zip([](const int& x, const int& y){
|
||||
STATIC_REQUIRE(map_join([](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){
|
||||
STATIC_REQUIRE(map_join([](const int& x, const int& y, const int& z){
|
||||
return x + y + z;
|
||||
}, int2{1}, int2{1}, int2{1}) == int2(3));
|
||||
|
||||
STATIC_REQUIRE(fold([](int acc, const int& x){
|
||||
STATIC_REQUIRE(fold_join([](int acc, const int& x){
|
||||
return acc + x;
|
||||
}, 0, int2{1}) == 2);
|
||||
|
||||
STATIC_REQUIRE(fold([](int acc, const int& x, const int& y){
|
||||
STATIC_REQUIRE(fold_join([](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){
|
||||
STATIC_REQUIRE(fold1_join([](const int& acc, const int& x){
|
||||
return acc + x;
|
||||
}, int2{1}) == 2);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,22 @@ TEST_CASE("vmath/vec") {
|
||||
STATIC_REQUIRE(sizeof(int4{}) == sizeof(int) * 4);
|
||||
}
|
||||
|
||||
SUBCASE("guides") {
|
||||
STATIC_REQUIRE(vec{1,2}.size == 2);
|
||||
|
||||
STATIC_REQUIRE(vec{1,2,3}.size == 3);
|
||||
STATIC_REQUIRE(vec{{1,2},3}.size == 3);
|
||||
STATIC_REQUIRE(vec{1,{2,3}}.size == 3);
|
||||
|
||||
STATIC_REQUIRE(vec{1,2,3,4}.size == 4);
|
||||
STATIC_REQUIRE(vec{vec{1,2},3,4}.size == 4);
|
||||
STATIC_REQUIRE(vec{1,vec{2,3},4}.size == 4);
|
||||
STATIC_REQUIRE(vec{1,2,vec{3,4}}.size == 4);
|
||||
STATIC_REQUIRE(vec{vec{1,2},vec{3,4}}.size == 4);
|
||||
STATIC_REQUIRE(vec{vec{1,2,3},4}.size == 4);
|
||||
STATIC_REQUIRE(vec{1,vec{2,3,4}}.size == 4);
|
||||
}
|
||||
|
||||
SUBCASE("ctors") {
|
||||
{
|
||||
STATIC_REQUIRE(int2().x == 0);
|
||||
@@ -102,6 +118,99 @@ TEST_CASE("vmath/vec") {
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("iter") {
|
||||
{
|
||||
int2 v{1,2};
|
||||
|
||||
REQUIRE(*v.begin() == 1);
|
||||
REQUIRE(*(v.begin() + 1) == 2);
|
||||
REQUIRE(*(v.end() - 1) == 2);
|
||||
REQUIRE(*(v.end() - 2) == 1);
|
||||
REQUIRE(v.begin() + 2 == v.end());
|
||||
REQUIRE(v.end() - 2 == v.begin());
|
||||
|
||||
REQUIRE(*v.cbegin() == 1);
|
||||
REQUIRE(*(v.cbegin() + 1) == 2);
|
||||
REQUIRE(*(v.cend() - 1) == 2);
|
||||
REQUIRE(*(v.cend() - 2) == 1);
|
||||
REQUIRE(v.cbegin() + 2 == v.cend());
|
||||
REQUIRE(v.cend() - 2 == v.cbegin());
|
||||
|
||||
REQUIRE(*v.rbegin() == 2);
|
||||
REQUIRE(*(v.rbegin() + 1) == 1);
|
||||
REQUIRE(*(v.rend() - 1) == 1);
|
||||
REQUIRE(*(v.rend() - 2) == 2);
|
||||
REQUIRE(v.rbegin() + 2 == v.rend());
|
||||
REQUIRE(v.rend() - 2 == v.rbegin());
|
||||
|
||||
REQUIRE(*v.crbegin() == 2);
|
||||
REQUIRE(*(v.crbegin() + 1) == 1);
|
||||
REQUIRE(*(v.crend() - 1) == 1);
|
||||
REQUIRE(*(v.crend() - 2) == 2);
|
||||
REQUIRE(v.crbegin() + 2 == v.crend());
|
||||
REQUIRE(v.crend() - 2 == v.crbegin());
|
||||
|
||||
*v.begin() = 3;
|
||||
REQUIRE(v == int2{3,2});
|
||||
*v.rbegin() = 4;
|
||||
REQUIRE(v == int2{3,4});
|
||||
}
|
||||
{
|
||||
const int2 v{1,2};
|
||||
|
||||
REQUIRE(*v.begin() == 1);
|
||||
REQUIRE(*(v.begin() + 1) == 2);
|
||||
REQUIRE(*(v.end() - 1) == 2);
|
||||
REQUIRE(*(v.end() - 2) == 1);
|
||||
REQUIRE(v.begin() + 2 == v.end());
|
||||
REQUIRE(v.end() - 2 == v.begin());
|
||||
|
||||
REQUIRE(*v.cbegin() == 1);
|
||||
REQUIRE(*(v.cbegin() + 1) == 2);
|
||||
REQUIRE(*(v.cend() - 1) == 2);
|
||||
REQUIRE(*(v.cend() - 2) == 1);
|
||||
REQUIRE(v.cbegin() + 2 == v.cend());
|
||||
REQUIRE(v.cend() - 2 == v.cbegin());
|
||||
|
||||
REQUIRE(*v.rbegin() == 2);
|
||||
REQUIRE(*(v.rbegin() + 1) == 1);
|
||||
REQUIRE(*(v.rend() - 1) == 1);
|
||||
REQUIRE(*(v.rend() - 2) == 2);
|
||||
REQUIRE(v.rbegin() + 2 == v.rend());
|
||||
REQUIRE(v.rend() - 2 == v.rbegin());
|
||||
|
||||
REQUIRE(*v.crbegin() == 2);
|
||||
REQUIRE(*(v.crbegin() + 1) == 1);
|
||||
REQUIRE(*(v.crend() - 1) == 1);
|
||||
REQUIRE(*(v.crend() - 2) == 2);
|
||||
REQUIRE(v.crbegin() + 2 == v.crend());
|
||||
REQUIRE(v.crend() - 2 == v.crbegin());
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("data") {
|
||||
{
|
||||
int2 i2;
|
||||
REQUIRE(i2.data() == &i2[0]);
|
||||
|
||||
int3 i3;
|
||||
REQUIRE(i3.data() == &i3[0]);
|
||||
|
||||
int4 i4;
|
||||
REQUIRE(i4.data() == &i4[0]);
|
||||
}
|
||||
{
|
||||
const int2 i2;
|
||||
REQUIRE(i2.data() == &i2[0]);
|
||||
|
||||
const int3 i3;
|
||||
REQUIRE(i3.data() == &i3[0]);
|
||||
|
||||
const int4 i4;
|
||||
REQUIRE(i4.data() == &i4[0]);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("operator[]") {
|
||||
{
|
||||
STATIC_REQUIRE(int2(1,2).x == 1);
|
||||
|
||||
Reference in New Issue
Block a user