added structured binding support for matrix
This commit is contained in:
parent
98685e49ed
commit
f3365d0669
4 changed files with 44 additions and 11 deletions
|
@ -23,28 +23,32 @@
|
|||
#ifndef PW_CORE_MATRIX_HPP
|
||||
#define PW_CORE_MATRIX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <pw/core/globals.hpp>
|
||||
#include <pw/core/math.hpp>
|
||||
#include <pw/core/vector.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace pw {
|
||||
|
||||
template <typename Scalar, unsigned int Rows, unsigned int Cols>
|
||||
template <typename Scalar, std::size_t Rows, std::size_t Cols>
|
||||
struct matrix final {
|
||||
|
||||
static_assert(Rows > 0 && Cols > 0, "undefined matrix type");
|
||||
static_assert(Rows > 0 && Cols > 0, "Undefined matrix type.");
|
||||
|
||||
static constexpr unsigned int diag_size{std::min(Rows, Cols)};
|
||||
static constexpr unsigned int rows{Rows};
|
||||
static constexpr unsigned int cols{Cols};
|
||||
static constexpr bool is_square{Rows == Cols};
|
||||
|
||||
using size_type = std::common_type_t<decltype(Rows), decltype(Cols)>;
|
||||
using row_type = vector<Scalar, Cols>;
|
||||
using column_type = vector<Scalar, Rows>;
|
||||
using diag_type = vector<Scalar, diag_size>;
|
||||
using transpose_type = matrix<Scalar, Cols, Rows>;
|
||||
using minor_type = matrix<Scalar, Cols - 1, Rows - 1>;
|
||||
using column_type = vector<Scalar, Rows>;
|
||||
|
||||
vector<vector<Scalar, Cols>, Rows> m_{};
|
||||
|
||||
|
@ -56,6 +60,14 @@ struct matrix final {
|
|||
return std::forward<decltype(self)>(self).m_[r];
|
||||
}
|
||||
|
||||
//
|
||||
// part of tuple-protocol
|
||||
//
|
||||
template <size_type idx> auto get(this auto&& self) -> decltype(auto) {
|
||||
static_assert(idx < Rows, "Out of bounds access to a member.");
|
||||
return std::forward_like<decltype(self)>(self.m_[idx]);
|
||||
}
|
||||
|
||||
constexpr auto diagonal() const noexcept -> diag_type {
|
||||
return [this]<std::size_t... Is>(std::index_sequence<Is...>) {
|
||||
return diag_type{(*this)[Is][Is]...};
|
||||
|
@ -226,4 +238,16 @@ constexpr auto operator*(const matrix<ScalarA, Ra, Ca>& A,
|
|||
|
||||
} // namespace pw
|
||||
|
||||
//
|
||||
// tuple - protocol
|
||||
//
|
||||
template <class Scalar, std::size_t R, std::size_t C>
|
||||
struct std::tuple_size<pw::matrix<Scalar, R, C>>
|
||||
: std::integral_constant<std::size_t, R> {};
|
||||
|
||||
template <std::size_t I, class Scalar, std::size_t R, std::size_t C>
|
||||
struct std::tuple_element<I, pw::matrix<Scalar, R, C>> {
|
||||
using type = pw::matrix<Scalar, R, C>::row_type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,7 +40,9 @@ concept Vector3 = (N == 3);
|
|||
template <typename T, auto N>
|
||||
concept Vector4 = (N == 4);
|
||||
|
||||
template <typename Scalar, std::size_t N> struct vector {
|
||||
template <typename Scalar, std::size_t N> struct vector final {
|
||||
|
||||
static_assert(N > 0, "Undefined vector space.");
|
||||
|
||||
using value_type = Scalar;
|
||||
using size_type = decltype(N);
|
||||
|
@ -71,7 +73,7 @@ template <typename Scalar, std::size_t N> struct vector {
|
|||
template <typename... Args>
|
||||
static constexpr auto
|
||||
make(Args&&... values) noexcept -> vector<Scalar, sizeof...(Args)> {
|
||||
static_assert(sizeof...(Args) == N, "incorrect number of arguments");
|
||||
static_assert(sizeof...(Args) == N, "Incorrect number of arguments.");
|
||||
return {{Scalar(values)...}};
|
||||
}
|
||||
|
||||
|
@ -84,7 +86,7 @@ template <typename Scalar, std::size_t N> struct vector {
|
|||
template <typename... Args>
|
||||
constexpr auto swizzle(Args&&... indices) const noexcept
|
||||
-> vector<Scalar, sizeof...(Args)> {
|
||||
return {{Scalar(v_[indices])...}};
|
||||
return {{Scalar{v_[indices]}...}};
|
||||
}
|
||||
|
||||
constexpr auto minor(std::unsigned_integral auto d0) const noexcept {
|
||||
|
@ -102,9 +104,9 @@ template <typename Scalar, std::size_t N> struct vector {
|
|||
}
|
||||
|
||||
static constexpr auto lerp(const vector& A, const vector& B,
|
||||
const Scalar& factor) -> vector {
|
||||
const Scalar& t) -> vector {
|
||||
return [&]<std::size_t... Ss>(std::index_sequence<Ss...>) {
|
||||
return vector<Scalar, N>{{A[Ss] + factor * (B[Ss] - A[Ss])...}};
|
||||
return vector<Scalar, N>{{A[Ss] + t * (B[Ss] - A[Ss])...}};
|
||||
}(std::make_index_sequence<N>{});
|
||||
}
|
||||
|
||||
|
@ -254,10 +256,10 @@ template <typename Scalar, std::size_t N> struct vector {
|
|||
};
|
||||
|
||||
//
|
||||
// tuple like for structured bindings
|
||||
// part of tuple-protocol
|
||||
//
|
||||
template <size_type idx> auto get(this auto&& self) -> decltype(auto) {
|
||||
static_assert(idx < N, "out of bounds access to a member.");
|
||||
static_assert(idx < N, "Out of bounds access to a member.");
|
||||
return std::forward_like<decltype(self)>(self.v_[idx]);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include <pw/core/serialize.hpp>
|
||||
#include <pw/core/vector.hpp>
|
||||
|
||||
#include <print>
|
||||
|
||||
auto main() -> int {
|
||||
|
||||
pw::debug::d() << "pixwerx.matrix.test\n";
|
||||
|
@ -38,4 +40,10 @@ auto main() -> int {
|
|||
auto m22_tp_col1 = m22_tp.column(1);
|
||||
pw::debug::d() << "matrix<2,2>{1,2,3,4}.transposed().column(1) -> \n"
|
||||
<< pw::serialize::to_string(m22_tp_col1);
|
||||
|
||||
auto& [r1, r2] = m22_inv;
|
||||
|
||||
auto& [r1_x, r1_y] = r1;
|
||||
|
||||
std::print("r1.x:{} r1.y:{}\n", r1_x, r1_y);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
|
||||
auto main() -> int {
|
||||
|
||||
auto v2_A = pw::vector{3.2, 1.2};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue