44 static constexpr size_t mat_rows = ROWS;
49 static constexpr size_t mat_cols = COLS;
66 template <
unsigned rows,
unsigned cols>
70 using array_type = std::array<scalar_type, mat_rows * mat_cols>;
77 constexpr Matrix() noexcept = default;
84 std::fill(std::begin(m_elements), std::end(m_elements), val);
92 m_elements(std::move(array))
100 constexpr Matrix(std::initializer_list<scalar_type> elements)
noexcept {
101 std::ranges::move(elements, std::begin(m_elements));
110 template <
unsigned rows,
unsigned cols>
112 for (
size_t r { 0 }; r < rows && r < mat_rows; ++r)
113 std::ranges::copy(_other.
row(r), std::begin(m_elements) + r * mat_cols);
152 std::array<scalar_type, mat_rows * mat_cols> data { };
154 for (
size_t i = 0; i < mat_rows && i < mat_cols; ++i)
155 data[i * mat_cols + i] = 1.0f;
166 return m_elements.data();
174 return m_elements.data();
181 consteval size_t size() const noexcept {
182 return mat_rows * mat_cols;
190 return m_elements.begin();
197 constexpr auto end() noexcept {
198 return m_elements.end();
206 return m_elements.cbegin();
213 constexpr auto cend() const noexcept {
214 return m_elements.cend();
224 assert(row < mat_rows && col < mat_cols);
226 return m_elements[row * mat_cols + col];
236 assert(row < mat_rows && col < mat_cols);
238 return m_elements[row * mat_cols + col];
246 constexpr std::span<const scalar_type>
row(
size_t row)
const noexcept {
247 assert(row < mat_rows);
249 return std::span(m_elements.begin() + row * mat_cols, mat_cols);
257 constexpr std::span<scalar_type>
row(
size_t row)
noexcept {
258 assert(row < mat_rows);
260 return std::span(m_elements.begin() + row * mat_cols, mat_cols);
272 constexpr std::array<scalar_type, mat_cols>
column(
size_t col)
const noexcept {
273 assert(col <= mat_cols);
275 return m_elements | std::views::drop(col) | std::views::stride(mat_cols) | std::ranges::to<std::array<scalar_type, mat_cols>>();
278#ifdef __cpp_multidimensional_subscript
285 constexpr scalar_type operator[](
size_t row,
size_t col)
const noexcept {
286 return this->at(row, col);
295 constexpr scalar_type& operator[](
size_t row,
size_t col)
noexcept {
296 return this->at(row, col);
306 return this->at(position.first, position.second);
315 return this->at(position.first, position.second);
318#ifdef __cpp_lib_mdspan
322 constexpr operator std::mdspan<const scalar_type, std::extents<std::size_t, mat_rows, mat_cols>>()
const noexcept {
323 return std::mdspan<const scalar_type, std::extents<std::size_t, mat_rows, mat_cols>>(m_elements.data());
329 constexpr operator std::mdspan<scalar_type, std::extents<std::size_t, mat_rows, mat_cols>>()
noexcept {
330 return std::mdspan<scalar_type, std::extents<std::size_t, mat_rows, mat_cols>>(m_elements.data());
337 constexpr operator std::array<T, mat_rows * mat_cols>() const noexcept {
344 constexpr operator std::vector<T>() const noexcept {
345 return std::vector<T>(std::begin(m_elements), std::end(m_elements));
351 constexpr operator std::span<const scalar_type>() const noexcept {
352 return std::span(m_elements.data(), m_elements.size());
358 constexpr operator std::span<scalar_type>() noexcept {
359 return std::span(m_elements.data(), m_elements.size());
371 std::array<scalar_type, mat_cols * mat_rows> data { };
373 for (
int r{ 0 }; r < mat_rows; ++r)
375 auto row = this->row(r);
377 for (
int c{ 0 }; c < mat_cols; ++c)
378 data[c * mat_rows + r] = row[c];
392#ifdef LITEFX_BUILD_WITH_GLM
399 constexpr Matrix(
const glm::mat<mat_cols, mat_rows, scalar_type>& mat)
noexcept {
400 for (
int r { 0 }; r < mat_rows; ++r)
401 for (
int c { 0 }; c < mat_cols; ++c)
402 m_elements[r * mat_cols + c] = mat[c][r];
409 constexpr Matrix(glm::mat<mat_cols, mat_rows, scalar_type>&& mat)
noexcept {
410 for (
size_t r { 0 }; r < mat_rows; ++r)
411 for (
size_t c { 0 }; c < mat_cols; ++c)
412 m_elements[r * mat_cols + c] = std::move(mat[c][r]);
419 template <
unsigned rows,
unsigned cols>
420 constexpr operator glm::mat<cols, rows, scalar_type>() const noexcept requires (mat_rows >= rows && mat_cols >= cols) {
421 std::array<scalar_type, static_cast<size_t>(cols * rows)> data;
422 glm::mat<cols, rows, scalar_type> mat;
424 for (
size_t c { 0 }; c < cols; ++c)
425 for (
size_t r { 0 }; r < rows; ++r)
426 data[c * mat_rows + r] = this->at(r, c);
428 std::memcpy(&mat, data.data(), data.size() *
sizeof(scalar_type));
436 constexpr operator glm::mat<2, 2, scalar_type>() const noexcept requires (mat_rows >= 2 && mat_cols >= 2) {
437 return glm::mat<2, 2, scalar_type>(at(0, 0), at(1, 0), at(0, 1), at(1, 1));
444 constexpr operator glm::mat<2, 3, scalar_type>() const noexcept requires (mat_rows >= 3 && mat_cols >= 2) {
445 return glm::mat<2, 3, scalar_type>(at(0, 0), at(1, 0), at(2, 0), at(0, 1), at(1, 1), at(2, 1));
452 constexpr operator glm::mat<2, 4, scalar_type>() const noexcept requires (mat_rows >= 4 && mat_cols >= 2) {
453 return glm::mat<2, 4, scalar_type>(at(0, 0), at(1, 0), at(2, 0), at(3, 0), at(0, 1), at(1, 1), at(2, 1), at(3, 1));
460 constexpr operator glm::mat<3, 2, scalar_type>() const noexcept requires (mat_rows >= 2 && mat_cols >= 3) {
461 return glm::mat<3, 2, scalar_type>(at(0, 0), at(1, 0), at(0, 1), at(1, 1), at(0, 2), at(1, 2));
468 constexpr operator glm::mat<4, 2, scalar_type>() const noexcept requires (mat_rows >= 2 && mat_cols >= 4) {
469 return glm::mat<4, 2, scalar_type>(at(0, 0), at(1, 0), at(0, 1), at(1, 1), at(0, 2), at(1, 2), at(0, 3), at(1, 3));
476 constexpr operator glm::mat<3, 3, scalar_type>() const noexcept requires (mat_rows >= 3 && mat_cols >= 3) {
477 return glm::mat<3, 3, scalar_type>(at(0, 0), at(1, 0), at(2, 0), at(0, 1), at(1, 1), at(2, 1), at(0, 2), at(1, 2), at(2, 2));
484 constexpr operator glm::mat<3, 4, scalar_type>() const noexcept requires (mat_rows >= 4 && mat_cols >= 3) {
485 return glm::mat<3, 4, scalar_type>(at(0, 0), at(1, 0), at(2, 0), at(3, 0), at(0, 1), at(1, 1), at(2, 1), at(3, 1), at(0, 2), at(1, 2), at(2, 2), at(3, 2));
492 constexpr operator glm::mat<4, 3, scalar_type>() const noexcept requires (mat_rows >= 3 && mat_cols >= 4) {
493 return glm::mat<4, 3, scalar_type>(at(0, 0), at(1, 0), at(2, 0), at(0, 1), at(1, 1), at(2, 1), at(0, 2), at(1, 2), at(2, 2), at(0, 3), at(1, 3), at(2, 3));
500 constexpr operator glm::mat<4, 4, scalar_type>() const noexcept requires (mat_rows >= 4 && mat_cols >= 4) {
501 return glm::mat<4, 4, scalar_type>(at(0, 0), at(1, 0), at(2, 0), at(3, 0), at(0, 1), at(1, 1), at(2, 1), at(3, 1), at(0, 2), at(1, 2), at(2, 2), at(3, 2), at(0, 3), at(1, 3), at(2, 3), at(3, 3));
505#ifdef LITEFX_BUILD_WITH_DIRECTX_MATH
511 constexpr Matrix(
const DirectX::XMFLOAT3X3& mat)
noexcept {
512 for (
int r { 0 }; r < 3; ++r)
513 for (
int c { 0 }; c < 3; ++c)
514 at(r, c) = mat(r, c);
521 constexpr Matrix(
const DirectX::XMFLOAT4X3& mat)
noexcept {
522 for (
int r { 0 }; r < 4; ++r)
523 for (
int c { 0 }; c < 3; ++c)
524 at(r, c) = mat(r, c);
531 constexpr Matrix(
const DirectX::XMFLOAT3X4& mat)
noexcept {
532 for (
int r { 0 }; r < 3; ++r)
533 for (
int c { 0 }; c < 4; ++c)
534 at(r, c) = mat(r, c);
541 constexpr Matrix(
const DirectX::XMFLOAT4X4& mat)
noexcept {
542 for (
int r { 0 }; r < 4; ++r)
543 for (
int c { 0 }; c < 4; ++c)
544 at(r, c) = mat(r, c);
551 constexpr operator DirectX::XMMATRIX() const noexcept requires ((mat_rows == 3 || mat_rows == 4) && (mat_cols == 3 || mat_cols == 4) && std::convertible_to<scalar_type,
float>) {
552 if constexpr (mat_rows == 3 && mat_cols == 3)
554 DirectX::XMFLOAT3X3 mat =
static_cast<DirectX::XMFLOAT3X3
>(*this);
555 return DirectX::XMLoadFloat3x3(&mat);
557 else if constexpr (mat_rows == 3 && mat_cols == 4)
559 DirectX::XMFLOAT3X4 mat =
static_cast<DirectX::XMFLOAT3X4
>(*this);
560 return DirectX::XMLoadFloat3x4(&mat);
562 else if constexpr (mat_rows == 4 && mat_cols == 3)
564 DirectX::XMFLOAT4X3 mat =
static_cast<DirectX::XMFLOAT4X3
>(*this);
565 return DirectX::XMLoadFloat4x3(&mat);
567 if constexpr (mat_rows == 4 && mat_cols == 4)
569 DirectX::XMFLOAT4X4 mat =
static_cast<DirectX::XMFLOAT4X4
>(*this);
570 return DirectX::XMLoadFloat4x4(&mat);
580 constexpr operator DirectX::XMFLOAT3X3() const noexcept requires (mat_rows >= 3 && mat_cols >= 3 && std::convertible_to<scalar_type,
float>) {
581 return DirectX::XMFLOAT3X3(at(0, 0), at(0, 1), at(0, 2), at(1, 0), at(1, 2), at(2, 0), at(2, 1), at(2, 2));
588 constexpr operator DirectX::XMFLOAT4X3() const noexcept requires (mat_rows >= 4 && mat_cols >= 3 && std::convertible_to<scalar_type,
float>) {
589 return DirectX::XMFLOAT4X3(at(0, 0), at(0, 1), at(0, 2), at(1, 0), at(1, 2), at(2, 0), at(2, 1), at(2, 2), at(3, 0), at(3, 1), at(3, 2));
596 constexpr operator DirectX::XMFLOAT3X4() const noexcept requires (mat_rows >= 3 && mat_cols >= 4 && std::convertible_to<scalar_type,
float>) {
597 return DirectX::XMFLOAT3X4(at(0, 0), at(0, 1), at(0, 2), at(0, 3), at(1, 0), at(1, 2), at(1, 3), at(2, 0), at(2, 1), at(2, 2), at(2, 3));
604 constexpr operator DirectX::XMFLOAT4X4() const noexcept requires (mat_rows >= 4 && mat_cols >= 4 && std::convertible_to<scalar_type,
float>) {
605 return DirectX::XMFLOAT4X4(at(0, 0), at(0, 1), at(0, 2), at(0, 3), at(1, 0), at(1, 2), at(1, 3), at(2, 0), at(2, 1), at(2, 2), at(2, 3), at(3, 0), at(3, 1), at(3, 2), at(3, 3));