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`.
137 lines
2.4 KiB
C++
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
|
|
|