215 lines
3.6 KiB
C++
215 lines
3.6 KiB
C++
#pragma once
|
|
|
|
#include "mtl/target.hpp"
|
|
|
|
#include <cstddef>
|
|
|
|
#include "mtl/fixed.hpp"
|
|
|
|
namespace mtl {
|
|
|
|
template <size_t M, size_t N>
|
|
class mat;
|
|
|
|
template <size_t N>
|
|
class vec {
|
|
public:
|
|
fixed e[N];
|
|
|
|
constexpr vec() noexcept {}
|
|
|
|
constexpr vec(const vec<N>& other) noexcept {
|
|
// We need to explicitly define the copy constructor, otherwise
|
|
// GCC uses memcpy to copy while in Thumb mode, and that's slow.
|
|
#pragma GCC unroll 4 // Force unroll loops. Can't use pragmas or attributes
|
|
// because they don't work for inlined functions. Requires
|
|
// GCC 8.1
|
|
for (size_t i = 0; i < N; ++i) {
|
|
e[i] = other.e[i];
|
|
}
|
|
}
|
|
constexpr vec(const fixed (&_e)[N]) noexcept {
|
|
#pragma GCC unroll 4
|
|
for (size_t i = 0; i < N; ++i) {
|
|
e[i] = _e[i];
|
|
}
|
|
}
|
|
|
|
constexpr fixed& operator[](size_t i) noexcept {
|
|
return e[i];
|
|
}
|
|
constexpr const fixed& operator[](size_t i) const noexcept {
|
|
return e[i];
|
|
}
|
|
|
|
vec<N> operator+(const vec<N>& rhs) const noexcept {
|
|
vec<N> res;
|
|
|
|
#pragma GCC unroll 4
|
|
for (size_t i = 0; i < N; ++i) {
|
|
res[i] = e[i] + rhs[i];
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
vec<N> operator-(const vec<N>& rhs) const noexcept {
|
|
vec<N> res;
|
|
|
|
#pragma GCC unroll 4
|
|
for (size_t i = 0; i < N; ++i) {
|
|
res[i] = e[i] - rhs[i];
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
vec<N> operator-() const noexcept {
|
|
vec<N> res;
|
|
|
|
#pragma GCC unroll 4
|
|
for (size_t i = 0; i < N; ++i) {
|
|
res[i] = -e[i];
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
vec<N> operator*(fixed rhs) const noexcept {
|
|
vec<N> res;
|
|
|
|
#pragma GCC unroll 4
|
|
for (size_t i = 0; i < N; ++i) {
|
|
res[i] = e[i] * rhs;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
friend vec<N> operator*(fixed lhs, vec<N> rhs) noexcept {
|
|
return rhs * lhs;
|
|
}
|
|
|
|
fixed operator*(const vec<N>& rhs) const noexcept {
|
|
fixed res;
|
|
|
|
#pragma GCC unroll 4
|
|
for (size_t i = 0; i < N; ++i) {
|
|
res += e[i] * rhs[i];
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
vec<N> operator/(fixed rhs) const noexcept {
|
|
vec<N> r;
|
|
|
|
#pragma GCC unroll 4
|
|
for (size_t i = 0; i < N; ++i) {
|
|
r[i] = e[i] / rhs;
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
fixed magnitude_sqr() const noexcept {
|
|
fixed r;
|
|
|
|
#pragma GCC unroll 4
|
|
for (size_t i = 0; i < N; ++i) {
|
|
r += e[i] * e[i];
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
mat<1, N> transpose() const noexcept {
|
|
mat<1, N> r;
|
|
|
|
#pragma GCC unroll 4
|
|
for (size_t i = 0; i < N; ++i) {
|
|
r.e[0][i] = e[i];
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
bool operator==(const vec<N>& rhs) noexcept {
|
|
#pragma GCC unroll 4
|
|
for (size_t i = 0; i < N; ++i) {
|
|
if (e[i] != rhs.e[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
bool operator!=(const vec<N>& rhs) noexcept {
|
|
return !(*this == rhs);
|
|
}
|
|
};
|
|
|
|
class vec2 : public vec<2> {
|
|
public:
|
|
fixed& x = e[0];
|
|
fixed& y = e[1];
|
|
|
|
constexpr vec2() noexcept {}
|
|
constexpr vec2(const vec<2>& other) noexcept : vec(other) {}
|
|
constexpr vec2(fixed _x, fixed _y) noexcept {
|
|
x = _x;
|
|
y = _y;
|
|
}
|
|
};
|
|
|
|
class vec3 : public vec<3> {
|
|
public:
|
|
fixed& x = e[0];
|
|
fixed& y = e[1];
|
|
fixed& z = e[2];
|
|
|
|
constexpr vec3() noexcept {}
|
|
constexpr vec3(const vec<3>& other) noexcept : vec(other) {}
|
|
constexpr vec3(fixed _x, fixed _y, fixed _z) noexcept {
|
|
x = _x;
|
|
y = _y;
|
|
z = _z;
|
|
}
|
|
};
|
|
|
|
class vec4 : public vec<4> {
|
|
public:
|
|
fixed& x = e[0];
|
|
fixed& y = e[1];
|
|
fixed& z = e[2];
|
|
fixed& w = e[3];
|
|
|
|
constexpr vec4() noexcept {}
|
|
constexpr vec4(const vec<4>& other) noexcept : vec(other) {}
|
|
constexpr vec4(fixed _x, fixed _y, fixed _z, fixed _w) noexcept {
|
|
x = _x;
|
|
y = _y;
|
|
z = _z;
|
|
w = _w;
|
|
}
|
|
};
|
|
|
|
template <typename STREAM_TYPE, size_t N>
|
|
STREAM_TYPE& operator<<(STREAM_TYPE& lhs, const vec<N>& rhs) {
|
|
lhs << '<';
|
|
|
|
for (size_t i = 0; i < N; ++i) {
|
|
lhs << rhs.e[i];
|
|
|
|
if (i < N - 1) {
|
|
lhs << ", ";
|
|
}
|
|
}
|
|
|
|
lhs << '>';
|
|
|
|
return lhs;
|
|
}
|
|
|
|
} // namespace mtl
|
|
|