summaryrefslogtreecommitdiff
path: root/src/math.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/math.hpp')
-rw-r--r--src/math.hpp231
1 files changed, 231 insertions, 0 deletions
diff --git a/src/math.hpp b/src/math.hpp
new file mode 100644
index 0000000..b958092
--- /dev/null
+++ b/src/math.hpp
@@ -0,0 +1,231 @@
+template <typename T, size_t N>
+class vec_t {
+ template<size_t index, typename... U>
+ void load_from_args(void)
+ {
+ static_assert(index < N + 1, "too many elements in the initializer");
+ static_assert(index > N - 1, "too few elements in the initializer");
+ }
+
+ template<size_t index, typename... U>
+ void load_from_args(T first, U... rest)
+ {
+ v[index] = first;
+ load_from_args<index + 1>(rest...);
+ }
+
+public:
+ T v[N];
+
+ // Basic operations
+
+ vec_t() = default;
+
+ template<typename... U>
+ vec_t(T first, U... rest)
+ {
+ load_from_args<0>(first, rest...);
+ }
+
+ template<typename U>
+ vec_t(vec_t<U, N> b)
+ {
+ for (size_t i = 0; i < N; i++)
+ v[i] = (T)b[i];
+ }
+
+ T& operator[](size_t i)
+ {
+ return v[i];
+ }
+
+ const T& operator[](size_t i) const
+ {
+ return v[i];
+ }
+
+ // Comparison
+
+ friend bool operator==(const vec_t<T, N> &a, const vec_t<T, N> &b)
+ {
+ for (size_t i = 0; i < N; i++)
+ if (a[i] != b[i])
+ return false;
+
+ return true;
+ }
+
+ // Good enough for maps or sets.
+ friend bool operator<(const vec_t<T, N> &a, const vec_t<T, N> &b)
+ {
+ for (size_t i = 0; i < N; i++) {
+ if (a[i] < b[i])
+ return true;
+ else if (a[i] > b[i])
+ return false;
+ }
+
+ return false;
+ }
+
+ // Arithmetics
+
+ friend vec_t<T, N> operator+(const vec_t<T, N> &v)
+ {
+ return v;
+ }
+
+ friend vec_t<T, N> operator+(const vec_t<T, N> &a, const vec_t<T, N> &b)
+ {
+ vec_t<T, N> r;
+
+ for (size_t i = 0; i < N; i++)
+ r[i] = a[i] + b[i];
+
+ return r;
+ }
+
+ friend vec_t<T, N> &operator+=(vec_t<T, N> &v, const vec_t<T, N> &b)
+ {
+ for (size_t i = 0; i < N; i++)
+ v[i] += b[i];
+
+ return v;
+ }
+
+ friend vec_t<T, N> operator-(const vec_t<T, N> &v)
+ {
+ return -1 * v;
+ }
+
+ friend vec_t<T, N> operator-(const vec_t<T, N> &a, const vec_t<T, N> &b)
+ {
+ vec_t<T, N> r;
+
+ for (size_t i = 0; i < N; i++)
+ r[i] = a[i] - b[i];
+
+ return r;
+ }
+
+ friend vec_t<T, N> &operator-=(vec_t<T, N> &v, const vec_t<T, N> &b)
+ {
+ for (size_t i = 0; i < N; i++)
+ v[i] -= b[i];
+
+ return v;
+ }
+
+ friend T operator*(const vec_t<T, N> &a, const vec_t<T, N> &b)
+ {
+ T r = (T)0;
+
+ for (size_t i = 0; i < N; i++)
+ r += a[i] * b[i];
+
+ return r;
+ }
+
+ friend vec_t<T, N> operator*(const vec_t<T, N> &a, const T &b)
+ {
+ vec_t<T, N> r;
+
+ for (size_t i = 0; i < N; i++)
+ r[i] = a[i] * b;
+
+ return r;
+ }
+
+ friend vec_t<T, N> operator*(const T &b, const vec_t<T, N> &a)
+ {
+ return a * b;
+ }
+
+ friend vec_t<T, N> &operator*=(vec_t<T, N> &v, const T &b)
+ {
+ for (size_t i = 0; i < N; i++)
+ v[i] *= b;
+
+ return v;
+ }
+
+ friend vec_t<T, N> operator/(const vec_t<T, N> &a, const T &b)
+ {
+ vec_t<T, N> r;
+
+ for (size_t i = 0; i < N; i++)
+ r[i] = a[i] / b;
+
+ return r;
+ }
+
+ friend vec_t<T, N> operator/(const T &b, const vec_t<T, N> &a)
+ {
+ return a / b;
+ }
+
+ friend vec_t<T, N> &operator/=(vec_t<T, N> &v, const T &b)
+ {
+ for (size_t i = 0; i < N; i++)
+ v[i] /= b;
+
+ return v;
+ }
+
+ // Compatibility with SFML
+
+ template <typename U>
+ operator sf::Vector2<U>() const
+ {
+ static_assert(N == 2, "conversion of vec_t with N != 2 to sf::Vector2");
+ return sf::Vector2<U>((U)v[0], (U)v[1]);
+ }
+
+ template <typename U>
+ vec_t(sf::Vector2<U> b)
+ {
+ static_assert(N == 2, "conversion of sf::Vector2 to vec_t with N != 2");
+ v[0] = b.x;
+ v[1] = b.y;
+ }
+
+ // Compatibility with iostream
+
+ friend std::ostream& operator<<(std::ostream& stream, vec_t<T, N> v)
+ {
+ stream << "(";
+ for (size_t i = 0; i < N; i++) {
+ if (i)
+ stream << ", ";
+ stream << v.v[i];
+ }
+ stream << ")";
+
+ return stream;
+ }
+};
+
+// Shorthands
+typedef vec_t<float, 2> v2f_t;
+typedef vec_t<double, 2> v2d_t;
+
+template <typename T, size_t N>
+class rect_t {
+public:
+ vec_t<T, N> a, b;
+
+ rect_t() = default;
+
+ rect_t(vec_t<T, N> a_, vec_t<T, N> b_)
+ {
+ a = a_;
+ b = b_;
+ }
+
+ friend std::ostream& operator<<(std::ostream& stream, rect_t<T, N> r)
+ {
+ stream << "(" << r.a << ", " << r.b << ")";
+ return stream;
+ }
+};
+