diff --git a/src/core/include/pw/core/matrix.hpp b/src/core/include/pw/core/matrix.hpp
index 5199228..0a305e2 100644
--- a/src/core/include/pw/core/matrix.hpp
+++ b/src/core/include/pw/core/matrix.hpp
@@ -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
diff --git a/src/core/include/pw/core/vector.hpp b/src/core/include/pw/core/vector.hpp
index bf589d9..0008c25 100644
--- a/src/core/include/pw/core/vector.hpp
+++ b/src/core/include/pw/core/vector.hpp
@@ -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]);
     }
 
diff --git a/src/core/tests/pwcore_test_matrix.cpp b/src/core/tests/pwcore_test_matrix.cpp
index 594142d..a63e4f7 100644
--- a/src/core/tests/pwcore_test_matrix.cpp
+++ b/src/core/tests/pwcore_test_matrix.cpp
@@ -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);
 }
diff --git a/src/core/tests/pwcore_test_vector.cpp b/src/core/tests/pwcore_test_vector.cpp
index 697038e..446671d 100644
--- a/src/core/tests/pwcore_test_vector.cpp
+++ b/src/core/tests/pwcore_test_vector.cpp
@@ -6,7 +6,6 @@
 #include <tuple>
 #include <vector>
 
-
 auto main() -> int {
 
     auto v2_A = pw::vector{3.2, 1.2};