#include "Vector.hh" #include #include #include #include "Strings.hh" namespace phosg { template Vector2::Vector2() : x(0), y(0) {} template Vector2::Vector2(T x, T y) : x(x), y(y) {} template Vector2 Vector2::operator-() const { return Vector2(-this->x, -this->y); } template Vector2 Vector2::operator+(const Vector2& other) const { return Vector2(this->x + other.x, this->y + other.y); } template Vector2 Vector2::operator-(const Vector2& other) const { return Vector2(this->x - other.x, this->y - other.y); } template Vector2 Vector2::operator+(T other) const { return Vector2(this->x + other, this->y + other); } template Vector2 Vector2::operator-(T other) const { return Vector2(this->x - other, this->y - other); } template Vector2 Vector2::operator*(T other) const { return Vector2(this->x * other, this->y * other); } template Vector2 Vector2::operator/(T other) const { return Vector2(this->x / other, this->y / other); } template Vector2 Vector2::operator%(T other) const { return Vector2(this->x % other, this->y % other); } template Vector2& Vector2::operator+=(const Vector2& other) { this->x += other.x; this->y += other.y; return *this; } template Vector2& Vector2::operator-=(const Vector2& other) { this->x -= other.x; this->y -= other.y; return *this; } template Vector2& Vector2::operator+=(T other) { this->x += other; this->y += other; return *this; } template Vector2& Vector2::operator-=(T other) { this->x -= other; this->y -= other; return *this; } template Vector2& Vector2::operator*=(T other) { this->x *= other; this->y *= other; return *this; } template Vector2& Vector2::operator/=(T other) { this->x /= other; this->y /= other; return *this; } template Vector2& Vector2::operator%=(T other) { this->x %= other; this->y %= other; return *this; } template bool Vector2::operator!() const { return (this->x == 0) && (this->y == 0); } template bool Vector2::operator==(const Vector2& other) const { return (this->x == other.x) && (this->y == other.y); } template bool Vector2::operator!=(const Vector2& other) const { return !(this->operator==(other)); } template bool Vector2::operator<(const Vector2& other) const { if (this->x < other.x) { return true; } if (this->x > other.x) { return false; } return this->y < other.y; } template T Vector2::at(size_t dim) const { return reinterpret_cast(this)[dim]; } template T Vector2::norm1() const { return this->x + this->y; } template double Vector2::norm() const { return sqrt(this->norm2()); } template T Vector2::norm2() const { return (this->x * this->x) + (this->y * this->y); } template T Vector2::dot(const Vector2& other) const { return (this->x * other.x) + (this->y * other.y); } template std::string Vector2::str() const { return std::format("[{:g}, {:g}]", this->x, this->y); } template constexpr size_t Vector2::dimensions() { return 2; } template Vector3::Vector3() : x(0), y(0), z(0) {} template Vector3::Vector3(T x, T y, T z) : x(x), y(y), z(z) {} template Vector3::Vector3(const Vector2& xy, T z) : x(xy.x), y(xy.y), z(z) {} template Vector3 Vector3::operator-() const { return Vector3(-this->x, -this->y, -this->z); } template Vector3 Vector3::operator+(const Vector3& other) const { return Vector3(this->x + other.x, this->y + other.y, this->z + other.z); } template Vector3 Vector3::operator-(const Vector3& other) const { return Vector3(this->x - other.x, this->y - other.y, this->z - other.z); } template Vector3 Vector3::operator+(T other) const { return Vector3(this->x + other, this->y + other, this->z + other); } template Vector3 Vector3::operator-(T other) const { return Vector3(this->x - other, this->y - other, this->z - other); } template Vector3 Vector3::operator*(T other) const { return Vector3(this->x * other, this->y * other, this->z * other); } template Vector3 Vector3::operator/(T other) const { return Vector3(this->x / other, this->y / other, this->z / other); } template Vector3 Vector3::operator%(T other) const { return Vector3(this->x % other, this->y % other, this->z % other); } template Vector3& Vector3::operator+=(const Vector3& other) { this->x += other.x; this->y += other.y; this->z += other.z; return *this; } template Vector3& Vector3::operator-=(const Vector3& other) { this->x -= other.x; this->y -= other.y; this->z -= other.z; return *this; } template Vector3& Vector3::operator+=(T other) { this->x += other; this->y += other; this->z += other; return *this; } template Vector3& Vector3::operator-=(T other) { this->x -= other; this->y -= other; this->z -= other; return *this; } template Vector3& Vector3::operator*=(T other) { this->x *= other; this->y *= other; this->z *= other; return *this; } template Vector3& Vector3::operator/=(T other) { this->x /= other; this->y /= other; this->z /= other; return *this; } template Vector3& Vector3::operator%=(T other) { this->x %= other; this->y %= other; this->z %= other; return *this; } template bool Vector3::operator!() const { return (this->x == 0) && (this->y == 0) && (this->z == 0); } template bool Vector3::operator==(const Vector3& other) const { return (this->x == other.x) && (this->y == other.y) && (this->z == other.z); } template bool Vector3::operator!=(const Vector3& other) const { return !(this->operator==(other)); } template bool Vector3::operator<(const Vector3& other) const { if (this->x < other.x) { return true; } if (this->x > other.x) { return false; } if (this->y < other.y) { return true; } if (this->y > other.y) { return false; } return this->z < other.z; } template T Vector3::at(size_t dim) const { return reinterpret_cast(this)[dim]; } template T Vector3::norm1() const { return this->x + this->y + this->z; } template double Vector3::norm() const { return sqrt(this->norm2()); } template T Vector3::norm2() const { return (this->x * this->x) + (this->y * this->y) + (this->z * this->z); } template T Vector3::dot(const Vector3& other) const { return (this->x * other.x) + (this->y * other.y) + (this->z * other.z); } template Vector3 Vector3::cross(const Vector3& other) const { return Vector3( this->y * other.z - this->z * other.y, this->z * other.x - this->x * other.z, this->x * other.y - this->y * other.x); } template std::string Vector3::str() const { return std::format("[{:g}, {:g}, {:g}]", this->x, this->y, this->z); } template constexpr size_t Vector3::dimensions() { return 3; } template Vector4::Vector4() : x(0), y(0), z(0), w(0) {} template Vector4::Vector4(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {} template Vector4::Vector4(const Vector2& xy, T z, T w) : x(xy.x), y(xy.y), z(z), w(w) {} template Vector4::Vector4(const Vector3& xyz, T w) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {} template Vector4 Vector4::operator-() const { return Vector4(-this->x, -this->y, -this->z, -this->w); } template Vector4 Vector4::operator+(const Vector4& other) const { return Vector4(this->x + other.x, this->y + other.y, this->z + other.z, this->w + other.w); } template Vector4 Vector4::operator-(const Vector4& other) const { return Vector4(this->x - other.x, this->y - other.y, this->z - other.z, this->w - other.w); } template Vector4 Vector4::operator+(T other) const { return Vector4(this->x + other, this->y + other, this->z + other, this->w + other); } template Vector4 Vector4::operator-(T other) const { return Vector4(this->x - other, this->y - other, this->z - other, this->w - other); } template Vector4 Vector4::operator*(T other) const { return Vector4(this->x * other, this->y * other, this->z * other, this->w * other); } template Vector4 Vector4::operator/(T other) const { return Vector4(this->x / other, this->y / other, this->z / other, this->w / other); } template Vector4 Vector4::operator%(T other) const { return Vector4(this->x % other, this->y % other, this->z % other, this->w % other); } template Vector4& Vector4::operator+=(const Vector4& other) { this->x += other.x; this->y += other.y; this->z += other.z; this->w += other.w; return *this; } template Vector4& Vector4::operator-=(const Vector4& other) { this->x -= other.x; this->y -= other.y; this->z -= other.z; this->w -= other.w; return *this; } template Vector4& Vector4::operator+=(T other) { this->x += other; this->y += other; this->z += other; this->w += other; return *this; } template Vector4& Vector4::operator-=(T other) { this->x -= other; this->y -= other; this->z -= other; this->w -= other; return *this; } template Vector4& Vector4::operator*=(T other) { this->x *= other; this->y *= other; this->z *= other; this->w *= other; return *this; } template Vector4& Vector4::operator/=(T other) { this->x /= other; this->y /= other; this->z /= other; this->w /= other; return *this; } template Vector4& Vector4::operator%=(T other) { this->x %= other; this->y %= other; this->z %= other; this->w %= other; return *this; } template bool Vector4::operator!() const { return (this->x == 0) && (this->y == 0) && (this->z == 0) && (this->w == 0); } template bool Vector4::operator==(const Vector4& other) const { return (this->x == other.x) && (this->y == other.y) && (this->z == other.z) && (this->w == other.w); } template bool Vector4::operator!=(const Vector4& other) const { return !(this->operator==(other)); } template bool Vector4::operator<(const Vector4& other) const { if (this->x < other.x) { return true; } if (this->x > other.x) { return false; } if (this->y < other.y) { return true; } if (this->y > other.y) { return false; } if (this->z < other.z) { return true; } if (this->z > other.z) { return false; } return this->w < other.w; } template T Vector4::at(size_t dim) const { return reinterpret_cast(this)[dim]; } template T Vector4::norm1() const { return this->x + this->y + this->z + this->w; } template double Vector4::norm() const { return sqrt(this->norm2()); } template T Vector4::norm2() const { return (this->x * this->x) + (this->y * this->y) + (this->z * this->z) + (this->w * this->w); } template T Vector4::dot(const Vector4& other) const { return (this->x * other.x) + (this->y * other.y) + (this->z * other.z) + (this->w * other.w); } template std::string Vector4::str() const { return std::format("[{:g}, {:g}, {:g}, {:g}]", this->x, this->y, this->z, this->w); } template constexpr size_t Vector4::dimensions() { return 4; } template Matrix4::Matrix4() { for (size_t x = 0; x < 4; x++) { for (size_t y = 0; y < 4; y++) { this->m[x][y] = (y == x); } } } template Matrix4 Matrix4::operator+(const Matrix4& other) const { Matrix4 res; for (size_t z = 0; z < 16; z++) { res.v[z] = this->v[z] + other.v[z]; } return res; } template Matrix4 Matrix4::operator-(const Matrix4& other) const { Matrix4 res; for (size_t z = 0; z < 16; z++) { res.v[z] = this->v[z] - other.v[z]; } return res; } template Matrix4 Matrix4::operator+(T other) const { Matrix4 res; for (size_t z = 0; z < 16; z++) { res.v[z] = this->v[z] + other; } return res; } template Matrix4 Matrix4::operator-(T other) const { Matrix4 res; for (size_t z = 0; z < 16; z++) { res.v[z] = this->v[z] - other; } return res; } template Matrix4 Matrix4::operator*(T other) const { Matrix4 res; for (size_t z = 0; z < 16; z++) { res.v[z] = this->v[z] * other; } return res; } template Matrix4 Matrix4::operator/(T other) const { Matrix4 res; for (size_t z = 0; z < 16; z++) { res.v[z] = this->v[z] / other; } return res; } template Matrix4 Matrix4::operator%(T other) const { Matrix4 res; for (size_t z = 0; z < 16; z++) { res.v[z] = this->v[z] % other; } return res; } template Matrix4& Matrix4::operator+=(const Matrix4& other) { for (size_t z = 0; z < 16; z++) { this->v[z] += other.v[z]; } return *this; } template Matrix4& Matrix4::operator-=(const Matrix4& other) { for (size_t z = 0; z < 16; z++) { this->v[z] -= other.v[z]; } return *this; } template Matrix4& Matrix4::operator+=(T other) { for (size_t z = 0; z < 16; z++) { this->v[z] += other; } return *this; } template Matrix4& Matrix4::operator-=(T other) { for (size_t z = 0; z < 16; z++) { this->v[z] -= other; } return *this; } template Matrix4& Matrix4::operator*=(T other) { for (size_t z = 0; z < 16; z++) { this->v[z] *= other; } return *this; } template Matrix4& Matrix4::operator/=(T other) { for (size_t z = 0; z < 16; z++) { this->v[z] /= other; } return *this; } template Matrix4& Matrix4::operator%=(T other) { for (size_t z = 0; z < 16; z++) { this->v[z] %= other; } return *this; } template Vector4 Matrix4::operator*(const Vector4& other) const { return Vector4( this->m[0][0] * other.x + this->m[1][0] * other.y + this->m[2][0] * other.z + this->m[3][0] * other.w, this->m[0][1] * other.x + this->m[1][1] * other.y + this->m[2][1] * other.z + this->m[3][1] * other.w, this->m[0][2] * other.x + this->m[1][2] * other.y + this->m[2][2] * other.z + this->m[3][2] * other.w, this->m[0][3] * other.x + this->m[1][3] * other.y + this->m[2][3] * other.z + this->m[3][3] * other.w); } template Matrix4 Matrix4::operator*(const Matrix4& other) const { Matrix4 res; for (size_t x = 0; x < 4; x++) { for (size_t y = 0; y < 4; y++) { double value = 0; for (size_t z = 0; z < 4; z++) { value += this->m[z][y] * other.m[x][z]; } res.m[x][y] = value; } } return res; } template Matrix4 Matrix4::operator*=(const Matrix4& other) { Matrix4 res = *this * other; *this = res; return *this; } template bool Matrix4::operator==(const Matrix4& other) const { for (size_t z = 0; z < 16; z++) { if (this->v[z] != other.v[z]) { return false; } } return true; } template bool Matrix4::operator!=(const Matrix4& other) const { return !(this->operator==(other)); } template Matrix4 Matrix4::transposition() const { Matrix4 res; for (size_t x = 0; x < 4; x++) { for (size_t y = 0; y < 4; y++) { res.m[y][x] = this->m[x][y]; } } return res; } template Matrix4& Matrix4::transpose() { Matrix4 t = this->transposition(); *this = t; return *this; } template Matrix4 Matrix4::inverse() const { Matrix4 res = *this; res.invert(); return res; } template Matrix4& Matrix4::invert() { Matrix4 left = *this; *this = Matrix4(); // identity for (size_t z = 0; z < 4; z++) { // make m[z][z] be 1 double row_divisor = left.m[z][z]; if (row_divisor == 0.0) { throw std::runtime_error("matrix is not invertible"); } for (size_t x = 0; x < 4; x++) { left.m[x][z] /= row_divisor; this->m[x][z] /= row_divisor; } // make m[z][y] be zero for all y != z by adding rows for (size_t y = 0; y < 4; y++) { if (y == z) { continue; } double add_factor = -left.m[z][y]; if (add_factor == 0) { continue; } for (size_t x = 0; x < 4; x++) { left.m[x][y] += left.m[x][z] * add_factor; this->m[x][y] += this->m[x][z] * add_factor; } } } return *this; } template std::string Matrix4::str() const { return std::format("[[{:g}, {:g}, {:g}, {:g}], [{:g}, {:g}, {:g}, {:g}], [{:g}, {:g}, {:g}, {:g}], [{:g}, {:g}, {:g}, {:g}]]", this->m[0][0], this->m[1][0], this->m[2][0], this->m[3][0], this->m[0][1], this->m[1][1], this->m[2][1], this->m[3][1], this->m[0][2], this->m[1][2], this->m[2][2], this->m[3][2], this->m[0][3], this->m[1][3], this->m[2][3], this->m[3][3]); } } // namespace phosg