Skip to content

Commit

Permalink
Add macro system for vector templates of any size
Browse files Browse the repository at this point in the history
  • Loading branch information
Hop311 committed Nov 26, 2024
1 parent df5e690 commit 5a2aebe
Show file tree
Hide file tree
Showing 2 changed files with 306 additions and 153 deletions.
187 changes: 34 additions & 153 deletions src/openvic-simulation/types/Vector.hpp
Original file line number Diff line number Diff line change
@@ -1,161 +1,42 @@
#pragma once

#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"

namespace OpenVic {

template<typename T>
struct vec2_t {
/* PROPERTY generated getter functions will return 2D vectors by value, rather than const reference. */
using ov_return_by_value = void;

using type = T;

T x, y;

constexpr vec2_t() = default;
explicit constexpr vec2_t(T new_val) : x { new_val }, y { new_val } {}
constexpr vec2_t(T new_x, T new_y) : x { new_x }, y { new_y } {}

constexpr vec2_t(vec2_t const&) = default;
constexpr vec2_t(vec2_t&&) = default;
constexpr vec2_t& operator=(vec2_t const&) = default;
constexpr vec2_t& operator=(vec2_t&&) = default;

template<typename S>
constexpr explicit operator vec2_t<S>() const {
return { static_cast<S>(x), static_cast<S>(y) };
}

constexpr vec2_t abs() const {
return { x >= 0 ? x : -x, y >= 0 ? y : -y };
}
constexpr T length_squared() const {
return x * x + y * y;
}
#define VEC_TYPE vec2_t
#define FOR_VEC_COMPONENTS(F, SEP) F(x) SEP F(y)
#include "VectorN.inc"

constexpr bool nonnegative() const {
return x >= 0 && y >= 0;
}
/* Checks that both coordinates are less than their corresponding values in the argument vector.
* This is intended for checking coordinates lie within certain bounds, it is not suitable for sorting vectors. */
constexpr bool less_than(vec2_t const& vec) const {
return x < vec.x && y < vec.y;
}
#define VEC_TYPE vec3_t
#define FOR_VEC_COMPONENTS(F, SEP) F(x) SEP F(y) SEP F(z)
#include "VectorN.inc"

constexpr T* data() {
return reinterpret_cast<T*>(this);
}
constexpr T const* data() const {
return reinterpret_cast<T const*>(this);
}
#define VEC_TYPE vec4_t
#define FOR_VEC_COMPONENTS(F, SEP) F(x) SEP F(y) SEP F(z) SEP F(w)
#include "VectorN.inc"

constexpr T& operator[](size_t index) {
return data()[index & 1];
}
constexpr T const& operator[](size_t index) const {
return data()[index & 1];
}

constexpr friend vec2_t operator+(vec2_t const& left, vec2_t const& right) {
return { left.x + right.x, left.y + right.y };
}
constexpr vec2_t& operator+=(vec2_t const& right) {
x += right.x;
y += right.y;
return *this;
}
constexpr friend vec2_t operator+(vec2_t const& left, T const& right) {
return { left.x + right, left.y + right };
}
constexpr friend vec2_t operator+(T const& left, vec2_t const& right) {
return { left + right.x, left + right.y };
}
constexpr vec2_t& operator+=(T const& right) {
x += right;
y += right;
return *this;
}

constexpr friend vec2_t operator-(vec2_t const& arg) {
return { -arg.x, -arg.y };
}

constexpr friend vec2_t operator-(vec2_t const& left, vec2_t const& right) {
return { left.x - right.x, left.y - right.y };
}
constexpr vec2_t& operator-=(vec2_t const& right) {
x -= right.x;
y -= right.y;
return *this;
}
constexpr friend vec2_t operator-(vec2_t const& left, T const& right) {
return { left.x - right, left.y - right };
}
constexpr friend vec2_t operator-(T const& left, vec2_t const& right) {
return { left - right.x, left - right.y };
}
constexpr vec2_t& operator-=(T const& right) {
x -= right;
y -= right;
return *this;
}

constexpr friend vec2_t operator*(vec2_t const& left, vec2_t const& right) {
return { left.x * right.x, left.y * right.y };
}
constexpr vec2_t& operator*=(vec2_t const& right) {
x *= right.x;
y *= right.y;
return *this;
}
constexpr friend vec2_t operator*(vec2_t const& left, T const& right) {
return { left.x * right, left.y * right };
}
constexpr friend vec2_t operator*(T const& left, vec2_t const& right) {
return { left * right.x, left * right.y };
}
constexpr vec2_t& operator*=(T const& right) {
x *= right;
y *= right;
return *this;
}

constexpr friend vec2_t operator/(vec2_t const& left, vec2_t const& right) {
return { left.x / right.x, left.y / right.y };
}
constexpr vec2_t& operator/=(vec2_t const& right) {
x /= right.x;
y /= right.y;
return *this;
}
constexpr friend vec2_t operator/(vec2_t const& left, T const& right) {
return { left.x / right, left.y / right };
}
constexpr friend vec2_t operator/(T const& left, vec2_t const& right) {
return { left / right.x, left / right.y };
}
constexpr vec2_t& operator/=(T const& right) {
x /= right;
y /= right;
return *this;
}

constexpr friend bool operator==(vec2_t const& left, vec2_t const& right) {
return left.x == right.x && left.y == right.y;
}
constexpr friend bool operator!=(vec2_t const& left, vec2_t const& right) {
return left.x != right.x || left.y != right.y;
}

constexpr friend std::ostream& operator<<(std::ostream& stream, vec2_t const& value) {
return stream << "(" << value.x << ", " << value.y << ")";
}
};
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"

using ivec2_t = vec2_t<int32_t>;
using fvec2_t = vec2_t<fixed_point_t>;
namespace OpenVic {

static_assert(sizeof(ivec2_t) == 2 * sizeof(ivec2_t::type), "ivec2_t size does not equal the sum of its parts' sizes");
static_assert(sizeof(fvec2_t) == 2 * sizeof(fvec2_t::type), "fvec2_t size does not equal the sum of its parts' sizes");
#define MAKE_VEC_ALIAS(prefix, type, size) \
using prefix##vec##size##_t = vec##size##_t<type>; \
static_assert( \
sizeof(prefix##vec##size##_t) == size * sizeof(type), \
#prefix "vec" #size "_t size does not equal the sum of its parts' sizes" \
);

#define MAKE_VEC_ALIASES(prefix, type) \
MAKE_VEC_ALIAS(prefix, type, 2) \
MAKE_VEC_ALIAS(prefix, type, 3) \
MAKE_VEC_ALIAS(prefix, type, 4)

MAKE_VEC_ALIASES(i, int32_t)
MAKE_VEC_ALIASES(f, fixed_point_t)

#undef MAKE_VEC_ALIASES
#undef MAKE_VEC_ALIAS

// Check that everything is ordered correctly in the union
static_assert(offsetof(fvec4_t, x) == offsetof(fvec2_t, components[0]));
static_assert(offsetof(fvec4_t, y) == offsetof(fvec2_t, components[1]));
static_assert(offsetof(fvec4_t, z) == offsetof(fvec2_t, components[2]));
static_assert(offsetof(fvec4_t, w) == offsetof(fvec2_t, components[3]));
}
Loading

0 comments on commit 5a2aebe

Please sign in to comment.