added structured binding support for matrix

This commit is contained in:
Hartmut Seichter 2024-07-14 23:16:14 +02:00
parent 98685e49ed
commit f3365d0669
4 changed files with 44 additions and 11 deletions

View file

@ -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

View file

@ -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]);
}

View file

@ -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);
}

View file

@ -6,7 +6,6 @@
#include <tuple>
#include <vector>
auto main() -> int {
auto v2_A = pw::vector{3.2, 1.2};