mtl/include/mtl/mat_impl.hpp
Madeline Busig a449c4f749 Add conditional test compilation and split matrix instantiations
This commit adds the ability to conditionally compile tests. To
implement this, common source files needed to be moved to a subdirectory
`common`.

Additionally, this commit splits each `mat` template instantiation into
a separate source file. This enables the linker to discard unused
instantations. If each instantiation is placed in the same file and also
into the .iwram section, the linker will include every symbol in the
resulting binary, leading to an extremely high IWRAM usage. To introduce
this split, a new header file "mat_impl.hpp" was added containing
implementation details for the template instantiations. "mat_impl.hpp"
should ONLY be included by the source files containing explicit
instantiations of `mat`.
2024-10-07 23:49:01 -07:00

137 lines
2.4 KiB
C++

/*
* This file should only be included by files that explicitly instantiate
* matrix classes.
*/
#pragma once
#pragma GCC push_options
#pragma GCC optimize("unroll-loops")
#include "mtl/mat.hpp"
#include "mtl/vec.hpp"
namespace mtl {
template <size_t M, size_t N>
mat<M, N> mat<M, N>::operator+(const mat<M, N>& rhs) const {
mat<M, N> r;
for (size_t im = 0; im < M; ++im) {
for (size_t in = 0; in < N; ++in) {
r.e[im][in] = e[im][in] + rhs.e[im][in];
}
}
return r;
}
template <size_t M, size_t N>
mat<M, N> mat<M, N>::operator-(const mat<M, N>& rhs) const {
mat<M, N> r;
for (size_t im = 0; im < M; ++im) {
for (size_t in = 0; in < N; ++in) {
r.e[im][in] = e[im][in] - rhs.e[im][in];
}
}
return r;
}
template <size_t M, size_t N>
mat<M, N> mat<M, N>::operator*(fixed rhs) const {
mat<M, N> r;
for (size_t im = 0; im < M; ++im) {
for (size_t in = 0; in < N; ++in) {
r.e[im][in] = e[im][in] * rhs;
}
}
return r;
}
template <size_t M, size_t N>
mat<M, N> mat<M, N>::operator/(fixed rhs) const {
mat<M, N> r;
for (size_t im = 0; im < M; ++im) {
for (size_t in = 0; in < N; ++in) {
r.e[im][in] = e[im][in] / rhs;
}
}
return r;
}
template <size_t M, size_t N>
vec<M> mat<M, N>::operator*(const vec<N>& rhs) const noexcept {
vec<M> r;
for (size_t i = 0; i < M; ++i) {
r.e[i] = row(i) * rhs;
}
return r;
}
template <size_t M, size_t N>
template <size_t RHS_N>
mat<M, RHS_N> mat<M, N>::operator*(const mat<N, RHS_N>& rhs) const noexcept {
mat<M, RHS_N> r;
for (size_t im = 0; im < M; ++im) {
for (size_t in = 0; in < RHS_N; ++in) {
r.e[im][in] = row(im) * rhs.col(in);
}
}
return r;
}
template <size_t S>
mat<S, S> operator*(const vec<S>& lhs, const mat<1, S>& rhs) {
mat<S, S> r;
for (size_t im = 0; im < S; ++im) {
for (size_t in = 0; in < S; ++in) {
r.e[im][in] = lhs[im] * rhs.e[0][in];
}
}
return r;
}
template <size_t M, size_t N>
bool mat<M, N>::operator==(const mat<M, N>& rhs) const {
for (size_t im = 0; im < M; ++im) {
for (size_t in = 0; in < N; ++in) {
if (e[im][in] != rhs.e[im][in]) {
return false;
}
}
}
return true;
}
template <>
template <size_t D, std::enable_if_t<D == 4, bool>>
mat<4, 4> mat<4, 4>::translation(const vec<D - 1>& v) {
mat<4, 4> r;
r.e[0][0] = 1;
r.e[1][1] = 1;
r.e[2][2] = 1;
r.e[3][3] = 1;
r.e[0][3] = v.e[0];
r.e[1][3] = v.e[1];
r.e[2][3] = v.e[2];
return r;
}
} // namespace mtl
#pragma GCC pop_options