32#include <nlohmann/json.hpp>
40 using JSON = nlohmann::json;
48 template <
size_t w,
size_t h,
typename T>
61 data.fill(
static_cast<T>(0));
88 Matrix(std::array<T, w*h>&& arr) :
data(std::move(arr)) {
117 if (i > w*h)
throw std::runtime_error(
"Invalid matrix index");
131 if (i > w*h)
throw std::runtime_error(
"Invalid matrix index");
145 if (col > w || row > h)
throw std::runtime_error(
"Invalid matrix column/row");
147 return data[row * w + col];
159 if (col > w || row > h)
throw std::runtime_error(
"Invalid matrix column/row");
161 return data[row * w + col];
180 inline const T&
get(
size_t i)
const {
190 inline T&
get(
size_t col,
size_t row) {
191 return data[row * w + col];
200 inline const T&
get(
size_t col,
size_t row)
const {
201 return data[row * w + col];
211 for (
size_t i = 0; i < w*h; i++) mat.
data[i] =
data[i] + other.
data[i];
221 for (
size_t i = 0; i < w*h; i++) other.data[i] +=
data[i];
230 for (
size_t i = 0; i < w*h; i++)
data[i] += other.
data[i];
240 for (
size_t i = 0; i < w*h; i++) mat.
data[i] =
data[i] - other.
data[i];
250 for (
size_t i = 0; i < w*h; i++) other.data[i] =
data[i] - other.data[i];
259 for (
size_t i = 0; i < w*h; i++)
data[i] -= other.
data[i];
269 for (
size_t i = 0; i < w*h; i++) mat.
data[i] =
data[i] * scalar;
278 for (
size_t i = 0; i < w*h; i++)
data[i] *= scalar;
288 for (
size_t i = 0; i < h; i++)
289 for (
size_t j = 0; j < w2; j++)
290 for (
size_t k = 0; k < w; k++)
291 mat.
get(j, i) +=
get(k, i) * other.
get(j, k);
301 for (
size_t c = 0; c < w; c++)
302 for (
size_t r = 0; r < h; r++)
303 mat.
get(r, c) =
get(c, r);
317 if (row1 > h || row2 > h)
throw std::runtime_error(
"Invalid matrix row");
319 std::swap_ranges(
data.begin() + row1 * w,
data.begin() + row1 * w + w,
data.begin() + row2 * w);
330 if (row > h)
throw std::runtime_error(
"Invalid matrix row");
332 for (
size_t x = 0; x < w; x++) {
333 get(x, row) *= scalar;
346 if (row1 > h || row2 > h)
throw std::runtime_error(
"Invalid matrix row");
348 for (
size_t x = 0; x < w; x++) {
349 get(x, row1) += scalar *
get(x, row2);
360 template <
size_t W = w,
size_t H = h>
typename std::enable_if<W == 2 && H == 2, Vector2<T>>::type
370 template <
size_t W = w,
size_t H = h>
typename std::enable_if<W == 2 && H == 2, Vector2<T>>::type
372 vec.x =
data[0] * vec.x +
data[1] * vec.y;
373 vec.y =
data[2] * vec.x +
data[2] * vec.y;
382 template <
size_t W = w,
size_t H = h>
typename std::enable_if<W == 3 && H == 3, Vector3<T>>::type
396 template <
size_t W = w,
size_t H = h>
typename std::enable_if<W == 3 && H == 3, Vector3<T>>::type
398 vec.x =
data[0] * vec.x +
data[1] * vec.y +
data[2] * vec.z;
399 vec.y =
data[3] * vec.x +
data[4] * vec.y +
data[5] * vec.z;
400 vec.z =
data[6] * vec.x +
data[7] * vec.y +
data[8] * vec.z;
409 template <
size_t W = w,
size_t H = h>
typename std::enable_if<W == 4 && H == 4, Vector4<T>>::type
424 template <
size_t W = w,
size_t H = h>
typename std::enable_if<W == 4 && H == 4, Vector4<T>>::type
426 vec.x =
data[0] * vec.x +
data[1] * vec.y +
data[2] * vec.z +
data[3] * vec.w;
427 vec.y =
data[4] * vec.x +
data[5] * vec.y +
data[6] * vec.z +
data[7] * vec.w;
428 vec.z =
data[8] * vec.x +
data[9] * vec.y +
data[10] * vec.z +
data[11] * vec.w;
429 vec.w =
data[12] * vec.x +
data[13] * vec.y +
data[14] * vec.z +
data[15] * vec.w;
438 template <
typename R,
size_t W = w,
size_t H = h>
439 typename std::enable_if<W == 2 && H == 2, R>::type
det()
const {
449 template <
typename R,
size_t W = w,
size_t H = h>
450 typename std::enable_if<W == 3 && H == 3, R>::type
det()
const {
451 return static_cast<R>(
466 template <
typename R,
size_t W = w,
size_t H = h>
467 typename std::enable_if<
W ==
H && (
W > 3) && std::is_signed<R>::value,
R>::type
det()
const {
468 throw std::runtime_error(
"Matrix Determinants are Unimplemented");
475 template <
size_t W = w,
size_t H = h>
476 typename std::enable_if<W == 2 && H == 2, Matrix<W, H, T>>::type
inverse() {
480 }) * (
static_cast<T>(1)/det<T>());
487 template <
size_t W = w,
size_t H = h>
488 typename std::enable_if<W == 3 && H == 3, Matrix<W, H, T>>::type
inverse() {
489 auto calc = [&](
size_t a,
size_t b,
size_t c,
size_t d) ->
T {
493 calc(4, 5, 7, 8), -calc(1, 2, 7, 8), calc(1, 2, 4, 5),
494 -calc(3, 5, 6, 8), calc(0, 2, 6, 8), -calc(0, 2, 3, 5),
495 calc(3, 4, 6, 7), -calc(0, 1, 6, 7), calc(0, 1, 3, 4)
496 }) * (
static_cast<T>(1)/det<T>());
523 template <
size_t w,
size_t h,
typename T>
525 os <<
"Mat(Width: " << w <<
", Height: " << h <<
") :";
526 for (
size_t y = 0; y < h; y++) {
528 for (
size_t x = 0; x < w; x++) {
529 os << std::setw(5) << std::setfill(
' ') << mat(x, y) <<
" ";
538 template <
size_t w,
size_t h,
typename T>
540 p = j.
get<std::array<T, w*h>>();
546 template <
size_t w,
size_t h,
typename T>
T & get(size_t col, size_t row)
Matrix(const std::array< T, w *h > &arr)
void operator-=(const Matrix< w, h, T > &other)
std::enable_if< W==4 &&H==4, Vector4< T > >::type operator*(const Vector4< T > &vec) const
std::enable_if< W==3 &&H==3, Vector3< T > >::type operator*(const Vector3< T > &vec) const
std::enable_if< W==3 &&H==3, R >::type det() const
const T & get(size_t col, size_t row) const
Matrix< h, w, T > transpose() const
void operator+=(const Matrix< w, h, T > &other)
std::enable_if< W==3 &&H==3, Vector3< T > >::type operator*(Vector3< T > &&vec) const
std::enable_if< W==2 &&H==2, R >::type det() const
Matrix< w, h, T > operator+(const Matrix< w, h, T > &other) const
void scaleRow(size_t row, T scalar)
std::enable_if< W==2 &&H==2, Vector2< T > >::type operator*(const Vector2< T > &vec) const
Matrix< w, h, T > operator*(T scalar) const
std::enable_if< W==H &&(W >3)&&std::is_signed< R >::value, R >::type det() const
const T & get(size_t i) const
std::array< T, w *h > data
std::enable_if< W==2 &&H==2, Matrix< W, H, T > >::type inverse()
std::enable_if< W==2 &&H==2, Vector2< T > >::type operator*(Vector2< T > &&vec) const
Matrix(std::array< T, w *h > &&arr)
void swapRows(size_t row1, size_t row2)
Matrix< w2, h, T > operator*(const Matrix< w2, w, T > &other) const
Matrix< w, h, T > operator+(Matrix< w, h, T > &&other) const
Matrix< w, h, T > operator-(const Matrix< w, h, T > &other) const
const T & operator()(size_t col, size_t row) const
void addScaledRow(size_t row1, size_t row2, T scalar)
void operator*=(T scalar)
T & operator()(size_t col, size_t row)
const T & operator[](size_t i) const
std::enable_if< W==4 &&H==4, Vector4< T > >::type operator*(Vector4< T > &&vec) const
Matrix< w, h, T > operator-(Matrix< w, h, T > &&other) const
std::enable_if< W==3 &&H==3, Matrix< W, H, T > >::type inverse()
Matrix< 3, 3, double > Matrix3d
Matrix< 2, 2, float > Matrix2f
void to_json(JSON &j, const Matrix< w, h, T > &p)
Matrix< 3, 3, int > Matrix3i
Matrix< 3, 3, long > Matrix3l
Matrix< 2, 2, double > Matrix2d
Matrix< 4, 4, int > Matrix4i
Matrix< 2, 2, int > Matrix2i
void from_json(const JSON &j, Matrix< w, h, T > &p)
Matrix< 4, 4, long > Matrix4l
Matrix< 3, 3, float > Matrix3f
Matrix< 2, 2, long > Matrix2l
Matrix< 4, 4, double > Matrix4d
std::ostream & operator<<(std::ostream &os, const Kale::Matrix< w, h, T > &mat)
Matrix< 4, 4, float > Matrix4f