-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add macro system for vector templates of any size
- Loading branch information
Showing
2 changed files
with
306 additions
and
153 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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])); | ||
} |
Oops, something went wrong.