From d95473e3a3024d061d9425aa0124e322237c585b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Fatka?= <fatkaj@ntis.zcu.cz>
Date: Tue, 21 Feb 2017 17:43:42 +0100
Subject: [PATCH 01/11] Improved math::Vector code and added tests.

---
 include/cece/math/Vector.hpp    | 1042 ++++++++++++++++++++++---------
 include/cece/math/Zero.hpp      |    6 +-
 include/cece/math/constants.hpp |    6 +-
 unittests/math/CMakeLists.txt   |    3 +-
 unittests/math/Vector_test.cpp  |  650 +++++++++++++++++++
 5 files changed, 1421 insertions(+), 286 deletions(-)
 create mode 100644 unittests/math/Vector_test.cpp

diff --git a/include/cece/math/Vector.hpp b/include/cece/math/Vector.hpp
index 23c4480..c3537b6 100644
--- a/include/cece/math/Vector.hpp
+++ b/include/cece/math/Vector.hpp
@@ -1,5 +1,5 @@
 /* ************************************************************************ */
-/* Georgiev Lab (c) 2015-2016                                               */
+/* Georgiev Lab (c) 2015-2017                                               */
 /* ************************************************************************ */
 /* Department of Cybernetics                                                */
 /* Faculty of Applied Sciences                                              */
@@ -29,6 +29,7 @@
 
 // C++
 #include <cmath>
+#include <initializer_list>
 #include <type_traits>
 
 // CeCe
@@ -49,14 +50,16 @@ namespace math {
 /* ************************************************************************ */
 
 /**
- * @brief N dimensional vector.
+ * @brief      N dimensional vector.
  *
- * @tparam T Element type.
- * @tparam N Number of elements.
+ * @tparam     T     Element type.
+ * @tparam     N     Number of elements.
  */
-template<typename T, unsigned N>
+template<typename T, int N>
 class BasicVector
 {
+    static_assert(N > 0, "Cannot create empty vector");
+
 
 // Public Types
 public:
@@ -65,62 +68,77 @@ class BasicVector
     /// BasicVector value type.
     using ValueType = T;
 
+    /// Element type squared.
+    using ValueTypeSq = decltype(std::declval<T>() * std::declval<T>());
 
-// Public Contants
+
+// Public Ctors
 public:
 
 
-    /// Number of elements
-    static constexpr unsigned SIZE = N;
+    /**
+     * @brief      Default constructor.
+     */
+    BasicVector() noexcept;
 
 
-// Public Ctors
-public:
+    /**
+     * @brief      Constructor.
+     *
+     * @param      data  The source data.
+     */
+    BasicVector(std::initializer_list<T> data) noexcept;
 
 
     /**
-     * @brief Default constructor.
+     * @brief      Constructor.
+     *
+     * @param      data  The source data.
      */
-    BasicVector() noexcept
-        : m_data{}
-    {
-        // Nothing to do
-    }
+    explicit BasicVector(T (&data)[N]) noexcept;
 
 
     /**
-     * @brief Constructor.
+     * @brief      Constructor.
      *
-     * @param data
+     * @param      data  The source data.
      */
-    explicit BasicVector(StaticArray<T, N> data) noexcept
-        : m_data(data)
-    {
-        // Nothing to do
-    }
+    explicit BasicVector(StaticArray<T, N> data) noexcept;
 
 
     /**
-     * @brief Zero value constructor.
+     * @brief      Zero value constructor.
+     *
+     * @param[in]  zero  The zero value.
      */
-    BasicVector(Zero_t) noexcept
-    {
-        for (unsigned i = 0; i < N; ++i)
-            m_data[i] = T{};
-    }
+    BasicVector(Zero_t zero) noexcept;
 
 
     /**
-     * @brief Copy constructor.
+     * @brief      Copy constructor.
      *
-     * @param v Source vector.
+     * @param[in]  src   The source vector.
      */
-    template<typename T2>
-    explicit BasicVector(const BasicVector<T2, N>& v) noexcept
-    {
-        for (unsigned i = 0; i < N; ++i)
-            m_data[i] = static_cast<T>(v[i]);
-    }
+    BasicVector(const BasicVector& src) noexcept;
+
+
+    /**
+     * @brief      Move constructor.
+     *
+     * @param[in]  src   The source vector.
+     */
+    BasicVector(BasicVector&& src) noexcept;
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param      v     The source vector.
+     *
+     * @tparam     T2    The source vector element type.
+     */
+    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
+    explicit BasicVector(const BasicVector<T2, N>& src) noexcept;
 
 
 // Public Operators
@@ -128,170 +146,220 @@ class BasicVector
 
 
     /**
-     * @brief Unary plus operator.
+     * @brief      Copy constructor.
      *
-     * @return
+     * @param[in]  zero  The zero value.
+     *
+     * @return     *this.
      */
-    BasicVector operator+() const noexcept
-    {
-        return *this;
-    }
+    BasicVector& operator=(Zero_t zero) noexcept;
 
 
     /**
-     * @brief Unary minus operator.
+     * @brief      Copy constructor.
      *
-     * @return
+     * @param[in]  data  The source data.
+     *
+     * @return     *this.
      */
-    BasicVector operator-() const noexcept
-    {
-        BasicVector res;
+    BasicVector& operator=(std::initializer_list<T> data) noexcept;
 
-        for (unsigned i = 0; i < N; ++i)
-            res[i] = -m_data[i];
 
-        return res;
-    }
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  data  The source data.
+     *
+     * @return     *this.
+     */
+    BasicVector& operator=(T (&data)[N]) noexcept;
 
 
     /**
-     * @brief Addition operator.
+     * @brief      Copy constructor.
      *
-     * @tparam T1 Type of right operand.
+     * @param[in]  data  The source data.
      *
-     * @param rhs Right operand.
+     * @return     *this.
+     */
+    BasicVector& operator=(StaticArray<T, N> data) noexcept;
+
+
+    /**
+     * @brief      Copy constructor.
      *
-     * @return *this.
+     * @param[in]  src   The source vector.
+     *
+     * @return     *this.
      */
-    template<typename T1, typename std::enable_if<std::is_same<decltype(T{} + T1{}), T>::value>::type* = nullptr>
-    BasicVector& operator+=(const BasicVector<T1, N>& rhs) noexcept
-    {
-        for (unsigned i = 0; i < N; ++i)
-            m_data[i] += rhs[i];
+    BasicVector& operator=(const BasicVector& src) noexcept;
 
-        return *this;
-    }
+
+    /**
+     * @brief      Move constructor.
+     *
+     * @param[in]  src   The source vector.
+     *
+     * @return     *this.
+     */
+    BasicVector& operator=(BasicVector&& src) noexcept;
 
 
     /**
-     * @brief Subtraction operator.
+     * @brief      Copy constructor.
      *
-     * @tparam T1 Type of value in BasicVector operand.
+     * @param      v     The source vector.
      *
-     * @param rhs Right operand.
+     * @tparam     T2    The source vector element type.
      *
-     * @return *this.
+     * @return     *this.
      */
-    template<typename T1, typename std::enable_if<std::is_same<decltype(T{} - T1{}), T>::value>::type* = nullptr>
-    BasicVector& operator-=(const BasicVector<T1, N>& rhs) noexcept
-    {
-        for (unsigned i = 0; i < N; ++i)
-            m_data[i] -= rhs[i];
+    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
+    BasicVector& operator=(const BasicVector<T2, N>& src) noexcept;
 
-        return *this;
-    }
+
+    /**
+     * @brief      Unary plus operator.
+     *
+     * @return     Vector.
+     */
+    BasicVector operator+() const noexcept;
 
 
     /**
-     * @brief Multiplication operator.
+     * @brief      Unary minus operator.
      *
-     * @tparam T1 Type of right operand.
+     * @return     Vector.
+     */
+    BasicVector operator-() const noexcept;
+
+
+    /**
+     * @brief      Addition operator.
      *
-     * @param rhs Right operand.
+     * @param      rhs        Right operand.
      *
-     * @return *this.
+     * @tparam     T1         Type of right operand.
+     *
+     * @return     *this.
      */
-    template<typename T1, typename std::enable_if<std::is_same<decltype(T{} * T1{}), T>::value>::type* = nullptr>
-    BasicVector& operator*=(T1 rhs) noexcept
-    {
-        for (unsigned i = 0; i < N; ++i)
-            m_data[i] *= rhs;
-
-        return *this;
-    }
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() + std::declval<T1>()),
+        T
+    >::value>::type* = nullptr>
+    BasicVector& operator+=(const BasicVector<T1, N>& rhs) noexcept;
 
 
     /**
-     * @brief Multiplication operator.
+     * @brief      Subtraction operator.
      *
-     * @tparam T1 Type of value in BasicVector operand.
+     * @param      rhs        Right operand.
      *
-     * @param rhs Right operand.
+     * @tparam     T1         Type of value in BasicVector operand.
      *
-     * @return *this.
+     * @return     *this.
      */
-    template<typename T1, typename std::enable_if<std::is_same<decltype(T{} * T1{}), T>::value>::type* = nullptr>
-    BasicVector& operator*=(const BasicVector<T1, N>& rhs) noexcept
-    {
-        for (unsigned i = 0; i < N; ++i)
-            m_data[i] *= rhs[i];
-
-        return *this;
-    }
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() - std::declval<T1>()),
+        T
+    >::value>::type* = nullptr>
+    BasicVector& operator-=(const BasicVector<T1, N>& rhs) noexcept;
 
 
     /**
-     * @brief Division operator.
+     * @brief      Multiplication operator.
      *
-     * @tparam T1 Type of right operand.
+     * @param      rhs        Right operand.
      *
-     * @param rhs Right operand.
+     * @tparam     T1         Type of right operand.
      *
-     * @return *this.
+     * @return     *this.
      */
-    template<typename T1, typename std::enable_if<std::is_same<decltype(T{} / T1{}), T>::value>::type* = nullptr>
-    BasicVector& operator/=(T1 rhs) noexcept
-    {
-        for (unsigned i = 0; i < N; ++i)
-            m_data[i] /= rhs;
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() * std::declval<T1>()),
+        T
+    >::value || std::is_constructible<
+        T,
+        decltype(std::declval<T>() * std::declval<T1>())
+    >::value>::type* = nullptr>
+    BasicVector& operator*=(T1 rhs) noexcept;
 
-        return *this;
-    }
+
+    /**
+     * @brief      Multiplication operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of value in BasicVector operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() * std::declval<T1>()),
+        T
+    >::value || std::is_constructible<
+        T,
+        decltype(std::declval<T>() * std::declval<T1>())
+    >::value>::type* = nullptr>
+    BasicVector& operator*=(const BasicVector<T1, N>& rhs) noexcept;
 
 
     /**
-     * @brief Division operator.
+     * @brief      Division operator.
      *
-     * @tparam T1 Type of value in BasicVector operand.
+     * @param      rhs        Right operand.
      *
-     * @param rhs Right operand.
+     * @tparam     T1         Type of right operand.
      *
-     * @return *this.
+     * @return     *this.
      */
-    template<typename T1, typename std::enable_if<std::is_same<decltype(T{} / T1{}), T>::value>::type* = nullptr>
-    BasicVector& operator/=(const BasicVector<T1, N>& rhs) noexcept
-    {
-        for (unsigned i = 0; i < N; ++i)
-            m_data[i] /= rhs[i];
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() / std::declval<T1>()),
+        T
+    >::value || std::is_constructible<
+        T,
+        decltype(std::declval<T>() * std::declval<T1>())
+    >::value>::type* = nullptr>
+    BasicVector& operator/=(T1 rhs) noexcept;
 
-        return *this;
-    }
+
+    /**
+     * @brief      Division operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of value in BasicVector operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() / std::declval<T1>()),
+        T
+    >::value || std::is_constructible<
+        T,
+        decltype(std::declval<T>() * std::declval<T1>())
+    >::value>::type* = nullptr>
+    BasicVector& operator/=(const BasicVector<T1, N>& rhs) noexcept;
 
 
     /**
-     * @brief Access operator.
+     * @brief      Access operator.
      *
-     * @param pos
+     * @param      pos   The position.
      *
-     * @return
+     * @return     Reference to the element.
      */
-    T& operator[](unsigned pos) noexcept
-    {
-        return m_data[pos];
-    }
+    T& operator[](int pos) noexcept;
 
 
     /**
-     * @brief Access operator.
+     * @brief      Access operator.
      *
-     * @param pos
+     * @param      pos   The position.
      *
-     * @return
+     * @return     Reference to the element.
      */
-    const T& operator[](unsigned pos) const noexcept
-    {
-        return m_data[pos];
-    }
+    const T& operator[](int pos) const noexcept;
 
 
 // Public Accessors
@@ -299,37 +367,45 @@ class BasicVector
 
 
     /**
-     * @brief Check if given value is in given range.
+     * @brief      Returns vector size.
      *
-     * @param value Given value.
-     * @param low   Minimum value (>=).
-     * @param high  Maximum value (<).
+     * @return     The size.
+     */
+    int getSize() const noexcept;
+
+
+    /**
+     * @brief      Check if given value is in given range.
      *
-     * @return
+     * @param      value  Given value.
+     * @param      low    Minimum value (>=).
+     * @param      high   Maximum value (<).
+     *
+     * @return     If given value is in given range.
      */
-    static bool inRange(T value, T low, T high) noexcept
-    {
-        return value >= low && value < high;
-    }
+    static bool inRange(T value, T low, T high) noexcept;
 
 
     /**
-     * @brief Check if current vector is in given range.
+     * @brief      Check if current vector is in given range.
      *
-     * @param low  Minimum coordinates (>=).
-     * @param high Maximum coordinates (<).
+     * @param      low   Minimum coordinates (>=).
+     * @param      high  Maximum coordinates (<).
      *
-     * @return
+     * @return     If current value is in given range.
      */
-    bool inRange(const BasicVector& low, const BasicVector& high) const noexcept
-    {
-        bool res = true;
+    bool inRange(const BasicVector& low, const BasicVector& high) const noexcept;
 
-        for (unsigned i = 0; i < N; ++i)
-            res = res && inRange(m_data[i], low[i], high[i]);
 
-        return res;
-    }
+    /**
+     * @brief      Check if current vector is in given range where the low range
+     *             is Zero vector.
+     *
+     * @param      high  Maximum coordinates (<).
+     *
+     * @return     If current value is in given range.
+     */
+    bool inRange(const BasicVector& high) const noexcept;
 
 
 // Public Operations
@@ -337,87 +413,60 @@ class BasicVector
 
 
     /**
-     * @brief Calculate vector length.
+     * @brief      Calculate vector length.
      *
-     * @return
+     * @return     The length.
      */
-    T getLength() const noexcept
-    {
-        using std::sqrt;
-        return static_cast<T>(sqrt(getLengthSquared()));
-    }
+    ValueType getLength() const noexcept;
 
 
     /**
-     * @brief Calculate vector length - squared.
+     * @brief      Calculate vector length - squared.
      *
-     * @return
+     * @return     The length squared.
      */
-    decltype(T{} * T{}) getLengthSquared() const noexcept
-    {
-        return dot(*this);
-    }
+    ValueTypeSq getLengthSquared() const noexcept;
 
 
     /**
-     * @brief Calculate dot of two vectors.
+     * @brief      Calculate dot of two vectors.
      *
-     * @param rhs Second vector.
+     * @param      rhs   Second vector.
      *
-     * @return Dot product.
+     * @return     Dot product.
      */
-    decltype(T{} * T{}) dot(const BasicVector& rhs) const noexcept
-    {
-        decltype(T{} * T{}) res{};
-
-        for (unsigned i = 0; i < N; ++i)
-            res += m_data[i] * rhs[i];
-
-        return res;
-    }
+    ValueTypeSq dot(const BasicVector& rhs) const noexcept;
 
 
     /**
-     * @brief Calculate vectors squared distance.
+     * @brief      Calculate vectors squared distance.
      *
-     * @param rhs Second vector.
+     * @param      rhs   Second vector.
      *
-     * @return Distance.
+     * @return     Distance.
      */
-    decltype(std::declval<T>() * std::declval<T>()) distanceSquared(const BasicVector& rhs) const noexcept
-    {
-        return (*this - rhs).getLengthSquared();
-    }
+    ValueTypeSq distanceSquared(const BasicVector& rhs) const noexcept;
 
 
     /**
-     * @brief Calculate vectors distance.
+     * @brief      Calculate vectors distance.
      *
-     * @param rhs Second vector.
+     * @param      rhs   Second vector.
      *
-     * @return Distance.
+     * @return     Distance.
      */
-    T distance(const BasicVector& rhs) const noexcept
-    {
-        return (*this - rhs).getLength();
-    }
+    ValueType distance(const BasicVector& rhs) const noexcept;
 
 
     /**
-     * @brief Inverse current vector (1 / *this).
+     * @brief      Inverse current vector (1 / *this).
      *
-     * @return
+     * @tparam     T2    Type of result vector's element.
+     *
+     * @return     Inversed vector.
      */
-    template<typename T2>
-    BasicVector<T2, SIZE> inversed() const noexcept
-    {
-        BasicVector<T2, SIZE> res;
-
-        for (unsigned i = 0; i < N; ++i)
-            res[i] = T2(1) / m_data[i];
-
-        return res;
-    }
+    template<typename T2 = T>
+    BasicVector<T2, N> inversed() const noexcept;
 
 
 // Public Operations
@@ -431,23 +480,15 @@ class BasicVector
      *
      * @return
      */
-    static BasicVector createSingle(T val) noexcept
-    {
-        BasicVector res;
-
-        for (unsigned i = 0; i < N; ++i)
-            res[i] = val;
-
-        return res;
-    }
+    static BasicVector createSingle(T val) noexcept;
 
 
 // Private Data Members
 private:
 
-
     /// BasicVector data.
     StaticArray<T, N> m_data;
+
 };
 
 /* ************************************************************************ */
@@ -472,7 +513,7 @@ class BasicVector<T, 2>
 
 
     /// Number of elements
-    static constexpr unsigned SIZE = 2;
+    static constexpr int SIZE = 2;
 
 
 // Public Ctors
@@ -540,7 +581,7 @@ class BasicVector<T, 2>
      *
      * @return
      */
-    T& operator[](unsigned pos) noexcept
+    T& operator[](int pos) noexcept
     {
         CECE_ASSERT(pos < SIZE);
         return (&m_x)[pos];
@@ -554,7 +595,7 @@ class BasicVector<T, 2>
      *
      * @return
      */
-    const T& operator[](unsigned pos) const noexcept
+    const T& operator[](int pos) const noexcept
     {
         CECE_ASSERT(pos < SIZE);
         return (&m_x)[pos];
@@ -700,7 +741,7 @@ class BasicVector<T, 2>
      *
      * @return
      */
-    unsigned getSize() const noexcept
+    int getSize() const noexcept
     {
         return SIZE;
     }
@@ -992,7 +1033,7 @@ class BasicVector<T, 3>
 
 
     /// Number of elements
-    static constexpr unsigned SIZE = 3;
+    static constexpr int SIZE = 3;
 
 
 // Public Ctors
@@ -1065,7 +1106,7 @@ class BasicVector<T, 3>
      *
      * @return
      */
-    T& operator[](unsigned pos) noexcept
+    T& operator[](int pos) noexcept
     {
         CECE_ASSERT(pos < SIZE);
         return (&m_x)[pos];
@@ -1079,7 +1120,7 @@ class BasicVector<T, 3>
      *
      * @return
      */
-    const T& operator[](unsigned pos) const noexcept
+    const T& operator[](int pos) const noexcept
     {
         CECE_ASSERT(pos < SIZE);
         return (&m_x)[pos];
@@ -1231,7 +1272,7 @@ class BasicVector<T, 3>
      *
      * @return
      */
-    unsigned getSize() const noexcept
+    int getSize() const noexcept
     {
         return SIZE;
     }
@@ -1586,16 +1627,30 @@ using VectorInt = Vector<int>;
 /* ************************************************************************ */
 
 /**
- * @brief Vector of unsigned int.
+ * @brief Vector of float.
+ */
+using VectorFloat = Vector<float>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief Vector of float.
+ */
+using VectorDouble = Vector<float>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief Vector of float.
  */
-using VectorUint = Vector<unsigned int>;
+using VectorLongDouble = Vector<float>;
 
 /* ************************************************************************ */
 
 /**
  * @brief Vector of float.
  */
-using VectorFloat = Vector<RealType>;
+using VectorReal = Vector<RealType>;
 
 /* ************************************************************************ */
 
@@ -1611,12 +1666,12 @@ using VectorFloat = Vector<RealType>;
  *
  * @return Result vector.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline BasicVector<decltype(T1{} + T2{}), N> operator+(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     BasicVector<decltype(T1{} + T2{}), N> res;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] + rhs[i];
 
     return res;
@@ -1658,12 +1713,12 @@ inline BasicVector<decltype(T1{} + T2{}), 2> operator+(const BasicVector<T1, 2>&
  *
  * @return Result vector.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline BasicVector<decltype(T1{} + T2{}), N> operator+(const BasicVector<T1, N>& lhs, T2 rhs) noexcept
 {
     BasicVector<decltype(T1{} + T2{}), N> res;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] + rhs;
 
     return res;
@@ -1705,12 +1760,12 @@ inline BasicVector<decltype(T1{} + T2{}), 2> operator+(const BasicVector<T1, 2>&
  *
  * @return Result vector.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline BasicVector<decltype(T1{} + T2{}), N> operator+(T1 lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     BasicVector<decltype(T1{} + T2{}), N> res;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs + rhs[i];
 
     return res;
@@ -1751,12 +1806,12 @@ inline BasicVector<decltype(T1{} + T2{}), 2> operator+(T1 lhs, const BasicVector
  *
  * @return Result vector.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline BasicVector<decltype(T1{} - T2{}), N> operator-(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     BasicVector<decltype(T1{} - T2{}), N> res;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] - rhs[i];
 
     return res;
@@ -1797,12 +1852,12 @@ inline BasicVector<decltype(T1{} - T2{}), 2> operator-(const BasicVector<T1, 2>&
  *
  * @return Result vector.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline BasicVector<decltype(T1{} - T2{}), N> operator-(const BasicVector<T1, N>& lhs, T2 rhs) noexcept
 {
     BasicVector<decltype(T1{} - T2{}), N> res;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] - rhs;
 
     return res;
@@ -1843,12 +1898,12 @@ inline BasicVector<decltype(T1{} - T2{}), 2> operator-(const BasicVector<T1, 2>&
  *
  * @return Result vector.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline BasicVector<decltype(T1{} - T2{}), N> operator-(T1 lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     BasicVector<decltype(T1{} - T2{}), N> res;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs - rhs[i];
 
     return res;
@@ -1889,12 +1944,12 @@ inline BasicVector<decltype(T1{} - T2{}), 2> operator-(T1 lhs, const BasicVector
  *
  * @return Result vector.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline BasicVector<decltype(T1{} * T2{}), N> operator*(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     BasicVector<decltype(T1{} * T2{}), N> res;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] * rhs[i];
 
     return res;
@@ -1935,12 +1990,12 @@ inline BasicVector<decltype(T1{} * T2{}), 2> operator*(const BasicVector<T1, 2>&
  *
  * @return Result vector.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline BasicVector<decltype(T1{} * T2{}), N> operator*(const BasicVector<T1, N>& lhs, T2 rhs) noexcept
 {
     BasicVector<decltype(T1{} * T2{}), N> res;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] * rhs;
 
     return res;
@@ -1981,12 +2036,12 @@ inline BasicVector<decltype(T1{} * T2{}), 2> operator*(const BasicVector<T1, 2>&
  *
  * @return Result vector.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline BasicVector<decltype(T1{} * T2{}), N> operator*(T1 lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     BasicVector<decltype(T1{} * T2{}), N> res;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs * rhs[i];
 
     return res;
@@ -2027,12 +2082,12 @@ inline BasicVector<decltype(T1{} * T2{}), 2> operator*(T1 lhs, const BasicVector
  *
  * @return Result vector.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline BasicVector<decltype(T1{} / T2{}), N> operator/(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     BasicVector<decltype(T1{} / T2{}), N> res;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] / rhs[i];
 
     return res;
@@ -2073,12 +2128,12 @@ inline BasicVector<decltype(T1{} / T2{}), 2> operator/(const BasicVector<T1, 2>&
  *
  * @return Result vector.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline BasicVector<decltype(T1{} / T2{}), N> operator/(const BasicVector<T1, N>& lhs, T2 rhs) noexcept
 {
     BasicVector<decltype(T1{} / T2{}), N> res;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] / rhs;
 
     return res;
@@ -2119,12 +2174,12 @@ inline BasicVector<decltype(T1{} / T2{}), 2> operator/(const BasicVector<T1, 2>&
  *
  * @return Result vector.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline BasicVector<decltype(T1{} / T2{}), N> operator/(T1 lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     BasicVector<decltype(T1{} / T2{}), N> res;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs / rhs[i];
 
     return res;
@@ -2162,12 +2217,12 @@ inline BasicVector<decltype(T1{} / T2{}), 2> operator/(T1 lhs, const BasicVector
  *
  * @return
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline bool operator==(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     bool res = true;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res = res && lhs[i] == rhs[i];
 
     return res;
@@ -2202,7 +2257,7 @@ inline bool operator==(const BasicVector<T1, 2>& lhs, const BasicVector<T2, 2>&
  *
  * @return
  */
-template<typename T1, unsigned N>
+template<typename T1, int N>
 inline bool operator==(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
 {
     return lhs == BasicVector<T1, N>(Zero);
@@ -2218,7 +2273,7 @@ inline bool operator==(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
  *
  * @return
  */
-template<typename T1, unsigned N>
+template<typename T1, int N>
 inline bool operator==(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
 {
     return BasicVector<T1, N>(Zero) == rhs;
@@ -2234,7 +2289,7 @@ inline bool operator==(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
  *
  * @return
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline bool operator!=(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     return !operator==(lhs, rhs);
@@ -2250,7 +2305,7 @@ inline bool operator!=(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>&
  *
  * @return
  */
-template<typename T1, unsigned N>
+template<typename T1, int N>
 inline bool operator!=(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
 {
     return !operator==(lhs, rhs);
@@ -2266,7 +2321,7 @@ inline bool operator!=(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
  *
  * @return
  */
-template<typename T1, unsigned N>
+template<typename T1, int N>
 inline bool operator!=(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
 {
     return !operator==(lhs, rhs);
@@ -2282,12 +2337,12 @@ inline bool operator!=(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
  *
  * @return
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline bool operator<(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     bool res = true;
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res = res && ((lhs[i] < rhs[i]) || !(rhs[i] < lhs[i]));
 
     return res;
@@ -2303,7 +2358,7 @@ inline bool operator<(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& r
  *
  * @return
  */
-template<typename T1, unsigned N>
+template<typename T1, int N>
 inline bool operator<(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
 {
     return lhs < BasicVector<T1, N>{Zero};
@@ -2319,7 +2374,7 @@ inline bool operator<(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
  *
  * @return
  */
-template<typename T1, unsigned N>
+template<typename T1, int N>
 inline bool operator<(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
 {
     return BasicVector<T1, N>{Zero} < rhs;
@@ -2335,7 +2390,7 @@ inline bool operator<(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
  *
  * @return
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline bool operator<=(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     return !operator>(lhs, rhs);
@@ -2351,7 +2406,7 @@ inline bool operator<=(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>&
  *
  * @return
  */
-template<typename T1, unsigned N>
+template<typename T1, int N>
 inline bool operator<=(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
 {
     return !operator>(lhs, rhs);
@@ -2367,7 +2422,7 @@ inline bool operator<=(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
  *
  * @return
  */
-template<typename T1, unsigned N>
+template<typename T1, int N>
 inline bool operator<=(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
 {
     return !operator>(lhs, rhs);
@@ -2383,7 +2438,7 @@ inline bool operator<=(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
  *
  * @return
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline bool operator>(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     // Reversed operands
@@ -2400,7 +2455,7 @@ inline bool operator>(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& r
  *
  * @return
  */
-template<typename T1, unsigned N>
+template<typename T1, int N>
 inline bool operator>(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
 {
     // Reversed operands
@@ -2417,7 +2472,7 @@ inline bool operator>(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
  *
  * @return
  */
-template<typename T1, unsigned N>
+template<typename T1, int N>
 inline bool operator>(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
 {
     // Reversed operands
@@ -2434,7 +2489,7 @@ inline bool operator>(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
  *
  * @return
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline bool operator>=(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     return !operator<(lhs, rhs);
@@ -2450,7 +2505,7 @@ inline bool operator>=(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>&
  *
  * @return
  */
-template<typename T1, unsigned N>
+template<typename T1, int N>
 inline bool operator>=(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
 {
     return !operator<(lhs, rhs);
@@ -2466,7 +2521,7 @@ inline bool operator>=(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
  *
  * @return
  */
-template<typename T1, unsigned N>
+template<typename T1, int N>
 inline bool operator>=(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
 {
     return !operator<(lhs, rhs);
@@ -2482,12 +2537,12 @@ inline bool operator>=(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
  *
  * @return Dot product.
  */
-template<typename T1, typename T2, unsigned N>
+template<typename T1, typename T2, int N>
 inline decltype(T1{} * T2{}) dot(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
 {
     decltype(T1{} * T2{}) res{};
 
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
         res += lhs[i] * rhs[i];
 
     return res;
@@ -2557,10 +2612,10 @@ cross(const T1& lhs, const BasicVector<T2, 2>& rhs) noexcept
  *
  * @return is.
  */
-template<typename T, unsigned N>
+template<typename T, int N>
 io::InStream& operator>>(io::InStream& is, BasicVector<T, N>& vector)
 {
-    unsigned i = 0;
+    int i = 0;
 
     for (; i < N; ++i)
     {
@@ -2573,7 +2628,7 @@ io::InStream& operator>>(io::InStream& is, BasicVector<T, N>& vector)
 
     // Copy missing values
     // TODO: have this feature?
-    for (unsigned j = i; j < N; ++j)
+    for (int j = i; j < N; ++j)
         vector[j] = vector[i - 1];
 
     return is;
@@ -2589,10 +2644,10 @@ io::InStream& operator>>(io::InStream& is, BasicVector<T, N>& vector)
  *
  * @return os.
  */
-template<typename T, unsigned N>
+template<typename T, int N>
 io::OutStream& operator<<(io::OutStream& os, const BasicVector<T, N>& vector) noexcept
 {
-    for (unsigned i = 0; i < N; ++i)
+    for (int i = 0; i < N; ++i)
     {
         if (i != 0)
             os << " ";
@@ -2606,8 +2661,437 @@ io::OutStream& operator<<(io::OutStream& os, const BasicVector<T, N>& vector) no
 /* ************************************************************************ */
 
 extern template class BasicVector<RealType, DIMENSION>;
-extern template class BasicVector<unsigned int, DIMENSION>;
-extern template class BasicVector<int, DIMENSION>;
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>::BasicVector() noexcept
+    : m_data{}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>::BasicVector(std::initializer_list<T> data) noexcept
+{
+    CECE_ASSERT(data.size() == N);
+
+    using std::begin;
+    auto it = begin(data);
+
+    for (int i = 0; i < N; ++i, ++it)
+        m_data[i] = *it;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>::BasicVector(T (&data)[N]) noexcept
+{
+    using std::begin;
+    auto it = begin(data);
+
+    for (int i = 0; i < N; ++i, ++it)
+        m_data[i] = *it;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>::BasicVector(StaticArray<T, N> data) noexcept
+    : m_data(data)
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>::BasicVector(Zero_t zero) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] = T{};
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>::BasicVector(const BasicVector& src) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] = src.m_data[i];
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>::BasicVector(BasicVector&& src) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] = std::move(src.m_data[i]);
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
+inline BasicVector<T, N>::BasicVector(const BasicVector<T2, N>& src) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] = T(src[i]);
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(Zero_t zero) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] = T{};
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(std::initializer_list<T> data) noexcept
+{
+    CECE_ASSERT(data.size() == N);
+
+    using std::begin;
+    auto it = begin(data);
+
+    for (int i = 0; i < N; ++i, ++it)
+        m_data[i] = *it;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(T (&data)[N]) noexcept
+{
+    using std::begin;
+    auto it = begin(data);
+
+    for (int i = 0; i < N; ++i, ++it)
+        m_data[i] = *it;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(StaticArray<T, N> data) noexcept
+{
+    m_data = data;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(const BasicVector& src) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] = src.m_data[i];
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(BasicVector&& src) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] = std::move(src.m_data[i]);
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(const BasicVector<T2, N>& src) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] = T(src[i]);
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N> BasicVector<T, N>::operator+() const noexcept
+{
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N> BasicVector<T, N>::operator-() const noexcept
+{
+    BasicVector res;
+
+    for (int i = 0; i < N; ++i)
+        res[i] = -m_data[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() + std::declval<T1>()),
+    T
+>::value>::type*>
+inline BasicVector<T, N>& BasicVector<T, N>::operator+=(const BasicVector<T1, N>& rhs) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] += rhs[i];
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() - std::declval<T1>()),
+    T
+>::value>::type*>
+inline BasicVector<T, N>& BasicVector<T, N>::operator-=(const BasicVector<T1, N>& rhs) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] -= rhs[i];
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() * std::declval<T1>()),
+    T
+>::value || std::is_constructible<
+    T,
+    decltype(std::declval<T>() * std::declval<T1>())
+>::value>::type*>
+inline BasicVector<T, N>& BasicVector<T, N>::operator*=(T1 rhs) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] *= rhs;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() * std::declval<T1>()),
+    T
+>::value || std::is_constructible<
+    T,
+    decltype(std::declval<T>() * std::declval<T1>())
+>::value>::type*>
+inline BasicVector<T, N>& BasicVector<T, N>::operator*=(const BasicVector<T1, N>& rhs) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] *= rhs[i];
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() / std::declval<T1>()),
+    T
+>::value || std::is_constructible<
+    T,
+    decltype(std::declval<T>() * std::declval<T1>())
+>::value>::type*>
+inline BasicVector<T, N>& BasicVector<T, N>::operator/=(T1 rhs) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] /= rhs;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() / std::declval<T1>()),
+    T
+>::value || std::is_constructible<
+    T,
+    decltype(std::declval<T>() * std::declval<T1>())
+>::value>::type*>
+inline BasicVector<T, N>& BasicVector<T, N>::operator/=(const BasicVector<T1, N>& rhs) noexcept
+{
+    for (int i = 0; i < N; ++i)
+        m_data[i] /= rhs[i];
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline T& BasicVector<T, N>::operator[](int pos) noexcept
+{
+    CECE_ASSERT(pos >= 0);
+    CECE_ASSERT(pos < N);
+    return m_data[pos];
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline const T& BasicVector<T, N>::operator[](int pos) const noexcept
+{
+    CECE_ASSERT(pos >= 0);
+    CECE_ASSERT(pos < N);
+    return m_data[pos];
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+int BasicVector<T, N>::getSize() const noexcept
+{
+    return N;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline bool BasicVector<T, N>::inRange(T value, T low, T high) noexcept
+{
+    return value >= low && value < high;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline bool BasicVector<T, N>::inRange(const BasicVector& low, const BasicVector& high) const noexcept
+{
+    bool res = true;
+
+    for (int i = 0; i < N; ++i)
+        res = res && inRange(m_data[i], low[i], high[i]);
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline bool BasicVector<T, N>::inRange(const BasicVector& high) const noexcept
+{
+    return inRange(Zero, high);
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline typename BasicVector<T, N>::ValueType BasicVector<T, N>::getLength() const noexcept
+{
+    using std::sqrt;
+    return static_cast<T>(sqrt(getLengthSquared()));
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline typename BasicVector<T, N>::ValueTypeSq BasicVector<T, N>::getLengthSquared() const noexcept
+{
+    return dot(*this);
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline typename BasicVector<T, N>::ValueTypeSq BasicVector<T, N>::dot(const BasicVector& rhs) const noexcept
+{
+    ValueTypeSq res{};
+
+    for (int i = 0; i < N; ++i)
+        res += m_data[i] * rhs[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline typename BasicVector<T, N>::ValueTypeSq BasicVector<T, N>::distanceSquared(const BasicVector& rhs) const noexcept
+{
+    return (*this - rhs).getLengthSquared();
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline typename BasicVector<T, N>::ValueType BasicVector<T, N>::distance(const BasicVector& rhs) const noexcept
+{
+    return (*this - rhs).getLength();
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+template<typename T2>
+inline BasicVector<T2, N> BasicVector<T, N>::inversed() const noexcept
+{
+    BasicVector<T2, N> res;
+
+    for (int i = 0; i < N; ++i)
+        res[i] = T2(1) / m_data[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline BasicVector<T, N> BasicVector<T, N>::createSingle(T val) noexcept
+{
+    BasicVector res;
+
+    for (int i = 0; i < N; ++i)
+        res[i] = val;
+
+    return res;
+}
 
 /* ************************************************************************ */
 
diff --git a/include/cece/math/Zero.hpp b/include/cece/math/Zero.hpp
index b02b3ca..7b13f36 100644
--- a/include/cece/math/Zero.hpp
+++ b/include/cece/math/Zero.hpp
@@ -1,5 +1,5 @@
 /* ************************************************************************ */
-/* Georgiev Lab (c) 2015-2016                                               */
+/* Georgiev Lab (c) 2015-2017                                               */
 /* ************************************************************************ */
 /* Department of Cybernetics                                                */
 /* Faculty of Applied Sciences                                              */
@@ -33,8 +33,8 @@ namespace math {
 /* ************************************************************************ */
 
 /**
- * @brief Special value used by other types to check if value is zero. The idea is
- * similar with nullptr (nullptr_t).
+ * @brief      Special value used by other types to check if value is zero. The
+ *             idea is similar with nullptr (nullptr_t).
  */
 constexpr struct Zero_t {} Zero{};
 
diff --git a/include/cece/math/constants.hpp b/include/cece/math/constants.hpp
index 18a6a27..1e97488 100644
--- a/include/cece/math/constants.hpp
+++ b/include/cece/math/constants.hpp
@@ -1,5 +1,5 @@
 /* ************************************************************************ */
-/* Georgiev Lab (c) 2015-2016                                               */
+/* Georgiev Lab (c) 2015-2017                                               */
 /* ************************************************************************ */
 /* Department of Cybernetics                                                */
 /* Faculty of Applied Sciences                                              */
@@ -38,14 +38,14 @@ namespace math {
 /* ************************************************************************ */
 
 /**
- * @brief PI constant.
+ * @brief      PI constant.
  */
 constexpr RealType PI = 3.14159265359;
 
 /* ************************************************************************ */
 
 /**
- * @brief Euler number constant.
+ * @brief      Euler number constant.
  */
 constexpr RealType E = 2.718281828459;
 
diff --git a/unittests/math/CMakeLists.txt b/unittests/math/CMakeLists.txt
index 03f6f4e..dc505b8 100644
--- a/unittests/math/CMakeLists.txt
+++ b/unittests/math/CMakeLists.txt
@@ -1,5 +1,5 @@
 # ######################################################################### #
-# Georgiev Lab (c) 2015-2016                                                #
+# Georgiev Lab (c) 2015-2017                                                #
 # ######################################################################### #
 # Department of Cybernetics                                                 #
 # Faculty of Applied Sciences                                               #
@@ -25,6 +25,7 @@
 
 cece_add_test(core
     SOURCES
+        Vector_test.cpp
         VectorRangeTest.cpp
 )
 
diff --git a/unittests/math/Vector_test.cpp b/unittests/math/Vector_test.cpp
new file mode 100644
index 0000000..e4ce1f2
--- /dev/null
+++ b/unittests/math/Vector_test.cpp
@@ -0,0 +1,650 @@
+/* ************************************************************************ */
+/* Georgiev Lab (c) 2015-2017                                               */
+/* ************************************************************************ */
+/* Department of Cybernetics                                                */
+/* Faculty of Applied Sciences                                              */
+/* University of West Bohemia in Pilsen                                     */
+/* ************************************************************************ */
+/*                                                                          */
+/* This file is part of CeCe.                                               */
+/*                                                                          */
+/* CeCe is free software: you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by     */
+/* the Free Software Foundation, either version 3 of the License, or        */
+/* (at your option) any later version.                                      */
+/*                                                                          */
+/* CeCe is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/* GNU General Public License for more details.                             */
+/*                                                                          */
+/* You should have received a copy of the GNU General Public License        */
+/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
+/*                                                                          */
+/* ************************************************************************ */
+
+// GTest
+#include "gtest/gtest.h"
+
+// CeCe
+#include "cece/math/Vector.hpp"
+
+/* ************************************************************************ */
+
+using namespace cece;
+using namespace cece::math;
+
+/* ************************************************************************ */
+
+TEST(Vector, ctor)
+{
+    {
+        BasicVector<int, 5> vec;
+
+        EXPECT_EQ(5, vec.getSize());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+        EXPECT_EQ(0, vec[3]);
+        EXPECT_EQ(0, vec[4]);
+    }
+
+    {
+        BasicVector<int, 10> vec(Zero);
+
+        EXPECT_EQ(10, vec.getSize());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+        EXPECT_EQ(0, vec[3]);
+        EXPECT_EQ(0, vec[4]);
+        EXPECT_EQ(0, vec[5]);
+        EXPECT_EQ(0, vec[6]);
+        EXPECT_EQ(0, vec[7]);
+        EXPECT_EQ(0, vec[8]);
+        EXPECT_EQ(0, vec[9]);
+    }
+
+    {
+        BasicVector<float, 5> vec = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+
+        EXPECT_EQ(5, vec.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec[4]);
+    }
+
+    {
+        float data[5] = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+
+        BasicVector<float, 5> vec(data);
+
+        EXPECT_EQ(5, vec.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec[4]);
+    }
+
+    {
+        StaticArray<float, 5> data = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+
+        BasicVector<float, 5> vec(data);
+
+        EXPECT_EQ(5, vec.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec[4]);
+    }
+
+    {
+        const BasicVector<float, 5> vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec1[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec1[4]);
+
+        BasicVector<float, 5> vec2(vec1);
+
+        EXPECT_EQ(5, vec2.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec2[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec2[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec2[4]);
+    }
+
+    {
+        BasicVector<float, 5> vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec1[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec1[4]);
+
+        BasicVector<float, 5> vec2(std::move(vec1));
+
+        EXPECT_EQ(5, vec2.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec2[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec2[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec2[4]);
+    }
+
+    {
+        const BasicVector<int, 5> vec1 = {1, 3, 0, 45, -34};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+        EXPECT_EQ(0, vec1[2]);
+        EXPECT_EQ(45, vec1[3]);
+        EXPECT_EQ(-34, vec1[4]);
+
+        BasicVector<float, 5> vec2(vec1);
+
+        EXPECT_EQ(5, vec2.getSize());
+        EXPECT_FLOAT_EQ(1.0, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec2[2]);
+        EXPECT_FLOAT_EQ(45.0f, vec2[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec2[4]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector, assignment)
+{
+    {
+        BasicVector<int, 10> vec{1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+
+        EXPECT_EQ(10, vec.getSize());
+        EXPECT_EQ(1, vec[0]);
+        EXPECT_EQ(1, vec[1]);
+        EXPECT_EQ(1, vec[2]);
+        EXPECT_EQ(1, vec[3]);
+        EXPECT_EQ(1, vec[4]);
+        EXPECT_EQ(1, vec[5]);
+        EXPECT_EQ(1, vec[6]);
+        EXPECT_EQ(1, vec[7]);
+        EXPECT_EQ(1, vec[8]);
+        EXPECT_EQ(1, vec[9]);
+
+        vec = Zero;
+
+        EXPECT_EQ(10, vec.getSize());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+        EXPECT_EQ(0, vec[3]);
+        EXPECT_EQ(0, vec[4]);
+        EXPECT_EQ(0, vec[5]);
+        EXPECT_EQ(0, vec[6]);
+        EXPECT_EQ(0, vec[7]);
+        EXPECT_EQ(0, vec[8]);
+        EXPECT_EQ(0, vec[9]);
+    }
+
+    {
+        BasicVector<float, 5> vec;
+
+        EXPECT_EQ(5, vec.getSize());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+        EXPECT_EQ(0, vec[3]);
+        EXPECT_EQ(0, vec[4]);
+
+        vec = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+
+        EXPECT_EQ(5, vec.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec[4]);
+    }
+
+    {
+        BasicVector<float, 5> vec;
+
+        EXPECT_EQ(5, vec.getSize());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+        EXPECT_EQ(0, vec[3]);
+        EXPECT_EQ(0, vec[4]);
+
+        float data[5] = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+
+        vec = data;
+
+        EXPECT_EQ(5, vec.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec[4]);
+    }
+
+    {
+        BasicVector<float, 5> vec;
+
+        EXPECT_EQ(5, vec.getSize());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+        EXPECT_EQ(0, vec[3]);
+        EXPECT_EQ(0, vec[4]);
+
+        StaticArray<float, 5> data = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+
+        vec = data;
+
+        EXPECT_EQ(5, vec.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec[4]);
+    }
+
+    {
+        const BasicVector<float, 5> vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec1[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec1[4]);
+
+        BasicVector<float, 5> vec2;
+
+        vec2 = vec1;
+
+        EXPECT_EQ(5, vec2.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec2[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec2[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec2[4]);
+    }
+
+    {
+        BasicVector<float, 5> vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec1[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec1[4]);
+
+        BasicVector<float, 5> vec2;
+
+        vec2 = std::move(vec1);
+
+        EXPECT_EQ(5, vec2.getSize());
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec2[2]);
+        EXPECT_FLOAT_EQ(45.1f, vec2[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec2[4]);
+    }
+
+    {
+        const BasicVector<int, 5> vec1 = {1, 3, 0, 45, -34};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+        EXPECT_EQ(0, vec1[2]);
+        EXPECT_EQ(45, vec1[3]);
+        EXPECT_EQ(-34, vec1[4]);
+
+        BasicVector<float, 5> vec2;
+
+        vec2 = vec1;
+
+        EXPECT_EQ(5, vec2.getSize());
+        EXPECT_FLOAT_EQ(1.0, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec2[2]);
+        EXPECT_FLOAT_EQ(45.0f, vec2[3]);
+        EXPECT_FLOAT_EQ(-34.0f, vec2[4]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector, operators)
+{
+    {
+        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -300.8f};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-5.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-300.8f, vec1[4]);
+
+        BasicVector<float, 5> vec2 = +vec1;
+
+        EXPECT_EQ(5, vec2.getSize());
+        EXPECT_FLOAT_EQ(1.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(-5.0f, vec2[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec2[3]);
+        EXPECT_FLOAT_EQ(-300.8f, vec2[4]);
+    }
+
+    {
+        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -300.8f};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-5.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-300.8f, vec1[4]);
+
+        BasicVector<float, 5> vec2 = -vec1;
+
+        EXPECT_EQ(5, vec2.getSize());
+        EXPECT_FLOAT_EQ(-1.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(-2.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(5.0f, vec2[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec2[3]);
+        EXPECT_FLOAT_EQ(300.8f, vec2[4]);
+    }
+
+    {
+        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-5.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-3.8f, vec1[4]);
+
+        BasicVector<float, 5> vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        vec1 += vec2;
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(2.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-2.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(4.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(1.2f, vec1[4]);
+    }
+
+    {
+        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-5.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-3.8f, vec1[4]);
+
+        BasicVector<float, 5> vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        vec1 -= vec2;
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(0.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(-4.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-8.8f, vec1[4]);
+    }
+
+    {
+        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-5.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-3.8f, vec1[4]);
+
+        vec1 *= 2.0;
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(2.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-10.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-7.6f, vec1[4]);
+    }
+
+    {
+        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-5.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-3.8f, vec1[4]);
+
+        BasicVector<float, 5> vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        vec1 *= vec2;
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-15.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-19.0f, vec1[4]);
+    }
+
+    {
+        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-5.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-3.8f, vec1[4]);
+
+        vec1 /= 2.0;
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(0.5f, vec1[0]);
+        EXPECT_FLOAT_EQ(1.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-2.5f, vec1[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-1.9f, vec1[4]);
+    }
+
+    {
+        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-5.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-3.8f, vec1[4]);
+
+        BasicVector<float, 5> vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        vec1 /= vec2;
+
+        EXPECT_EQ(5, vec1.getSize());
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(1.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-5.0f / 3.0f, vec1[2]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[3]);
+        EXPECT_FLOAT_EQ(-3.8f / 5.0f, vec1[4]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector, inRange)
+{
+    {
+        const BasicVector<float, 5> vecMin{-10.0f, -5.0f, 0.0f, 5.0f, 10.0f};
+        const BasicVector<float, 5> vecMax{10.0f, 20.0f, 30.0f, 40.0f, 50.0f};
+
+        BasicVector<float, 5> vec1;
+        BasicVector<float, 5> vec2{-15.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+        BasicVector<float, 5> vec3{5.0f, 0.0f, 0.0f, 10.0f, 40.0f};
+        BasicVector<float, 5> vec4{5.0f, 0.0f, 0.0f, 5.0f, 40.0f};
+
+        EXPECT_FALSE(vec1.inRange(vecMin, vecMax));
+        EXPECT_FALSE(vec2.inRange(vecMin, vecMax));
+        EXPECT_TRUE(vec3.inRange(vecMin, vecMax));
+        EXPECT_TRUE(vec4.inRange(vecMin, vecMax));
+    }
+
+    {
+        const BasicVector<float, 5> vecMax{10.0f, 20.0f, 30.0f, 40.0f, 50.0f};
+
+        BasicVector<float, 5> vec1;
+        BasicVector<float, 5> vec2{-15.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+        BasicVector<float, 5> vec3{5.0f, 0.0f, -3.0f, 0.0f, 40.0f};
+        BasicVector<float, 5> vec4{5.0f, 0.0f, 0.0f, 5.0f, 40.0f};
+
+        EXPECT_TRUE(vec1.inRange(vecMax));
+        EXPECT_FALSE(vec2.inRange(vecMax));
+        EXPECT_FALSE(vec3.inRange(vecMax));
+        EXPECT_TRUE(vec4.inRange(vecMax));
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector, memberFunctions)
+{
+    {
+        const BasicVector<float, 5> vec;
+
+        EXPECT_FLOAT_EQ(0, vec.getLength());
+    }
+
+    {
+        const BasicVector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+
+        EXPECT_FLOAT_EQ(7.4162f, vec.getLength());
+    }
+
+    {
+        const BasicVector<float, 5> vec;
+
+        EXPECT_FLOAT_EQ(0, vec.getLengthSquared());
+    }
+
+    {
+        const BasicVector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+
+        EXPECT_FLOAT_EQ(55, vec.getLengthSquared());
+    }
+
+    {
+        const BasicVector<float, 5> vec;
+
+        EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
+    }
+
+    {
+        const BasicVector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+
+        EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
+    }
+
+    {
+        const BasicVector<float, 5> vec1;
+        const BasicVector<float, 5> vec2;
+
+        EXPECT_FLOAT_EQ(0, vec1.dot(vec2));
+    }
+
+    {
+        const BasicVector<float, 5> vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        const BasicVector<float, 5> vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
+
+        EXPECT_FLOAT_EQ(35, vec1.dot(vec2));
+    }
+
+    {
+        const BasicVector<float, 5> vec;
+
+        EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
+    }
+
+    {
+        const BasicVector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+
+        EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
+    }
+
+    {
+        const BasicVector<float, 5> vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        const BasicVector<float, 5> vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
+
+        EXPECT_FLOAT_EQ(40.0f, vec1.distanceSquared(vec2));
+    }
+
+    {
+        const BasicVector<float, 5> vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        const BasicVector<float, 5> vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
+
+        EXPECT_FLOAT_EQ(6.3245554f, vec1.distance(vec2));
+    }
+
+    {
+        const BasicVector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+
+        auto inv = vec.inversed();
+
+        EXPECT_EQ(5, inv.getSize());
+        EXPECT_FLOAT_EQ(1.0f, inv[0]);
+        EXPECT_FLOAT_EQ(0.5f, inv[1]);
+        EXPECT_FLOAT_EQ(1.0f / 3.0f, inv[2]);
+        EXPECT_FLOAT_EQ(0.25f, inv[3]);
+        EXPECT_FLOAT_EQ(0.2f, inv[4]);
+    }
+
+    {
+        auto vec = BasicVector<float, 5>::createSingle(1);
+
+        EXPECT_EQ(5, vec.getSize());
+        EXPECT_FLOAT_EQ(1.0f, vec[0]);
+        EXPECT_FLOAT_EQ(1.0f, vec[1]);
+        EXPECT_FLOAT_EQ(1.0f, vec[2]);
+        EXPECT_FLOAT_EQ(1.0f, vec[3]);
+        EXPECT_FLOAT_EQ(1.0f, vec[4]);
+    }
+
+    {
+        auto vec = BasicVector<float, 5>::createSingle(375.1721f);
+
+        EXPECT_EQ(5, vec.getSize());
+        EXPECT_FLOAT_EQ(375.1721f, vec[0]);
+        EXPECT_FLOAT_EQ(375.1721f, vec[1]);
+        EXPECT_FLOAT_EQ(375.1721f, vec[2]);
+        EXPECT_FLOAT_EQ(375.1721f, vec[3]);
+        EXPECT_FLOAT_EQ(375.1721f, vec[4]);
+    }
+}
+
+/* ************************************************************************ */

From a76650de97ba33eae1ed03d371cddf51e0128678 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Fatka?= <fatkaj@ntis.zcu.cz>
Date: Tue, 7 Mar 2017 16:29:38 +0100
Subject: [PATCH 02/11] Created specialized Vector2 and Vector3 types.

---
 include/cece/math/Vector.hpp    | 1464 +------------------------------
 include/cece/math/Vector2.hpp   | 1365 ++++++++++++++++++++++++++++
 include/cece/math/Vector3.hpp   | 1392 +++++++++++++++++++++++++++++
 src/math/CMakeLists.txt         |    4 +-
 src/math/Vector2.cpp            |   46 +
 src/math/Vector3.cpp            |   46 +
 unittests/math/CMakeLists.txt   |    1 +
 unittests/math/Vector2_test.cpp |  427 +++++++++
 8 files changed, 3312 insertions(+), 1433 deletions(-)
 create mode 100644 include/cece/math/Vector2.hpp
 create mode 100644 include/cece/math/Vector3.hpp
 create mode 100644 src/math/Vector2.cpp
 create mode 100644 src/math/Vector3.cpp
 create mode 100644 unittests/math/Vector2_test.cpp

diff --git a/include/cece/math/Vector.hpp b/include/cece/math/Vector.hpp
index c3537b6..0282e53 100644
--- a/include/cece/math/Vector.hpp
+++ b/include/cece/math/Vector.hpp
@@ -41,6 +41,8 @@
 #include "cece/io/OutStream.hpp"
 #include "cece/unit/math.hpp"
 #include "cece/unit/Units.hpp"
+#include "cece/math/Vector2.hpp"
+#include "cece/math/Vector3.hpp"
 
 /* ************************************************************************ */
 
@@ -474,11 +476,11 @@ class BasicVector
 
 
     /**
-     * @brief Create from single value.
+     * @brief      Create from single value.
      *
-     * @param val
+     * @param      val   The value.
      *
-     * @return
+     * @return     Vector of vals.
      */
     static BasicVector createSingle(T val) noexcept;
 
@@ -493,1106 +495,41 @@ class BasicVector
 
 /* ************************************************************************ */
 
-/**
- * @brief Two dimensional vector.
- */
-template<typename T>
-class BasicVector<T, 2>
-{
-
-// Public Types
-public:
-
-
-    /// BasicVector value type.
-    using ValueType = T;
-
-
-// Public Contants
-public:
-
-
-    /// Number of elements
-    static constexpr int SIZE = 2;
-
-
-// Public Ctors
-public:
-
-
-    /**
-     * @brief Default constructor.
-     */
-    BasicVector() noexcept
-        : m_x{}
-        , m_y{}
-    {
-        // Nothing to do
-    }
-
-
-    /**
-     * @brief Constructor.
-     *
-     * @param x
-     * @param y
-     */
-    BasicVector(T x, T y) noexcept
-        : m_x(x)
-        , m_y(y)
-    {
-        // Nothing to do
-    }
-
-
-    /**
-     * @brief Zero value constructor.
-     */
-    BasicVector(Zero_t) noexcept
-        : m_x{}
-        , m_y{}
-    {
-        // Nothing to do
-    }
-
-
-    /**
-     * @brief Copy constructor.
-     *
-     * @param rhs Source vector.
-     */
-    template<typename T2>
-    explicit BasicVector(const BasicVector<T2, SIZE>& rhs) noexcept
-        : m_x(static_cast<T>(rhs.getX()))
-        , m_y(static_cast<T>(rhs.getY()))
-    {
-        // Nothing to do
-    }
-
-
-// Public Operators
-public:
-
-
-    /**
-     * @brief Access operator.
-     *
-     * @param pos
-     *
-     * @return
-     */
-    T& operator[](int pos) noexcept
-    {
-        CECE_ASSERT(pos < SIZE);
-        return (&m_x)[pos];
-    }
-
-
-    /**
-     * @brief Access operator.
-     *
-     * @param pos
-     *
-     * @return
-     */
-    const T& operator[](int pos) const noexcept
-    {
-        CECE_ASSERT(pos < SIZE);
-        return (&m_x)[pos];
-    }
-
-
-    /**
-     * @brief Unary plus operator.
-     *
-     * @return
-     */
-    BasicVector operator+() const noexcept
-    {
-        return *this;
-    }
-
-
-    /**
-     * @brief Unary minus operator.
-     *
-     * @return
-     */
-    BasicVector operator-() const noexcept
-    {
-        return BasicVector{-getX(), -getY()};
-    }
-
-
-    /**
-     * @brief Addition operator.
-     *
-     * @tparam T1 Type of right operand.
-     *
-     * @param rhs Right operand.
-     *
-     * @return *this.
-     */
-    template<typename T1>
-    BasicVector& operator+=(const BasicVector<T1, SIZE>& rhs) noexcept
-    {
-        m_x += rhs.getX();
-        m_y += rhs.getY();
-        return *this;
-    }
-
-
-    /**
-     * @brief Subtraction operator.
-     *
-     * @tparam T1 Type of value in BasicVector operand.
-     *
-     * @param rhs Right operand.
-     *
-     * @return *this.
-     */
-    template<typename T1>
-    BasicVector& operator-=(const BasicVector<T1, SIZE>& rhs) noexcept
-    {
-        m_x -= rhs.getX();
-        m_y -= rhs.getY();
-        return *this;
-    }
-
-
-    /**
-     * @brief Multiplication operator.
-     *
-     * @tparam T1 Type of right operand.
-     *
-     * @param rhs Right operand.
-     *
-     * @return *this.
-     */
-    template<typename T1>
-    BasicVector& operator*=(T1 rhs) noexcept
-    {
-        m_x *= rhs;
-        m_y *= rhs;
-        return *this;
-    }
-
-
-    /**
-     * @brief Multiplication operator.
-     *
-     * @tparam T1 Type of value in BasicVector operand.
-     *
-     * @param rhs Right operand.
-     *
-     * @return *this.
-     */
-    template<typename T1>
-    BasicVector& operator*=(const BasicVector<T1, SIZE>& rhs) noexcept
-    {
-        m_x *= rhs.getX();
-        m_y *= rhs.getY();
-        return *this;
-    }
-
-
-    /**
-     * @brief Division operator.
-     *
-     * @tparam T1 Type of right operand.
-     *
-     * @param rhs Right operand.
-     *
-     * @return *this.
-     */
-    template<typename T1>
-    BasicVector& operator/=(T1 rhs) noexcept
-    {
-        m_x /= rhs;
-        m_y /= rhs;
-        return *this;
-    }
-
-
-    /**
-     * @brief Division operator.
-     *
-     * @tparam T1 Type of value in BasicVector operand.
-     *
-     * @param rhs Right operand.
-     *
-     * @return *this.
-     */
-    template<typename T1>
-    BasicVector& operator/=(const BasicVector<T1, SIZE>& rhs) noexcept
-    {
-        m_x /= rhs.getX();
-        m_y /= rhs.getY();
-        return *this;
-    }
-
-
-// Public Accessors
-public:
-
-
-    /**
-     * @brief Returns vector size.
-     *
-     * @return
-     */
-    int getSize() const noexcept
-    {
-        return SIZE;
-    }
-
-
-    /**
-     * @brief Returns X coordinate.
-     *
-     * @return
-     */
-    T& x() noexcept
-    {
-        return m_x;
-    }
-
-
-    /**
-     * @brief Returns X coordinate.
-     *
-     * @return
-     */
-    const T& getX() const noexcept
-    {
-        return m_x;
-    }
-
-
-    /**
-     * @brief Returns Y coordinate.
-     *
-     * @return
-     */
-    T& y() noexcept
-    {
-        return m_y;
-    }
-
-
-    /**
-     * @brief Returns Y coordinate.
-     *
-     * @return
-     */
-    const T& getY() const noexcept
-    {
-        return m_y;
-    }
-
-
-    /**
-     * @brief Returns width.
-     *
-     * @return
-     */
-    T& width() noexcept
-    {
-        return m_x;
-    }
-
-
-    /**
-     * @brief Returns width.
-     *
-     * @return
-     */
-    const T& getWidth() const noexcept
-    {
-        return m_x;
-    }
-
-
-    /**
-     * @brief Returns height.
-     *
-     * @return
-     */
-    T& height() noexcept
-    {
-        return m_y;
-    }
-
-
-    /**
-     * @brief Returns height.
-     *
-     * @return
-     */
-    const T& getHeight() const noexcept
-    {
-        return m_y;
-    }
-
-
-// Public Mutators
-public:
-
-
-    /**
-     * @brief Set X coordinate.
-     *
-     * @param x
-     */
-    void setX(T x) noexcept
-    {
-        m_x = x;
-    }
-
-
-    /**
-     * @brief Set Y coordinate.
-     *
-     * @param y
-     */
-    void setY(T y) noexcept
-    {
-        m_y = y;
-    }
-
-
-    /**
-     * @brief Check if given value is in given range.
-     *
-     * @param value Given value.
-     * @param low   Minimum value (>=).
-     * @param high  Maximum value (<).
-     *
-     * @return
-     */
-    static bool inRange(T value, T low, T high) noexcept
-    {
-        return value >= low && value < high;
-    }
-
-
-    /**
-     * @brief Check if current vector is in given range.
-     *
-     * @param low  Minimum coordinates (>=).
-     * @param high Maximum coordinates (<).
-     *
-     * @return
-     */
-    bool inRange(const BasicVector& low, const BasicVector& high) const noexcept
-    {
-        return (
-            inRange(getX(), low.getX(), high.getX()) &&
-            inRange(getY(), low.getY(), high.getY())
-        );
-    }
-
-
-// Public Operations
-public:
-
-
-    /**
-     * @brief Calculate vector length.
-     *
-     * @return
-     */
-    T getLength() const noexcept
-    {
-        using std::sqrt;
-        return static_cast<T>(sqrt(getLengthSquared()));
-    }
-
-
-    /**
-     * @brief Calculate vector length - squared.
-     *
-     * @return
-     */
-    decltype(T{} * T{}) getLengthSquared() const noexcept
-    {
-        return dot(*this);
-    }
-
-
-    /**
-     * @brief Calculate dot of two vectors.
-     *
-     * @param rhs Second vector.
-     *
-     * @return Dot product.
-     */
-    decltype(T{} * T{}) dot(const BasicVector& rhs) const noexcept
-    {
-        return {getX() * rhs.getX() + getY() * rhs.getY()};
-    }
-
-
-    /**
-     * @brief Calculate vectors squared distance.
-     *
-     * @param rhs Second vector.
-     *
-     * @return Distance.
-     */
-    decltype(std::declval<T>() * std::declval<T>()) distanceSquared(const BasicVector& rhs) const noexcept
-    {
-        return (*this - rhs).getLengthSquared();
-    }
-
-
-    /**
-     * @brief Calculate vectors distance.
-     *
-     * @param rhs Second vector.
-     *
-     * @return Distance.
-     */
-    T distance(const BasicVector& rhs) const noexcept
-    {
-        return (*this - rhs).getLength();
-    }
-
-
-    /**
-     * @brief Inverse current vector (1 / *this).
-     *
-     * @return
-     */
-    template<typename T2>
-    BasicVector<T2, SIZE> inversed() const noexcept
-    {
-        return BasicVector<T2, SIZE>{T2(1) / getX(), T2(1) / getY()};
-    }
-
-
-    /**
-     * @brief Rotate current vector and return rotated version.
-     *
-     * @param angle Rotation angle.
-     *
-     * @return
-     */
-    BasicVector rotated(unit::Angle angle) const noexcept
-    {
-        return BasicVector(
-            static_cast<T>(getX() * cos(static_cast<RealType>(angle)) - getY() * sin(static_cast<RealType>(angle))),
-            static_cast<T>(getX() * sin(static_cast<RealType>(angle)) + getY() * cos(static_cast<RealType>(angle)))
-        );
-    }
-
-
-    /**
-     * @brief Create from single value.
-     *
-     * @param val
-     *
-     * @return
-     */
-    static BasicVector createSingle(T val) noexcept
-    {
-        return BasicVector{val, val};
-    }
-
-
-// Private Data Members
-private:
-
-    /// X coordinate.
-    T m_x{};
-
-    /// Y coordinate.
-    T m_y{};
-
-};
-
-/* ************************************************************************ */
-
-/**
- * @brief Three dimensional vector.
- */
-template<typename T>
-class BasicVector<T, 3>
-{
-
-// Public Types
-public:
-
-
-    /// BasicVector value type.
-    using ValueType = T;
-
-
-// Public Contants
-public:
-
-
-    /// Number of elements
-    static constexpr int SIZE = 3;
-
-
-// Public Ctors
-public:
-
-
-    /**
-     * @brief Default constructor.
-     */
-    BasicVector() noexcept
-        : m_x{}
-        , m_y{}
-        , m_z{}
-    {
-        // Nothing to do
-    }
-
-
-    /**
-     * @brief Constructor.
-     *
-     * @param x
-     * @param y
-     * @param z
-     */
-    BasicVector(T x, T y, T z) noexcept
-        : m_x(x)
-        , m_y(y)
-        , m_z(z)
-    {
-        // Nothing to do
-    }
-
-
-    /**
-     * @brief Zero value constructor.
-     */
-    BasicVector(Zero_t) noexcept
-        : m_x{}
-        , m_y{}
-        , m_z{}
-    {
-        // Nothing to do
-    }
-
-
-    /**
-     * @brief Copy constructor.
-     *
-     * @param rhs Source vector.
-     */
-    template<typename T2>
-    explicit BasicVector(const BasicVector<T2, SIZE>& rhs) noexcept
-        : m_x(static_cast<T>(rhs.getX()))
-        , m_y(static_cast<T>(rhs.getY()))
-        , m_z(static_cast<T>(rhs.getZ()))
-    {
-        // Nothing to do
-    }
-
-
-// Public Operators
-public:
-
-
-    /**
-     * @brief Access operator.
-     *
-     * @param pos
-     *
-     * @return
-     */
-    T& operator[](int pos) noexcept
-    {
-        CECE_ASSERT(pos < SIZE);
-        return (&m_x)[pos];
-    }
-
-
-    /**
-     * @brief Access operator.
-     *
-     * @param pos
-     *
-     * @return
-     */
-    const T& operator[](int pos) const noexcept
-    {
-        CECE_ASSERT(pos < SIZE);
-        return (&m_x)[pos];
-    }
-
-
-    /**
-     * @brief Unary plus operator.
-     *
-     * @return
-     */
-    BasicVector operator+() const noexcept
-    {
-        return *this;
-    }
-
-
-    /**
-     * @brief Unary minus operator.
-     *
-     * @return
-     */
-    BasicVector operator-() const noexcept
-    {
-        return BasicVector{-getX(), -getY(), -getZ()};
-    }
-
-
-    /**
-     * @brief Addition operator.
-     *
-     * @tparam T1 Type of right operand.
-     *
-     * @param rhs Right operand.
-     *
-     * @return *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<decltype(T{} + T1{}), T>::value>::type* = nullptr>
-    BasicVector& operator+=(const BasicVector<T1, SIZE>& rhs) noexcept
-    {
-        m_x += rhs.getX();
-        m_y += rhs.getY();
-        m_z += rhs.getZ();
-        return *this;
-    }
-
-
-    /**
-     * @brief Subtraction operator.
-     *
-     * @tparam T1 Type of value in BasicVector operand.
-     *
-     * @param rhs Right operand.
-     *
-     * @return *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<decltype(T{} - T1{}), T>::value>::type* = nullptr>
-    BasicVector& operator-=(const BasicVector<T1, SIZE>& rhs) noexcept
-    {
-        m_x -= rhs.getX();
-        m_y -= rhs.getY();
-        m_z -= rhs.getZ();
-        return *this;
-    }
-
-
-    /**
-     * @brief Multiplication operator.
-     *
-     * @tparam T1 Type of right operand.
-     *
-     * @param rhs Right operand.
-     *
-     * @return *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<decltype(T{} * T1{}), T>::value>::type* = nullptr>
-    BasicVector& operator*=(T1 rhs) noexcept
-    {
-        m_x *= rhs;
-        m_y *= rhs;
-        m_z *= rhs;
-        return *this;
-    }
-
-
-    /**
-     * @brief Multiplication operator.
-     *
-     * @tparam T1 Type of value in BasicVector operand.
-     *
-     * @param rhs Right operand.
-     *
-     * @return *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<decltype(T{} * T1{}), T>::value>::type* = nullptr>
-    BasicVector& operator*=(const BasicVector<T1, SIZE>& rhs) noexcept
-    {
-        m_x *= rhs.getX();
-        m_y *= rhs.getY();
-        m_z *= rhs.getZ();
-        return *this;
-    }
-
-
-    /**
-     * @brief Division operator.
-     *
-     * @tparam T1 Type of right operand.
-     *
-     * @param rhs Right operand.
-     *
-     * @return *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<decltype(T{} / T1{}), T>::value>::type* = nullptr>
-    BasicVector& operator/=(T1 rhs) noexcept
-    {
-        m_x /= rhs;
-        m_y /= rhs;
-        m_z /= rhs;
-        return *this;
-    }
-
-
-    /**
-     * @brief Division operator.
-     *
-     * @tparam T1 Type of value in BasicVector operand.
-     *
-     * @param rhs Right operand.
-     *
-     * @return *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<decltype(T{} / T1{}), T>::value>::type* = nullptr>
-    BasicVector& operator/=(const BasicVector<T1, SIZE>& rhs) noexcept
-    {
-        m_x /= rhs.getX();
-        m_y /= rhs.getY();
-        m_z /= rhs.getZ();
-        return *this;
-    }
-
-
-// Public Accessors
-public:
-
-
-    /**
-     * @brief Returns vector size.
-     *
-     * @return
-     */
-    int getSize() const noexcept
-    {
-        return SIZE;
-    }
-
-
-    /**
-     * @brief Returns X coordinate.
-     *
-     * @return
-     */
-    T& x() noexcept
-    {
-        return m_x;
-    }
-
-
-    /**
-     * @brief Returns X coordinate.
-     *
-     * @return
-     */
-    const T& getX() const noexcept
-    {
-        return m_x;
-    }
-
-
-    /**
-     * @brief Returns Y coordinate.
-     *
-     * @return
-     */
-    T& y() noexcept
-    {
-        return m_y;
-    }
-
-
-    /**
-     * @brief Returns Y coordinate.
-     *
-     * @return
-     */
-    const T& getY() const noexcept
-    {
-        return m_y;
-    }
-
-
-    /**
-     * @brief Returns Z coordinate.
-     *
-     * @return
-     */
-    T& z() noexcept
-    {
-        return m_z;
-    }
-
-
-    /**
-     * @brief Returns Z coordinate.
-     *
-     * @return
-     */
-    const T& getZ() const noexcept
-    {
-        return m_z;
-    }
-
-
-    /**
-     * @brief Returns width.
-     *
-     * @return
-     */
-    T& width() noexcept
-    {
-        return m_x;
-    }
-
-
-    /**
-     * @brief Returns width.
-     *
-     * @return
-     */
-    const T& getWidth() const noexcept
-    {
-        return m_x;
-    }
-
-
-    /**
-     * @brief Returns height.
-     *
-     * @return
-     */
-    T& height() noexcept
-    {
-        return m_y;
-    }
-
-
-    /**
-     * @brief Returns height.
-     *
-     * @return
-     */
-    const T& getHeight() const noexcept
-    {
-        return m_y;
-    }
-
-
-    /**
-     * @brief Returns depth.
-     *
-     * @return
-     */
-    T& depth() noexcept
-    {
-        return m_z;
-    }
-
-
-    /**
-     * @brief Returns depth.
-     *
-     * @return
-     */
-    const T& getDepth() const noexcept
-    {
-        return m_z;
-    }
-
-
-    /**
-     * @brief Check if given value is in given range.
-     *
-     * @param value Given value.
-     * @param low   Minimum value (>=).
-     * @param high  Maximum value (<).
-     *
-     * @return
-     */
-    static bool inRange(T value, T low, T high) noexcept
-    {
-        return value >= low && value < high;
-    }
-
-
-    /**
-     * @brief Check if current vector is in given range.
-     *
-     * @param low  Minimum coordinates (>=).
-     * @param high Maximum coordinates (<).
-     *
-     * @return
-     */
-    bool inRange(const BasicVector& low, const BasicVector& high) const noexcept
-    {
-        return (
-            inRange(getX(), low.getX(), high.getX()) &&
-            inRange(getY(), low.getY(), high.getY()) &&
-            inRange(getZ(), low.getZ(), high.getZ())
-        );
-    }
-
-
-
-// Public Mutators
-public:
-
-
-    /**
-     * @brief Set X coordinate.
-     *
-     * @param x
-     */
-    void setX(T x) noexcept
-    {
-        m_x = x;
-    }
-
-
-    /**
-     * @brief Set Y coordinate.
-     *
-     * @param y
-     */
-    void setY(T y) noexcept
-    {
-        m_y = y;
-    }
-
-
-    /**
-     * @brief Set Z coordinate.
-     *
-     * @param z
-     */
-    void setZ(T z) noexcept
-    {
-        m_z = z;
-    }
-
-
-// Public Operations
-public:
-
-
-    /**
-     * @brief Calculate vector length.
-     *
-     * @return
-     */
-    template<typename T1 = decltype(T{} * T{}), typename std::enable_if<std::is_scalar<T1>::value>::type* = nullptr>
-    T getLength() const noexcept
-    {
-        using std::sqrt;
-        return static_cast<T>(sqrt(getLengthSquared()));
-    }
-
-
-    /**
-     * @brief Calculate vector length - squared.
-     *
-     * @return
-     */
-    decltype(T{} * T{}) getLengthSquared() const noexcept
-    {
-        return dot(*this);
-    }
-
-
-    /**
-     * @brief Calculate dot of two vectors.
-     *
-     * @param rhs Second vector.
-     *
-     * @return Dot product.
-     */
-    decltype(T{} * T{}) dot(const BasicVector& rhs) const noexcept
-    {
-        return {
-            getX() * rhs.getX() +
-            getY() * rhs.getY() +
-            getZ() * rhs.getZ()
-        };
-    }
-
-
-    /**
-     * @brief Calculate vectors squared distance.
-     *
-     * @param rhs Second vector.
-     *
-     * @return Distance.
-     */
-    decltype(std::declval<T>() * std::declval<T>()) distanceSquared(const BasicVector& rhs) const noexcept
-    {
-        return (*this - rhs).getLengthSquared();
-    }
-
-
-    /**
-     * @brief Calculate vectors distance.
-     *
-     * @param rhs Second vector.
-     *
-     * @return Distance.
-     */
-    T distance(const BasicVector& rhs) const noexcept
-    {
-        return (*this - rhs).getLength();
-    }
-
-
-    /**
-     * @brief Inverse current vector (1 / *this).
-     *
-     * @return
-     */
-    template<typename T2>
-    BasicVector<T2, SIZE> inversed() const noexcept
-    {
-        return BasicVector<T2, SIZE>{
-            T2(1) / getX(),
-            T2(1) / getY(),
-            T2(1) / getZ()
-        };
-    }
-
+// TODO: rework
+template<typename T>
+struct BasicVector<T, 2> : public BasicVector2<T>
+{
+    using BasicVector2<T>::BasicVector2;
 
-    /**
-     * @brief Create from single value.
-     *
-     * @param val
-     *
-     * @return
-     */
-    static BasicVector createSingle(T val) noexcept
+    BasicVector() {};
+    BasicVector(const BasicVector2<T>& src)
+        : BasicVector2<T>(src)
     {
-        return {val, val, val};
+        //
     }
 
+    const T& getWidth() const noexcept { return BasicVector2<T>::getX(); }
+    const T& getHeight() const noexcept { return BasicVector2<T>::getY(); }
+};
 
-// Private Data Members
-private:
-
-    /// X coordinate.
-    T m_x{};
+/* ************************************************************************ */
 
-    /// Y coordinate.
-    T m_y{};
+// TODO: rework
+template<typename T>
+struct BasicVector<T, 3> : public BasicVector3<T>
+{
+    using BasicVector3<T>::BasicVector3;
 
-    /// Z coordinate.
-    T m_z{};
+    BasicVector() {};
+    BasicVector(const BasicVector3<T>& src)
+        : BasicVector3<T>(src)
+    {
+        //
+    }
 
+    const T& getWidth() const noexcept { return BasicVector3<T>::getX(); }
+    const T& getHeight() const noexcept { return BasicVector3<T>::getY(); }
+    const T& getDepth() const noexcept { return BasicVector3<T>::getZ(); }
 };
 
 /* ************************************************************************ */
@@ -1679,28 +616,6 @@ inline BasicVector<decltype(T1{} + T2{}), N> operator+(const BasicVector<T1, N>&
 
 /* ************************************************************************ */
 
-/**
- * @brief Addition operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2>
-inline BasicVector<decltype(T1{} + T2{}), 2> operator+(const BasicVector<T1, 2>& lhs, const BasicVector<T2, 2>& rhs) noexcept
-{
-    return BasicVector<decltype(T1{} + T2{}), 2>{
-        lhs.getX() + rhs.getX(),
-        lhs.getY() + rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Addition operator.
  *
@@ -1726,28 +641,6 @@ inline BasicVector<decltype(T1{} + T2{}), N> operator+(const BasicVector<T1, N>&
 
 /* ************************************************************************ */
 
-/**
- * @brief Addition operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of second operand.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2>
-inline BasicVector<decltype(T1{} + T2{}), 2> operator+(const BasicVector<T1, 2>& lhs, T2 rhs) noexcept
-{
-    return BasicVector<decltype(T1{} + T2{}), 2>{
-        lhs.getX() + rhs,
-        lhs.getY() + rhs
-    };
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Addition operator.
  *
@@ -1773,28 +666,6 @@ inline BasicVector<decltype(T1{} + T2{}), N> operator+(T1 lhs, const BasicVector
 
 /* ************************************************************************ */
 
-/**
- * @brief Addition operator.
- *
- * @tparam T1 Type of first operand.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2>
-inline BasicVector<decltype(T1{} + T2{}), 2> operator+(T1 lhs, const BasicVector<T2, 2>& rhs) noexcept
-{
-    return BasicVector<decltype(T1{} + T2{}), 2>{
-        lhs + rhs.getX(),
-        lhs + rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Substract operator.
  *
@@ -1819,28 +690,6 @@ inline BasicVector<decltype(T1{} - T2{}), N> operator-(const BasicVector<T1, N>&
 
 /* ************************************************************************ */
 
-/**
- * @brief Substract operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2>
-inline BasicVector<decltype(T1{} - T2{}), 2> operator-(const BasicVector<T1, 2>& lhs, const BasicVector<T2, 2>& rhs) noexcept
-{
-    return BasicVector<decltype(T1{} - T2{}), 2>{
-        lhs.getX() - rhs.getX(),
-        lhs.getY() - rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Substract operator.
  *
@@ -1865,28 +714,6 @@ inline BasicVector<decltype(T1{} - T2{}), N> operator-(const BasicVector<T1, N>&
 
 /* ************************************************************************ */
 
-/**
- * @brief Substract operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of second operand.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2>
-inline BasicVector<decltype(T1{} - T2{}), 2> operator-(const BasicVector<T1, 2>& lhs, T2 rhs) noexcept
-{
-    return BasicVector<decltype(T1{} - T2{}), 2>{
-        lhs.getX() - rhs,
-        lhs.getY() - rhs
-    };
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Substract operator.
  *
@@ -1911,28 +738,6 @@ inline BasicVector<decltype(T1{} - T2{}), N> operator-(T1 lhs, const BasicVector
 
 /* ************************************************************************ */
 
-/**
- * @brief Substract operator.
- *
- * @tparam T1 Type of first operand.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2>
-inline BasicVector<decltype(T1{} - T2{}), 2> operator-(T1 lhs, const BasicVector<T2, 2>& rhs) noexcept
-{
-    return BasicVector<decltype(T1{} - T2{}), 2>{
-        lhs - rhs.getX(),
-        lhs - rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Multiplication operator.
  *
@@ -1957,28 +762,6 @@ inline BasicVector<decltype(T1{} * T2{}), N> operator*(const BasicVector<T1, N>&
 
 /* ************************************************************************ */
 
-/**
- * @brief Multiplication operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2>
-inline BasicVector<decltype(T1{} * T2{}), 2> operator*(const BasicVector<T1, 2>& lhs, const BasicVector<T2, 2>& rhs) noexcept
-{
-    return BasicVector<decltype(T1{} * T2{}), 2>{
-        lhs.getX() * rhs.getX(),
-        lhs.getY() * rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Multiplication operator.
  *
@@ -2003,28 +786,6 @@ inline BasicVector<decltype(T1{} * T2{}), N> operator*(const BasicVector<T1, N>&
 
 /* ************************************************************************ */
 
-/**
- * @brief Multiplication operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of second operand.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2>
-inline BasicVector<decltype(T1{} * T2{}), 2> operator*(const BasicVector<T1, 2>& lhs, T2 rhs) noexcept
-{
-    return BasicVector<decltype(T1{} * T2{}), 2>{
-        lhs.getX() * rhs,
-        lhs.getY() * rhs
-    };
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Multiplication operator.
  *
@@ -2049,28 +810,6 @@ inline BasicVector<decltype(T1{} * T2{}), N> operator*(T1 lhs, const BasicVector
 
 /* ************************************************************************ */
 
-/**
- * @brief Multiplication operator.
- *
- * @tparam T1 Type of first operand.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2>
-inline BasicVector<decltype(T1{} * T2{}), 2> operator*(T1 lhs, const BasicVector<T2, 2>& rhs) noexcept
-{
-    return BasicVector<decltype(T1{} * T2{}), 2>{
-        lhs * rhs.getX(),
-        lhs * rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Division operator.
  *
@@ -2095,28 +834,6 @@ inline BasicVector<decltype(T1{} / T2{}), N> operator/(const BasicVector<T1, N>&
 
 /* ************************************************************************ */
 
-/**
- * @brief Division operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2>
-inline BasicVector<decltype(T1{} / T2{}), 2> operator/(const BasicVector<T1, 2>& lhs, const BasicVector<T2, 2>& rhs) noexcept
-{
-    return BasicVector<decltype(T1{} / T2{}), 2>{
-        lhs.getX() / rhs.getX(),
-        lhs.getY() / rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Division operator.
  *
@@ -2141,28 +858,6 @@ inline BasicVector<decltype(T1{} / T2{}), N> operator/(const BasicVector<T1, N>&
 
 /* ************************************************************************ */
 
-/**
- * @brief Division operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of second operand.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2>
-inline BasicVector<decltype(T1{} / T2{}), 2> operator/(const BasicVector<T1, 2>& lhs, T2 rhs) noexcept
-{
-    return BasicVector<decltype(T1{} / T2{}), 2>{
-        lhs.getX() / rhs,
-        lhs.getY() / rhs
-    };
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Division operator.
  *
@@ -2187,28 +882,6 @@ inline BasicVector<decltype(T1{} / T2{}), N> operator/(T1 lhs, const BasicVector
 
 /* ************************************************************************ */
 
-/**
- * @brief Division operator.
- *
- * @tparam T1 Type of first operand.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2>
-inline BasicVector<decltype(T1{} / T2{}), 2> operator/(T1 lhs, const BasicVector<T2, 2>& rhs) noexcept
-{
-    return BasicVector<decltype(T1{} / T2{}), 2>{
-        lhs / rhs.getX(),
-        lhs / rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Compare vectors.
  *
@@ -2230,25 +903,6 @@ inline bool operator==(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>&
 
 /* ************************************************************************ */
 
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, typename T2>
-inline bool operator==(const BasicVector<T1, 2>& lhs, const BasicVector<T2, 2>& rhs) noexcept
-{
-    return
-        lhs.getX() == rhs.getX() &&
-        lhs.getY() == rhs.getY()
-    ;
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Compare vectors.
  *
@@ -2550,60 +1204,6 @@ inline decltype(T1{} * T2{}) dot(const BasicVector<T1, N>& lhs, const BasicVecto
 
 /* ************************************************************************ */
 
-/**
- * @brief Calculate cross product of two vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Cross product.
- */
-template<typename T1, typename T2>
-inline
-decltype(std::declval<T1>() * std::declval<T2>())
-cross(const BasicVector<T1, 2>& lhs, const BasicVector<T2, 2>& rhs) noexcept
-{
-    return {lhs.getX() * rhs.getY() - lhs.getY() * rhs.getX()};
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Calculate cross product of two vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Cross product.
- */
-template<typename T1, typename T2>
-inline
-BasicVector<decltype(std::declval<T1>() * std::declval<T2>()), 2>
-cross(const BasicVector<T1, 2>& lhs, const T2& rhs) noexcept
-{
-    return {rhs * lhs.getY(), -rhs * lhs.getX()};
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Calculate cross product of two vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Cross product.
- */
-template<typename T1, typename T2>
-inline
-BasicVector<decltype(std::declval<T1>() * std::declval<T2>()), 2>
-cross(const T1& lhs, const BasicVector<T2, 2>& rhs) noexcept
-{
-    return {-lhs * rhs.getY(), lhs * rhs.getX()};
-}
-
-/* ************************************************************************ */
-
 /**
  * @brief Input stream operator.
  *
diff --git a/include/cece/math/Vector2.hpp b/include/cece/math/Vector2.hpp
new file mode 100644
index 0000000..679992c
--- /dev/null
+++ b/include/cece/math/Vector2.hpp
@@ -0,0 +1,1365 @@
+/* ************************************************************************ */
+/* Georgiev Lab (c) 2015-2017                                               */
+/* ************************************************************************ */
+/* Department of Cybernetics                                                */
+/* Faculty of Applied Sciences                                              */
+/* University of West Bohemia in Pilsen                                     */
+/* ************************************************************************ */
+/*                                                                          */
+/* This file is part of CeCe.                                               */
+/*                                                                          */
+/* CeCe is free software: you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by     */
+/* the Free Software Foundation, either version 3 of the License, or        */
+/* (at your option) any later version.                                      */
+/*                                                                          */
+/* CeCe is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/* GNU General Public License for more details.                             */
+/*                                                                          */
+/* You should have received a copy of the GNU General Public License        */
+/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
+/*                                                                          */
+/* ************************************************************************ */
+
+#pragma once
+
+/* ************************************************************************ */
+
+// C++
+#include <cmath>
+#include <type_traits>
+
+// CeCe
+#include "cece/common.hpp"
+#include "cece/Assert.hpp"
+#include "cece/math/Zero.hpp"
+#include "cece/unit/math.hpp"
+#include "cece/unit/Units.hpp"
+
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Two dimensional vector.
+ *
+ * @tparam     T     Element type.
+ */
+template<typename T>
+class BasicVector2
+{
+
+
+// Public Types
+public:
+
+
+    /// BasicVector2 value type.
+    using ValueType = T;
+
+    /// Element type squared.
+    using ValueTypeSq = decltype(std::declval<T>() * std::declval<T>());
+
+
+// Public Ctors
+public:
+
+
+    /**
+     * @brief      Default constructor.
+     */
+    BasicVector2() noexcept;
+
+
+    /**
+     * @brief      Constructor.
+     *
+     * @param      x     The X coordinate.
+     * @param      y     The Y coordinate.
+     */
+    BasicVector2(T x, T y) noexcept;
+
+
+    /**
+     * @brief      Zero value constructor.
+     *
+     * @param[in]  zero  The zero value.
+     */
+    BasicVector2(Zero_t zero) noexcept;
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  src   The source vector.
+     */
+    BasicVector2(const BasicVector2& src) noexcept;
+
+
+    /**
+     * @brief      Move constructor.
+     *
+     * @param[in]  src   The source vector.
+     */
+    BasicVector2(BasicVector2&& src) noexcept;
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param      rhs   Source vector.
+     *
+     * @tparam     T2    The source vector element type.
+     */
+    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
+    BasicVector2(const BasicVector2<T2>& rhs) noexcept;
+
+
+// Public Operators
+public:
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  zero  The zero value.
+     *
+     * @return     *this.
+     */
+    BasicVector2& operator=(Zero_t zero) noexcept;
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  src   The source vector.
+     *
+     * @return     *this.
+     */
+    BasicVector2& operator=(const BasicVector2& src) noexcept;
+
+
+    /**
+     * @brief      Move constructor.
+     *
+     * @param[in]  src   The source vector.
+     *
+     * @return     *this.
+     */
+    BasicVector2& operator=(BasicVector2&& src) noexcept;
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param      v     The source vector.
+     *
+     * @tparam     T2    The source vector element type.
+     *
+     * @return     *this.
+     */
+    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
+    BasicVector2& operator=(const BasicVector2<T2>& src) noexcept;
+
+
+    /**
+     * @brief      Unary plus operator.
+     *
+     * @return     Vector.
+     */
+    BasicVector2 operator+() const noexcept;
+
+
+    /**
+     * @brief      Unary minus operator.
+     *
+     * @return     Vector.
+     */
+    BasicVector2 operator-() const noexcept;
+
+
+    /**
+     * @brief      Addition operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of right operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() + std::declval<T1>()),
+        T
+    >::value>::type* = nullptr>
+    BasicVector2& operator+=(const BasicVector2<T1>& rhs) noexcept;
+
+
+    /**
+     * @brief      Subtraction operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of value in BasicVector2 operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() - std::declval<T1>()),
+        T
+    >::value>::type* = nullptr>
+    BasicVector2& operator-=(const BasicVector2<T1>& rhs) noexcept;
+
+
+    /**
+     * @brief      Multiplication operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of right operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() * std::declval<T1>()),
+        T
+    >::value || std::is_constructible<
+        T,
+        decltype(std::declval<T>() * std::declval<T1>())
+    >::value>::type* = nullptr>
+    BasicVector2& operator*=(T1 rhs) noexcept;
+
+
+    /**
+     * @brief      Multiplication operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of value in BasicVector2 operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() * std::declval<T1>()),
+        T
+    >::value || std::is_constructible<
+        T,
+        decltype(std::declval<T>() * std::declval<T1>())
+    >::value>::type* = nullptr>
+    BasicVector2& operator*=(const BasicVector2<T1>& rhs) noexcept;
+
+
+    /**
+     * @brief      Division operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of right operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() / std::declval<T1>()),
+        T
+    >::value || std::is_constructible<
+        T,
+        decltype(std::declval<T>() * std::declval<T1>())
+    >::value>::type* = nullptr>
+    BasicVector2& operator/=(T1 rhs) noexcept;
+
+
+    /**
+     * @brief      Division operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of value in BasicVector2 operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() / std::declval<T1>()),
+        T
+    >::value || std::is_constructible<
+        T,
+        decltype(std::declval<T>() * std::declval<T1>())
+    >::value>::type* = nullptr>
+    BasicVector2& operator/=(const BasicVector2<T1>& rhs) noexcept;
+
+
+    /**
+     * @brief      Access operator.
+     *
+     * @param      pos   The position.
+     *
+     * @return     Reference to the element.
+     */
+    T& operator[](int pos) noexcept;
+
+
+    /**
+     * @brief      Access operator.
+     *
+     * @param      pos   The position.
+     *
+     * @return     Reference to the element.
+     */
+    const T& operator[](int pos) const noexcept;
+
+
+// Public Accessors
+public:
+
+
+    /**
+     * @brief      Returns X coordinate.
+     *
+     * @return     Reference to X coordinate.
+     */
+    T& x() noexcept;
+
+
+    /**
+     * @brief      Returns X coordinate.
+     *
+     * @return     The X coordinate.
+     */
+    const T& getX() const noexcept;
+
+
+    /**
+     * @brief      Set X coordinate.
+     *
+     * @param      x     The X coordinate.
+     */
+    void setX(T x) noexcept;
+
+
+    /**
+     * @brief      Returns Y coordinate.
+     *
+     * @return     Referent co Y coordinate.
+     */
+    T& y() noexcept;
+
+
+    /**
+     * @brief      Returns Y coordinate.
+     *
+     * @return     The Y coordinate.
+     */
+    const T& getY() const noexcept;
+
+
+    /**
+     * @brief      Set Y coordinate.
+     *
+     * @param      y     The Y coordinate.
+     */
+    void setY(T y) noexcept;
+
+
+    /**
+     * @brief      Check if given value is in given range.
+     *
+     * @param      value  Given value.
+     * @param      low    Minimum value (>=).
+     * @param      high   Maximum value (<).
+     *
+     * @return     If given value is in given range.
+     */
+    static bool inRange(T value, T low, T high) noexcept;
+
+
+    /**
+     * @brief      Check if current vector is in given range.
+     *
+     * @param      low   Minimum coordinates (>=).
+     * @param      high  Maximum coordinates (<).
+     *
+     * @return     If current value is in given range.
+     */
+    bool inRange(const BasicVector2& low, const BasicVector2& high) const noexcept;
+
+
+    /**
+     * @brief      Check if current vector is in given range where the low range
+     *             is Zero vector.
+     *
+     * @param      high  Maximum coordinates (<).
+     *
+     * @return     If current value is in given range.
+     */
+    bool inRange(const BasicVector2& high) const noexcept;
+
+
+// Public Operations
+public:
+
+
+    /**
+     * @brief      Calculate vector length.
+     *
+     * @return     The length.
+     */
+    ValueType getLength() const noexcept;
+
+
+    /**
+     * @brief      Calculate vector length - squared.
+     *
+     * @return     The length squared.
+     */
+    ValueTypeSq getLengthSquared() const noexcept;
+
+
+    /**
+     * @brief      Calculate dot of two vectors.
+     *
+     * @param      rhs   Second vector.
+     *
+     * @return     Dot product.
+     */
+    ValueTypeSq dot(const BasicVector2& rhs) const noexcept;
+
+
+    /**
+     * @brief      Calculate vectors squared distance.
+     *
+     * @param      rhs   Second vector.
+     *
+     * @return     Distance.
+     */
+    ValueTypeSq distanceSquared(const BasicVector2& rhs) const noexcept;
+
+
+    /**
+     * @brief      Calculate vectors distance.
+     *
+     * @param      rhs   Second vector.
+     *
+     * @return     Distance.
+     */
+    ValueType distance(const BasicVector2& rhs) const noexcept;
+
+
+    /**
+     * @brief      Inverse current vector (1 / *this).
+     *
+     * @tparam     T2    Type of result vector's element.
+     *
+     * @return     Inversed vector.
+     */
+    template<typename T2 = T>
+    BasicVector2<T2> inversed() const noexcept;
+
+
+    /**
+     * @brief      Rotate current vector and return rotated version.
+     *
+     * @param      angle  Rotation angle.
+     *
+     * @return     Rotated vector.
+     */
+    BasicVector2 rotated(unit::Angle angle) const noexcept;
+
+
+    /**
+     * @brief      Create from single value.
+     *
+     * @param      val   The value
+     *
+     * @return     Vector of {val, val}.
+     */
+    static BasicVector2 createSingle(T val) noexcept;
+
+
+// Private Data Members
+private:
+
+    /// X coordinate.
+    T m_x;
+
+    /// Y coordinate.
+    T m_y;
+
+};
+
+/* ************************************************************************ */
+
+extern template class BasicVector2<float>;
+extern template class BasicVector2<double>;
+extern template class BasicVector2<unsigned int>;
+extern template class BasicVector2<int>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Addition operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector2.
+ * @tparam     T2    Type of value in second BasicVector2.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Addition operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector2.
+ * @tparam     T2    Type of second operand.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const BasicVector2<T1>& lhs, T2 rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Addition operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of first operand.
+ * @tparam     T2    Type of value in second BasicVector2.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(T1 lhs, const BasicVector2<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Substract operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector2.
+ * @tparam     T2    Type of value in second BasicVector2.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Substract operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector2.
+ * @tparam     T2    Type of second operand.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const BasicVector2<T1>& lhs, T2 rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Substract operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of first operand.
+ * @tparam     T2    Type of value in second BasicVector2.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(T1 lhs, const BasicVector2<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Multiplication operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector2.
+ * @tparam     T2    Type of value in second BasicVector2.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Multiplication operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector2.
+ * @tparam     T2    Type of second operand.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const BasicVector2<T1>& lhs, T2 rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Multiplication operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of first operand.
+ * @tparam     T2    Type of value in second BasicVector2.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(T1 lhs, const BasicVector2<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Division operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector2.
+ * @tparam     T2    Type of value in second BasicVector2.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Division operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector2.
+ * @tparam     T2    Type of second operand.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const BasicVector2<T1>& lhs, T2 rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Division operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of first operand.
+ * @tparam     T2    Type of value in second BasicVector2.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(T1 lhs, const BasicVector2<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    The first type.
+ * @tparam     T2    The second type.
+ *
+ * @return     Comparision result.
+ */
+template<typename T1, typename T2>
+inline bool operator==(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Calculate cross product of two vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    The first type.
+ * @tparam     T2    The second type.
+ *
+ * @return     Cross product.
+ */
+template<typename T1, typename T2>
+inline
+decltype(std::declval<T1>() * std::declval<T2>())
+cross(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Calculate cross product of two vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    The first type.
+ * @tparam     T2    The second type.
+ *
+ * @return     Cross product.
+ */
+template<typename T1, typename T2>
+inline
+BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
+cross(const BasicVector2<T1>& lhs, const T2& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Calculate cross product of two vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    The first type.
+ * @tparam     T2    The second type.
+ *
+ * @return     Cross product.
+ */
+template<typename T1, typename T2>
+inline
+BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
+cross(const T1& lhs, const BasicVector2<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector2<T>::BasicVector2() noexcept
+    : m_x{}
+    , m_y{}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector2<T>::BasicVector2(T x, T y) noexcept
+    : m_x(x)
+    , m_y(y)
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector2<T>::BasicVector2(Zero_t zero) noexcept
+    : m_x{}
+    , m_y{}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector2<T>::BasicVector2(const BasicVector2& src) noexcept
+    : m_x{src.getX()}
+    , m_y{src.getY()}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector2<T>::BasicVector2(BasicVector2&& src) noexcept
+    : m_x{std::move(src.m_x)}
+    , m_y{std::move(src.m_y)}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
+inline BasicVector2<T>::BasicVector2(const BasicVector2<T2>& rhs) noexcept
+    : m_x(rhs.getX())
+    , m_y(rhs.getY())
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector2<T>& BasicVector2<T>::operator=(Zero_t zero) noexcept
+{
+    m_x = T{};
+    m_y = T{};
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector2<T>& BasicVector2<T>::operator=(const BasicVector2& src) noexcept
+{
+    m_x = src.m_x;
+    m_y = src.m_y;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector2<T>& BasicVector2<T>::operator=(BasicVector2&& src) noexcept
+{
+    m_x = std::move(src.m_x);
+    m_y = std::move(src.m_y);
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
+inline BasicVector2<T>& BasicVector2<T>::operator=(const BasicVector2<T2>& src) noexcept
+{
+    m_x = T(src.getX());
+    m_y = T(src.getY());
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector2<T> BasicVector2<T>::operator+() const noexcept
+{
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector2<T> BasicVector2<T>::operator-() const noexcept
+{
+    return {-m_x, -m_y};
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() + std::declval<T1>()),
+    T
+>::value>::type*>
+inline BasicVector2<T>& BasicVector2<T>::operator+=(const BasicVector2<T1>& rhs) noexcept
+{
+    m_x += rhs.getX();
+    m_y += rhs.getY();
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() - std::declval<T1>()),
+    T
+>::value>::type*>
+inline BasicVector2<T>& BasicVector2<T>::operator-=(const BasicVector2<T1>& rhs) noexcept
+{
+    m_x -= rhs.getX();
+    m_y -= rhs.getY();
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() * std::declval<T1>()),
+    T
+>::value || std::is_constructible<
+    T,
+    decltype(std::declval<T>() * std::declval<T1>())
+>::value>::type*>
+inline BasicVector2<T>& BasicVector2<T>::operator*=(T1 rhs) noexcept
+{
+    m_x *= rhs;
+    m_y *= rhs;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() * std::declval<T1>()),
+    T
+>::value || std::is_constructible<
+    T,
+    decltype(std::declval<T>() * std::declval<T1>())
+>::value>::type*>
+inline BasicVector2<T>& BasicVector2<T>::operator*=(const BasicVector2<T1>& rhs) noexcept
+{
+    m_x *= rhs.getX();
+    m_y *= rhs.getY();
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() / std::declval<T1>()),
+    T
+>::value || std::is_constructible<
+    T,
+    decltype(std::declval<T>() * std::declval<T1>())
+>::value>::type*>
+inline BasicVector2<T>& BasicVector2<T>::operator/=(T1 rhs) noexcept
+{
+    m_x /= rhs;
+    m_y /= rhs;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() / std::declval<T1>()),
+    T
+>::value || std::is_constructible<
+    T,
+    decltype(std::declval<T>() * std::declval<T1>())
+>::value>::type*>
+inline BasicVector2<T>& BasicVector2<T>::operator/=(const BasicVector2<T1>& rhs) noexcept
+{
+    m_x /= rhs.getX();
+    m_y /= rhs.getY();
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline T& BasicVector2<T>::operator[](int pos) noexcept
+{
+    CECE_ASSERT(pos >= 0);
+    CECE_ASSERT(pos < 2);
+    return (&m_x)[pos];
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& BasicVector2<T>::operator[](int pos) const noexcept
+{
+    CECE_ASSERT(pos >= 0);
+    CECE_ASSERT(pos < 2);
+    return (&m_x)[pos];
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline T& BasicVector2<T>::x() noexcept
+{
+    return m_x;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& BasicVector2<T>::getX() const noexcept
+{
+    return m_x;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void BasicVector2<T>::setX(T x) noexcept
+{
+    m_x = std::move(x);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline T& BasicVector2<T>::y() noexcept
+{
+    return m_y;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& BasicVector2<T>::getY() const noexcept
+{
+    return m_y;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void BasicVector2<T>::setY(T y) noexcept
+{
+    m_y = std::move(y);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline bool BasicVector2<T>::inRange(T value, T low, T high) noexcept
+{
+    return value >= low && value < high;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline bool BasicVector2<T>::inRange(const BasicVector2& low, const BasicVector2& high) const noexcept
+{
+    bool res = true;
+
+    res = res && inRange(getX(), low.getX(), high.getX());
+    res = res && inRange(getY(), low.getY(), high.getY());
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline bool BasicVector2<T>::inRange(const BasicVector2& high) const noexcept
+{
+    return inRange(Zero, high);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline typename BasicVector2<T>::ValueType BasicVector2<T>::getLength() const noexcept
+{
+    using std::sqrt;
+    return static_cast<T>(sqrt(getLengthSquared()));
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline typename BasicVector2<T>::ValueTypeSq BasicVector2<T>::getLengthSquared() const noexcept
+{
+    return dot(*this);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline typename BasicVector2<T>::ValueTypeSq BasicVector2<T>::dot(const BasicVector2& rhs) const noexcept
+{
+    return getX() * rhs.getX() + getY() * rhs.getY();
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline typename BasicVector2<T>::ValueTypeSq BasicVector2<T>::distanceSquared(const BasicVector2& rhs) const noexcept
+{
+    return (*this - rhs).getLengthSquared();
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline typename BasicVector2<T>::ValueType BasicVector2<T>::distance(const BasicVector2& rhs) const noexcept
+{
+    return (*this - rhs).getLength();
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T2>
+inline BasicVector2<T2> BasicVector2<T>::inversed() const noexcept
+{
+    return {T2(1) / getX(), T2(1) / getY()};
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector2<T> BasicVector2<T>::rotated(unit::Angle angle) const noexcept
+{
+    return {
+        static_cast<T>(getX() * cos(static_cast<RealType>(angle)) - getY() * sin(static_cast<RealType>(angle))),
+        static_cast<T>(getX() * sin(static_cast<RealType>(angle)) + getY() * cos(static_cast<RealType>(angle)))
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector2<T> BasicVector2<T>::createSingle(T val) noexcept
+{
+    return {val, val};
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
+{
+    return {
+        lhs.getX() + rhs.getX(),
+        lhs.getY() + rhs.getY()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const BasicVector2<T1>& lhs, T2 rhs) noexcept
+{
+    return {
+        lhs.getX() + rhs,
+        lhs.getY() + rhs
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(T1 lhs, const BasicVector2<T2>& rhs) noexcept
+{
+    return {
+        lhs + rhs.getX(),
+        lhs + rhs.getY()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
+{
+    return {
+        lhs.getX() - rhs.getX(),
+        lhs.getY() - rhs.getY()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const BasicVector2<T1>& lhs, T2 rhs) noexcept
+{
+    return {
+        lhs.getX() - rhs,
+        lhs.getY() - rhs
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(T1 lhs, const BasicVector2<T2>& rhs) noexcept
+{
+    return {
+        lhs - rhs.getX(),
+        lhs - rhs.getY()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
+{
+    return {
+        lhs.getX() * rhs.getX(),
+        lhs.getY() * rhs.getY()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const BasicVector2<T1>& lhs, T2 rhs) noexcept
+{
+    return {
+        lhs.getX() * rhs,
+        lhs.getY() * rhs
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(T1 lhs, const BasicVector2<T2>& rhs) noexcept
+{
+    return {
+        lhs * rhs.getX(),
+        lhs * rhs.getY()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
+{
+    return {
+        lhs.getX() / rhs.getX(),
+        lhs.getY() / rhs.getY()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const BasicVector2<T1>& lhs, T2 rhs) noexcept
+{
+    return {
+        lhs.getX() / rhs,
+        lhs.getY() / rhs
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector2<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(T1 lhs, const BasicVector2<T2>& rhs) noexcept
+{
+    return {
+        lhs / rhs.getX(),
+        lhs / rhs.getY()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline bool operator==(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
+{
+    return
+        lhs.getX() == rhs.getX() &&
+        lhs.getY() == rhs.getY()
+    ;
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline
+decltype(std::declval<T1>() * std::declval<T2>())
+cross(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
+{
+    return {lhs.getX() * rhs.getY() - lhs.getY() * rhs.getX()};
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline
+BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
+cross(const BasicVector2<T1>& lhs, const T2& rhs) noexcept
+{
+    return {rhs * lhs.getY(), -rhs * lhs.getX()};
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline
+BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
+cross(const T1& lhs, const BasicVector2<T2>& rhs) noexcept
+{
+    return {-lhs * rhs.getY(), lhs * rhs.getX()};
+}
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
diff --git a/include/cece/math/Vector3.hpp b/include/cece/math/Vector3.hpp
new file mode 100644
index 0000000..54ca338
--- /dev/null
+++ b/include/cece/math/Vector3.hpp
@@ -0,0 +1,1392 @@
+/* ************************************************************************ */
+/* Georgiev Lab (c) 2015-2017                                               */
+/* ************************************************************************ */
+/* Department of Cybernetics                                                */
+/* Faculty of Applied Sciences                                              */
+/* University of West Bohemia in Pilsen                                     */
+/* ************************************************************************ */
+/*                                                                          */
+/* This file is part of CeCe.                                               */
+/*                                                                          */
+/* CeCe is free software: you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by     */
+/* the Free Software Foundation, either version 3 of the License, or        */
+/* (at your option) any later version.                                      */
+/*                                                                          */
+/* CeCe is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/* GNU General Public License for more details.                             */
+/*                                                                          */
+/* You should have received a copy of the GNU General Public License        */
+/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
+/*                                                                          */
+/* ************************************************************************ */
+
+#pragma once
+
+/* ************************************************************************ */
+
+// C++
+#include <cmath>
+#include <type_traits>
+
+// CeCe
+#include "cece/common.hpp"
+#include "cece/Assert.hpp"
+#include "cece/math/Zero.hpp"
+#include "cece/unit/math.hpp"
+#include "cece/unit/Units.hpp"
+
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Three dimensional vector.
+ *
+ * @tparam     T     Element type.
+ */
+template<typename T>
+class BasicVector3
+{
+
+
+// Public Types
+public:
+
+
+    /// BasicVector3 value type.
+    using ValueType = T;
+
+    /// Element type squared.
+    using ValueTypeSq = decltype(std::declval<T>() * std::declval<T>());
+
+
+// Public Ctors
+public:
+
+
+    /**
+     * @brief      Default constructor.
+     */
+    BasicVector3() noexcept;
+
+
+    /**
+     * @brief      Constructor.
+     *
+     * @param      x     The X coordinate.
+     * @param      y     The Y coordinate.
+     * @param      y     The Z coordinate.
+     */
+    BasicVector3(T x, T y, T z) noexcept;
+
+
+    /**
+     * @brief      Zero value constructor.
+     *
+     * @param[in]  zero  The zero value.
+     */
+    BasicVector3(Zero_t zero) noexcept;
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  src   The source vector.
+     */
+    BasicVector3(const BasicVector3& src) noexcept;
+
+
+    /**
+     * @brief      Move constructor.
+     *
+     * @param[in]  src   The source vector.
+     */
+    BasicVector3(BasicVector3&& src) noexcept;
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param      rhs   Source vector.
+     *
+     * @tparam     T2    The source vector element type.
+     */
+    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
+    BasicVector3(const BasicVector3<T2>& rhs) noexcept;
+
+
+// Public Operators
+public:
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  zero  The zero value.
+     *
+     * @return     *this.
+     */
+    BasicVector3& operator=(Zero_t zero) noexcept;
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  src   The source vector.
+     *
+     * @return     *this.
+     */
+    BasicVector3& operator=(const BasicVector3& src) noexcept;
+
+
+    /**
+     * @brief      Move constructor.
+     *
+     * @param[in]  src   The source vector.
+     *
+     * @return     *this.
+     */
+    BasicVector3& operator=(BasicVector3&& src) noexcept;
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param      v     The source vector.
+     *
+     * @tparam     T2    The source vector element type.
+     *
+     * @return     *this.
+     */
+    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
+    BasicVector3& operator=(const BasicVector3<T2>& src) noexcept;
+
+
+    /**
+     * @brief      Unary plus operator.
+     *
+     * @return     Vector.
+     */
+    BasicVector3 operator+() const noexcept;
+
+
+    /**
+     * @brief      Unary minus operator.
+     *
+     * @return     Vector.
+     */
+    BasicVector3 operator-() const noexcept;
+
+
+    /**
+     * @brief      Addition operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of right operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() + std::declval<T1>()),
+        T
+    >::value>::type* = nullptr>
+    BasicVector3& operator+=(const BasicVector3<T1>& rhs) noexcept;
+
+
+    /**
+     * @brief      Subtraction operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of value in BasicVector3 operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() - std::declval<T1>()),
+        T
+    >::value>::type* = nullptr>
+    BasicVector3& operator-=(const BasicVector3<T1>& rhs) noexcept;
+
+
+    /**
+     * @brief      Multiplication operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of right operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() * std::declval<T1>()),
+        T
+    >::value || std::is_constructible<
+        T,
+        decltype(std::declval<T>() * std::declval<T1>())
+    >::value>::type* = nullptr>
+    BasicVector3& operator*=(T1 rhs) noexcept;
+
+
+    /**
+     * @brief      Multiplication operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of value in BasicVector3 operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() * std::declval<T1>()),
+        T
+    >::value || std::is_constructible<
+        T,
+        decltype(std::declval<T>() * std::declval<T1>())
+    >::value>::type* = nullptr>
+    BasicVector3& operator*=(const BasicVector3<T1>& rhs) noexcept;
+
+
+    /**
+     * @brief      Division operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of right operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() / std::declval<T1>()),
+        T
+    >::value || std::is_constructible<
+        T,
+        decltype(std::declval<T>() * std::declval<T1>())
+    >::value>::type* = nullptr>
+    BasicVector3& operator/=(T1 rhs) noexcept;
+
+
+    /**
+     * @brief      Division operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         Type of value in BasicVector3 operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1, typename std::enable_if<std::is_same<
+        decltype(std::declval<T>() / std::declval<T1>()),
+        T
+    >::value || std::is_constructible<
+        T,
+        decltype(std::declval<T>() * std::declval<T1>())
+    >::value>::type* = nullptr>
+    BasicVector3& operator/=(const BasicVector3<T1>& rhs) noexcept;
+
+
+    /**
+     * @brief      Access operator.
+     *
+     * @param      pos   The position.
+     *
+     * @return     Reference to the element.
+     */
+    T& operator[](int pos) noexcept;
+
+
+    /**
+     * @brief      Access operator.
+     *
+     * @param      pos   The position.
+     *
+     * @return     Reference to the element.
+     */
+    const T& operator[](int pos) const noexcept;
+
+
+// Public Accessors
+public:
+
+
+    /**
+     * @brief      Returns X coordinate.
+     *
+     * @return     Reference to X coordinate.
+     */
+    T& x() noexcept;
+
+
+    /**
+     * @brief      Returns X coordinate.
+     *
+     * @return     The X coordinate.
+     */
+    const T& getX() const noexcept;
+
+
+    /**
+     * @brief      Set X coordinate.
+     *
+     * @param      x     The X coordinate.
+     */
+    void setX(T x) noexcept;
+
+
+    /**
+     * @brief      Returns Y coordinate.
+     *
+     * @return     Referent co Y coordinate.
+     */
+    T& y() noexcept;
+
+
+    /**
+     * @brief      Returns Y coordinate.
+     *
+     * @return     The Y coordinate.
+     */
+    const T& getY() const noexcept;
+
+
+    /**
+     * @brief      Set Y coordinate.
+     *
+     * @param      y     The Y coordinate.
+     */
+    void setY(T y) noexcept;
+
+
+    /**
+     * @brief      Returns Z coordinate.
+     *
+     * @return     Referent co Z coordinate.
+     */
+    T& z() noexcept;
+
+
+    /**
+     * @brief      Returns Z coordinate.
+     *
+     * @return     The Z coordinate.
+     */
+    const T& getZ() const noexcept;
+
+
+    /**
+     * @brief      Set Z coordinate.
+     *
+     * @param      z     The Z coordinate.
+     */
+    void setZ(T z) noexcept;
+
+
+    /**
+     * @brief      Check if given value is in given range.
+     *
+     * @param      value  Given value.
+     * @param      low    Minimum value (>=).
+     * @param      high   Maximum value (<).
+     *
+     * @return     If given value is in given range.
+     */
+    static bool inRange(T value, T low, T high) noexcept;
+
+
+    /**
+     * @brief      Check if current vector is in given range.
+     *
+     * @param      low   Minimum coordinates (>=).
+     * @param      high  Maximum coordinates (<).
+     *
+     * @return     If current value is in given range.
+     */
+    bool inRange(const BasicVector3& low, const BasicVector3& high) const noexcept;
+
+
+    /**
+     * @brief      Check if current vector is in given range where the low range
+     *             is Zero vector.
+     *
+     * @param      high  Maximum coordinates (<).
+     *
+     * @return     If current value is in given range.
+     */
+    bool inRange(const BasicVector3& high) const noexcept;
+
+
+// Public Operations
+public:
+
+
+    /**
+     * @brief      Calculate vector length.
+     *
+     * @return     The length.
+     */
+    ValueType getLength() const noexcept;
+
+
+    /**
+     * @brief      Calculate vector length - squared.
+     *
+     * @return     The length squared.
+     */
+    ValueTypeSq getLengthSquared() const noexcept;
+
+
+    /**
+     * @brief      Calculate dot of two vectors.
+     *
+     * @param      rhs   Second vector.
+     *
+     * @return     Dot product.
+     */
+    ValueTypeSq dot(const BasicVector3& rhs) const noexcept;
+
+
+    /**
+     * @brief      Calculate vectors squared distance.
+     *
+     * @param      rhs   Second vector.
+     *
+     * @return     Distance.
+     */
+    ValueTypeSq distanceSquared(const BasicVector3& rhs) const noexcept;
+
+
+    /**
+     * @brief      Calculate vectors distance.
+     *
+     * @param      rhs   Second vector.
+     *
+     * @return     Distance.
+     */
+    ValueType distance(const BasicVector3& rhs) const noexcept;
+
+
+    /**
+     * @brief      Inverse current vector (1 / *this).
+     *
+     * @tparam     T2    Type of result vector's element.
+     *
+     * @return     Inversed vector.
+     */
+    template<typename T2 = T>
+    BasicVector3<T2> inversed() const noexcept;
+
+
+    /**
+     * @brief      Rotate current vector and return rotated version.
+     *
+     * @param      angle  Rotation angle.
+     *
+     * @return     Rotated vector.
+     */
+    BasicVector3 rotated(unit::Angle angle) const noexcept;
+
+
+    /**
+     * @brief      Create from single value.
+     *
+     * @param      val   The value
+     *
+     * @return     Vector of {val, val}.
+     */
+    static BasicVector3 createSingle(T val) noexcept;
+
+
+// Private Data Members
+private:
+
+    /// X coordinate.
+    T m_x;
+
+    /// Y coordinate.
+    T m_y;
+
+    /// Z coordinate.
+    T m_z;
+
+};
+
+/* ************************************************************************ */
+
+extern template class BasicVector3<float>;
+extern template class BasicVector3<double>;
+extern template class BasicVector3<unsigned int>;
+extern template class BasicVector3<int>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Addition operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector3.
+ * @tparam     T2    Type of value in second BasicVector3.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Addition operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector3.
+ * @tparam     T2    Type of second operand.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const BasicVector3<T1>& lhs, T2 rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Addition operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of first operand.
+ * @tparam     T2    Type of value in second BasicVector3.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(T1 lhs, const BasicVector3<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Substract operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector3.
+ * @tparam     T2    Type of value in second BasicVector3.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Substract operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector3.
+ * @tparam     T2    Type of second operand.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const BasicVector3<T1>& lhs, T2 rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Substract operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of first operand.
+ * @tparam     T2    Type of value in second BasicVector3.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(T1 lhs, const BasicVector3<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Multiplication operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector3.
+ * @tparam     T2    Type of value in second BasicVector3.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Multiplication operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector3.
+ * @tparam     T2    Type of second operand.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const BasicVector3<T1>& lhs, T2 rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Multiplication operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of first operand.
+ * @tparam     T2    Type of value in second BasicVector3.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(T1 lhs, const BasicVector3<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Division operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector3.
+ * @tparam     T2    Type of value in second BasicVector3.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Division operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first BasicVector3.
+ * @tparam     T2    Type of second operand.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const BasicVector3<T1>& lhs, T2 rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Division operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of first operand.
+ * @tparam     T2    Type of value in second BasicVector3.
+ *
+ * @return     Result vector.
+ */
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(T1 lhs, const BasicVector3<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    The first type.
+ * @tparam     T2    The second type.
+ *
+ * @return     Comparision result.
+ */
+template<typename T1, typename T2>
+inline bool operator==(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Calculate cross product of two vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    The first type.
+ * @tparam     T2    The second type.
+ *
+ * @return     Cross product.
+ */
+template<typename T1, typename T2>
+inline
+BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
+cross(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector3<T>::BasicVector3() noexcept
+    : m_x{}
+    , m_y{}
+    , m_z{}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector3<T>::BasicVector3(T x, T y, T z) noexcept
+    : m_x(x)
+    , m_y(y)
+    , m_z(y)
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector3<T>::BasicVector3(Zero_t zero) noexcept
+    : m_x{}
+    , m_y{}
+    , m_z{}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector3<T>::BasicVector3(const BasicVector3& src) noexcept
+    : m_x{src.getX()}
+    , m_y{src.getY()}
+    , m_z{src.getZ()}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector3<T>::BasicVector3(BasicVector3&& src) noexcept
+    : m_x{std::move(src.m_x)}
+    , m_y{std::move(src.m_y)}
+    , m_z{std::move(src.m_z)}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
+inline BasicVector3<T>::BasicVector3(const BasicVector3<T2>& rhs) noexcept
+    : m_x(rhs.getX())
+    , m_y(rhs.getY())
+    , m_z(rhs.getZ())
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector3<T>& BasicVector3<T>::operator=(Zero_t zero) noexcept
+{
+    m_x = T{};
+    m_y = T{};
+    m_z = T{};
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector3<T>& BasicVector3<T>::operator=(const BasicVector3& src) noexcept
+{
+    m_x = src.m_x;
+    m_y = src.m_y;
+    m_z = src.m_z;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector3<T>& BasicVector3<T>::operator=(BasicVector3&& src) noexcept
+{
+    m_x = std::move(src.m_x);
+    m_y = std::move(src.m_y);
+    m_z = std::move(src.m_z);
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
+inline BasicVector3<T>& BasicVector3<T>::operator=(const BasicVector3<T2>& src) noexcept
+{
+    m_x = T(src.getX());
+    m_y = T(src.getY());
+    m_z = T(src.getZ());
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector3<T> BasicVector3<T>::operator+() const noexcept
+{
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector3<T> BasicVector3<T>::operator-() const noexcept
+{
+    return {-m_x, -m_y, -m_z};
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() + std::declval<T1>()),
+    T
+>::value>::type*>
+inline BasicVector3<T>& BasicVector3<T>::operator+=(const BasicVector3<T1>& rhs) noexcept
+{
+    m_x += rhs.getX();
+    m_y += rhs.getY();
+    m_z += rhs.getZ();
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() - std::declval<T1>()),
+    T
+>::value>::type*>
+inline BasicVector3<T>& BasicVector3<T>::operator-=(const BasicVector3<T1>& rhs) noexcept
+{
+    m_x -= rhs.getX();
+    m_y -= rhs.getY();
+    m_z -= rhs.getZ();
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() * std::declval<T1>()),
+    T
+>::value || std::is_constructible<
+    T,
+    decltype(std::declval<T>() * std::declval<T1>())
+>::value>::type*>
+inline BasicVector3<T>& BasicVector3<T>::operator*=(T1 rhs) noexcept
+{
+    m_x *= rhs;
+    m_y *= rhs;
+    m_z *= rhs;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() * std::declval<T1>()),
+    T
+>::value || std::is_constructible<
+    T,
+    decltype(std::declval<T>() * std::declval<T1>())
+>::value>::type*>
+inline BasicVector3<T>& BasicVector3<T>::operator*=(const BasicVector3<T1>& rhs) noexcept
+{
+    m_x *= rhs.getX();
+    m_y *= rhs.getY();
+    m_z *= rhs.getZ();
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() / std::declval<T1>()),
+    T
+>::value || std::is_constructible<
+    T,
+    decltype(std::declval<T>() * std::declval<T1>())
+>::value>::type*>
+inline BasicVector3<T>& BasicVector3<T>::operator/=(T1 rhs) noexcept
+{
+    m_x /= rhs;
+    m_y /= rhs;
+    m_z /= rhs;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T1, typename std::enable_if<std::is_same<
+    decltype(std::declval<T>() / std::declval<T1>()),
+    T
+>::value || std::is_constructible<
+    T,
+    decltype(std::declval<T>() * std::declval<T1>())
+>::value>::type*>
+inline BasicVector3<T>& BasicVector3<T>::operator/=(const BasicVector3<T1>& rhs) noexcept
+{
+    m_x /= rhs.getX();
+    m_y /= rhs.getY();
+    m_z /= rhs.getZ();
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline T& BasicVector3<T>::operator[](int pos) noexcept
+{
+    CECE_ASSERT(pos >= 0);
+    CECE_ASSERT(pos < 3);
+    return (&m_x)[pos];
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& BasicVector3<T>::operator[](int pos) const noexcept
+{
+    CECE_ASSERT(pos >= 0);
+    CECE_ASSERT(pos < 3);
+    return (&m_x)[pos];
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline T& BasicVector3<T>::x() noexcept
+{
+    return m_x;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& BasicVector3<T>::getX() const noexcept
+{
+    return m_x;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void BasicVector3<T>::setX(T x) noexcept
+{
+    m_x = std::move(x);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline T& BasicVector3<T>::y() noexcept
+{
+    return m_y;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& BasicVector3<T>::getY() const noexcept
+{
+    return m_y;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void BasicVector3<T>::setY(T y) noexcept
+{
+    m_y = std::move(y);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline T& BasicVector3<T>::z() noexcept
+{
+    return m_z;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& BasicVector3<T>::getZ() const noexcept
+{
+    return m_z;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void BasicVector3<T>::setZ(T z) noexcept
+{
+    m_z = std::move(z);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline bool BasicVector3<T>::inRange(T value, T low, T high) noexcept
+{
+    return value >= low && value < high;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline bool BasicVector3<T>::inRange(const BasicVector3& low, const BasicVector3& high) const noexcept
+{
+    bool res = true;
+
+    res = res && inRange(getX(), low.getX(), high.getX());
+    res = res && inRange(getY(), low.getY(), high.getY());
+    res = res && inRange(getZ(), low.getZ(), high.getZ());
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline bool BasicVector3<T>::inRange(const BasicVector3& high) const noexcept
+{
+    return inRange(Zero, high);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline typename BasicVector3<T>::ValueType BasicVector3<T>::getLength() const noexcept
+{
+    using std::sqrt;
+    return static_cast<T>(sqrt(getLengthSquared()));
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline typename BasicVector3<T>::ValueTypeSq BasicVector3<T>::getLengthSquared() const noexcept
+{
+    return dot(*this);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline typename BasicVector3<T>::ValueTypeSq BasicVector3<T>::dot(const BasicVector3& rhs) const noexcept
+{
+    return
+        getX() * rhs.getX() +
+        getY() * rhs.getY() +
+        getZ() * rhs.getZ()
+    ;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline typename BasicVector3<T>::ValueTypeSq BasicVector3<T>::distanceSquared(const BasicVector3& rhs) const noexcept
+{
+    return (*this - rhs).getLengthSquared();
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline typename BasicVector3<T>::ValueType BasicVector3<T>::distance(const BasicVector3& rhs) const noexcept
+{
+    return (*this - rhs).getLength();
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T2>
+inline BasicVector3<T2> BasicVector3<T>::inversed() const noexcept
+{
+    return {
+        T2(1) / getX(),
+        T2(1) / getY(),
+        T2(1) / getZ()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline BasicVector3<T> BasicVector3<T>::createSingle(T val) noexcept
+{
+    return {val, val, val};
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
+{
+    return {
+        lhs.getX() + rhs.getX(),
+        lhs.getY() + rhs.getY(),
+        lhs.getZ() + rhs.getZ()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const BasicVector3<T1>& lhs, T2 rhs) noexcept
+{
+    return {
+        lhs.getX() + rhs,
+        lhs.getY() + rhs,
+        lhs.getZ() + rhs
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(T1 lhs, const BasicVector3<T2>& rhs) noexcept
+{
+    return {
+        lhs + rhs.getX(),
+        lhs + rhs.getY(),
+        lhs + rhs.getZ()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
+{
+    return {
+        lhs.getX() - rhs.getX(),
+        lhs.getY() - rhs.getY(),
+        lhs.getZ() - rhs.getZ()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const BasicVector3<T1>& lhs, T2 rhs) noexcept
+{
+    return {
+        lhs.getX() - rhs,
+        lhs.getY() - rhs,
+        lhs.getZ() - rhs
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(T1 lhs, const BasicVector3<T2>& rhs) noexcept
+{
+    return {
+        lhs - rhs.getX(),
+        lhs - rhs.getY(),
+        lhs - rhs.getZ()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
+{
+    return {
+        lhs.getX() * rhs.getX(),
+        lhs.getY() * rhs.getY(),
+        lhs.getZ() * rhs.getZ()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const BasicVector3<T1>& lhs, T2 rhs) noexcept
+{
+    return {
+        lhs.getX() * rhs,
+        lhs.getY() * rhs,
+        lhs.getZ() * rhs
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(T1 lhs, const BasicVector3<T2>& rhs) noexcept
+{
+    return {
+        lhs * rhs.getX(),
+        lhs * rhs.getY(),
+        lhs * rhs.getZ()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
+{
+    return {
+        lhs.getX() / rhs.getX(),
+        lhs.getY() / rhs.getY(),
+        lhs.getZ() / rhs.getZ()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const BasicVector3<T1>& lhs, T2 rhs) noexcept
+{
+    return {
+        lhs.getX() / rhs,
+        lhs.getY() / rhs,
+        lhs.getZ() / rhs
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline BasicVector3<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(T1 lhs, const BasicVector3<T2>& rhs) noexcept
+{
+    return {
+        lhs / rhs.getX(),
+        lhs / rhs.getY(),
+        lhs / rhs.getZ()
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline bool operator==(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
+{
+    return
+        lhs.getX() == rhs.getX() &&
+        lhs.getY() == rhs.getY() &&
+        lhs.getZ() == rhs.getZ()
+    ;
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline
+BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
+cross(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
+{
+    return {
+        lhs.getY() * rhs.getZ() - lhs.getZ() * rhs.getY(),
+        lhs.getZ() * rhs.getX() - lhs.getX() * rhs.getZ(),
+        lhs.getX() * rhs.getY() - lhs.getY() * rhs.getX()
+    };
+}
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
diff --git a/src/math/CMakeLists.txt b/src/math/CMakeLists.txt
index 526f590..ca0401b 100644
--- a/src/math/CMakeLists.txt
+++ b/src/math/CMakeLists.txt
@@ -1,5 +1,5 @@
 # ######################################################################### #
-# Georgiev Lab (c) 2015-2016                                                #
+# Georgiev Lab (c) 2015-2017                                                #
 # ######################################################################### #
 # Department of Cybernetics                                                 #
 # Faculty of Applied Sciences                                               #
@@ -25,6 +25,8 @@
 
 set(SRCS
     Vector.cpp
+    Vector2.cpp
+    Vector3.cpp
     Grid.cpp
 )
 
diff --git a/src/math/Vector2.cpp b/src/math/Vector2.cpp
new file mode 100644
index 0000000..69745c6
--- /dev/null
+++ b/src/math/Vector2.cpp
@@ -0,0 +1,46 @@
+/* ************************************************************************ */
+/* Georgiev Lab (c) 2015-2017                                               */
+/* ************************************************************************ */
+/* Department of Cybernetics                                                */
+/* Faculty of Applied Sciences                                              */
+/* University of West Bohemia in Pilsen                                     */
+/* ************************************************************************ */
+/*                                                                          */
+/* This file is part of CeCe.                                               */
+/*                                                                          */
+/* CeCe is free software: you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by     */
+/* the Free Software Foundation, either version 3 of the License, or        */
+/* (at your option) any later version.                                      */
+/*                                                                          */
+/* CeCe is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/* GNU General Public License for more details.                             */
+/*                                                                          */
+/* You should have received a copy of the GNU General Public License        */
+/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
+/*                                                                          */
+/* ************************************************************************ */
+
+// Declaration
+#include "cece/math/Vector2.hpp"
+
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+template class BasicVector2<float>;
+template class BasicVector2<double>;
+template class BasicVector2<unsigned int>;
+template class BasicVector2<int>;
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
diff --git a/src/math/Vector3.cpp b/src/math/Vector3.cpp
new file mode 100644
index 0000000..c8d3a51
--- /dev/null
+++ b/src/math/Vector3.cpp
@@ -0,0 +1,46 @@
+/* ************************************************************************ */
+/* Georgiev Lab (c) 2015-2017                                               */
+/* ************************************************************************ */
+/* Department of Cybernetics                                                */
+/* Faculty of Applied Sciences                                              */
+/* University of West Bohemia in Pilsen                                     */
+/* ************************************************************************ */
+/*                                                                          */
+/* This file is part of CeCe.                                               */
+/*                                                                          */
+/* CeCe is free software: you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by     */
+/* the Free Software Foundation, either version 3 of the License, or        */
+/* (at your option) any later version.                                      */
+/*                                                                          */
+/* CeCe is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/* GNU General Public License for more details.                             */
+/*                                                                          */
+/* You should have received a copy of the GNU General Public License        */
+/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
+/*                                                                          */
+/* ************************************************************************ */
+
+// Declaration
+#include "cece/math/Vector3.hpp"
+
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+template class BasicVector3<float>;
+template class BasicVector3<double>;
+template class BasicVector3<unsigned int>;
+template class BasicVector3<int>;
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
diff --git a/unittests/math/CMakeLists.txt b/unittests/math/CMakeLists.txt
index dc505b8..6574948 100644
--- a/unittests/math/CMakeLists.txt
+++ b/unittests/math/CMakeLists.txt
@@ -26,6 +26,7 @@
 cece_add_test(core
     SOURCES
         Vector_test.cpp
+        Vector2_test.cpp
         VectorRangeTest.cpp
 )
 
diff --git a/unittests/math/Vector2_test.cpp b/unittests/math/Vector2_test.cpp
new file mode 100644
index 0000000..bc8c62a
--- /dev/null
+++ b/unittests/math/Vector2_test.cpp
@@ -0,0 +1,427 @@
+/* ************************************************************************ */
+/* Georgiev Lab (c) 2015-2017                                               */
+/* ************************************************************************ */
+/* Department of Cybernetics                                                */
+/* Faculty of Applied Sciences                                              */
+/* University of West Bohemia in Pilsen                                     */
+/* ************************************************************************ */
+/*                                                                          */
+/* This file is part of CeCe.                                               */
+/*                                                                          */
+/* CeCe is free software: you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by     */
+/* the Free Software Foundation, either version 3 of the License, or        */
+/* (at your option) any later version.                                      */
+/*                                                                          */
+/* CeCe is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/* GNU General Public License for more details.                             */
+/*                                                                          */
+/* You should have received a copy of the GNU General Public License        */
+/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
+/*                                                                          */
+/* ************************************************************************ */
+
+// GTest
+#include "gtest/gtest.h"
+
+// CeCe
+#include "cece/math/Vector2.hpp"
+
+/* ************************************************************************ */
+
+using namespace cece;
+using namespace cece::math;
+
+/* ************************************************************************ */
+
+TEST(Vector2, ctor)
+{
+    {
+        BasicVector2<int> vec;
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+    }
+
+    {
+        BasicVector2<int> vec(Zero);
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+    }
+
+    {
+        BasicVector2<float> vec = {1.2f, 3.0f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec[1]);
+    }
+
+    {
+        const BasicVector2<float> vec1 = {1.2f, 3.0f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec1.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec1.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+
+        BasicVector2<float> vec2(vec1);
+
+        EXPECT_FLOAT_EQ(1.2f, vec2.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+    }
+
+    {
+        BasicVector2<float> vec1 = {1.2f, 3.0f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec1.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec1.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+
+        BasicVector2<float> vec2(std::move(vec1));
+
+        EXPECT_FLOAT_EQ(1.2f, vec2.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+    }
+
+    {
+        const BasicVector2<int> vec1 = {1, 3};
+
+        EXPECT_EQ(1, vec1.getX());
+        EXPECT_EQ(3, vec1.getY());
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+
+        BasicVector2<float> vec2(vec1);
+
+        EXPECT_FLOAT_EQ(1.0f, vec2.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(1.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector2, assignment)
+{
+    {
+        BasicVector2<int> vec{1, 1};
+
+        EXPECT_EQ(1, vec[0]);
+        EXPECT_EQ(1, vec[1]);
+
+        vec = Zero;
+
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+    }
+
+    {
+        BasicVector2<float> vec;
+
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+
+        vec = {1.2f, 3.0f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec[1]);
+    }
+
+    {
+        const BasicVector2<float> vec1 = {1.2f, 3.0f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+
+        BasicVector2<float> vec2;
+
+        vec2 = vec1;
+
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+    }
+
+    {
+        BasicVector2<float> vec1 = {1.2f, 3.0f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+
+        BasicVector2<float> vec2;
+
+        vec2 = std::move(vec1);
+
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+    }
+
+    {
+        const BasicVector2<int> vec1 = {1, 3};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+
+        BasicVector2<float> vec2;
+
+        vec2 = vec1;
+
+        EXPECT_FLOAT_EQ(1.0, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector2, operators)
+{
+    {
+        BasicVector2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        BasicVector2<float> vec2 = +vec1;
+
+        EXPECT_FLOAT_EQ(1.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec2[1]);
+    }
+
+    {
+        BasicVector2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        BasicVector2<float> vec2 = -vec1;
+
+        EXPECT_FLOAT_EQ(-1.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(-2.0f, vec2[1]);
+    }
+
+    {
+        BasicVector2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        BasicVector2<float> vec2{1.0f, 2.0f};
+        vec1 += vec2;
+
+        EXPECT_FLOAT_EQ(2.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
+    }
+
+    {
+        BasicVector2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        BasicVector2<float> vec2{1.0f, 2.0f};
+        vec1 -= vec2;
+
+        EXPECT_FLOAT_EQ(0.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[1]);
+    }
+
+    {
+        BasicVector2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        vec1 *= 2.0;
+
+        EXPECT_FLOAT_EQ(2.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
+    }
+
+    {
+        BasicVector2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        BasicVector2<float> vec2{1.0f, 2.0f};
+        vec1 *= vec2;
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
+    }
+
+    {
+        BasicVector2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        vec1 /= 2.0;
+
+        EXPECT_FLOAT_EQ(0.5f, vec1[0]);
+        EXPECT_FLOAT_EQ(1.0f, vec1[1]);
+    }
+
+    {
+        BasicVector2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        BasicVector2<float> vec2{1.0f, 2.0f};
+        vec1 /= vec2;
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(1.0f, vec1[1]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector2, inRange)
+{
+    {
+        const BasicVector2<float> vecMin{-10.0f, -5.0f};
+        const BasicVector2<float> vecMax{10.0f, 20.0f};
+
+        BasicVector2<float> vec1;
+        BasicVector2<float> vec2{-15.0f, 0.0f};
+        BasicVector2<float> vec3{5.0f, 0.0f};
+
+        EXPECT_TRUE(vec1.inRange(vecMin, vecMax));
+        EXPECT_FALSE(vec2.inRange(vecMin, vecMax));
+        EXPECT_TRUE(vec3.inRange(vecMin, vecMax));
+    }
+
+    {
+        const BasicVector2<float> vecMax{10.0f, 20.0f};
+
+        BasicVector2<float> vec1;
+        BasicVector2<float> vec2{-15.0f, 0.0f};
+        BasicVector2<float> vec3{5.0f, 0.0f};
+
+        EXPECT_TRUE(vec1.inRange(vecMax));
+        EXPECT_FALSE(vec2.inRange(vecMax));
+        EXPECT_TRUE(vec3.inRange(vecMax));
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector2, memberFunctions)
+{
+    {
+        const BasicVector2<float> vec;
+
+        EXPECT_FLOAT_EQ(0, vec.getLength());
+    }
+
+    {
+        const BasicVector2<float> vec{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(2.2360680f, vec.getLength());
+    }
+
+    {
+        const BasicVector2<float> vec;
+
+        EXPECT_FLOAT_EQ(0, vec.getLengthSquared());
+    }
+
+    {
+        const BasicVector2<float> vec{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(5, vec.getLengthSquared());
+    }
+
+    {
+        const BasicVector2<float> vec;
+
+        EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
+    }
+
+    {
+        const BasicVector2<float> vec{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
+    }
+
+    {
+        const BasicVector2<float> vec1;
+        const BasicVector2<float> vec2;
+
+        EXPECT_FLOAT_EQ(0, vec1.dot(vec2));
+    }
+
+    {
+        const BasicVector2<float> vec1{1.0f, 2.0f};
+        const BasicVector2<float> vec2{5.0f, 4.0f};
+
+        EXPECT_FLOAT_EQ(13, vec1.dot(vec2));
+    }
+
+    {
+        const BasicVector2<float> vec;
+
+        EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
+    }
+
+    {
+        const BasicVector2<float> vec{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
+    }
+
+    {
+        const BasicVector2<float> vec1{1.0f, 2.0f};
+        const BasicVector2<float> vec2{5.0f, 4.0f};
+
+        EXPECT_FLOAT_EQ(20.0f, vec1.distanceSquared(vec2));
+    }
+
+    {
+        const BasicVector2<float> vec1{1.0f, 2.0f};
+        const BasicVector2<float> vec2{5.0f, 4.0f};
+
+        EXPECT_FLOAT_EQ(4.4721360f, vec1.distance(vec2));
+    }
+
+    {
+        const BasicVector2<float> vec{1.0f, 2.0f};
+
+        auto inv = vec.inversed();
+
+        EXPECT_FLOAT_EQ(1.0f, inv[0]);
+        EXPECT_FLOAT_EQ(0.5f, inv[1]);
+    }
+
+    {
+        auto vec = BasicVector2<float>::createSingle(1);
+
+        EXPECT_FLOAT_EQ(1.0f, vec[0]);
+        EXPECT_FLOAT_EQ(1.0f, vec[1]);
+    }
+
+    {
+        auto vec = BasicVector2<float>::createSingle(375.1721f);
+
+        EXPECT_FLOAT_EQ(375.1721f, vec[0]);
+        EXPECT_FLOAT_EQ(375.1721f, vec[1]);
+    }
+}
+
+/* ************************************************************************ */

From 7cc87b16d1fe7071443442db8c209e8d0eeb2a38 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Fatka?= <fatkaj@ntis.zcu.cz>
Date: Thu, 9 Mar 2017 17:28:15 +0100
Subject: [PATCH 03/11] Renamed BasicVector(2/3) to Vector(2/3) and some
 changes in API.

---
 include/cece/math/Vector.hpp      |  26 +-
 include/cece/math/Vector2.hpp     | 425 +++++++++++++--------------
 include/cece/math/Vector3.hpp     | 290 +++++++++---------
 include/cece/math/VectorRange.hpp |  58 ++--
 src/math/Vector2.cpp              |   8 +-
 src/math/Vector3.cpp              |   8 +-
 unittests/math/CMakeLists.txt     |   1 +
 unittests/math/Vector2_test.cpp   | 199 +++++++++----
 unittests/math/Vector3_test.cpp   | 473 ++++++++++++++++++++++++++++++
 9 files changed, 1008 insertions(+), 480 deletions(-)
 create mode 100644 unittests/math/Vector3_test.cpp

diff --git a/include/cece/math/Vector.hpp b/include/cece/math/Vector.hpp
index 0282e53..ab050e5 100644
--- a/include/cece/math/Vector.hpp
+++ b/include/cece/math/Vector.hpp
@@ -497,39 +497,39 @@ class BasicVector
 
 // TODO: rework
 template<typename T>
-struct BasicVector<T, 2> : public BasicVector2<T>
+struct BasicVector<T, 2> : public Vector2<T>
 {
-    using BasicVector2<T>::BasicVector2;
+    using Vector2<T>::Vector2;
 
     BasicVector() {};
-    BasicVector(const BasicVector2<T>& src)
-        : BasicVector2<T>(src)
+    BasicVector(const Vector2<T>& src)
+        : Vector2<T>(src)
     {
         //
     }
 
-    const T& getWidth() const noexcept { return BasicVector2<T>::getX(); }
-    const T& getHeight() const noexcept { return BasicVector2<T>::getY(); }
+    const T& getWidth() const noexcept { return Vector2<T>::getX(); }
+    const T& getHeight() const noexcept { return Vector2<T>::getY(); }
 };
 
 /* ************************************************************************ */
 
 // TODO: rework
 template<typename T>
-struct BasicVector<T, 3> : public BasicVector3<T>
+struct BasicVector<T, 3> : public Vector3<T>
 {
-    using BasicVector3<T>::BasicVector3;
+    using Vector3<T>::Vector3;
 
     BasicVector() {};
-    BasicVector(const BasicVector3<T>& src)
-        : BasicVector3<T>(src)
+    BasicVector(const Vector3<T>& src)
+        : Vector3<T>(src)
     {
         //
     }
 
-    const T& getWidth() const noexcept { return BasicVector3<T>::getX(); }
-    const T& getHeight() const noexcept { return BasicVector3<T>::getY(); }
-    const T& getDepth() const noexcept { return BasicVector3<T>::getZ(); }
+    const T& getWidth() const noexcept { return Vector3<T>::getX(); }
+    const T& getHeight() const noexcept { return Vector3<T>::getY(); }
+    const T& getDepth() const noexcept { return Vector3<T>::getZ(); }
 };
 
 /* ************************************************************************ */
diff --git a/include/cece/math/Vector2.hpp b/include/cece/math/Vector2.hpp
index 679992c..32f8970 100644
--- a/include/cece/math/Vector2.hpp
+++ b/include/cece/math/Vector2.hpp
@@ -51,7 +51,7 @@ namespace math {
  * @tparam     T     Element type.
  */
 template<typename T>
-class BasicVector2
+class Vector2
 {
 
 
@@ -59,13 +59,23 @@ class BasicVector2
 public:
 
 
-    /// BasicVector2 value type.
+    /// Vector2 value type.
     using ValueType = T;
 
     /// Element type squared.
     using ValueTypeSq = decltype(std::declval<T>() * std::declval<T>());
 
 
+// Public Data Members
+public:
+
+    /// X coordinate.
+    T x;
+
+    /// Y coordinate.
+    T y;
+
+
 // Public Ctors
 public:
 
@@ -73,7 +83,7 @@ class BasicVector2
     /**
      * @brief      Default constructor.
      */
-    BasicVector2() noexcept;
+    Vector2() noexcept;
 
 
     /**
@@ -82,7 +92,7 @@ class BasicVector2
      * @param      x     The X coordinate.
      * @param      y     The Y coordinate.
      */
-    BasicVector2(T x, T y) noexcept;
+    Vector2(T x, T y) noexcept;
 
 
     /**
@@ -90,7 +100,7 @@ class BasicVector2
      *
      * @param[in]  zero  The zero value.
      */
-    BasicVector2(Zero_t zero) noexcept;
+    Vector2(Zero_t zero) noexcept;
 
 
     /**
@@ -98,7 +108,7 @@ class BasicVector2
      *
      * @param[in]  src   The source vector.
      */
-    BasicVector2(const BasicVector2& src) noexcept;
+    Vector2(const Vector2& src) noexcept;
 
 
     /**
@@ -106,7 +116,7 @@ class BasicVector2
      *
      * @param[in]  src   The source vector.
      */
-    BasicVector2(BasicVector2&& src) noexcept;
+    Vector2(Vector2&& src) noexcept;
 
 
     /**
@@ -117,7 +127,7 @@ class BasicVector2
      * @tparam     T2    The source vector element type.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    BasicVector2(const BasicVector2<T2>& rhs) noexcept;
+    Vector2(const Vector2<T2>& rhs) noexcept;
 
 
 // Public Operators
@@ -131,7 +141,7 @@ class BasicVector2
      *
      * @return     *this.
      */
-    BasicVector2& operator=(Zero_t zero) noexcept;
+    Vector2& operator=(Zero_t zero) noexcept;
 
 
     /**
@@ -141,7 +151,7 @@ class BasicVector2
      *
      * @return     *this.
      */
-    BasicVector2& operator=(const BasicVector2& src) noexcept;
+    Vector2& operator=(const Vector2& src) noexcept;
 
 
     /**
@@ -151,7 +161,7 @@ class BasicVector2
      *
      * @return     *this.
      */
-    BasicVector2& operator=(BasicVector2&& src) noexcept;
+    Vector2& operator=(Vector2&& src) noexcept;
 
 
     /**
@@ -164,7 +174,7 @@ class BasicVector2
      * @return     *this.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    BasicVector2& operator=(const BasicVector2<T2>& src) noexcept;
+    Vector2& operator=(const Vector2<T2>& src) noexcept;
 
 
     /**
@@ -172,7 +182,7 @@ class BasicVector2
      *
      * @return     Vector.
      */
-    BasicVector2 operator+() const noexcept;
+    Vector2 operator+() const noexcept;
 
 
     /**
@@ -180,7 +190,7 @@ class BasicVector2
      *
      * @return     Vector.
      */
-    BasicVector2 operator-() const noexcept;
+    Vector2 operator-() const noexcept;
 
 
     /**
@@ -196,7 +206,7 @@ class BasicVector2
         decltype(std::declval<T>() + std::declval<T1>()),
         T
     >::value>::type* = nullptr>
-    BasicVector2& operator+=(const BasicVector2<T1>& rhs) noexcept;
+    Vector2& operator+=(const Vector2<T1>& rhs) noexcept;
 
 
     /**
@@ -204,7 +214,7 @@ class BasicVector2
      *
      * @param      rhs        Right operand.
      *
-     * @tparam     T1         Type of value in BasicVector2 operand.
+     * @tparam     T1         Type of value in Vector2 operand.
      *
      * @return     *this.
      */
@@ -212,7 +222,7 @@ class BasicVector2
         decltype(std::declval<T>() - std::declval<T1>()),
         T
     >::value>::type* = nullptr>
-    BasicVector2& operator-=(const BasicVector2<T1>& rhs) noexcept;
+    Vector2& operator-=(const Vector2<T1>& rhs) noexcept;
 
 
     /**
@@ -231,7 +241,7 @@ class BasicVector2
         T,
         decltype(std::declval<T>() * std::declval<T1>())
     >::value>::type* = nullptr>
-    BasicVector2& operator*=(T1 rhs) noexcept;
+    Vector2& operator*=(T1 rhs) noexcept;
 
 
     /**
@@ -239,7 +249,7 @@ class BasicVector2
      *
      * @param      rhs        Right operand.
      *
-     * @tparam     T1         Type of value in BasicVector2 operand.
+     * @tparam     T1         Type of value in Vector2 operand.
      *
      * @return     *this.
      */
@@ -250,7 +260,7 @@ class BasicVector2
         T,
         decltype(std::declval<T>() * std::declval<T1>())
     >::value>::type* = nullptr>
-    BasicVector2& operator*=(const BasicVector2<T1>& rhs) noexcept;
+    Vector2& operator*=(const Vector2<T1>& rhs) noexcept;
 
 
     /**
@@ -269,7 +279,7 @@ class BasicVector2
         T,
         decltype(std::declval<T>() * std::declval<T1>())
     >::value>::type* = nullptr>
-    BasicVector2& operator/=(T1 rhs) noexcept;
+    Vector2& operator/=(T1 rhs) noexcept;
 
 
     /**
@@ -277,7 +287,7 @@ class BasicVector2
      *
      * @param      rhs        Right operand.
      *
-     * @tparam     T1         Type of value in BasicVector2 operand.
+     * @tparam     T1         Type of value in Vector2 operand.
      *
      * @return     *this.
      */
@@ -288,7 +298,7 @@ class BasicVector2
         T,
         decltype(std::declval<T>() * std::declval<T1>())
     >::value>::type* = nullptr>
-    BasicVector2& operator/=(const BasicVector2<T1>& rhs) noexcept;
+    Vector2& operator/=(const Vector2<T1>& rhs) noexcept;
 
 
     /**
@@ -315,14 +325,6 @@ class BasicVector2
 public:
 
 
-    /**
-     * @brief      Returns X coordinate.
-     *
-     * @return     Reference to X coordinate.
-     */
-    T& x() noexcept;
-
-
     /**
      * @brief      Returns X coordinate.
      *
@@ -339,14 +341,6 @@ class BasicVector2
     void setX(T x) noexcept;
 
 
-    /**
-     * @brief      Returns Y coordinate.
-     *
-     * @return     Referent co Y coordinate.
-     */
-    T& y() noexcept;
-
-
     /**
      * @brief      Returns Y coordinate.
      *
@@ -383,7 +377,7 @@ class BasicVector2
      *
      * @return     If current value is in given range.
      */
-    bool inRange(const BasicVector2& low, const BasicVector2& high) const noexcept;
+    bool inRange(const Vector2& low, const Vector2& high) const noexcept;
 
 
     /**
@@ -394,7 +388,7 @@ class BasicVector2
      *
      * @return     If current value is in given range.
      */
-    bool inRange(const BasicVector2& high) const noexcept;
+    bool inRange(const Vector2& high) const noexcept;
 
 
 // Public Operations
@@ -424,7 +418,7 @@ class BasicVector2
      *
      * @return     Dot product.
      */
-    ValueTypeSq dot(const BasicVector2& rhs) const noexcept;
+    ValueTypeSq dot(const Vector2& rhs) const noexcept;
 
 
     /**
@@ -434,7 +428,7 @@ class BasicVector2
      *
      * @return     Distance.
      */
-    ValueTypeSq distanceSquared(const BasicVector2& rhs) const noexcept;
+    ValueTypeSq distanceSquared(const Vector2& rhs) const noexcept;
 
 
     /**
@@ -444,7 +438,7 @@ class BasicVector2
      *
      * @return     Distance.
      */
-    ValueType distance(const BasicVector2& rhs) const noexcept;
+    ValueType distance(const Vector2& rhs) const noexcept;
 
 
     /**
@@ -455,17 +449,18 @@ class BasicVector2
      * @return     Inversed vector.
      */
     template<typename T2 = T>
-    BasicVector2<T2> inversed() const noexcept;
+    Vector2<T2> inversed() const noexcept;
 
 
     /**
-     * @brief      Rotate current vector and return rotated version.
+     * @brief      Rotate current vector counter-clockwise and return rotated
+     *             version.
      *
      * @param      angle  Rotation angle.
      *
      * @return     Rotated vector.
      */
-    BasicVector2 rotated(unit::Angle angle) const noexcept;
+    Vector2 rotated(unit::Angle angle) const noexcept;
 
 
     /**
@@ -475,26 +470,16 @@ class BasicVector2
      *
      * @return     Vector of {val, val}.
      */
-    static BasicVector2 createSingle(T val) noexcept;
-
-
-// Private Data Members
-private:
-
-    /// X coordinate.
-    T m_x;
-
-    /// Y coordinate.
-    T m_y;
+    static Vector2 createSingle(T val) noexcept;
 
 };
 
 /* ************************************************************************ */
 
-extern template class BasicVector2<float>;
-extern template class BasicVector2<double>;
-extern template class BasicVector2<unsigned int>;
-extern template class BasicVector2<int>;
+extern template class Vector2<float>;
+extern template class Vector2<double>;
+extern template class Vector2<unsigned int>;
+extern template class Vector2<int>;
 
 /* ************************************************************************ */
 
@@ -504,14 +489,14 @@ extern template class BasicVector2<int>;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector2.
- * @tparam     T2    Type of value in second BasicVector2.
+ * @tparam     T1    Type of value in first Vector2.
+ * @tparam     T2    Type of value in second Vector2.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
+inline Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -521,14 +506,14 @@ operator+(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector2.
+ * @tparam     T1    Type of value in first Vector2.
  * @tparam     T2    Type of second operand.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const BasicVector2<T1>& lhs, T2 rhs) noexcept;
+inline Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const Vector2<T1>& lhs, T2 rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -539,13 +524,13 @@ operator+(const BasicVector2<T1>& lhs, T2 rhs) noexcept;
  * @param      rhs   Right operand.
  *
  * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second BasicVector2.
+ * @tparam     T2    Type of value in second Vector2.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(T1 lhs, const BasicVector2<T2>& rhs) noexcept;
+inline Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(T1 lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -555,14 +540,14 @@ operator+(T1 lhs, const BasicVector2<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector2.
- * @tparam     T2    Type of value in second BasicVector2.
+ * @tparam     T1    Type of value in first Vector2.
+ * @tparam     T2    Type of value in second Vector2.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
+inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -572,14 +557,14 @@ operator-(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector2.
+ * @tparam     T1    Type of value in first Vector2.
  * @tparam     T2    Type of second operand.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const BasicVector2<T1>& lhs, T2 rhs) noexcept;
+inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const Vector2<T1>& lhs, T2 rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -590,13 +575,13 @@ operator-(const BasicVector2<T1>& lhs, T2 rhs) noexcept;
  * @param      rhs   Right operand.
  *
  * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second BasicVector2.
+ * @tparam     T2    Type of value in second Vector2.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(T1 lhs, const BasicVector2<T2>& rhs) noexcept;
+inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(T1 lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -606,14 +591,14 @@ operator-(T1 lhs, const BasicVector2<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector2.
- * @tparam     T2    Type of value in second BasicVector2.
+ * @tparam     T1    Type of value in first Vector2.
+ * @tparam     T2    Type of value in second Vector2.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
+inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -623,14 +608,14 @@ operator*(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector2.
+ * @tparam     T1    Type of value in first Vector2.
  * @tparam     T2    Type of second operand.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const BasicVector2<T1>& lhs, T2 rhs) noexcept;
+inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const Vector2<T1>& lhs, T2 rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -641,13 +626,13 @@ operator*(const BasicVector2<T1>& lhs, T2 rhs) noexcept;
  * @param      rhs   Right operand.
  *
  * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second BasicVector2.
+ * @tparam     T2    Type of value in second Vector2.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(T1 lhs, const BasicVector2<T2>& rhs) noexcept;
+inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(T1 lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -657,14 +642,14 @@ operator*(T1 lhs, const BasicVector2<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector2.
- * @tparam     T2    Type of value in second BasicVector2.
+ * @tparam     T1    Type of value in first Vector2.
+ * @tparam     T2    Type of value in second Vector2.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
+inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -674,14 +659,14 @@ operator/(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector2.
+ * @tparam     T1    Type of value in first Vector2.
  * @tparam     T2    Type of second operand.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const BasicVector2<T1>& lhs, T2 rhs) noexcept;
+inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const Vector2<T1>& lhs, T2 rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -692,13 +677,13 @@ operator/(const BasicVector2<T1>& lhs, T2 rhs) noexcept;
  * @param      rhs   Right operand.
  *
  * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second BasicVector2.
+ * @tparam     T2    Type of value in second Vector2.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(T1 lhs, const BasicVector2<T2>& rhs) noexcept;
+inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(T1 lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -714,7 +699,7 @@ operator/(T1 lhs, const BasicVector2<T2>& rhs) noexcept;
  * @return     Comparision result.
  */
 template<typename T1, typename T2>
-inline bool operator==(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
+inline bool operator==(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -732,7 +717,7 @@ inline bool operator==(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs)
 template<typename T1, typename T2>
 inline
 decltype(std::declval<T1>() * std::declval<T2>())
-cross(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
+cross(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -749,8 +734,8 @@ cross(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept;
  */
 template<typename T1, typename T2>
 inline
-BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const BasicVector2<T1>& lhs, const T2& rhs) noexcept;
+Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+cross(const Vector2<T1>& lhs, const T2& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -767,8 +752,8 @@ cross(const BasicVector2<T1>& lhs, const T2& rhs) noexcept;
  */
 template<typename T1, typename T2>
 inline
-BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const T1& lhs, const BasicVector2<T2>& rhs) noexcept;
+Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+cross(const T1& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -785,9 +770,9 @@ namespace math {
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector2<T>::BasicVector2() noexcept
-    : m_x{}
-    , m_y{}
+inline Vector2<T>::Vector2() noexcept
+    : x{}
+    , y{}
 {
     // Nothing to do
 }
@@ -795,9 +780,9 @@ inline BasicVector2<T>::BasicVector2() noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector2<T>::BasicVector2(T x, T y) noexcept
-    : m_x(x)
-    , m_y(y)
+inline Vector2<T>::Vector2(T x, T y) noexcept
+    : x{std::move(x)}
+    , y{std::move(y)}
 {
     // Nothing to do
 }
@@ -805,9 +790,9 @@ inline BasicVector2<T>::BasicVector2(T x, T y) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector2<T>::BasicVector2(Zero_t zero) noexcept
-    : m_x{}
-    , m_y{}
+inline Vector2<T>::Vector2(Zero_t zero) noexcept
+    : x{}
+    , y{}
 {
     // Nothing to do
 }
@@ -815,9 +800,9 @@ inline BasicVector2<T>::BasicVector2(Zero_t zero) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector2<T>::BasicVector2(const BasicVector2& src) noexcept
-    : m_x{src.getX()}
-    , m_y{src.getY()}
+inline Vector2<T>::Vector2(const Vector2& src) noexcept
+    : x{src.getX()}
+    , y{src.getY()}
 {
     // Nothing to do
 }
@@ -825,9 +810,9 @@ inline BasicVector2<T>::BasicVector2(const BasicVector2& src) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector2<T>::BasicVector2(BasicVector2&& src) noexcept
-    : m_x{std::move(src.m_x)}
-    , m_y{std::move(src.m_y)}
+inline Vector2<T>::Vector2(Vector2&& src) noexcept
+    : x{std::move(src.x)}
+    , y{std::move(src.y)}
 {
     // Nothing to do
 }
@@ -836,9 +821,9 @@ inline BasicVector2<T>::BasicVector2(BasicVector2&& src) noexcept
 
 template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline BasicVector2<T>::BasicVector2(const BasicVector2<T2>& rhs) noexcept
-    : m_x(rhs.getX())
-    , m_y(rhs.getY())
+inline Vector2<T>::Vector2(const Vector2<T2>& rhs) noexcept
+    : x(rhs.getX())
+    , y(rhs.getY())
 {
     // Nothing to do
 }
@@ -846,10 +831,10 @@ inline BasicVector2<T>::BasicVector2(const BasicVector2<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector2<T>& BasicVector2<T>::operator=(Zero_t zero) noexcept
+inline Vector2<T>& Vector2<T>::operator=(Zero_t zero) noexcept
 {
-    m_x = T{};
-    m_y = T{};
+    x = T{};
+    y = T{};
 
     return *this;
 }
@@ -857,10 +842,10 @@ inline BasicVector2<T>& BasicVector2<T>::operator=(Zero_t zero) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector2<T>& BasicVector2<T>::operator=(const BasicVector2& src) noexcept
+inline Vector2<T>& Vector2<T>::operator=(const Vector2& src) noexcept
 {
-    m_x = src.m_x;
-    m_y = src.m_y;
+    x = src.x;
+    y = src.y;
 
     return *this;
 }
@@ -868,10 +853,10 @@ inline BasicVector2<T>& BasicVector2<T>::operator=(const BasicVector2& src) noex
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector2<T>& BasicVector2<T>::operator=(BasicVector2&& src) noexcept
+inline Vector2<T>& Vector2<T>::operator=(Vector2&& src) noexcept
 {
-    m_x = std::move(src.m_x);
-    m_y = std::move(src.m_y);
+    x = std::move(src.x);
+    y = std::move(src.y);
 
     return *this;
 }
@@ -880,10 +865,10 @@ inline BasicVector2<T>& BasicVector2<T>::operator=(BasicVector2&& src) noexcept
 
 template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline BasicVector2<T>& BasicVector2<T>::operator=(const BasicVector2<T2>& src) noexcept
+inline Vector2<T>& Vector2<T>::operator=(const Vector2<T2>& src) noexcept
 {
-    m_x = T(src.getX());
-    m_y = T(src.getY());
+    x = T(src.getX());
+    y = T(src.getY());
 
     return *this;
 }
@@ -891,7 +876,7 @@ inline BasicVector2<T>& BasicVector2<T>::operator=(const BasicVector2<T2>& src)
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector2<T> BasicVector2<T>::operator+() const noexcept
+inline Vector2<T> Vector2<T>::operator+() const noexcept
 {
     return *this;
 }
@@ -899,9 +884,9 @@ inline BasicVector2<T> BasicVector2<T>::operator+() const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector2<T> BasicVector2<T>::operator-() const noexcept
+inline Vector2<T> Vector2<T>::operator-() const noexcept
 {
-    return {-m_x, -m_y};
+    return {-x, -y};
 }
 
 /* ************************************************************************ */
@@ -911,10 +896,10 @@ template<typename T1, typename std::enable_if<std::is_same<
     decltype(std::declval<T>() + std::declval<T1>()),
     T
 >::value>::type*>
-inline BasicVector2<T>& BasicVector2<T>::operator+=(const BasicVector2<T1>& rhs) noexcept
+inline Vector2<T>& Vector2<T>::operator+=(const Vector2<T1>& rhs) noexcept
 {
-    m_x += rhs.getX();
-    m_y += rhs.getY();
+    x += rhs.getX();
+    y += rhs.getY();
 
     return *this;
 }
@@ -926,10 +911,10 @@ template<typename T1, typename std::enable_if<std::is_same<
     decltype(std::declval<T>() - std::declval<T1>()),
     T
 >::value>::type*>
-inline BasicVector2<T>& BasicVector2<T>::operator-=(const BasicVector2<T1>& rhs) noexcept
+inline Vector2<T>& Vector2<T>::operator-=(const Vector2<T1>& rhs) noexcept
 {
-    m_x -= rhs.getX();
-    m_y -= rhs.getY();
+    x -= rhs.getX();
+    y -= rhs.getY();
 
     return *this;
 }
@@ -944,10 +929,10 @@ template<typename T1, typename std::enable_if<std::is_same<
     T,
     decltype(std::declval<T>() * std::declval<T1>())
 >::value>::type*>
-inline BasicVector2<T>& BasicVector2<T>::operator*=(T1 rhs) noexcept
+inline Vector2<T>& Vector2<T>::operator*=(T1 rhs) noexcept
 {
-    m_x *= rhs;
-    m_y *= rhs;
+    x *= rhs;
+    y *= rhs;
 
     return *this;
 }
@@ -962,10 +947,10 @@ template<typename T1, typename std::enable_if<std::is_same<
     T,
     decltype(std::declval<T>() * std::declval<T1>())
 >::value>::type*>
-inline BasicVector2<T>& BasicVector2<T>::operator*=(const BasicVector2<T1>& rhs) noexcept
+inline Vector2<T>& Vector2<T>::operator*=(const Vector2<T1>& rhs) noexcept
 {
-    m_x *= rhs.getX();
-    m_y *= rhs.getY();
+    x *= rhs.getX();
+    y *= rhs.getY();
 
     return *this;
 }
@@ -980,10 +965,10 @@ template<typename T1, typename std::enable_if<std::is_same<
     T,
     decltype(std::declval<T>() * std::declval<T1>())
 >::value>::type*>
-inline BasicVector2<T>& BasicVector2<T>::operator/=(T1 rhs) noexcept
+inline Vector2<T>& Vector2<T>::operator/=(T1 rhs) noexcept
 {
-    m_x /= rhs;
-    m_y /= rhs;
+    x /= rhs;
+    y /= rhs;
 
     return *this;
 }
@@ -998,10 +983,10 @@ template<typename T1, typename std::enable_if<std::is_same<
     T,
     decltype(std::declval<T>() * std::declval<T1>())
 >::value>::type*>
-inline BasicVector2<T>& BasicVector2<T>::operator/=(const BasicVector2<T1>& rhs) noexcept
+inline Vector2<T>& Vector2<T>::operator/=(const Vector2<T1>& rhs) noexcept
 {
-    m_x /= rhs.getX();
-    m_y /= rhs.getY();
+    x /= rhs.getX();
+    y /= rhs.getY();
 
     return *this;
 }
@@ -1009,75 +994,59 @@ inline BasicVector2<T>& BasicVector2<T>::operator/=(const BasicVector2<T1>& rhs)
 /* ************************************************************************ */
 
 template<typename T>
-inline T& BasicVector2<T>::operator[](int pos) noexcept
+inline T& Vector2<T>::operator[](int pos) noexcept
 {
     CECE_ASSERT(pos >= 0);
     CECE_ASSERT(pos < 2);
-    return (&m_x)[pos];
+    return (&x)[pos];
 }
 
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& BasicVector2<T>::operator[](int pos) const noexcept
+inline const T& Vector2<T>::operator[](int pos) const noexcept
 {
     CECE_ASSERT(pos >= 0);
     CECE_ASSERT(pos < 2);
-    return (&m_x)[pos];
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline T& BasicVector2<T>::x() noexcept
-{
-    return m_x;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline const T& BasicVector2<T>::getX() const noexcept
-{
-    return m_x;
+    return (&x)[pos];
 }
 
 /* ************************************************************************ */
 
 template<typename T>
-inline void BasicVector2<T>::setX(T x) noexcept
+inline const T& Vector2<T>::getX() const noexcept
 {
-    m_x = std::move(x);
+    return x;
 }
 
 /* ************************************************************************ */
 
 template<typename T>
-inline T& BasicVector2<T>::y() noexcept
+inline void Vector2<T>::setX(T x) noexcept
 {
-    return m_y;
+    this->x = std::move(x);
 }
 
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& BasicVector2<T>::getY() const noexcept
+inline const T& Vector2<T>::getY() const noexcept
 {
-    return m_y;
+    return y;
 }
 
 /* ************************************************************************ */
 
 template<typename T>
-inline void BasicVector2<T>::setY(T y) noexcept
+inline void Vector2<T>::setY(T y) noexcept
 {
-    m_y = std::move(y);
+    this->y = std::move(y);
 }
 
 /* ************************************************************************ */
 
 template<typename T>
-inline bool BasicVector2<T>::inRange(T value, T low, T high) noexcept
+inline bool Vector2<T>::inRange(T value, T low, T high) noexcept
 {
     return value >= low && value < high;
 }
@@ -1085,7 +1054,7 @@ inline bool BasicVector2<T>::inRange(T value, T low, T high) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline bool BasicVector2<T>::inRange(const BasicVector2& low, const BasicVector2& high) const noexcept
+inline bool Vector2<T>::inRange(const Vector2& low, const Vector2& high) const noexcept
 {
     bool res = true;
 
@@ -1098,7 +1067,7 @@ inline bool BasicVector2<T>::inRange(const BasicVector2& low, const BasicVector2
 /* ************************************************************************ */
 
 template<typename T>
-inline bool BasicVector2<T>::inRange(const BasicVector2& high) const noexcept
+inline bool Vector2<T>::inRange(const Vector2& high) const noexcept
 {
     return inRange(Zero, high);
 }
@@ -1106,7 +1075,7 @@ inline bool BasicVector2<T>::inRange(const BasicVector2& high) const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline typename BasicVector2<T>::ValueType BasicVector2<T>::getLength() const noexcept
+inline typename Vector2<T>::ValueType Vector2<T>::getLength() const noexcept
 {
     using std::sqrt;
     return static_cast<T>(sqrt(getLengthSquared()));
@@ -1115,7 +1084,7 @@ inline typename BasicVector2<T>::ValueType BasicVector2<T>::getLength() const no
 /* ************************************************************************ */
 
 template<typename T>
-inline typename BasicVector2<T>::ValueTypeSq BasicVector2<T>::getLengthSquared() const noexcept
+inline typename Vector2<T>::ValueTypeSq Vector2<T>::getLengthSquared() const noexcept
 {
     return dot(*this);
 }
@@ -1123,7 +1092,7 @@ inline typename BasicVector2<T>::ValueTypeSq BasicVector2<T>::getLengthSquared()
 /* ************************************************************************ */
 
 template<typename T>
-inline typename BasicVector2<T>::ValueTypeSq BasicVector2<T>::dot(const BasicVector2& rhs) const noexcept
+inline typename Vector2<T>::ValueTypeSq Vector2<T>::dot(const Vector2& rhs) const noexcept
 {
     return getX() * rhs.getX() + getY() * rhs.getY();
 }
@@ -1131,7 +1100,7 @@ inline typename BasicVector2<T>::ValueTypeSq BasicVector2<T>::dot(const BasicVec
 /* ************************************************************************ */
 
 template<typename T>
-inline typename BasicVector2<T>::ValueTypeSq BasicVector2<T>::distanceSquared(const BasicVector2& rhs) const noexcept
+inline typename Vector2<T>::ValueTypeSq Vector2<T>::distanceSquared(const Vector2& rhs) const noexcept
 {
     return (*this - rhs).getLengthSquared();
 }
@@ -1139,7 +1108,7 @@ inline typename BasicVector2<T>::ValueTypeSq BasicVector2<T>::distanceSquared(co
 /* ************************************************************************ */
 
 template<typename T>
-inline typename BasicVector2<T>::ValueType BasicVector2<T>::distance(const BasicVector2& rhs) const noexcept
+inline typename Vector2<T>::ValueType Vector2<T>::distance(const Vector2& rhs) const noexcept
 {
     return (*this - rhs).getLength();
 }
@@ -1148,7 +1117,7 @@ inline typename BasicVector2<T>::ValueType BasicVector2<T>::distance(const Basic
 
 template<typename T>
 template<typename T2>
-inline BasicVector2<T2> BasicVector2<T>::inversed() const noexcept
+inline Vector2<T2> Vector2<T>::inversed() const noexcept
 {
     return {T2(1) / getX(), T2(1) / getY()};
 }
@@ -1156,7 +1125,7 @@ inline BasicVector2<T2> BasicVector2<T>::inversed() const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector2<T> BasicVector2<T>::rotated(unit::Angle angle) const noexcept
+inline Vector2<T> Vector2<T>::rotated(unit::Angle angle) const noexcept
 {
     return {
         static_cast<T>(getX() * cos(static_cast<RealType>(angle)) - getY() * sin(static_cast<RealType>(angle))),
@@ -1167,7 +1136,7 @@ inline BasicVector2<T> BasicVector2<T>::rotated(unit::Angle angle) const noexcep
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector2<T> BasicVector2<T>::createSingle(T val) noexcept
+inline Vector2<T> Vector2<T>::createSingle(T val) noexcept
 {
     return {val, val};
 }
@@ -1175,8 +1144,8 @@ inline BasicVector2<T> BasicVector2<T>::createSingle(T val) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
+inline Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
 {
     return {
         lhs.getX() + rhs.getX(),
@@ -1187,8 +1156,8 @@ operator+(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const BasicVector2<T1>& lhs, T2 rhs) noexcept
+inline Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const Vector2<T1>& lhs, T2 rhs) noexcept
 {
     return {
         lhs.getX() + rhs,
@@ -1199,8 +1168,8 @@ operator+(const BasicVector2<T1>& lhs, T2 rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(T1 lhs, const BasicVector2<T2>& rhs) noexcept
+inline Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(T1 lhs, const Vector2<T2>& rhs) noexcept
 {
     return {
         lhs + rhs.getX(),
@@ -1211,8 +1180,8 @@ operator+(T1 lhs, const BasicVector2<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
+inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
 {
     return {
         lhs.getX() - rhs.getX(),
@@ -1223,8 +1192,8 @@ operator-(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const BasicVector2<T1>& lhs, T2 rhs) noexcept
+inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const Vector2<T1>& lhs, T2 rhs) noexcept
 {
     return {
         lhs.getX() - rhs,
@@ -1235,8 +1204,8 @@ operator-(const BasicVector2<T1>& lhs, T2 rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(T1 lhs, const BasicVector2<T2>& rhs) noexcept
+inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(T1 lhs, const Vector2<T2>& rhs) noexcept
 {
     return {
         lhs - rhs.getX(),
@@ -1247,8 +1216,8 @@ operator-(T1 lhs, const BasicVector2<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
+inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
 {
     return {
         lhs.getX() * rhs.getX(),
@@ -1259,8 +1228,8 @@ operator*(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const BasicVector2<T1>& lhs, T2 rhs) noexcept
+inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const Vector2<T1>& lhs, T2 rhs) noexcept
 {
     return {
         lhs.getX() * rhs,
@@ -1271,8 +1240,8 @@ operator*(const BasicVector2<T1>& lhs, T2 rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(T1 lhs, const BasicVector2<T2>& rhs) noexcept
+inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(T1 lhs, const Vector2<T2>& rhs) noexcept
 {
     return {
         lhs * rhs.getX(),
@@ -1283,8 +1252,8 @@ operator*(T1 lhs, const BasicVector2<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
+inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
 {
     return {
         lhs.getX() / rhs.getX(),
@@ -1295,8 +1264,8 @@ operator/(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const BasicVector2<T1>& lhs, T2 rhs) noexcept
+inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const Vector2<T1>& lhs, T2 rhs) noexcept
 {
     return {
         lhs.getX() / rhs,
@@ -1307,8 +1276,8 @@ operator/(const BasicVector2<T1>& lhs, T2 rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector2<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(T1 lhs, const BasicVector2<T2>& rhs) noexcept
+inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(T1 lhs, const Vector2<T2>& rhs) noexcept
 {
     return {
         lhs / rhs.getX(),
@@ -1319,7 +1288,7 @@ operator/(T1 lhs, const BasicVector2<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline bool operator==(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
+inline bool operator==(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
 {
     return
         lhs.getX() == rhs.getX() &&
@@ -1332,7 +1301,7 @@ inline bool operator==(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs)
 template<typename T1, typename T2>
 inline
 decltype(std::declval<T1>() * std::declval<T2>())
-cross(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
+cross(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
 {
     return {lhs.getX() * rhs.getY() - lhs.getY() * rhs.getX()};
 }
@@ -1341,8 +1310,8 @@ cross(const BasicVector2<T1>& lhs, const BasicVector2<T2>& rhs) noexcept
 
 template<typename T1, typename T2>
 inline
-BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const BasicVector2<T1>& lhs, const T2& rhs) noexcept
+Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+cross(const Vector2<T1>& lhs, const T2& rhs) noexcept
 {
     return {rhs * lhs.getY(), -rhs * lhs.getX()};
 }
@@ -1351,8 +1320,8 @@ cross(const BasicVector2<T1>& lhs, const T2& rhs) noexcept
 
 template<typename T1, typename T2>
 inline
-BasicVector2<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const T1& lhs, const BasicVector2<T2>& rhs) noexcept
+Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+cross(const T1& lhs, const Vector2<T2>& rhs) noexcept
 {
     return {-lhs * rhs.getY(), lhs * rhs.getX()};
 }
diff --git a/include/cece/math/Vector3.hpp b/include/cece/math/Vector3.hpp
index 54ca338..93bce5d 100644
--- a/include/cece/math/Vector3.hpp
+++ b/include/cece/math/Vector3.hpp
@@ -51,7 +51,7 @@ namespace math {
  * @tparam     T     Element type.
  */
 template<typename T>
-class BasicVector3
+class Vector3
 {
 
 
@@ -59,7 +59,7 @@ class BasicVector3
 public:
 
 
-    /// BasicVector3 value type.
+    /// Vector3 value type.
     using ValueType = T;
 
     /// Element type squared.
@@ -73,7 +73,7 @@ class BasicVector3
     /**
      * @brief      Default constructor.
      */
-    BasicVector3() noexcept;
+    Vector3() noexcept;
 
 
     /**
@@ -83,7 +83,7 @@ class BasicVector3
      * @param      y     The Y coordinate.
      * @param      y     The Z coordinate.
      */
-    BasicVector3(T x, T y, T z) noexcept;
+    Vector3(T x, T y, T z) noexcept;
 
 
     /**
@@ -91,7 +91,7 @@ class BasicVector3
      *
      * @param[in]  zero  The zero value.
      */
-    BasicVector3(Zero_t zero) noexcept;
+    Vector3(Zero_t zero) noexcept;
 
 
     /**
@@ -99,7 +99,7 @@ class BasicVector3
      *
      * @param[in]  src   The source vector.
      */
-    BasicVector3(const BasicVector3& src) noexcept;
+    Vector3(const Vector3& src) noexcept;
 
 
     /**
@@ -107,7 +107,7 @@ class BasicVector3
      *
      * @param[in]  src   The source vector.
      */
-    BasicVector3(BasicVector3&& src) noexcept;
+    Vector3(Vector3&& src) noexcept;
 
 
     /**
@@ -118,7 +118,7 @@ class BasicVector3
      * @tparam     T2    The source vector element type.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    BasicVector3(const BasicVector3<T2>& rhs) noexcept;
+    Vector3(const Vector3<T2>& rhs) noexcept;
 
 
 // Public Operators
@@ -132,7 +132,7 @@ class BasicVector3
      *
      * @return     *this.
      */
-    BasicVector3& operator=(Zero_t zero) noexcept;
+    Vector3& operator=(Zero_t zero) noexcept;
 
 
     /**
@@ -142,7 +142,7 @@ class BasicVector3
      *
      * @return     *this.
      */
-    BasicVector3& operator=(const BasicVector3& src) noexcept;
+    Vector3& operator=(const Vector3& src) noexcept;
 
 
     /**
@@ -152,7 +152,7 @@ class BasicVector3
      *
      * @return     *this.
      */
-    BasicVector3& operator=(BasicVector3&& src) noexcept;
+    Vector3& operator=(Vector3&& src) noexcept;
 
 
     /**
@@ -165,7 +165,7 @@ class BasicVector3
      * @return     *this.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    BasicVector3& operator=(const BasicVector3<T2>& src) noexcept;
+    Vector3& operator=(const Vector3<T2>& src) noexcept;
 
 
     /**
@@ -173,7 +173,7 @@ class BasicVector3
      *
      * @return     Vector.
      */
-    BasicVector3 operator+() const noexcept;
+    Vector3 operator+() const noexcept;
 
 
     /**
@@ -181,7 +181,7 @@ class BasicVector3
      *
      * @return     Vector.
      */
-    BasicVector3 operator-() const noexcept;
+    Vector3 operator-() const noexcept;
 
 
     /**
@@ -197,7 +197,7 @@ class BasicVector3
         decltype(std::declval<T>() + std::declval<T1>()),
         T
     >::value>::type* = nullptr>
-    BasicVector3& operator+=(const BasicVector3<T1>& rhs) noexcept;
+    Vector3& operator+=(const Vector3<T1>& rhs) noexcept;
 
 
     /**
@@ -205,7 +205,7 @@ class BasicVector3
      *
      * @param      rhs        Right operand.
      *
-     * @tparam     T1         Type of value in BasicVector3 operand.
+     * @tparam     T1         Type of value in Vector3 operand.
      *
      * @return     *this.
      */
@@ -213,7 +213,7 @@ class BasicVector3
         decltype(std::declval<T>() - std::declval<T1>()),
         T
     >::value>::type* = nullptr>
-    BasicVector3& operator-=(const BasicVector3<T1>& rhs) noexcept;
+    Vector3& operator-=(const Vector3<T1>& rhs) noexcept;
 
 
     /**
@@ -232,7 +232,7 @@ class BasicVector3
         T,
         decltype(std::declval<T>() * std::declval<T1>())
     >::value>::type* = nullptr>
-    BasicVector3& operator*=(T1 rhs) noexcept;
+    Vector3& operator*=(T1 rhs) noexcept;
 
 
     /**
@@ -240,7 +240,7 @@ class BasicVector3
      *
      * @param      rhs        Right operand.
      *
-     * @tparam     T1         Type of value in BasicVector3 operand.
+     * @tparam     T1         Type of value in Vector3 operand.
      *
      * @return     *this.
      */
@@ -251,7 +251,7 @@ class BasicVector3
         T,
         decltype(std::declval<T>() * std::declval<T1>())
     >::value>::type* = nullptr>
-    BasicVector3& operator*=(const BasicVector3<T1>& rhs) noexcept;
+    Vector3& operator*=(const Vector3<T1>& rhs) noexcept;
 
 
     /**
@@ -270,7 +270,7 @@ class BasicVector3
         T,
         decltype(std::declval<T>() * std::declval<T1>())
     >::value>::type* = nullptr>
-    BasicVector3& operator/=(T1 rhs) noexcept;
+    Vector3& operator/=(T1 rhs) noexcept;
 
 
     /**
@@ -278,7 +278,7 @@ class BasicVector3
      *
      * @param      rhs        Right operand.
      *
-     * @tparam     T1         Type of value in BasicVector3 operand.
+     * @tparam     T1         Type of value in Vector3 operand.
      *
      * @return     *this.
      */
@@ -289,7 +289,7 @@ class BasicVector3
         T,
         decltype(std::declval<T>() * std::declval<T1>())
     >::value>::type* = nullptr>
-    BasicVector3& operator/=(const BasicVector3<T1>& rhs) noexcept;
+    Vector3& operator/=(const Vector3<T1>& rhs) noexcept;
 
 
     /**
@@ -408,7 +408,7 @@ class BasicVector3
      *
      * @return     If current value is in given range.
      */
-    bool inRange(const BasicVector3& low, const BasicVector3& high) const noexcept;
+    bool inRange(const Vector3& low, const Vector3& high) const noexcept;
 
 
     /**
@@ -419,7 +419,7 @@ class BasicVector3
      *
      * @return     If current value is in given range.
      */
-    bool inRange(const BasicVector3& high) const noexcept;
+    bool inRange(const Vector3& high) const noexcept;
 
 
 // Public Operations
@@ -449,7 +449,7 @@ class BasicVector3
      *
      * @return     Dot product.
      */
-    ValueTypeSq dot(const BasicVector3& rhs) const noexcept;
+    ValueTypeSq dot(const Vector3& rhs) const noexcept;
 
 
     /**
@@ -459,7 +459,7 @@ class BasicVector3
      *
      * @return     Distance.
      */
-    ValueTypeSq distanceSquared(const BasicVector3& rhs) const noexcept;
+    ValueTypeSq distanceSquared(const Vector3& rhs) const noexcept;
 
 
     /**
@@ -469,7 +469,7 @@ class BasicVector3
      *
      * @return     Distance.
      */
-    ValueType distance(const BasicVector3& rhs) const noexcept;
+    ValueType distance(const Vector3& rhs) const noexcept;
 
 
     /**
@@ -480,7 +480,7 @@ class BasicVector3
      * @return     Inversed vector.
      */
     template<typename T2 = T>
-    BasicVector3<T2> inversed() const noexcept;
+    Vector3<T2> inversed() const noexcept;
 
 
     /**
@@ -490,7 +490,7 @@ class BasicVector3
      *
      * @return     Rotated vector.
      */
-    BasicVector3 rotated(unit::Angle angle) const noexcept;
+    Vector3 rotated(unit::Angle angle) const noexcept;
 
 
     /**
@@ -500,7 +500,7 @@ class BasicVector3
      *
      * @return     Vector of {val, val}.
      */
-    static BasicVector3 createSingle(T val) noexcept;
+    static Vector3 createSingle(T val) noexcept;
 
 
 // Private Data Members
@@ -519,10 +519,10 @@ class BasicVector3
 
 /* ************************************************************************ */
 
-extern template class BasicVector3<float>;
-extern template class BasicVector3<double>;
-extern template class BasicVector3<unsigned int>;
-extern template class BasicVector3<int>;
+extern template class Vector3<float>;
+extern template class Vector3<double>;
+extern template class Vector3<unsigned int>;
+extern template class Vector3<int>;
 
 /* ************************************************************************ */
 
@@ -532,14 +532,14 @@ extern template class BasicVector3<int>;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector3.
- * @tparam     T2    Type of value in second BasicVector3.
+ * @tparam     T1    Type of value in first Vector3.
+ * @tparam     T2    Type of value in second Vector3.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
+inline Vector3<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -549,14 +549,14 @@ operator+(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector3.
+ * @tparam     T1    Type of value in first Vector3.
  * @tparam     T2    Type of second operand.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const BasicVector3<T1>& lhs, T2 rhs) noexcept;
+inline Vector3<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const Vector3<T1>& lhs, T2 rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -567,13 +567,13 @@ operator+(const BasicVector3<T1>& lhs, T2 rhs) noexcept;
  * @param      rhs   Right operand.
  *
  * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second BasicVector3.
+ * @tparam     T2    Type of value in second Vector3.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(T1 lhs, const BasicVector3<T2>& rhs) noexcept;
+inline Vector3<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(T1 lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -583,14 +583,14 @@ operator+(T1 lhs, const BasicVector3<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector3.
- * @tparam     T2    Type of value in second BasicVector3.
+ * @tparam     T1    Type of value in first Vector3.
+ * @tparam     T2    Type of value in second Vector3.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
+inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -600,14 +600,14 @@ operator-(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector3.
+ * @tparam     T1    Type of value in first Vector3.
  * @tparam     T2    Type of second operand.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const BasicVector3<T1>& lhs, T2 rhs) noexcept;
+inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const Vector3<T1>& lhs, T2 rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -618,13 +618,13 @@ operator-(const BasicVector3<T1>& lhs, T2 rhs) noexcept;
  * @param      rhs   Right operand.
  *
  * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second BasicVector3.
+ * @tparam     T2    Type of value in second Vector3.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(T1 lhs, const BasicVector3<T2>& rhs) noexcept;
+inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(T1 lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -634,14 +634,14 @@ operator-(T1 lhs, const BasicVector3<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector3.
- * @tparam     T2    Type of value in second BasicVector3.
+ * @tparam     T1    Type of value in first Vector3.
+ * @tparam     T2    Type of value in second Vector3.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
+inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -651,14 +651,14 @@ operator*(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector3.
+ * @tparam     T1    Type of value in first Vector3.
  * @tparam     T2    Type of second operand.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const BasicVector3<T1>& lhs, T2 rhs) noexcept;
+inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const Vector3<T1>& lhs, T2 rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -669,13 +669,13 @@ operator*(const BasicVector3<T1>& lhs, T2 rhs) noexcept;
  * @param      rhs   Right operand.
  *
  * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second BasicVector3.
+ * @tparam     T2    Type of value in second Vector3.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(T1 lhs, const BasicVector3<T2>& rhs) noexcept;
+inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(T1 lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -685,14 +685,14 @@ operator*(T1 lhs, const BasicVector3<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector3.
- * @tparam     T2    Type of value in second BasicVector3.
+ * @tparam     T1    Type of value in first Vector3.
+ * @tparam     T2    Type of value in second Vector3.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
+inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -702,14 +702,14 @@ operator/(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
  *
- * @tparam     T1    Type of value in first BasicVector3.
+ * @tparam     T1    Type of value in first Vector3.
  * @tparam     T2    Type of second operand.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const BasicVector3<T1>& lhs, T2 rhs) noexcept;
+inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const Vector3<T1>& lhs, T2 rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -720,13 +720,13 @@ operator/(const BasicVector3<T1>& lhs, T2 rhs) noexcept;
  * @param      rhs   Right operand.
  *
  * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second BasicVector3.
+ * @tparam     T2    Type of value in second Vector3.
  *
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(T1 lhs, const BasicVector3<T2>& rhs) noexcept;
+inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(T1 lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -742,7 +742,7 @@ operator/(T1 lhs, const BasicVector3<T2>& rhs) noexcept;
  * @return     Comparision result.
  */
 template<typename T1, typename T2>
-inline bool operator==(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
+inline bool operator==(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -759,8 +759,8 @@ inline bool operator==(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs)
  */
 template<typename T1, typename T2>
 inline
-BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept;
+Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
+cross(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -777,7 +777,7 @@ namespace math {
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector3<T>::BasicVector3() noexcept
+inline Vector3<T>::Vector3() noexcept
     : m_x{}
     , m_y{}
     , m_z{}
@@ -788,10 +788,10 @@ inline BasicVector3<T>::BasicVector3() noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector3<T>::BasicVector3(T x, T y, T z) noexcept
+inline Vector3<T>::Vector3(T x, T y, T z) noexcept
     : m_x(x)
     , m_y(y)
-    , m_z(y)
+    , m_z(z)
 {
     // Nothing to do
 }
@@ -799,7 +799,7 @@ inline BasicVector3<T>::BasicVector3(T x, T y, T z) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector3<T>::BasicVector3(Zero_t zero) noexcept
+inline Vector3<T>::Vector3(Zero_t zero) noexcept
     : m_x{}
     , m_y{}
     , m_z{}
@@ -810,7 +810,7 @@ inline BasicVector3<T>::BasicVector3(Zero_t zero) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector3<T>::BasicVector3(const BasicVector3& src) noexcept
+inline Vector3<T>::Vector3(const Vector3& src) noexcept
     : m_x{src.getX()}
     , m_y{src.getY()}
     , m_z{src.getZ()}
@@ -821,7 +821,7 @@ inline BasicVector3<T>::BasicVector3(const BasicVector3& src) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector3<T>::BasicVector3(BasicVector3&& src) noexcept
+inline Vector3<T>::Vector3(Vector3&& src) noexcept
     : m_x{std::move(src.m_x)}
     , m_y{std::move(src.m_y)}
     , m_z{std::move(src.m_z)}
@@ -833,7 +833,7 @@ inline BasicVector3<T>::BasicVector3(BasicVector3&& src) noexcept
 
 template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline BasicVector3<T>::BasicVector3(const BasicVector3<T2>& rhs) noexcept
+inline Vector3<T>::Vector3(const Vector3<T2>& rhs) noexcept
     : m_x(rhs.getX())
     , m_y(rhs.getY())
     , m_z(rhs.getZ())
@@ -844,7 +844,7 @@ inline BasicVector3<T>::BasicVector3(const BasicVector3<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector3<T>& BasicVector3<T>::operator=(Zero_t zero) noexcept
+inline Vector3<T>& Vector3<T>::operator=(Zero_t zero) noexcept
 {
     m_x = T{};
     m_y = T{};
@@ -856,7 +856,7 @@ inline BasicVector3<T>& BasicVector3<T>::operator=(Zero_t zero) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector3<T>& BasicVector3<T>::operator=(const BasicVector3& src) noexcept
+inline Vector3<T>& Vector3<T>::operator=(const Vector3& src) noexcept
 {
     m_x = src.m_x;
     m_y = src.m_y;
@@ -868,7 +868,7 @@ inline BasicVector3<T>& BasicVector3<T>::operator=(const BasicVector3& src) noex
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector3<T>& BasicVector3<T>::operator=(BasicVector3&& src) noexcept
+inline Vector3<T>& Vector3<T>::operator=(Vector3&& src) noexcept
 {
     m_x = std::move(src.m_x);
     m_y = std::move(src.m_y);
@@ -881,7 +881,7 @@ inline BasicVector3<T>& BasicVector3<T>::operator=(BasicVector3&& src) noexcept
 
 template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline BasicVector3<T>& BasicVector3<T>::operator=(const BasicVector3<T2>& src) noexcept
+inline Vector3<T>& Vector3<T>::operator=(const Vector3<T2>& src) noexcept
 {
     m_x = T(src.getX());
     m_y = T(src.getY());
@@ -893,7 +893,7 @@ inline BasicVector3<T>& BasicVector3<T>::operator=(const BasicVector3<T2>& src)
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector3<T> BasicVector3<T>::operator+() const noexcept
+inline Vector3<T> Vector3<T>::operator+() const noexcept
 {
     return *this;
 }
@@ -901,7 +901,7 @@ inline BasicVector3<T> BasicVector3<T>::operator+() const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector3<T> BasicVector3<T>::operator-() const noexcept
+inline Vector3<T> Vector3<T>::operator-() const noexcept
 {
     return {-m_x, -m_y, -m_z};
 }
@@ -913,7 +913,7 @@ template<typename T1, typename std::enable_if<std::is_same<
     decltype(std::declval<T>() + std::declval<T1>()),
     T
 >::value>::type*>
-inline BasicVector3<T>& BasicVector3<T>::operator+=(const BasicVector3<T1>& rhs) noexcept
+inline Vector3<T>& Vector3<T>::operator+=(const Vector3<T1>& rhs) noexcept
 {
     m_x += rhs.getX();
     m_y += rhs.getY();
@@ -929,7 +929,7 @@ template<typename T1, typename std::enable_if<std::is_same<
     decltype(std::declval<T>() - std::declval<T1>()),
     T
 >::value>::type*>
-inline BasicVector3<T>& BasicVector3<T>::operator-=(const BasicVector3<T1>& rhs) noexcept
+inline Vector3<T>& Vector3<T>::operator-=(const Vector3<T1>& rhs) noexcept
 {
     m_x -= rhs.getX();
     m_y -= rhs.getY();
@@ -948,7 +948,7 @@ template<typename T1, typename std::enable_if<std::is_same<
     T,
     decltype(std::declval<T>() * std::declval<T1>())
 >::value>::type*>
-inline BasicVector3<T>& BasicVector3<T>::operator*=(T1 rhs) noexcept
+inline Vector3<T>& Vector3<T>::operator*=(T1 rhs) noexcept
 {
     m_x *= rhs;
     m_y *= rhs;
@@ -967,7 +967,7 @@ template<typename T1, typename std::enable_if<std::is_same<
     T,
     decltype(std::declval<T>() * std::declval<T1>())
 >::value>::type*>
-inline BasicVector3<T>& BasicVector3<T>::operator*=(const BasicVector3<T1>& rhs) noexcept
+inline Vector3<T>& Vector3<T>::operator*=(const Vector3<T1>& rhs) noexcept
 {
     m_x *= rhs.getX();
     m_y *= rhs.getY();
@@ -986,7 +986,7 @@ template<typename T1, typename std::enable_if<std::is_same<
     T,
     decltype(std::declval<T>() * std::declval<T1>())
 >::value>::type*>
-inline BasicVector3<T>& BasicVector3<T>::operator/=(T1 rhs) noexcept
+inline Vector3<T>& Vector3<T>::operator/=(T1 rhs) noexcept
 {
     m_x /= rhs;
     m_y /= rhs;
@@ -1005,7 +1005,7 @@ template<typename T1, typename std::enable_if<std::is_same<
     T,
     decltype(std::declval<T>() * std::declval<T1>())
 >::value>::type*>
-inline BasicVector3<T>& BasicVector3<T>::operator/=(const BasicVector3<T1>& rhs) noexcept
+inline Vector3<T>& Vector3<T>::operator/=(const Vector3<T1>& rhs) noexcept
 {
     m_x /= rhs.getX();
     m_y /= rhs.getY();
@@ -1017,7 +1017,7 @@ inline BasicVector3<T>& BasicVector3<T>::operator/=(const BasicVector3<T1>& rhs)
 /* ************************************************************************ */
 
 template<typename T>
-inline T& BasicVector3<T>::operator[](int pos) noexcept
+inline T& Vector3<T>::operator[](int pos) noexcept
 {
     CECE_ASSERT(pos >= 0);
     CECE_ASSERT(pos < 3);
@@ -1027,7 +1027,7 @@ inline T& BasicVector3<T>::operator[](int pos) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& BasicVector3<T>::operator[](int pos) const noexcept
+inline const T& Vector3<T>::operator[](int pos) const noexcept
 {
     CECE_ASSERT(pos >= 0);
     CECE_ASSERT(pos < 3);
@@ -1037,7 +1037,7 @@ inline const T& BasicVector3<T>::operator[](int pos) const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline T& BasicVector3<T>::x() noexcept
+inline T& Vector3<T>::x() noexcept
 {
     return m_x;
 }
@@ -1045,7 +1045,7 @@ inline T& BasicVector3<T>::x() noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& BasicVector3<T>::getX() const noexcept
+inline const T& Vector3<T>::getX() const noexcept
 {
     return m_x;
 }
@@ -1053,7 +1053,7 @@ inline const T& BasicVector3<T>::getX() const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline void BasicVector3<T>::setX(T x) noexcept
+inline void Vector3<T>::setX(T x) noexcept
 {
     m_x = std::move(x);
 }
@@ -1061,7 +1061,7 @@ inline void BasicVector3<T>::setX(T x) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline T& BasicVector3<T>::y() noexcept
+inline T& Vector3<T>::y() noexcept
 {
     return m_y;
 }
@@ -1069,7 +1069,7 @@ inline T& BasicVector3<T>::y() noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& BasicVector3<T>::getY() const noexcept
+inline const T& Vector3<T>::getY() const noexcept
 {
     return m_y;
 }
@@ -1077,7 +1077,7 @@ inline const T& BasicVector3<T>::getY() const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline void BasicVector3<T>::setY(T y) noexcept
+inline void Vector3<T>::setY(T y) noexcept
 {
     m_y = std::move(y);
 }
@@ -1085,7 +1085,7 @@ inline void BasicVector3<T>::setY(T y) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline T& BasicVector3<T>::z() noexcept
+inline T& Vector3<T>::z() noexcept
 {
     return m_z;
 }
@@ -1093,7 +1093,7 @@ inline T& BasicVector3<T>::z() noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& BasicVector3<T>::getZ() const noexcept
+inline const T& Vector3<T>::getZ() const noexcept
 {
     return m_z;
 }
@@ -1101,7 +1101,7 @@ inline const T& BasicVector3<T>::getZ() const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline void BasicVector3<T>::setZ(T z) noexcept
+inline void Vector3<T>::setZ(T z) noexcept
 {
     m_z = std::move(z);
 }
@@ -1109,7 +1109,7 @@ inline void BasicVector3<T>::setZ(T z) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline bool BasicVector3<T>::inRange(T value, T low, T high) noexcept
+inline bool Vector3<T>::inRange(T value, T low, T high) noexcept
 {
     return value >= low && value < high;
 }
@@ -1117,7 +1117,7 @@ inline bool BasicVector3<T>::inRange(T value, T low, T high) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline bool BasicVector3<T>::inRange(const BasicVector3& low, const BasicVector3& high) const noexcept
+inline bool Vector3<T>::inRange(const Vector3& low, const Vector3& high) const noexcept
 {
     bool res = true;
 
@@ -1131,7 +1131,7 @@ inline bool BasicVector3<T>::inRange(const BasicVector3& low, const BasicVector3
 /* ************************************************************************ */
 
 template<typename T>
-inline bool BasicVector3<T>::inRange(const BasicVector3& high) const noexcept
+inline bool Vector3<T>::inRange(const Vector3& high) const noexcept
 {
     return inRange(Zero, high);
 }
@@ -1139,7 +1139,7 @@ inline bool BasicVector3<T>::inRange(const BasicVector3& high) const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline typename BasicVector3<T>::ValueType BasicVector3<T>::getLength() const noexcept
+inline typename Vector3<T>::ValueType Vector3<T>::getLength() const noexcept
 {
     using std::sqrt;
     return static_cast<T>(sqrt(getLengthSquared()));
@@ -1148,7 +1148,7 @@ inline typename BasicVector3<T>::ValueType BasicVector3<T>::getLength() const no
 /* ************************************************************************ */
 
 template<typename T>
-inline typename BasicVector3<T>::ValueTypeSq BasicVector3<T>::getLengthSquared() const noexcept
+inline typename Vector3<T>::ValueTypeSq Vector3<T>::getLengthSquared() const noexcept
 {
     return dot(*this);
 }
@@ -1156,7 +1156,7 @@ inline typename BasicVector3<T>::ValueTypeSq BasicVector3<T>::getLengthSquared()
 /* ************************************************************************ */
 
 template<typename T>
-inline typename BasicVector3<T>::ValueTypeSq BasicVector3<T>::dot(const BasicVector3& rhs) const noexcept
+inline typename Vector3<T>::ValueTypeSq Vector3<T>::dot(const Vector3& rhs) const noexcept
 {
     return
         getX() * rhs.getX() +
@@ -1168,7 +1168,7 @@ inline typename BasicVector3<T>::ValueTypeSq BasicVector3<T>::dot(const BasicVec
 /* ************************************************************************ */
 
 template<typename T>
-inline typename BasicVector3<T>::ValueTypeSq BasicVector3<T>::distanceSquared(const BasicVector3& rhs) const noexcept
+inline typename Vector3<T>::ValueTypeSq Vector3<T>::distanceSquared(const Vector3& rhs) const noexcept
 {
     return (*this - rhs).getLengthSquared();
 }
@@ -1176,7 +1176,7 @@ inline typename BasicVector3<T>::ValueTypeSq BasicVector3<T>::distanceSquared(co
 /* ************************************************************************ */
 
 template<typename T>
-inline typename BasicVector3<T>::ValueType BasicVector3<T>::distance(const BasicVector3& rhs) const noexcept
+inline typename Vector3<T>::ValueType Vector3<T>::distance(const Vector3& rhs) const noexcept
 {
     return (*this - rhs).getLength();
 }
@@ -1185,7 +1185,7 @@ inline typename BasicVector3<T>::ValueType BasicVector3<T>::distance(const Basic
 
 template<typename T>
 template<typename T2>
-inline BasicVector3<T2> BasicVector3<T>::inversed() const noexcept
+inline Vector3<T2> Vector3<T>::inversed() const noexcept
 {
     return {
         T2(1) / getX(),
@@ -1197,7 +1197,7 @@ inline BasicVector3<T2> BasicVector3<T>::inversed() const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline BasicVector3<T> BasicVector3<T>::createSingle(T val) noexcept
+inline Vector3<T> Vector3<T>::createSingle(T val) noexcept
 {
     return {val, val, val};
 }
@@ -1205,8 +1205,8 @@ inline BasicVector3<T> BasicVector3<T>::createSingle(T val) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
 {
     return {
         lhs.getX() + rhs.getX(),
@@ -1218,8 +1218,8 @@ operator+(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const BasicVector3<T1>& lhs, T2 rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(const Vector3<T1>& lhs, T2 rhs) noexcept
 {
     return {
         lhs.getX() + rhs,
@@ -1231,8 +1231,8 @@ operator+(const BasicVector3<T1>& lhs, T2 rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(T1 lhs, const BasicVector3<T2>& rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() + std::declval<T2>())>
+operator+(T1 lhs, const Vector3<T2>& rhs) noexcept
 {
     return {
         lhs + rhs.getX(),
@@ -1244,8 +1244,8 @@ operator+(T1 lhs, const BasicVector3<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
 {
     return {
         lhs.getX() - rhs.getX(),
@@ -1257,8 +1257,8 @@ operator-(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const BasicVector3<T1>& lhs, T2 rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(const Vector3<T1>& lhs, T2 rhs) noexcept
 {
     return {
         lhs.getX() - rhs,
@@ -1270,8 +1270,8 @@ operator-(const BasicVector3<T1>& lhs, T2 rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(T1 lhs, const BasicVector3<T2>& rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
+operator-(T1 lhs, const Vector3<T2>& rhs) noexcept
 {
     return {
         lhs - rhs.getX(),
@@ -1283,8 +1283,8 @@ operator-(T1 lhs, const BasicVector3<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
 {
     return {
         lhs.getX() * rhs.getX(),
@@ -1296,8 +1296,8 @@ operator*(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const BasicVector3<T1>& lhs, T2 rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(const Vector3<T1>& lhs, T2 rhs) noexcept
 {
     return {
         lhs.getX() * rhs,
@@ -1309,8 +1309,8 @@ operator*(const BasicVector3<T1>& lhs, T2 rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(T1 lhs, const BasicVector3<T2>& rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
+operator*(T1 lhs, const Vector3<T2>& rhs) noexcept
 {
     return {
         lhs * rhs.getX(),
@@ -1322,8 +1322,8 @@ operator*(T1 lhs, const BasicVector3<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
 {
     return {
         lhs.getX() / rhs.getX(),
@@ -1335,8 +1335,8 @@ operator/(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const BasicVector3<T1>& lhs, T2 rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(const Vector3<T1>& lhs, T2 rhs) noexcept
 {
     return {
         lhs.getX() / rhs,
@@ -1348,8 +1348,8 @@ operator/(const BasicVector3<T1>& lhs, T2 rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline BasicVector3<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(T1 lhs, const BasicVector3<T2>& rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
+operator/(T1 lhs, const Vector3<T2>& rhs) noexcept
 {
     return {
         lhs / rhs.getX(),
@@ -1361,7 +1361,7 @@ operator/(T1 lhs, const BasicVector3<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline bool operator==(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
+inline bool operator==(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
 {
     return
         lhs.getX() == rhs.getX() &&
@@ -1374,8 +1374,8 @@ inline bool operator==(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs)
 
 template<typename T1, typename T2>
 inline
-BasicVector3<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const BasicVector3<T1>& lhs, const BasicVector3<T2>& rhs) noexcept
+Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
+cross(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
 {
     return {
         lhs.getY() * rhs.getZ() - lhs.getZ() * rhs.getY(),
diff --git a/include/cece/math/VectorRange.hpp b/include/cece/math/VectorRange.hpp
index 1784654..e9f708e 100644
--- a/include/cece/math/VectorRange.hpp
+++ b/include/cece/math/VectorRange.hpp
@@ -1,5 +1,5 @@
 /* ************************************************************************ */
-/* Georgiev Lab (c) 2015-2016                                               */
+/* Georgiev Lab (c) 2015-2017                                               */
 /* ************************************************************************ */
 /* Department of Cybernetics                                                */
 /* Faculty of Applied Sciences                                              */
@@ -39,9 +39,9 @@ namespace math {
 /* ************************************************************************ */
 
 /**
- * @brief Wrapper for vector iterator.
+ * @brief      Wrapper for vector iterator.
  *
- * @tparam T Element type of Vector.
+ * @tparam     T     Element type of Vector.
  */
 template<typename T>
 struct IteratorVector
@@ -64,11 +64,11 @@ struct IteratorVector
 
 
     /**
-     * @brief Constructor.
+     * @brief      Constructor.
      *
-     * @param value Current value.
-     * @param max   Maximum value.
-     * @param min   Minimum value.
+     * @param      value  Current value.
+     * @param      max    Maximum value.
+     * @param      min    Minimum value.
      */
     IteratorVector(Vector<T> value, Vector<T> max, Vector<T> min = Zero) noexcept
         : m_value(std::move(value))
@@ -84,7 +84,7 @@ struct IteratorVector
 
 
     /**
-     * @brief Cast to value.
+     * @brief      Cast to value.
      */
     operator Vector<T>() const noexcept
     {
@@ -93,11 +93,11 @@ struct IteratorVector
 
 
     /**
-     * @brief Compares values.
+     * @brief      Compares values.
      *
-     * @param rhs Second value.
+     * @param      rhs   Second value.
      *
-     * @return Are values equal?
+     * @return     Are values equal?
      */
     bool operator==(const IteratorVector& rhs) const noexcept
     {
@@ -106,11 +106,11 @@ struct IteratorVector
 
 
     /**
-     * @brief Compares values.
+     * @brief      Compares values.
      *
-     * @param rhs Second value.
+     * @param      rhs   Second value.
      *
-     * @return Aren't values equal?
+     * @return     Aren't values equal?
      */
     bool operator!=(const IteratorVector& rhs) const noexcept
     {
@@ -119,9 +119,9 @@ struct IteratorVector
 
 
     /**
-     * @brief Dereference operator.
+     * @brief      Dereference operator.
      *
-     * @return A reference to the current token.
+     * @return     A reference to the current token.
      */
     reference operator*() const noexcept
     {
@@ -130,9 +130,9 @@ struct IteratorVector
 
 
     /**
-     * @brief Dereference operator.
+     * @brief      Dereference operator.
      *
-     * @return A pointer to the current token.
+     * @return     A pointer to the current token.
      */
     pointer operator->() const noexcept
     {
@@ -141,20 +141,20 @@ struct IteratorVector
 
 
     /**
-     * @brief Increment operator.
+     * @brief      Increment operator.
      *
-     * @return *this.
+     * @return     *this.
      */
     IteratorVector& operator++() noexcept
     {
-        if (m_value.x() == m_max.x())
+        if (m_value.x == m_max.x)
         {
-            m_value.x() = m_min.x();
-            ++m_value.y();
+            m_value.x = m_min.x;
+            ++m_value.y;
         }
         else
         {
-            ++m_value.x();
+            ++m_value.x;
         }
 
         return *this;
@@ -162,11 +162,15 @@ struct IteratorVector
 
 
     /**
-     * @brief Post-increment operator.
+     * @brief      Post-increment operator.
      *
-     * @note Is deleted (because I'm to lazy to write it).
+     * @note       Is deleted (because I'm to lazy to write it).
+     *
+     * @param[in]  dummy  The dummy.
+     *
+     * @return     Iterator.
      */
-    IteratorVector operator++(int) = delete;
+    IteratorVector operator++(int dummy) = delete;
 
 
 // Private Data Members
diff --git a/src/math/Vector2.cpp b/src/math/Vector2.cpp
index 69745c6..824623e 100644
--- a/src/math/Vector2.cpp
+++ b/src/math/Vector2.cpp
@@ -33,10 +33,10 @@ namespace math {
 
 /* ************************************************************************ */
 
-template class BasicVector2<float>;
-template class BasicVector2<double>;
-template class BasicVector2<unsigned int>;
-template class BasicVector2<int>;
+template class Vector2<float>;
+template class Vector2<double>;
+template class Vector2<unsigned int>;
+template class Vector2<int>;
 
 /* ************************************************************************ */
 
diff --git a/src/math/Vector3.cpp b/src/math/Vector3.cpp
index c8d3a51..8904c16 100644
--- a/src/math/Vector3.cpp
+++ b/src/math/Vector3.cpp
@@ -33,10 +33,10 @@ namespace math {
 
 /* ************************************************************************ */
 
-template class BasicVector3<float>;
-template class BasicVector3<double>;
-template class BasicVector3<unsigned int>;
-template class BasicVector3<int>;
+template class Vector3<float>;
+template class Vector3<double>;
+template class Vector3<unsigned int>;
+template class Vector3<int>;
 
 /* ************************************************************************ */
 
diff --git a/unittests/math/CMakeLists.txt b/unittests/math/CMakeLists.txt
index 6574948..d5a5575 100644
--- a/unittests/math/CMakeLists.txt
+++ b/unittests/math/CMakeLists.txt
@@ -27,6 +27,7 @@ cece_add_test(core
     SOURCES
         Vector_test.cpp
         Vector2_test.cpp
+        Vector3_test.cpp
         VectorRangeTest.cpp
 )
 
diff --git a/unittests/math/Vector2_test.cpp b/unittests/math/Vector2_test.cpp
index bc8c62a..9b45d9b 100644
--- a/unittests/math/Vector2_test.cpp
+++ b/unittests/math/Vector2_test.cpp
@@ -39,7 +39,7 @@ using namespace cece::math;
 TEST(Vector2, ctor)
 {
     {
-        BasicVector2<int> vec;
+        Vector2<int> vec;
 
         EXPECT_EQ(0, vec.getX());
         EXPECT_EQ(0, vec.getY());
@@ -48,7 +48,7 @@ TEST(Vector2, ctor)
     }
 
     {
-        BasicVector2<int> vec(Zero);
+        Vector2<int> vec(Zero);
 
         EXPECT_EQ(0, vec.getX());
         EXPECT_EQ(0, vec.getY());
@@ -57,7 +57,7 @@ TEST(Vector2, ctor)
     }
 
     {
-        BasicVector2<float> vec = {1.2f, 3.0f};
+        Vector2<float> vec = {1.2f, 3.0f};
 
         EXPECT_FLOAT_EQ(1.2f, vec.getX());
         EXPECT_FLOAT_EQ(3.0f, vec.getY());
@@ -66,14 +66,14 @@ TEST(Vector2, ctor)
     }
 
     {
-        const BasicVector2<float> vec1 = {1.2f, 3.0f};
+        const Vector2<float> vec1 = {1.2f, 3.0f};
 
         EXPECT_FLOAT_EQ(1.2f, vec1.getX());
         EXPECT_FLOAT_EQ(3.0f, vec1.getY());
         EXPECT_FLOAT_EQ(1.2f, vec1[0]);
         EXPECT_FLOAT_EQ(3.0f, vec1[1]);
 
-        BasicVector2<float> vec2(vec1);
+        Vector2<float> vec2(vec1);
 
         EXPECT_FLOAT_EQ(1.2f, vec2.getX());
         EXPECT_FLOAT_EQ(3.0f, vec2.getY());
@@ -82,14 +82,14 @@ TEST(Vector2, ctor)
     }
 
     {
-        BasicVector2<float> vec1 = {1.2f, 3.0f};
+        Vector2<float> vec1 = {1.2f, 3.0f};
 
         EXPECT_FLOAT_EQ(1.2f, vec1.getX());
         EXPECT_FLOAT_EQ(3.0f, vec1.getY());
         EXPECT_FLOAT_EQ(1.2f, vec1[0]);
         EXPECT_FLOAT_EQ(3.0f, vec1[1]);
 
-        BasicVector2<float> vec2(std::move(vec1));
+        Vector2<float> vec2(std::move(vec1));
 
         EXPECT_FLOAT_EQ(1.2f, vec2.getX());
         EXPECT_FLOAT_EQ(3.0f, vec2.getY());
@@ -98,14 +98,14 @@ TEST(Vector2, ctor)
     }
 
     {
-        const BasicVector2<int> vec1 = {1, 3};
+        const Vector2<int> vec1 = {1, 3};
 
         EXPECT_EQ(1, vec1.getX());
         EXPECT_EQ(3, vec1.getY());
         EXPECT_EQ(1, vec1[0]);
         EXPECT_EQ(3, vec1[1]);
 
-        BasicVector2<float> vec2(vec1);
+        Vector2<float> vec2(vec1);
 
         EXPECT_FLOAT_EQ(1.0f, vec2.getX());
         EXPECT_FLOAT_EQ(3.0f, vec2.getY());
@@ -119,7 +119,7 @@ TEST(Vector2, ctor)
 TEST(Vector2, assignment)
 {
     {
-        BasicVector2<int> vec{1, 1};
+        Vector2<int> vec{1, 1};
 
         EXPECT_EQ(1, vec[0]);
         EXPECT_EQ(1, vec[1]);
@@ -131,7 +131,7 @@ TEST(Vector2, assignment)
     }
 
     {
-        BasicVector2<float> vec;
+        Vector2<float> vec;
 
         EXPECT_EQ(0, vec[0]);
         EXPECT_EQ(0, vec[1]);
@@ -143,12 +143,12 @@ TEST(Vector2, assignment)
     }
 
     {
-        const BasicVector2<float> vec1 = {1.2f, 3.0f};
+        const Vector2<float> vec1 = {1.2f, 3.0f};
 
         EXPECT_FLOAT_EQ(1.2f, vec1[0]);
         EXPECT_FLOAT_EQ(3.0f, vec1[1]);
 
-        BasicVector2<float> vec2;
+        Vector2<float> vec2;
 
         vec2 = vec1;
 
@@ -157,12 +157,12 @@ TEST(Vector2, assignment)
     }
 
     {
-        BasicVector2<float> vec1 = {1.2f, 3.0f};
+        Vector2<float> vec1 = {1.2f, 3.0f};
 
         EXPECT_FLOAT_EQ(1.2f, vec1[0]);
         EXPECT_FLOAT_EQ(3.0f, vec1[1]);
 
-        BasicVector2<float> vec2;
+        Vector2<float> vec2;
 
         vec2 = std::move(vec1);
 
@@ -171,12 +171,12 @@ TEST(Vector2, assignment)
     }
 
     {
-        const BasicVector2<int> vec1 = {1, 3};
+        const Vector2<int> vec1 = {1, 3};
 
         EXPECT_EQ(1, vec1[0]);
         EXPECT_EQ(3, vec1[1]);
 
-        BasicVector2<float> vec2;
+        Vector2<float> vec2;
 
         vec2 = vec1;
 
@@ -190,36 +190,36 @@ TEST(Vector2, assignment)
 TEST(Vector2, operators)
 {
     {
-        BasicVector2<float> vec1{1.0f, 2.0f};
+        Vector2<float> vec1{1.0f, 2.0f};
 
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
         EXPECT_FLOAT_EQ(2.0f, vec1[1]);
 
-        BasicVector2<float> vec2 = +vec1;
+        Vector2<float> vec2 = +vec1;
 
         EXPECT_FLOAT_EQ(1.0f, vec2[0]);
         EXPECT_FLOAT_EQ(2.0f, vec2[1]);
     }
 
     {
-        BasicVector2<float> vec1{1.0f, 2.0f};
+        Vector2<float> vec1{1.0f, 2.0f};
 
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
         EXPECT_FLOAT_EQ(2.0f, vec1[1]);
 
-        BasicVector2<float> vec2 = -vec1;
+        Vector2<float> vec2 = -vec1;
 
         EXPECT_FLOAT_EQ(-1.0f, vec2[0]);
         EXPECT_FLOAT_EQ(-2.0f, vec2[1]);
     }
 
     {
-        BasicVector2<float> vec1{1.0f, 2.0f};
+        Vector2<float> vec1{1.0f, 2.0f};
 
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
         EXPECT_FLOAT_EQ(2.0f, vec1[1]);
 
-        BasicVector2<float> vec2{1.0f, 2.0f};
+        Vector2<float> vec2{1.0f, 2.0f};
         vec1 += vec2;
 
         EXPECT_FLOAT_EQ(2.0f, vec1[0]);
@@ -227,12 +227,12 @@ TEST(Vector2, operators)
     }
 
     {
-        BasicVector2<float> vec1{1.0f, 2.0f};
+        Vector2<float> vec1{1.0f, 2.0f};
 
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
         EXPECT_FLOAT_EQ(2.0f, vec1[1]);
 
-        BasicVector2<float> vec2{1.0f, 2.0f};
+        Vector2<float> vec2{1.0f, 2.0f};
         vec1 -= vec2;
 
         EXPECT_FLOAT_EQ(0.0f, vec1[0]);
@@ -240,7 +240,7 @@ TEST(Vector2, operators)
     }
 
     {
-        BasicVector2<float> vec1{1.0f, 2.0f};
+        Vector2<float> vec1{1.0f, 2.0f};
 
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
         EXPECT_FLOAT_EQ(2.0f, vec1[1]);
@@ -252,12 +252,12 @@ TEST(Vector2, operators)
     }
 
     {
-        BasicVector2<float> vec1{1.0f, 2.0f};
+        Vector2<float> vec1{1.0f, 2.0f};
 
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
         EXPECT_FLOAT_EQ(2.0f, vec1[1]);
 
-        BasicVector2<float> vec2{1.0f, 2.0f};
+        Vector2<float> vec2{1.0f, 2.0f};
         vec1 *= vec2;
 
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
@@ -265,7 +265,7 @@ TEST(Vector2, operators)
     }
 
     {
-        BasicVector2<float> vec1{1.0f, 2.0f};
+        Vector2<float> vec1{1.0f, 2.0f};
 
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
         EXPECT_FLOAT_EQ(2.0f, vec1[1]);
@@ -277,12 +277,12 @@ TEST(Vector2, operators)
     }
 
     {
-        BasicVector2<float> vec1{1.0f, 2.0f};
+        Vector2<float> vec1{1.0f, 2.0f};
 
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
         EXPECT_FLOAT_EQ(2.0f, vec1[1]);
 
-        BasicVector2<float> vec2{1.0f, 2.0f};
+        Vector2<float> vec2{1.0f, 2.0f};
         vec1 /= vec2;
 
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
@@ -295,12 +295,12 @@ TEST(Vector2, operators)
 TEST(Vector2, inRange)
 {
     {
-        const BasicVector2<float> vecMin{-10.0f, -5.0f};
-        const BasicVector2<float> vecMax{10.0f, 20.0f};
+        const Vector2<float> vecMin{-10.0f, -5.0f};
+        const Vector2<float> vecMax{10.0f, 20.0f};
 
-        BasicVector2<float> vec1;
-        BasicVector2<float> vec2{-15.0f, 0.0f};
-        BasicVector2<float> vec3{5.0f, 0.0f};
+        Vector2<float> vec1;
+        Vector2<float> vec2{-15.0f, 0.0f};
+        Vector2<float> vec3{5.0f, 0.0f};
 
         EXPECT_TRUE(vec1.inRange(vecMin, vecMax));
         EXPECT_FALSE(vec2.inRange(vecMin, vecMax));
@@ -308,11 +308,11 @@ TEST(Vector2, inRange)
     }
 
     {
-        const BasicVector2<float> vecMax{10.0f, 20.0f};
+        const Vector2<float> vecMax{10.0f, 20.0f};
 
-        BasicVector2<float> vec1;
-        BasicVector2<float> vec2{-15.0f, 0.0f};
-        BasicVector2<float> vec3{5.0f, 0.0f};
+        Vector2<float> vec1;
+        Vector2<float> vec2{-15.0f, 0.0f};
+        Vector2<float> vec3{5.0f, 0.0f};
 
         EXPECT_TRUE(vec1.inRange(vecMax));
         EXPECT_FALSE(vec2.inRange(vecMax));
@@ -325,83 +325,83 @@ TEST(Vector2, inRange)
 TEST(Vector2, memberFunctions)
 {
     {
-        const BasicVector2<float> vec;
+        const Vector2<float> vec;
 
         EXPECT_FLOAT_EQ(0, vec.getLength());
     }
 
     {
-        const BasicVector2<float> vec{1.0f, 2.0f};
+        const Vector2<float> vec{1.0f, 2.0f};
 
         EXPECT_FLOAT_EQ(2.2360680f, vec.getLength());
     }
 
     {
-        const BasicVector2<float> vec;
+        const Vector2<float> vec;
 
         EXPECT_FLOAT_EQ(0, vec.getLengthSquared());
     }
 
     {
-        const BasicVector2<float> vec{1.0f, 2.0f};
+        const Vector2<float> vec{1.0f, 2.0f};
 
         EXPECT_FLOAT_EQ(5, vec.getLengthSquared());
     }
 
     {
-        const BasicVector2<float> vec;
+        const Vector2<float> vec;
 
         EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
     }
 
     {
-        const BasicVector2<float> vec{1.0f, 2.0f};
+        const Vector2<float> vec{1.0f, 2.0f};
 
         EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
     }
 
     {
-        const BasicVector2<float> vec1;
-        const BasicVector2<float> vec2;
+        const Vector2<float> vec1;
+        const Vector2<float> vec2;
 
         EXPECT_FLOAT_EQ(0, vec1.dot(vec2));
     }
 
     {
-        const BasicVector2<float> vec1{1.0f, 2.0f};
-        const BasicVector2<float> vec2{5.0f, 4.0f};
+        const Vector2<float> vec1{1.0f, 2.0f};
+        const Vector2<float> vec2{5.0f, 4.0f};
 
         EXPECT_FLOAT_EQ(13, vec1.dot(vec2));
     }
 
     {
-        const BasicVector2<float> vec;
+        const Vector2<float> vec;
 
         EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
     }
 
     {
-        const BasicVector2<float> vec{1.0f, 2.0f};
+        const Vector2<float> vec{1.0f, 2.0f};
 
         EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
     }
 
     {
-        const BasicVector2<float> vec1{1.0f, 2.0f};
-        const BasicVector2<float> vec2{5.0f, 4.0f};
+        const Vector2<float> vec1{1.0f, 2.0f};
+        const Vector2<float> vec2{5.0f, 4.0f};
 
         EXPECT_FLOAT_EQ(20.0f, vec1.distanceSquared(vec2));
     }
 
     {
-        const BasicVector2<float> vec1{1.0f, 2.0f};
-        const BasicVector2<float> vec2{5.0f, 4.0f};
+        const Vector2<float> vec1{1.0f, 2.0f};
+        const Vector2<float> vec2{5.0f, 4.0f};
 
         EXPECT_FLOAT_EQ(4.4721360f, vec1.distance(vec2));
     }
 
     {
-        const BasicVector2<float> vec{1.0f, 2.0f};
+        const Vector2<float> vec{1.0f, 2.0f};
 
         auto inv = vec.inversed();
 
@@ -410,14 +410,14 @@ TEST(Vector2, memberFunctions)
     }
 
     {
-        auto vec = BasicVector2<float>::createSingle(1);
+        auto vec = Vector2<float>::createSingle(1);
 
         EXPECT_FLOAT_EQ(1.0f, vec[0]);
         EXPECT_FLOAT_EQ(1.0f, vec[1]);
     }
 
     {
-        auto vec = BasicVector2<float>::createSingle(375.1721f);
+        auto vec = Vector2<float>::createSingle(375.1721f);
 
         EXPECT_FLOAT_EQ(375.1721f, vec[0]);
         EXPECT_FLOAT_EQ(375.1721f, vec[1]);
@@ -425,3 +425,84 @@ TEST(Vector2, memberFunctions)
 }
 
 /* ************************************************************************ */
+
+TEST(Vector2, mutators)
+{
+    {
+        Vector2<int> vec;
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+
+        vec.setX(100);
+
+        EXPECT_EQ(100, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+
+        vec.setY(50);
+
+        EXPECT_EQ(100, vec.getX());
+        EXPECT_EQ(50, vec.getY());
+    }
+
+    {
+        Vector2<int> vec;
+
+        EXPECT_EQ(0, vec.x);
+        EXPECT_EQ(0, vec.y);
+
+        vec.x = 100;
+
+        EXPECT_EQ(100, vec.x);
+        EXPECT_EQ(0, vec.y);
+
+        vec.y = 50;
+
+        EXPECT_EQ(100, vec.x);
+        EXPECT_EQ(50, vec.y);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector2, functions)
+{
+    {
+        Vector2<int> vec(1, 0);
+
+        EXPECT_EQ(1, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+
+        auto rot = vec.rotated(unit::deg2rad(90));
+
+        EXPECT_EQ(0, rot.getX());
+        EXPECT_EQ(1, rot.getY());
+    }
+
+    {
+        Vector2<int> vec(1, 0);
+
+        EXPECT_EQ(1, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+
+        auto rot = vec.rotated(unit::deg2rad(-90));
+
+        EXPECT_EQ(0, rot.getX());
+        EXPECT_EQ(-1, rot.getY());
+    }
+
+    {
+        Vector2<int> vec(1, 0);
+
+        EXPECT_EQ(1, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+
+        auto rot = vec.rotated(unit::deg2rad(180));
+
+        EXPECT_EQ(-1, rot.getX());
+        EXPECT_EQ(0, rot.getY());
+    }
+
+}
+
+/* ************************************************************************ */
diff --git a/unittests/math/Vector3_test.cpp b/unittests/math/Vector3_test.cpp
new file mode 100644
index 0000000..0e30b96
--- /dev/null
+++ b/unittests/math/Vector3_test.cpp
@@ -0,0 +1,473 @@
+/* ************************************************************************ */
+/* Georgiev Lab (c) 2015-2017                                               */
+/* ************************************************************************ */
+/* Department of Cybernetics                                                */
+/* Faculty of Applied Sciences                                              */
+/* University of West Bohemia in Pilsen                                     */
+/* ************************************************************************ */
+/*                                                                          */
+/* This file is part of CeCe.                                               */
+/*                                                                          */
+/* CeCe is free software: you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by     */
+/* the Free Software Foundation, either version 3 of the License, or        */
+/* (at your option) any later version.                                      */
+/*                                                                          */
+/* CeCe is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/* GNU General Public License for more details.                             */
+/*                                                                          */
+/* You should have received a copy of the GNU General Public License        */
+/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
+/*                                                                          */
+/* ************************************************************************ */
+
+// GTest
+#include "gtest/gtest.h"
+
+// CeCe
+#include "cece/math/Vector3.hpp"
+
+/* ************************************************************************ */
+
+using namespace cece;
+using namespace cece::math;
+
+/* ************************************************************************ */
+
+TEST(Vector3, ctor)
+{
+    {
+        Vector3<int> vec;
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+    }
+
+    {
+        Vector3<int> vec(Zero);
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+    }
+
+    {
+        Vector3<float> vec = {1.2f, 3.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec.getY());
+        EXPECT_FLOAT_EQ(-8.1f, vec.getZ());
+        EXPECT_FLOAT_EQ(1.2f, vec[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec[2]);
+    }
+
+    {
+        const Vector3<float> vec1 = {1.2f, 3.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec1.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec1.getY());
+        EXPECT_FLOAT_EQ(-8.1f, vec1.getZ());
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+
+        Vector3<float> vec2(vec1);
+
+        EXPECT_FLOAT_EQ(1.2f, vec2.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(-8.1f, vec2.getZ());
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec2[2]);
+    }
+
+    {
+        Vector3<float> vec1 = {1.2f, 3.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec1.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec1.getY());
+        EXPECT_FLOAT_EQ(-8.1f, vec1.getZ());
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+
+        Vector3<float> vec2(std::move(vec1));
+
+        EXPECT_FLOAT_EQ(1.2f, vec2.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(-8.1f, vec2.getZ());
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec2[2]);
+    }
+
+    {
+        const Vector3<int> vec1 = {1, 3, -8};
+
+        EXPECT_EQ(1, vec1.getX());
+        EXPECT_EQ(3, vec1.getY());
+        EXPECT_EQ(-8, vec1.getZ());
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+        EXPECT_EQ(-8, vec1[2]);
+
+        Vector3<float> vec2(vec1);
+
+        EXPECT_FLOAT_EQ(1.0f, vec2.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(-8.0f, vec2.getZ());
+        EXPECT_FLOAT_EQ(1.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(-8.0f, vec2[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, assignment)
+{
+    {
+        Vector3<int> vec{1, 1, 1};
+
+        EXPECT_EQ(1, vec[0]);
+        EXPECT_EQ(1, vec[1]);
+        EXPECT_EQ(1, vec[2]);
+
+        vec = Zero;
+
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+    }
+
+    {
+        Vector3<float> vec;
+
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+
+        vec = {1.2f, 3.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec[2]);
+    }
+
+    {
+        const Vector3<float> vec1 = {1.2f, 3.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+
+        Vector3<float> vec2;
+
+        vec2 = vec1;
+
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec2[2]);
+    }
+
+    {
+        Vector3<float> vec1 = {1.2f, 3.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+
+        Vector3<float> vec2;
+
+        vec2 = std::move(vec1);
+
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec2[2]);
+    }
+
+    {
+        const Vector3<int> vec1 = {1, 3, -8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+        EXPECT_EQ(-8, vec1[2]);
+
+        Vector3<float> vec2;
+
+        vec2 = vec1;
+
+        EXPECT_FLOAT_EQ(1.0, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(-8.0f, vec2[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, operators)
+{
+    {
+        Vector3<float> vec1{1.0f, 2.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+
+        Vector3<float> vec2 = +vec1;
+
+        EXPECT_FLOAT_EQ(1.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec2[2]);
+    }
+
+    {
+        Vector3<float> vec1{1.0f, 2.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+
+        Vector3<float> vec2 = -vec1;
+
+        EXPECT_FLOAT_EQ(-1.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(-2.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(8.1f, vec2[2]);
+    }
+
+    {
+        Vector3<float> vec1{1.0f, 2.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+
+        Vector3<float> vec2{1.0f, 2.0f, -8.1f};
+        vec1 += vec2;
+
+        EXPECT_FLOAT_EQ(2.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-16.2f, vec1[2]);
+    }
+
+    {
+        Vector3<float> vec1{1.0f, 2.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+
+        Vector3<float> vec2{1.0f, 2.0f, -8.1f};
+        vec1 -= vec2;
+
+        EXPECT_FLOAT_EQ(0.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[2]);
+    }
+
+    {
+        Vector3<float> vec1{1.0f, 2.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+
+        vec1 *= 2.0;
+
+        EXPECT_FLOAT_EQ(2.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-16.2f, vec1[2]);
+    }
+
+    {
+        Vector3<float> vec1{1.0f, 2.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+
+        Vector3<float> vec2{1.0f, 2.0f, -8.1f};
+        vec1 *= vec2;
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f * -8.1f, vec1[2]);
+    }
+
+    {
+        Vector3<float> vec1{1.0f, 2.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+
+        vec1 /= 2.0;
+
+        EXPECT_FLOAT_EQ(0.5f, vec1[0]);
+        EXPECT_FLOAT_EQ(1.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-4.05f, vec1[2]);
+    }
+
+    {
+        Vector3<float> vec1{1.0f, 2.0f, -8.1f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+
+        Vector3<float> vec2{1.0f, 2.0f, -8.1f};
+        vec1 /= vec2;
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(1.0f, vec1[1]);
+        EXPECT_FLOAT_EQ(1.0f, vec1[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, inRange)
+{
+    {
+        const Vector3<float> vecMin{-10.0f, -5.0f, -2.0f};
+        const Vector3<float> vecMax{10.0f, 20.0f, 5.0f};
+
+        Vector3<float> vec1;
+        Vector3<float> vec2{-15.0f, 0.0f, 0.0f};
+        Vector3<float> vec3{5.0f, 0.0f, 3.0f};
+
+        EXPECT_TRUE(vec1.inRange(vecMin, vecMax));
+        EXPECT_FALSE(vec2.inRange(vecMin, vecMax));
+        EXPECT_TRUE(vec3.inRange(vecMin, vecMax));
+    }
+
+    {
+        const Vector3<float> vecMax{10.0f, 20.0f, 8.0f};
+
+        Vector3<float> vec1;
+        Vector3<float> vec2{-15.0f, 0.0f, 3.0f};
+        Vector3<float> vec3{5.0f, 0.0f, 3.0f};
+
+        EXPECT_TRUE(vec1.inRange(vecMax));
+        EXPECT_FALSE(vec2.inRange(vecMax));
+        EXPECT_TRUE(vec3.inRange(vecMax));
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, memberFunctions)
+{
+    {
+        const Vector3<float> vec;
+
+        EXPECT_FLOAT_EQ(0, vec.getLength());
+    }
+
+    {
+        const Vector3<float> vec{1.0f, 2.0f, 3.0f};
+
+        EXPECT_FLOAT_EQ(3.7416574f, vec.getLength());
+    }
+
+    {
+        const Vector3<float> vec;
+
+        EXPECT_FLOAT_EQ(0, vec.getLengthSquared());
+    }
+
+    {
+        const Vector3<float> vec{1.0f, 2.0f, 3.0f};
+
+        EXPECT_FLOAT_EQ(14, vec.getLengthSquared());
+    }
+
+    {
+        const Vector3<float> vec;
+
+        EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
+    }
+
+    {
+        const Vector3<float> vec{1.0f, 2.0f, 3.0f};
+
+        EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
+    }
+
+    {
+        const Vector3<float> vec1;
+        const Vector3<float> vec2;
+
+        EXPECT_FLOAT_EQ(0, vec1.dot(vec2));
+    }
+
+    {
+        const Vector3<float> vec1{1.0f, 2.0f, 3.0f};
+        const Vector3<float> vec2{5.0f, 4.0f, 3.0f};
+
+        EXPECT_FLOAT_EQ(22, vec1.dot(vec2));
+    }
+
+    {
+        const Vector3<float> vec;
+
+        EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
+    }
+
+    {
+        const Vector3<float> vec{1.0f, 2.0f, 3.0f};
+
+        EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
+    }
+
+    {
+        const Vector3<float> vec1{1.0f, 2.0f, 3.0f};
+        const Vector3<float> vec2{5.0f, 4.0f, 3.0f};
+
+        EXPECT_FLOAT_EQ(20.0f, vec1.distanceSquared(vec2));
+    }
+
+    {
+        const Vector3<float> vec1{1.0f, 2.0f, 3.0f};
+        const Vector3<float> vec2{5.0f, 4.0f, 3.0f};
+
+        EXPECT_FLOAT_EQ(4.4721360f, vec1.distance(vec2));
+    }
+
+    {
+        const Vector3<float> vec{1.0f, 2.0f, 3.0f};
+
+        auto inv = vec.inversed();
+
+        EXPECT_FLOAT_EQ(1.0f, inv[0]);
+        EXPECT_FLOAT_EQ(0.5f, inv[1]);
+        EXPECT_FLOAT_EQ(1.0f / 3.0f, inv[2]);
+    }
+
+    {
+        auto vec = Vector3<float>::createSingle(1);
+
+        EXPECT_FLOAT_EQ(1.0f, vec[0]);
+        EXPECT_FLOAT_EQ(1.0f, vec[1]);
+        EXPECT_FLOAT_EQ(1.0f, vec[2]);
+    }
+
+    {
+        auto vec = Vector3<float>::createSingle(375.1721f);
+
+        EXPECT_FLOAT_EQ(375.1721f, vec[0]);
+        EXPECT_FLOAT_EQ(375.1721f, vec[1]);
+    }
+}
+
+/* ************************************************************************ */

From b643b82bbcb6fa53c9101908adad7b7807c9d3e1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Fatka?= <fatkaj@ntis.zcu.cz>
Date: Thu, 9 Mar 2017 17:45:19 +0100
Subject: [PATCH 04/11] Removed and added some operators from Vector2.

---
 include/cece/math/Vector2.hpp   | 161 +++++++-------------------------
 unittests/math/Vector2_test.cpp | 147 +++++++++++++++++++++++++++++
 2 files changed, 180 insertions(+), 128 deletions(-)

diff --git a/include/cece/math/Vector2.hpp b/include/cece/math/Vector2.hpp
index 32f8970..2de646d 100644
--- a/include/cece/math/Vector2.hpp
+++ b/include/cece/math/Vector2.hpp
@@ -495,45 +495,11 @@ extern template class Vector2<int>;
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
+Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
 operator+(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
-/**
- * @brief      Addition operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector2.
- * @tparam     T2    Type of second operand.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const Vector2<T1>& lhs, T2 rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Addition operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second Vector2.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(T1 lhs, const Vector2<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
 /**
  * @brief      Substract operator.
  *
@@ -546,45 +512,11 @@ operator+(T1 lhs, const Vector2<T2>& rhs) noexcept;
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
+Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
 operator-(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
-/**
- * @brief      Substract operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector2.
- * @tparam     T2    Type of second operand.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const Vector2<T1>& lhs, T2 rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Substract operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second Vector2.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(T1 lhs, const Vector2<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
 /**
  * @brief      Multiplication operator.
  *
@@ -597,7 +529,7 @@ operator-(T1 lhs, const Vector2<T2>& rhs) noexcept;
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
 operator*(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
@@ -614,7 +546,7 @@ operator*(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
 operator*(const Vector2<T1>& lhs, T2 rhs) noexcept;
 
 /* ************************************************************************ */
@@ -631,7 +563,7 @@ operator*(const Vector2<T1>& lhs, T2 rhs) noexcept;
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
+Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
 operator*(T1 lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
@@ -648,7 +580,7 @@ operator*(T1 lhs, const Vector2<T2>& rhs) noexcept;
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
+Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
 operator/(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
@@ -665,7 +597,7 @@ operator/(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
+Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
 operator/(const Vector2<T1>& lhs, T2 rhs) noexcept;
 
 /* ************************************************************************ */
@@ -682,7 +614,7 @@ operator/(const Vector2<T1>& lhs, T2 rhs) noexcept;
  * @return     Result vector.
  */
 template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
+Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
 operator/(T1 lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
@@ -699,7 +631,23 @@ operator/(T1 lhs, const Vector2<T2>& rhs) noexcept;
  * @return     Comparision result.
  */
 template<typename T1, typename T2>
-inline bool operator==(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
+bool operator==(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    The first type.
+ * @tparam     T2    The second type.
+ *
+ * @return     Comparision result.
+ */
+template<typename T1, typename T2>
+bool operator!=(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -715,7 +663,6 @@ inline bool operator==(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
  * @return     Cross product.
  */
 template<typename T1, typename T2>
-inline
 decltype(std::declval<T1>() * std::declval<T2>())
 cross(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
@@ -733,7 +680,6 @@ cross(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
  * @return     Cross product.
  */
 template<typename T1, typename T2>
-inline
 Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
 cross(const Vector2<T1>& lhs, const T2& rhs) noexcept;
 
@@ -751,7 +697,6 @@ cross(const Vector2<T1>& lhs, const T2& rhs) noexcept;
  * @return     Cross product.
  */
 template<typename T1, typename T2>
-inline
 Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
 cross(const T1& lhs, const Vector2<T2>& rhs) noexcept;
 
@@ -1155,30 +1100,6 @@ operator+(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const Vector2<T1>& lhs, T2 rhs) noexcept
-{
-    return {
-        lhs.getX() + rhs,
-        lhs.getY() + rhs
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(T1 lhs, const Vector2<T2>& rhs) noexcept
-{
-    return {
-        lhs + rhs.getX(),
-        lhs + rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
 template<typename T1, typename T2>
 inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
 operator-(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
@@ -1191,30 +1112,6 @@ operator-(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const Vector2<T1>& lhs, T2 rhs) noexcept
-{
-    return {
-        lhs.getX() - rhs,
-        lhs.getY() - rhs
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(T1 lhs, const Vector2<T2>& rhs) noexcept
-{
-    return {
-        lhs - rhs.getX(),
-        lhs - rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
 template<typename T1, typename T2>
 inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
 operator*(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
@@ -1298,6 +1195,14 @@ inline bool operator==(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
 
 /* ************************************************************************ */
 
+template<typename T1, typename T2>
+inline bool operator!=(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
+{
+    return !operator==(lhs, rhs);
+}
+
+/* ************************************************************************ */
+
 template<typename T1, typename T2>
 inline
 decltype(std::declval<T1>() * std::declval<T2>())
diff --git a/unittests/math/Vector2_test.cpp b/unittests/math/Vector2_test.cpp
index 9b45d9b..0d958cb 100644
--- a/unittests/math/Vector2_test.cpp
+++ b/unittests/math/Vector2_test.cpp
@@ -503,6 +503,153 @@ TEST(Vector2, functions)
         EXPECT_EQ(0, rot.getY());
     }
 
+
+    // TODO: cross, dot
+}
+
+/* ************************************************************************ */
+
+TEST(Vector2, freeOperators)
+{
+    {
+        const Vector2<float> vec1(5.3f, 8.9f);
+        const Vector2<float> vec2(3.3f, 1.2f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+
+        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
+
+        const auto vec3 = vec1 + vec2;
+        const auto vec4 = vec2 + vec1;
+
+        EXPECT_FLOAT_EQ(5.3f + 3.3f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f + 1.2f, vec3.getY());
+
+        EXPECT_FLOAT_EQ(3.3f + 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(1.2f + 8.9f, vec4.getY());
+    }
+
+    {
+        const Vector2<float> vec1(5.3f, 8.9f);
+        const Vector2<float> vec2(3.3f, 1.2f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+
+        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
+
+        const auto vec3 = vec1 - vec2;
+        const auto vec4 = vec2 - vec1;
+
+        EXPECT_FLOAT_EQ(5.3f - 3.3f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f - 1.2f, vec3.getY());
+
+        EXPECT_FLOAT_EQ(3.3f - 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(1.2f - 8.9f, vec4.getY());
+    }
+
+    {
+        const Vector2<float> vec1(5.3f, 8.9f);
+        const Vector2<float> vec2(3.3f, 1.2f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+
+        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
+
+        const auto vec3 = vec1 * vec2;
+        const auto vec4 = vec2 * vec1;
+
+        EXPECT_FLOAT_EQ(5.3f * 3.3f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f * 1.2f, vec3.getY());
+
+        EXPECT_FLOAT_EQ(3.3f * 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(1.2f * 8.9f, vec4.getY());
+    }
+
+    {
+        const Vector2<float> vec1(5.3f, 8.9f);
+        const Vector2<float> vec2(3.3f, 1.2f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+
+        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
+
+        const auto vec3 = vec1 / vec2;
+        const auto vec4 = vec2 / vec1;
+
+        EXPECT_FLOAT_EQ(5.3f / 3.3f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f / 1.2f, vec3.getY());
+
+        EXPECT_FLOAT_EQ(3.3f / 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(1.2f / 8.9f, vec4.getY());
+    }
+
+    {
+        const Vector2<float> vec1(5.3f, 8.9f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+
+        const auto vec3 = vec1 * 3.2f;
+        const auto vec4 = 3.2f * vec1;
+
+        EXPECT_FLOAT_EQ(5.3f * 3.2f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f * 3.2f, vec3.getY());
+
+        EXPECT_FLOAT_EQ(3.2f * 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(3.2f * 8.9f, vec4.getY());
+    }
+
+    {
+        const Vector2<float> vec1(5.3f, 8.9f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+
+        const auto vec3 = vec1 / 3.2f;
+        const auto vec4 = 3.2f / vec1;
+
+        EXPECT_FLOAT_EQ(5.3f / 3.2f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f / 3.2f, vec3.getY());
+
+        EXPECT_FLOAT_EQ(3.2f / 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(3.2f / 8.9f, vec4.getY());
+    }
+
+    {
+        const Vector2<float> vec1(5.3f, 8.9f);
+        const Vector2<float> vec2(5.3f, 8.9f);
+        const Vector2<float> vec3(1.3f, 8.9f);
+        const Vector2<float> vec4(5.3f, 0.9f);
+
+        EXPECT_EQ(vec1, vec1);
+        EXPECT_EQ(vec1, vec2);
+        EXPECT_NE(vec1, vec3);
+        EXPECT_NE(vec1, vec4);
+
+        EXPECT_EQ(vec2, vec1);
+        EXPECT_EQ(vec2, vec2);
+        EXPECT_NE(vec2, vec3);
+        EXPECT_NE(vec2, vec4);
+
+        EXPECT_NE(vec3, vec1);
+        EXPECT_NE(vec3, vec2);
+        EXPECT_EQ(vec3, vec3);
+        EXPECT_NE(vec3, vec4);
+
+        EXPECT_NE(vec4, vec1);
+        EXPECT_NE(vec4, vec2);
+        EXPECT_NE(vec4, vec3);
+        EXPECT_EQ(vec4, vec4);
+    }
+
 }
 
 /* ************************************************************************ */

From 97b0a25bc5bb484f8444d625a73d0088bf6ee007 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Fatka?= <fatkaj@ntis.zcu.cz>
Date: Fri, 17 Mar 2017 17:25:58 +0100
Subject: [PATCH 05/11] The math::Vector3 coverage improvement.

---
 include/cece/math/Vector3.hpp   | 389 ++++++-----------
 unittests/math/CMakeLists.txt   |   2 +-
 unittests/math/Vector3_test.cpp | 753 +++++++++++++++++++++++++++++---
 3 files changed, 828 insertions(+), 316 deletions(-)

diff --git a/include/cece/math/Vector3.hpp b/include/cece/math/Vector3.hpp
index 93bce5d..699fdf1 100644
--- a/include/cece/math/Vector3.hpp
+++ b/include/cece/math/Vector3.hpp
@@ -66,6 +66,20 @@ class Vector3
     using ValueTypeSq = decltype(std::declval<T>() * std::declval<T>());
 
 
+// Public Data Members
+public:
+
+
+    /// X coordinate.
+    T x;
+
+    /// Y coordinate.
+    T y;
+
+    /// Z coordinate.
+    T z;
+
+
 // Public Ctors
 public:
 
@@ -316,14 +330,6 @@ class Vector3
 public:
 
 
-    /**
-     * @brief      Returns X coordinate.
-     *
-     * @return     Reference to X coordinate.
-     */
-    T& x() noexcept;
-
-
     /**
      * @brief      Returns X coordinate.
      *
@@ -340,14 +346,6 @@ class Vector3
     void setX(T x) noexcept;
 
 
-    /**
-     * @brief      Returns Y coordinate.
-     *
-     * @return     Referent co Y coordinate.
-     */
-    T& y() noexcept;
-
-
     /**
      * @brief      Returns Y coordinate.
      *
@@ -364,14 +362,6 @@ class Vector3
     void setY(T y) noexcept;
 
 
-    /**
-     * @brief      Returns Z coordinate.
-     *
-     * @return     Referent co Z coordinate.
-     */
-    T& z() noexcept;
-
-
     /**
      * @brief      Returns Z coordinate.
      *
@@ -442,16 +432,6 @@ class Vector3
     ValueTypeSq getLengthSquared() const noexcept;
 
 
-    /**
-     * @brief      Calculate dot of two vectors.
-     *
-     * @param      rhs   Second vector.
-     *
-     * @return     Dot product.
-     */
-    ValueTypeSq dot(const Vector3& rhs) const noexcept;
-
-
     /**
      * @brief      Calculate vectors squared distance.
      *
@@ -502,19 +482,6 @@ class Vector3
      */
     static Vector3 createSingle(T val) noexcept;
 
-
-// Private Data Members
-private:
-
-    /// X coordinate.
-    T m_x;
-
-    /// Y coordinate.
-    T m_y;
-
-    /// Z coordinate.
-    T m_z;
-
 };
 
 /* ************************************************************************ */
@@ -543,40 +510,6 @@ operator+(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
-/**
- * @brief      Addition operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector3.
- * @tparam     T2    Type of second operand.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const Vector3<T1>& lhs, T2 rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Addition operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second Vector3.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(T1 lhs, const Vector3<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
 /**
  * @brief      Substract operator.
  *
@@ -594,40 +527,6 @@ operator-(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
-/**
- * @brief      Substract operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector3.
- * @tparam     T2    Type of second operand.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const Vector3<T1>& lhs, T2 rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Substract operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second Vector3.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(T1 lhs, const Vector3<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
 /**
  * @brief      Multiplication operator.
  *
@@ -746,6 +645,22 @@ inline bool operator==(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    The first type.
+ * @tparam     T2    The second type.
+ *
+ * @return     Comparision result.
+ */
+template<typename T1, typename T2>
+bool operator!=(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
 /**
  * @brief      Calculate cross product of two vectors.
  *
@@ -758,12 +673,28 @@ inline bool operator==(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
  * @return     Cross product.
  */
 template<typename T1, typename T2>
-inline
 Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
 cross(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
+/**
+ * @brief      Calculate dot product of two vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    The first type.
+ * @tparam     T2    The second type.
+ *
+ * @return     Dot product.
+ */
+template<typename T1, typename T2>
+decltype(std::declval<T1>() * std::declval<T2>())
+dot(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
+
+/* ************************************************************************ */
+
 }
 }
 
@@ -778,9 +709,9 @@ namespace math {
 
 template<typename T>
 inline Vector3<T>::Vector3() noexcept
-    : m_x{}
-    , m_y{}
-    , m_z{}
+    : x{}
+    , y{}
+    , z{}
 {
     // Nothing to do
 }
@@ -789,9 +720,9 @@ inline Vector3<T>::Vector3() noexcept
 
 template<typename T>
 inline Vector3<T>::Vector3(T x, T y, T z) noexcept
-    : m_x(x)
-    , m_y(y)
-    , m_z(z)
+    : x(x)
+    , y(y)
+    , z(z)
 {
     // Nothing to do
 }
@@ -800,9 +731,9 @@ inline Vector3<T>::Vector3(T x, T y, T z) noexcept
 
 template<typename T>
 inline Vector3<T>::Vector3(Zero_t zero) noexcept
-    : m_x{}
-    , m_y{}
-    , m_z{}
+    : x{}
+    , y{}
+    , z{}
 {
     // Nothing to do
 }
@@ -811,9 +742,9 @@ inline Vector3<T>::Vector3(Zero_t zero) noexcept
 
 template<typename T>
 inline Vector3<T>::Vector3(const Vector3& src) noexcept
-    : m_x{src.getX()}
-    , m_y{src.getY()}
-    , m_z{src.getZ()}
+    : x{src.getX()}
+    , y{src.getY()}
+    , z{src.getZ()}
 {
     // Nothing to do
 }
@@ -822,9 +753,9 @@ inline Vector3<T>::Vector3(const Vector3& src) noexcept
 
 template<typename T>
 inline Vector3<T>::Vector3(Vector3&& src) noexcept
-    : m_x{std::move(src.m_x)}
-    , m_y{std::move(src.m_y)}
-    , m_z{std::move(src.m_z)}
+    : x{std::move(src.x)}
+    , y{std::move(src.y)}
+    , z{std::move(src.z)}
 {
     // Nothing to do
 }
@@ -834,9 +765,9 @@ inline Vector3<T>::Vector3(Vector3&& src) noexcept
 template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
 inline Vector3<T>::Vector3(const Vector3<T2>& rhs) noexcept
-    : m_x(rhs.getX())
-    , m_y(rhs.getY())
-    , m_z(rhs.getZ())
+    : x(rhs.getX())
+    , y(rhs.getY())
+    , z(rhs.getZ())
 {
     // Nothing to do
 }
@@ -846,9 +777,9 @@ inline Vector3<T>::Vector3(const Vector3<T2>& rhs) noexcept
 template<typename T>
 inline Vector3<T>& Vector3<T>::operator=(Zero_t zero) noexcept
 {
-    m_x = T{};
-    m_y = T{};
-    m_z = T{};
+    x = T{};
+    y = T{};
+    z = T{};
 
     return *this;
 }
@@ -858,9 +789,9 @@ inline Vector3<T>& Vector3<T>::operator=(Zero_t zero) noexcept
 template<typename T>
 inline Vector3<T>& Vector3<T>::operator=(const Vector3& src) noexcept
 {
-    m_x = src.m_x;
-    m_y = src.m_y;
-    m_z = src.m_z;
+    x = src.x;
+    y = src.y;
+    z = src.z;
 
     return *this;
 }
@@ -870,9 +801,9 @@ inline Vector3<T>& Vector3<T>::operator=(const Vector3& src) noexcept
 template<typename T>
 inline Vector3<T>& Vector3<T>::operator=(Vector3&& src) noexcept
 {
-    m_x = std::move(src.m_x);
-    m_y = std::move(src.m_y);
-    m_z = std::move(src.m_z);
+    x = std::move(src.x);
+    y = std::move(src.y);
+    z = std::move(src.z);
 
     return *this;
 }
@@ -883,9 +814,9 @@ template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
 inline Vector3<T>& Vector3<T>::operator=(const Vector3<T2>& src) noexcept
 {
-    m_x = T(src.getX());
-    m_y = T(src.getY());
-    m_z = T(src.getZ());
+    x = T(src.getX());
+    y = T(src.getY());
+    z = T(src.getZ());
 
     return *this;
 }
@@ -903,7 +834,7 @@ inline Vector3<T> Vector3<T>::operator+() const noexcept
 template<typename T>
 inline Vector3<T> Vector3<T>::operator-() const noexcept
 {
-    return {-m_x, -m_y, -m_z};
+    return {-x, -y, -z};
 }
 
 /* ************************************************************************ */
@@ -915,9 +846,9 @@ template<typename T1, typename std::enable_if<std::is_same<
 >::value>::type*>
 inline Vector3<T>& Vector3<T>::operator+=(const Vector3<T1>& rhs) noexcept
 {
-    m_x += rhs.getX();
-    m_y += rhs.getY();
-    m_z += rhs.getZ();
+    x += rhs.getX();
+    y += rhs.getY();
+    z += rhs.getZ();
 
     return *this;
 }
@@ -931,9 +862,9 @@ template<typename T1, typename std::enable_if<std::is_same<
 >::value>::type*>
 inline Vector3<T>& Vector3<T>::operator-=(const Vector3<T1>& rhs) noexcept
 {
-    m_x -= rhs.getX();
-    m_y -= rhs.getY();
-    m_z -= rhs.getZ();
+    x -= rhs.getX();
+    y -= rhs.getY();
+    z -= rhs.getZ();
 
     return *this;
 }
@@ -950,9 +881,9 @@ template<typename T1, typename std::enable_if<std::is_same<
 >::value>::type*>
 inline Vector3<T>& Vector3<T>::operator*=(T1 rhs) noexcept
 {
-    m_x *= rhs;
-    m_y *= rhs;
-    m_z *= rhs;
+    x *= rhs;
+    y *= rhs;
+    z *= rhs;
 
     return *this;
 }
@@ -969,9 +900,9 @@ template<typename T1, typename std::enable_if<std::is_same<
 >::value>::type*>
 inline Vector3<T>& Vector3<T>::operator*=(const Vector3<T1>& rhs) noexcept
 {
-    m_x *= rhs.getX();
-    m_y *= rhs.getY();
-    m_z *= rhs.getZ();
+    x *= rhs.getX();
+    y *= rhs.getY();
+    z *= rhs.getZ();
 
     return *this;
 }
@@ -988,9 +919,9 @@ template<typename T1, typename std::enable_if<std::is_same<
 >::value>::type*>
 inline Vector3<T>& Vector3<T>::operator/=(T1 rhs) noexcept
 {
-    m_x /= rhs;
-    m_y /= rhs;
-    m_z /= rhs;
+    x /= rhs;
+    y /= rhs;
+    z /= rhs;
 
     return *this;
 }
@@ -1007,9 +938,9 @@ template<typename T1, typename std::enable_if<std::is_same<
 >::value>::type*>
 inline Vector3<T>& Vector3<T>::operator/=(const Vector3<T1>& rhs) noexcept
 {
-    m_x /= rhs.getX();
-    m_y /= rhs.getY();
-    m_z /= rhs.getZ();
+    x /= rhs.getX();
+    y /= rhs.getY();
+    z /= rhs.getZ();
 
     return *this;
 }
@@ -1021,7 +952,7 @@ inline T& Vector3<T>::operator[](int pos) noexcept
 {
     CECE_ASSERT(pos >= 0);
     CECE_ASSERT(pos < 3);
-    return (&m_x)[pos];
+    return (&x)[pos];
 }
 
 /* ************************************************************************ */
@@ -1031,15 +962,7 @@ inline const T& Vector3<T>::operator[](int pos) const noexcept
 {
     CECE_ASSERT(pos >= 0);
     CECE_ASSERT(pos < 3);
-    return (&m_x)[pos];
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline T& Vector3<T>::x() noexcept
-{
-    return m_x;
+    return (&x)[pos];
 }
 
 /* ************************************************************************ */
@@ -1047,7 +970,7 @@ inline T& Vector3<T>::x() noexcept
 template<typename T>
 inline const T& Vector3<T>::getX() const noexcept
 {
-    return m_x;
+    return x;
 }
 
 /* ************************************************************************ */
@@ -1055,15 +978,7 @@ inline const T& Vector3<T>::getX() const noexcept
 template<typename T>
 inline void Vector3<T>::setX(T x) noexcept
 {
-    m_x = std::move(x);
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline T& Vector3<T>::y() noexcept
-{
-    return m_y;
+    this->x = std::move(x);
 }
 
 /* ************************************************************************ */
@@ -1071,7 +986,7 @@ inline T& Vector3<T>::y() noexcept
 template<typename T>
 inline const T& Vector3<T>::getY() const noexcept
 {
-    return m_y;
+    return y;
 }
 
 /* ************************************************************************ */
@@ -1079,15 +994,7 @@ inline const T& Vector3<T>::getY() const noexcept
 template<typename T>
 inline void Vector3<T>::setY(T y) noexcept
 {
-    m_y = std::move(y);
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline T& Vector3<T>::z() noexcept
-{
-    return m_z;
+    this->y = std::move(y);
 }
 
 /* ************************************************************************ */
@@ -1095,7 +1002,7 @@ inline T& Vector3<T>::z() noexcept
 template<typename T>
 inline const T& Vector3<T>::getZ() const noexcept
 {
-    return m_z;
+    return z;
 }
 
 /* ************************************************************************ */
@@ -1103,7 +1010,7 @@ inline const T& Vector3<T>::getZ() const noexcept
 template<typename T>
 inline void Vector3<T>::setZ(T z) noexcept
 {
-    m_z = std::move(z);
+    this->z = std::move(z);
 }
 
 /* ************************************************************************ */
@@ -1149,19 +1056,11 @@ inline typename Vector3<T>::ValueType Vector3<T>::getLength() const noexcept
 
 template<typename T>
 inline typename Vector3<T>::ValueTypeSq Vector3<T>::getLengthSquared() const noexcept
-{
-    return dot(*this);
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline typename Vector3<T>::ValueTypeSq Vector3<T>::dot(const Vector3& rhs) const noexcept
 {
     return
-        getX() * rhs.getX() +
-        getY() * rhs.getY() +
-        getZ() * rhs.getZ()
+        getX() * getX() +
+        getY() * getY() +
+        getZ() * getZ()
     ;
 }
 
@@ -1217,32 +1116,6 @@ operator+(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const Vector3<T1>& lhs, T2 rhs) noexcept
-{
-    return {
-        lhs.getX() + rhs,
-        lhs.getY() + rhs,
-        lhs.getZ() + rhs
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(T1 lhs, const Vector3<T2>& rhs) noexcept
-{
-    return {
-        lhs + rhs.getX(),
-        lhs + rhs.getY(),
-        lhs + rhs.getZ()
-    };
-}
-
-/* ************************************************************************ */
-
 template<typename T1, typename T2>
 inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
 operator-(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
@@ -1256,32 +1129,6 @@ operator-(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const Vector3<T1>& lhs, T2 rhs) noexcept
-{
-    return {
-        lhs.getX() - rhs,
-        lhs.getY() - rhs,
-        lhs.getZ() - rhs
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(T1 lhs, const Vector3<T2>& rhs) noexcept
-{
-    return {
-        lhs - rhs.getX(),
-        lhs - rhs.getY(),
-        lhs - rhs.getZ()
-    };
-}
-
-/* ************************************************************************ */
-
 template<typename T1, typename T2>
 inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
 operator*(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
@@ -1372,6 +1219,14 @@ inline bool operator==(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
 
 /* ************************************************************************ */
 
+template<typename T1, typename T2>
+inline bool operator!=(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
+{
+    return !operator==(lhs, rhs);
+}
+
+/* ************************************************************************ */
+
 template<typename T1, typename T2>
 inline
 Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
@@ -1386,6 +1241,20 @@ cross(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
 
 /* ************************************************************************ */
 
+template<typename T1, typename T2>
+inline
+decltype(std::declval<T1>() * std::declval<T2>())
+dot(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
+{
+    return {
+        lhs.getX() * rhs.getX() +
+        lhs.getY() * rhs.getY() +
+        lhs.getZ() * rhs.getZ()
+    };
+}
+
+/* ************************************************************************ */
+
 }
 }
 
diff --git a/unittests/math/CMakeLists.txt b/unittests/math/CMakeLists.txt
index d5a5575..4893905 100644
--- a/unittests/math/CMakeLists.txt
+++ b/unittests/math/CMakeLists.txt
@@ -23,7 +23,7 @@
 #                                                                           #
 # ######################################################################### #
 
-cece_add_test(core
+cece_add_test(math
     SOURCES
         Vector_test.cpp
         Vector2_test.cpp
diff --git a/unittests/math/Vector3_test.cpp b/unittests/math/Vector3_test.cpp
index 0e30b96..e300661 100644
--- a/unittests/math/Vector3_test.cpp
+++ b/unittests/math/Vector3_test.cpp
@@ -36,7 +36,7 @@ using namespace cece::math;
 
 /* ************************************************************************ */
 
-TEST(Vector3, ctor)
+TEST(Vector3, ctorDefault)
 {
     {
         Vector3<int> vec;
@@ -49,6 +49,44 @@ TEST(Vector3, ctor)
         EXPECT_EQ(0, vec[2]);
     }
 
+    {
+        Vector3<unsigned int> vec;
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+    }
+
+    {
+        Vector3<float> vec;
+
+        EXPECT_FLOAT_EQ(0.0f, vec.getX());
+        EXPECT_FLOAT_EQ(0.0f, vec.getY());
+        EXPECT_FLOAT_EQ(0.0f, vec.getZ());
+        EXPECT_FLOAT_EQ(0.0f, vec[0]);
+        EXPECT_FLOAT_EQ(0.0f, vec[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec[2]);
+    }
+
+    {
+        Vector3<double> vec;
+
+        EXPECT_DOUBLE_EQ(0.0, vec.getX());
+        EXPECT_DOUBLE_EQ(0.0, vec.getY());
+        EXPECT_DOUBLE_EQ(0.0, vec.getZ());
+        EXPECT_DOUBLE_EQ(0.0, vec[0]);
+        EXPECT_DOUBLE_EQ(0.0, vec[1]);
+        EXPECT_DOUBLE_EQ(0.0, vec[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, ctorZero)
+{
     {
         Vector3<int> vec(Zero);
 
@@ -60,6 +98,66 @@ TEST(Vector3, ctor)
         EXPECT_EQ(0, vec[2]);
     }
 
+    {
+        Vector3<unsigned int> vec(Zero);
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+    }
+
+    {
+        Vector3<float> vec(Zero);
+
+        EXPECT_FLOAT_EQ(0.0f, vec.getX());
+        EXPECT_FLOAT_EQ(0.0f, vec.getY());
+        EXPECT_FLOAT_EQ(0.0f, vec.getZ());
+        EXPECT_FLOAT_EQ(0.0f, vec[0]);
+        EXPECT_FLOAT_EQ(0.0f, vec[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec[2]);
+    }
+
+    {
+        Vector3<double> vec(Zero);
+
+        EXPECT_DOUBLE_EQ(0.0, vec.getX());
+        EXPECT_DOUBLE_EQ(0.0, vec.getY());
+        EXPECT_DOUBLE_EQ(0.0, vec.getZ());
+        EXPECT_DOUBLE_EQ(0.0, vec[0]);
+        EXPECT_DOUBLE_EQ(0.0, vec[1]);
+        EXPECT_DOUBLE_EQ(0.0, vec[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, ctorElements)
+{
+    {
+        Vector3<int> vec = {1, 3, -8};
+
+        EXPECT_EQ(1, vec.getX());
+        EXPECT_EQ(3, vec.getY());
+        EXPECT_EQ(-8, vec.getZ());
+        EXPECT_EQ(1, vec[0]);
+        EXPECT_EQ(3, vec[1]);
+        EXPECT_EQ(-8, vec[2]);
+    }
+
+    {
+        Vector3<unsigned int> vec = {1, 3, 8};
+
+        EXPECT_EQ(1, vec.getX());
+        EXPECT_EQ(3, vec.getY());
+        EXPECT_EQ(8, vec.getZ());
+        EXPECT_EQ(1, vec[0]);
+        EXPECT_EQ(3, vec[1]);
+        EXPECT_EQ(8, vec[2]);
+    }
+
     {
         Vector3<float> vec = {1.2f, 3.0f, -8.1f};
 
@@ -71,6 +169,62 @@ TEST(Vector3, ctor)
         EXPECT_FLOAT_EQ(-8.1f, vec[2]);
     }
 
+    {
+        Vector3<double> vec = {1.2, 3.0, -8.1};
+
+        EXPECT_DOUBLE_EQ(1.2, vec.getX());
+        EXPECT_DOUBLE_EQ(3.0, vec.getY());
+        EXPECT_DOUBLE_EQ(-8.1, vec.getZ());
+        EXPECT_DOUBLE_EQ(1.2, vec[0]);
+        EXPECT_DOUBLE_EQ(3.0, vec[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, ctorCopy)
+{
+    {
+        const Vector3<int> vec1 = {1, 3, -8};
+
+        EXPECT_EQ(1, vec1.getX());
+        EXPECT_EQ(3, vec1.getY());
+        EXPECT_EQ(-8, vec1.getZ());
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+        EXPECT_EQ(-8, vec1[2]);
+
+        Vector3<float> vec2(vec1);
+
+        EXPECT_FLOAT_EQ(1.0f, vec2.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(-8.0f, vec2.getZ());
+        EXPECT_FLOAT_EQ(1.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(-8.0f, vec2[2]);
+    }
+
+    {
+        const Vector3<unsigned int> vec1 = {1, 3, 8};
+
+        EXPECT_EQ(1, vec1.getX());
+        EXPECT_EQ(3, vec1.getY());
+        EXPECT_EQ(8, vec1.getZ());
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+        EXPECT_EQ(8, vec1[2]);
+
+        Vector3<int> vec2(vec1);
+
+        EXPECT_EQ(1, vec2.getX());
+        EXPECT_EQ(3, vec2.getY());
+        EXPECT_EQ(8, vec2.getZ());
+        EXPECT_EQ(1, vec2[0]);
+        EXPECT_EQ(3, vec2[1]);
+        EXPECT_EQ(8, vec2[2]);
+    }
+
     {
         const Vector3<float> vec1 = {1.2f, 3.0f, -8.1f};
 
@@ -91,6 +245,72 @@ TEST(Vector3, ctor)
         EXPECT_FLOAT_EQ(-8.1f, vec2[2]);
     }
 
+    {
+        const Vector3<double> vec1 = {1.2, 3.0, -8.1};
+
+        EXPECT_DOUBLE_EQ(1.2, vec1.getX());
+        EXPECT_DOUBLE_EQ(3.0, vec1.getY());
+        EXPECT_DOUBLE_EQ(-8.1, vec1.getZ());
+        EXPECT_DOUBLE_EQ(1.2, vec1[0]);
+        EXPECT_DOUBLE_EQ(3.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec1[2]);
+
+        Vector3<double> vec2(vec1);
+
+        EXPECT_DOUBLE_EQ(1.2, vec2.getX());
+        EXPECT_DOUBLE_EQ(3.0, vec2.getY());
+        EXPECT_DOUBLE_EQ(-8.1, vec2.getZ());
+        EXPECT_DOUBLE_EQ(1.2, vec2[0]);
+        EXPECT_DOUBLE_EQ(3.0, vec2[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec2[2]);
+    }
+
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, ctorMove)
+{
+    {
+        Vector3<int> vec1 = {1, 3, -8};
+
+        EXPECT_EQ(1, vec1.getX());
+        EXPECT_EQ(3, vec1.getY());
+        EXPECT_EQ(-8, vec1.getZ());
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+        EXPECT_EQ(-8, vec1[2]);
+
+        Vector3<int> vec2(std::move(vec1));
+
+        EXPECT_EQ(1, vec2.getX());
+        EXPECT_EQ(3, vec2.getY());
+        EXPECT_EQ(-8, vec2.getZ());
+        EXPECT_EQ(1, vec2[0]);
+        EXPECT_EQ(3, vec2[1]);
+        EXPECT_EQ(-8, vec2[2]);
+    }
+
+    {
+        Vector3<unsigned int> vec1 = {1, 3, 8};
+
+        EXPECT_EQ(1, vec1.getX());
+        EXPECT_EQ(3, vec1.getY());
+        EXPECT_EQ(8, vec1.getZ());
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+        EXPECT_EQ(8, vec1[2]);
+
+        Vector3<unsigned int> vec2(std::move(vec1));
+
+        EXPECT_EQ(1, vec2.getX());
+        EXPECT_EQ(3, vec2.getY());
+        EXPECT_EQ(8, vec2.getZ());
+        EXPECT_EQ(1, vec2[0]);
+        EXPECT_EQ(3, vec2[1]);
+        EXPECT_EQ(8, vec2[2]);
+    }
+
     {
         Vector3<float> vec1 = {1.2f, 3.0f, -8.1f};
 
@@ -112,29 +332,29 @@ TEST(Vector3, ctor)
     }
 
     {
-        const Vector3<int> vec1 = {1, 3, -8};
-
-        EXPECT_EQ(1, vec1.getX());
-        EXPECT_EQ(3, vec1.getY());
-        EXPECT_EQ(-8, vec1.getZ());
-        EXPECT_EQ(1, vec1[0]);
-        EXPECT_EQ(3, vec1[1]);
-        EXPECT_EQ(-8, vec1[2]);
-
-        Vector3<float> vec2(vec1);
-
-        EXPECT_FLOAT_EQ(1.0f, vec2.getX());
-        EXPECT_FLOAT_EQ(3.0f, vec2.getY());
-        EXPECT_FLOAT_EQ(-8.0f, vec2.getZ());
-        EXPECT_FLOAT_EQ(1.0f, vec2[0]);
-        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
-        EXPECT_FLOAT_EQ(-8.0f, vec2[2]);
+        Vector3<double> vec1 = {1.2, 3.0, -8.1};
+
+        EXPECT_DOUBLE_EQ(1.2, vec1.getX());
+        EXPECT_DOUBLE_EQ(3.0, vec1.getY());
+        EXPECT_DOUBLE_EQ(-8.1, vec1.getZ());
+        EXPECT_DOUBLE_EQ(1.2, vec1[0]);
+        EXPECT_DOUBLE_EQ(3.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec1[2]);
+
+        Vector3<double> vec2(std::move(vec1));
+
+        EXPECT_DOUBLE_EQ(1.2, vec2.getX());
+        EXPECT_DOUBLE_EQ(3.0, vec2.getY());
+        EXPECT_DOUBLE_EQ(-8.1, vec2.getZ());
+        EXPECT_DOUBLE_EQ(1.2, vec2[0]);
+        EXPECT_DOUBLE_EQ(3.0, vec2[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec2[2]);
     }
 }
 
 /* ************************************************************************ */
 
-TEST(Vector3, assignment)
+TEST(Vector3, assignmentZero)
 {
     {
         Vector3<int> vec{1, 1, 1};
@@ -151,12 +371,87 @@ TEST(Vector3, assignment)
     }
 
     {
-        Vector3<float> vec;
+        Vector3<unsigned int> vec{1, 1, 1};
+
+        EXPECT_EQ(1, vec[0]);
+        EXPECT_EQ(1, vec[1]);
+        EXPECT_EQ(1, vec[2]);
+
+        vec = Zero;
+
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+    }
+
+    {
+        Vector3<float> vec{1.0f, 1.0f, 1.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec[0]);
+        EXPECT_FLOAT_EQ(1.0f, vec[1]);
+        EXPECT_FLOAT_EQ(1.0f, vec[2]);
+
+        vec = Zero;
+
+        EXPECT_FLOAT_EQ(0.0f, vec[0]);
+        EXPECT_FLOAT_EQ(0.0f, vec[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec[2]);
+    }
+
+    {
+        Vector3<double> vec{1.0, 1.0, 1.0};
+
+        EXPECT_DOUBLE_EQ(1.0, vec[0]);
+        EXPECT_DOUBLE_EQ(1.0, vec[1]);
+        EXPECT_DOUBLE_EQ(1.0, vec[2]);
+
+        vec = Zero;
+
+        EXPECT_DOUBLE_EQ(0.0, vec[0]);
+        EXPECT_DOUBLE_EQ(0.0, vec[1]);
+        EXPECT_DOUBLE_EQ(0.0, vec[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, assignmentElements)
+{
+    {
+        Vector3<int> vec;
+
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+
+        vec = {1, 3, -8};
+
+        EXPECT_EQ(1, vec[0]);
+        EXPECT_EQ(3, vec[1]);
+        EXPECT_EQ(-8, vec[2]);
+    }
+
+    {
+        Vector3<unsigned int> vec;
 
         EXPECT_EQ(0, vec[0]);
         EXPECT_EQ(0, vec[1]);
         EXPECT_EQ(0, vec[2]);
 
+        vec = {1, 3, 8};
+
+        EXPECT_EQ(1, vec[0]);
+        EXPECT_EQ(3, vec[1]);
+        EXPECT_EQ(8, vec[2]);
+    }
+
+    {
+        Vector3<float> vec;
+
+        EXPECT_FLOAT_EQ(0.0f, vec[0]);
+        EXPECT_FLOAT_EQ(0.0f, vec[1]);
+        EXPECT_FLOAT_EQ(0.0f, vec[2]);
+
         vec = {1.2f, 3.0f, -8.1f};
 
         EXPECT_FLOAT_EQ(1.2f, vec[0]);
@@ -164,6 +459,57 @@ TEST(Vector3, assignment)
         EXPECT_FLOAT_EQ(-8.1f, vec[2]);
     }
 
+    {
+        Vector3<double> vec;
+
+        EXPECT_DOUBLE_EQ(0.0, vec[0]);
+        EXPECT_DOUBLE_EQ(0.0, vec[1]);
+        EXPECT_DOUBLE_EQ(0.0, vec[2]);
+
+        vec = {1.2, 3.0, -8.1};
+
+        EXPECT_DOUBLE_EQ(1.2, vec[0]);
+        EXPECT_DOUBLE_EQ(3.0, vec[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, assignmentCopy)
+{
+    {
+        const Vector3<int> vec1 = {1, 3, -8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+        EXPECT_EQ(-8, vec1[2]);
+
+        Vector3<float> vec2;
+
+        vec2 = vec1;
+
+        EXPECT_FLOAT_EQ(1.0, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+        EXPECT_FLOAT_EQ(-8.0f, vec2[2]);
+    }
+
+    {
+        const Vector3<unsigned int> vec1 = {1, 3, 8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+        EXPECT_EQ(8, vec1[2]);
+
+        Vector3<int> vec2;
+
+        vec2 = vec1;
+
+        EXPECT_EQ(1, vec2[0]);
+        EXPECT_EQ(3, vec2[1]);
+        EXPECT_EQ(8, vec2[2]);
+    }
+
     {
         const Vector3<float> vec1 = {1.2f, 3.0f, -8.1f};
 
@@ -180,6 +526,59 @@ TEST(Vector3, assignment)
         EXPECT_FLOAT_EQ(-8.1f, vec2[2]);
     }
 
+    {
+        const Vector3<double> vec1 = {1.2, 3.0, -8.1};
+
+        EXPECT_DOUBLE_EQ(1.2, vec1[0]);
+        EXPECT_DOUBLE_EQ(3.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec1[2]);
+
+        Vector3<double> vec2;
+
+        vec2 = vec1;
+
+        EXPECT_DOUBLE_EQ(1.2, vec2[0]);
+        EXPECT_DOUBLE_EQ(3.0, vec2[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec2[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, assignmentMove)
+{
+    {
+        Vector3<int> vec1 = {1, 3, -8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+        EXPECT_EQ(-8, vec1[2]);
+
+        Vector3<int> vec2;
+
+        vec2 = std::move(vec1);
+
+        EXPECT_EQ(1, vec2[0]);
+        EXPECT_EQ(3, vec2[1]);
+        EXPECT_EQ(-8, vec2[2]);
+    }
+
+    {
+        Vector3<unsigned int> vec1 = {1, 3, 8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+        EXPECT_EQ(8, vec1[2]);
+
+        Vector3<unsigned int> vec2;
+
+        vec2 = std::move(vec1);
+
+        EXPECT_EQ(1, vec2[0]);
+        EXPECT_EQ(3, vec2[1]);
+        EXPECT_EQ(8, vec2[2]);
+    }
+
     {
         Vector3<float> vec1 = {1.2f, 3.0f, -8.1f};
 
@@ -197,19 +596,19 @@ TEST(Vector3, assignment)
     }
 
     {
-        const Vector3<int> vec1 = {1, 3, -8};
+        Vector3<double> vec1 = {1.2, 3.0, -8.1};
 
-        EXPECT_EQ(1, vec1[0]);
-        EXPECT_EQ(3, vec1[1]);
-        EXPECT_EQ(-8, vec1[2]);
+        EXPECT_DOUBLE_EQ(1.2, vec1[0]);
+        EXPECT_DOUBLE_EQ(3.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec1[2]);
 
-        Vector3<float> vec2;
+        Vector3<double> vec2;
 
-        vec2 = vec1;
+        vec2 = std::move(vec1);
 
-        EXPECT_FLOAT_EQ(1.0, vec2[0]);
-        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
-        EXPECT_FLOAT_EQ(-8.0f, vec2[2]);
+        EXPECT_DOUBLE_EQ(1.2, vec2[0]);
+        EXPECT_DOUBLE_EQ(3.0, vec2[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec2[2]);
     }
 }
 
@@ -392,32 +791,6 @@ TEST(Vector3, memberFunctions)
         EXPECT_FLOAT_EQ(14, vec.getLengthSquared());
     }
 
-    {
-        const Vector3<float> vec;
-
-        EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
-    }
-
-    {
-        const Vector3<float> vec{1.0f, 2.0f, 3.0f};
-
-        EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
-    }
-
-    {
-        const Vector3<float> vec1;
-        const Vector3<float> vec2;
-
-        EXPECT_FLOAT_EQ(0, vec1.dot(vec2));
-    }
-
-    {
-        const Vector3<float> vec1{1.0f, 2.0f, 3.0f};
-        const Vector3<float> vec2{5.0f, 4.0f, 3.0f};
-
-        EXPECT_FLOAT_EQ(22, vec1.dot(vec2));
-    }
-
     {
         const Vector3<float> vec;
 
@@ -471,3 +844,273 @@ TEST(Vector3, memberFunctions)
 }
 
 /* ************************************************************************ */
+
+TEST(Vector3, mutators)
+{
+    {
+        Vector3<int> vec;
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+
+        vec.setX(100);
+
+        EXPECT_EQ(100, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+
+        vec.setY(50);
+
+        EXPECT_EQ(100, vec.getX());
+        EXPECT_EQ(50, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+
+        vec.setZ(10);
+
+        EXPECT_EQ(100, vec.getX());
+        EXPECT_EQ(50, vec.getY());
+        EXPECT_EQ(10, vec.getZ());
+    }
+
+    {
+        Vector3<int> vec;
+
+        EXPECT_EQ(0, vec.x);
+        EXPECT_EQ(0, vec.y);
+        EXPECT_EQ(0, vec.z);
+
+        vec.x = 100;
+
+        EXPECT_EQ(100, vec.x);
+        EXPECT_EQ(0, vec.y);
+        EXPECT_EQ(0, vec.z);
+
+        vec.y = 50;
+
+        EXPECT_EQ(100, vec.x);
+        EXPECT_EQ(50, vec.y);
+        EXPECT_EQ(0, vec.z);
+
+        vec.z = 10;
+
+        EXPECT_EQ(100, vec.x);
+        EXPECT_EQ(50, vec.y);
+        EXPECT_EQ(10, vec.z);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, functions)
+{
+    {
+        Vector3<float> vec1(0.94333f, 0.73733f, 0.92636f);
+        Vector3<float> vec2(0.16110f, 0.61872f, 0.21556f);
+
+        EXPECT_FLOAT_EQ(0.94333f, vec1.getX());
+        EXPECT_FLOAT_EQ(0.73733f, vec1.getY());
+        EXPECT_FLOAT_EQ(0.92636f, vec1.getZ());
+
+        EXPECT_FLOAT_EQ(0.16110f, vec2.getX());
+        EXPECT_FLOAT_EQ(0.61872f, vec2.getY());
+        EXPECT_FLOAT_EQ(0.21556f, vec2.getZ());
+
+        auto vec3 = cross(vec1, vec2);
+
+        EXPECT_FLOAT_EQ(0.73733f * 0.21556f - 0.92636f * 0.61872f, vec3.getX());
+        EXPECT_FLOAT_EQ(0.92636f * 0.16110f - 0.94333f * 0.21556f, vec3.getY());
+        EXPECT_FLOAT_EQ(0.94333f * 0.61872f - 0.73733f * 0.16110f, vec3.getZ());
+    }
+
+    {
+        Vector3<float> vec1(0.94333f, 0.73733f, 0.92636f);
+        Vector3<float> vec2(0.16110f, 0.61872f, 0.21556f);
+
+        EXPECT_FLOAT_EQ(0.94333f, vec1.getX());
+        EXPECT_FLOAT_EQ(0.73733f, vec1.getY());
+        EXPECT_FLOAT_EQ(0.92636f, vec1.getZ());
+
+        EXPECT_FLOAT_EQ(0.16110f, vec2.getX());
+        EXPECT_FLOAT_EQ(0.61872f, vec2.getY());
+        EXPECT_FLOAT_EQ(0.21556f, vec2.getZ());
+
+        auto res = dot(vec1, vec2);
+
+        EXPECT_FLOAT_EQ(
+            0.94333f * 0.16110f +
+            0.73733f * 0.61872f +
+            0.92636f * 0.21556f,
+            res
+        );
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, freeOperators)
+{
+    {
+        const Vector3<float> vec1(5.3f, 8.9f, -8.1f);
+        const Vector3<float> vec2(3.3f, 1.2f, 2.5f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+        EXPECT_FLOAT_EQ(-8.1f, vec1.getZ());
+
+        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
+        EXPECT_FLOAT_EQ(2.5f, vec2.getZ());
+
+        const auto vec3 = vec1 + vec2;
+        const auto vec4 = vec2 + vec1;
+
+        EXPECT_FLOAT_EQ(5.3f + 3.3f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f + 1.2f, vec3.getY());
+        EXPECT_FLOAT_EQ(-8.1f + 2.5f, vec3.getZ());
+
+        EXPECT_FLOAT_EQ(3.3f + 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(1.2f + 8.9f, vec4.getY());
+        EXPECT_FLOAT_EQ(2.5f + -8.1f, vec4.getZ());
+    }
+
+    {
+        const Vector3<float> vec1(5.3f, 8.9f, -8.1f);
+        const Vector3<float> vec2(3.3f, 1.2f, 2.5f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+        EXPECT_FLOAT_EQ(-8.1f, vec1.getZ());
+
+        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
+        EXPECT_FLOAT_EQ(2.5f, vec2.getZ());
+
+        const auto vec3 = vec1 - vec2;
+        const auto vec4 = vec2 - vec1;
+
+        EXPECT_FLOAT_EQ(5.3f - 3.3f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f - 1.2f, vec3.getY());
+        EXPECT_FLOAT_EQ(-8.1f - 2.5f, vec3.getZ());
+
+        EXPECT_FLOAT_EQ(3.3f - 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(1.2f - 8.9f, vec4.getY());
+        EXPECT_FLOAT_EQ(2.5f - -8.1f, vec4.getZ());
+    }
+
+    {
+        const Vector3<float> vec1(5.3f, 8.9f, -8.1f);
+        const Vector3<float> vec2(3.3f, 1.2f, 2.5f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+        EXPECT_FLOAT_EQ(-8.1f, vec1.getZ());
+
+        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
+        EXPECT_FLOAT_EQ(2.5f, vec2.getZ());
+
+        const auto vec3 = vec1 * vec2;
+        const auto vec4 = vec2 * vec1;
+
+        EXPECT_FLOAT_EQ(5.3f * 3.3f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f * 1.2f, vec3.getY());
+        EXPECT_FLOAT_EQ(-8.1f * 2.5f, vec3.getZ());
+
+        EXPECT_FLOAT_EQ(3.3f * 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(1.2f * 8.9f, vec4.getY());
+        EXPECT_FLOAT_EQ(2.5f * -8.1f, vec4.getZ());
+    }
+
+    {
+        const Vector3<float> vec1(5.3f, 8.9f, -8.1f);
+        const Vector3<float> vec2(3.3f, 1.2f, 2.5f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+        EXPECT_FLOAT_EQ(-8.1f, vec1.getZ());
+
+        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
+        EXPECT_FLOAT_EQ(2.5f, vec2.getZ());
+
+        const auto vec3 = vec1 / vec2;
+        const auto vec4 = vec2 / vec1;
+
+        EXPECT_FLOAT_EQ(5.3f / 3.3f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f / 1.2f, vec3.getY());
+        EXPECT_FLOAT_EQ(-8.1f / 2.5f, vec3.getZ());
+
+        EXPECT_FLOAT_EQ(3.3f / 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(1.2f / 8.9f, vec4.getY());
+        EXPECT_FLOAT_EQ(2.5f / -8.1f, vec4.getZ());
+    }
+
+    {
+        const Vector3<float> vec1(5.3f, 8.9f, -8.1f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+        EXPECT_FLOAT_EQ(-8.1f, vec1.getZ());
+
+        const auto vec3 = vec1 * 3.2f;
+        const auto vec4 = 3.2f * vec1;
+
+        EXPECT_FLOAT_EQ(5.3f * 3.2f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f * 3.2f, vec3.getY());
+        EXPECT_FLOAT_EQ(-8.1f * 3.2f, vec3.getZ());
+
+        EXPECT_FLOAT_EQ(3.2f * 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(3.2f * 8.9f, vec4.getY());
+        EXPECT_FLOAT_EQ(3.2f * -8.1f, vec4.getZ());
+    }
+
+    {
+        const Vector3<float> vec1(5.3f, 8.9f, -8.1f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+        EXPECT_FLOAT_EQ(-8.1f, vec1.getZ());
+
+        const auto vec3 = vec1 / 3.2f;
+        const auto vec4 = 3.2f / vec1;
+
+        EXPECT_FLOAT_EQ(5.3f / 3.2f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f / 3.2f, vec3.getY());
+        EXPECT_FLOAT_EQ(-8.1f / 3.2f, vec3.getZ());
+
+        EXPECT_FLOAT_EQ(3.2f / 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(3.2f / 8.9f, vec4.getY());
+        EXPECT_FLOAT_EQ(3.2f / -8.1f, vec4.getZ());
+    }
+
+    {
+        const Vector3<float> vec1(5.3f, 8.9f, -8.1f);
+        const Vector3<float> vec2(5.3f, 8.9f, -8.1f);
+        const Vector3<float> vec3(1.3f, 8.9f, -3.1f);
+        const Vector3<float> vec4(5.3f, 0.9f, -1.1f);
+
+        EXPECT_EQ(vec1, vec1);
+        EXPECT_EQ(vec1, vec2);
+        EXPECT_NE(vec1, vec3);
+        EXPECT_NE(vec1, vec4);
+
+        EXPECT_EQ(vec2, vec1);
+        EXPECT_EQ(vec2, vec2);
+        EXPECT_NE(vec2, vec3);
+        EXPECT_NE(vec2, vec4);
+
+        EXPECT_NE(vec3, vec1);
+        EXPECT_NE(vec3, vec2);
+        EXPECT_EQ(vec3, vec3);
+        EXPECT_NE(vec3, vec4);
+
+        EXPECT_NE(vec4, vec1);
+        EXPECT_NE(vec4, vec2);
+        EXPECT_NE(vec4, vec3);
+        EXPECT_EQ(vec4, vec4);
+    }
+
+}
+
+/* ************************************************************************ */

From 3211479cbf4412350d03796b7db00b7f5f20ecbd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Fatka?= <fatkaj@ntis.zcu.cz>
Date: Fri, 24 Mar 2017 16:21:46 +0100
Subject: [PATCH 06/11] math::Vector2 and math::Vector3 cleanup.

---
 include/cece/math/Vector2.hpp   | 219 +-------------
 include/cece/math/Vector3.hpp   | 136 ---------
 unittests/math/Vector2_test.cpp | 110 ++-----
 unittests/math/Vector3_test.cpp | 495 +++++++++++++++++++++++++++-----
 4 files changed, 454 insertions(+), 506 deletions(-)

diff --git a/include/cece/math/Vector2.hpp b/include/cece/math/Vector2.hpp
index 2de646d..2b2e376 100644
--- a/include/cece/math/Vector2.hpp
+++ b/include/cece/math/Vector2.hpp
@@ -244,25 +244,6 @@ class Vector2
     Vector2& operator*=(T1 rhs) noexcept;
 
 
-    /**
-     * @brief      Multiplication operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of value in Vector2 operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() * std::declval<T1>()),
-        T
-    >::value || std::is_constructible<
-        T,
-        decltype(std::declval<T>() * std::declval<T1>())
-    >::value>::type* = nullptr>
-    Vector2& operator*=(const Vector2<T1>& rhs) noexcept;
-
-
     /**
      * @brief      Division operator.
      *
@@ -282,25 +263,6 @@ class Vector2
     Vector2& operator/=(T1 rhs) noexcept;
 
 
-    /**
-     * @brief      Division operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of value in Vector2 operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() / std::declval<T1>()),
-        T
-    >::value || std::is_constructible<
-        T,
-        decltype(std::declval<T>() * std::declval<T1>())
-    >::value>::type* = nullptr>
-    Vector2& operator/=(const Vector2<T1>& rhs) noexcept;
-
-
     /**
      * @brief      Access operator.
      *
@@ -411,16 +373,6 @@ class Vector2
     ValueTypeSq getLengthSquared() const noexcept;
 
 
-    /**
-     * @brief      Calculate dot of two vectors.
-     *
-     * @param      rhs   Second vector.
-     *
-     * @return     Dot product.
-     */
-    ValueTypeSq dot(const Vector2& rhs) const noexcept;
-
-
     /**
      * @brief      Calculate vectors squared distance.
      *
@@ -517,23 +469,6 @@ operator-(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
-/**
- * @brief      Multiplication operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector2.
- * @tparam     T2    Type of value in second Vector2.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
 /**
  * @brief      Multiplication operator.
  *
@@ -568,23 +503,6 @@ operator*(T1 lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
-/**
- * @brief      Division operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector2.
- * @tparam     T2    Type of value in second Vector2.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
 /**
  * @brief      Division operator.
  *
@@ -652,7 +570,7 @@ bool operator!=(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 /* ************************************************************************ */
 
 /**
- * @brief      Calculate cross product of two vectors.
+ * @brief      Calculate dot product of two vectors.
  *
  * @param      lhs   Left operand.
  * @param      rhs   Right operand.
@@ -660,45 +578,11 @@ bool operator!=(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
  * @tparam     T1    The first type.
  * @tparam     T2    The second type.
  *
- * @return     Cross product.
+ * @return     Dot product.
  */
 template<typename T1, typename T2>
 decltype(std::declval<T1>() * std::declval<T2>())
-cross(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Calculate cross product of two vectors.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    The first type.
- * @tparam     T2    The second type.
- *
- * @return     Cross product.
- */
-template<typename T1, typename T2>
-Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const Vector2<T1>& lhs, const T2& rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Calculate cross product of two vectors.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    The first type.
- * @tparam     T2    The second type.
- *
- * @return     Cross product.
- */
-template<typename T1, typename T2>
-Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const T1& lhs, const Vector2<T2>& rhs) noexcept;
+dot(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
@@ -884,24 +768,6 @@ inline Vector2<T>& Vector2<T>::operator*=(T1 rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() * std::declval<T1>()),
-    T
->::value || std::is_constructible<
-    T,
-    decltype(std::declval<T>() * std::declval<T1>())
->::value>::type*>
-inline Vector2<T>& Vector2<T>::operator*=(const Vector2<T1>& rhs) noexcept
-{
-    x *= rhs.getX();
-    y *= rhs.getY();
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
 template<typename T>
 template<typename T1, typename std::enable_if<std::is_same<
     decltype(std::declval<T>() / std::declval<T1>()),
@@ -920,24 +786,6 @@ inline Vector2<T>& Vector2<T>::operator/=(T1 rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() / std::declval<T1>()),
-    T
->::value || std::is_constructible<
-    T,
-    decltype(std::declval<T>() * std::declval<T1>())
->::value>::type*>
-inline Vector2<T>& Vector2<T>::operator/=(const Vector2<T1>& rhs) noexcept
-{
-    x /= rhs.getX();
-    y /= rhs.getY();
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
 template<typename T>
 inline T& Vector2<T>::operator[](int pos) noexcept
 {
@@ -1031,15 +879,7 @@ inline typename Vector2<T>::ValueType Vector2<T>::getLength() const noexcept
 template<typename T>
 inline typename Vector2<T>::ValueTypeSq Vector2<T>::getLengthSquared() const noexcept
 {
-    return dot(*this);
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline typename Vector2<T>::ValueTypeSq Vector2<T>::dot(const Vector2& rhs) const noexcept
-{
-    return getX() * rhs.getX() + getY() * rhs.getY();
+    return getX() * getX() + getY() * getY();
 }
 
 /* ************************************************************************ */
@@ -1112,18 +952,6 @@ operator-(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
-{
-    return {
-        lhs.getX() * rhs.getX(),
-        lhs.getY() * rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
 template<typename T1, typename T2>
 inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
 operator*(const Vector2<T1>& lhs, T2 rhs) noexcept
@@ -1148,18 +976,6 @@ operator*(T1 lhs, const Vector2<T2>& rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
-{
-    return {
-        lhs.getX() / rhs.getX(),
-        lhs.getY() / rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
 template<typename T1, typename T2>
 inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
 operator/(const Vector2<T1>& lhs, T2 rhs) noexcept
@@ -1206,29 +1022,12 @@ inline bool operator!=(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
 template<typename T1, typename T2>
 inline
 decltype(std::declval<T1>() * std::declval<T2>())
-cross(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
-{
-    return {lhs.getX() * rhs.getY() - lhs.getY() * rhs.getX()};
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline
-Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const Vector2<T1>& lhs, const T2& rhs) noexcept
+dot(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
 {
-    return {rhs * lhs.getY(), -rhs * lhs.getX()};
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline
-Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const T1& lhs, const Vector2<T2>& rhs) noexcept
-{
-    return {-lhs * rhs.getY(), lhs * rhs.getX()};
+    return {
+        lhs.getX() * rhs.getX() +
+        lhs.getY() * rhs.getY()
+    };
 }
 
 /* ************************************************************************ */
diff --git a/include/cece/math/Vector3.hpp b/include/cece/math/Vector3.hpp
index 699fdf1..2fd79cc 100644
--- a/include/cece/math/Vector3.hpp
+++ b/include/cece/math/Vector3.hpp
@@ -249,25 +249,6 @@ class Vector3
     Vector3& operator*=(T1 rhs) noexcept;
 
 
-    /**
-     * @brief      Multiplication operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of value in Vector3 operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() * std::declval<T1>()),
-        T
-    >::value || std::is_constructible<
-        T,
-        decltype(std::declval<T>() * std::declval<T1>())
-    >::value>::type* = nullptr>
-    Vector3& operator*=(const Vector3<T1>& rhs) noexcept;
-
-
     /**
      * @brief      Division operator.
      *
@@ -287,25 +268,6 @@ class Vector3
     Vector3& operator/=(T1 rhs) noexcept;
 
 
-    /**
-     * @brief      Division operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of value in Vector3 operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() / std::declval<T1>()),
-        T
-    >::value || std::is_constructible<
-        T,
-        decltype(std::declval<T>() * std::declval<T1>())
-    >::value>::type* = nullptr>
-    Vector3& operator/=(const Vector3<T1>& rhs) noexcept;
-
-
     /**
      * @brief      Access operator.
      *
@@ -527,23 +489,6 @@ operator-(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
-/**
- * @brief      Multiplication operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector3.
- * @tparam     T2    Type of value in second Vector3.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
 /**
  * @brief      Multiplication operator.
  *
@@ -578,23 +523,6 @@ operator*(T1 lhs, const Vector3<T2>& rhs) noexcept;
 
 /* ************************************************************************ */
 
-/**
- * @brief      Division operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector3.
- * @tparam     T2    Type of value in second Vector3.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
 /**
  * @brief      Division operator.
  *
@@ -890,25 +818,6 @@ inline Vector3<T>& Vector3<T>::operator*=(T1 rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() * std::declval<T1>()),
-    T
->::value || std::is_constructible<
-    T,
-    decltype(std::declval<T>() * std::declval<T1>())
->::value>::type*>
-inline Vector3<T>& Vector3<T>::operator*=(const Vector3<T1>& rhs) noexcept
-{
-    x *= rhs.getX();
-    y *= rhs.getY();
-    z *= rhs.getZ();
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
 template<typename T>
 template<typename T1, typename std::enable_if<std::is_same<
     decltype(std::declval<T>() / std::declval<T1>()),
@@ -928,25 +837,6 @@ inline Vector3<T>& Vector3<T>::operator/=(T1 rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() / std::declval<T1>()),
-    T
->::value || std::is_constructible<
-    T,
-    decltype(std::declval<T>() * std::declval<T1>())
->::value>::type*>
-inline Vector3<T>& Vector3<T>::operator/=(const Vector3<T1>& rhs) noexcept
-{
-    x /= rhs.getX();
-    y /= rhs.getY();
-    z /= rhs.getZ();
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
 template<typename T>
 inline T& Vector3<T>::operator[](int pos) noexcept
 {
@@ -1129,19 +1019,6 @@ operator-(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
-{
-    return {
-        lhs.getX() * rhs.getX(),
-        lhs.getY() * rhs.getY(),
-        lhs.getZ() * rhs.getZ()
-    };
-}
-
-/* ************************************************************************ */
-
 template<typename T1, typename T2>
 inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
 operator*(const Vector3<T1>& lhs, T2 rhs) noexcept
@@ -1168,19 +1045,6 @@ operator*(T1 lhs, const Vector3<T2>& rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
-{
-    return {
-        lhs.getX() / rhs.getX(),
-        lhs.getY() / rhs.getY(),
-        lhs.getZ() / rhs.getZ()
-    };
-}
-
-/* ************************************************************************ */
-
 template<typename T1, typename T2>
 inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
 operator/(const Vector3<T1>& lhs, T2 rhs) noexcept
diff --git a/unittests/math/Vector2_test.cpp b/unittests/math/Vector2_test.cpp
index 0d958cb..48aaa1d 100644
--- a/unittests/math/Vector2_test.cpp
+++ b/unittests/math/Vector2_test.cpp
@@ -251,19 +251,6 @@ TEST(Vector2, operators)
         EXPECT_FLOAT_EQ(4.0f, vec1[1]);
     }
 
-    {
-        Vector2<float> vec1{1.0f, 2.0f};
-
-        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
-        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
-
-        Vector2<float> vec2{1.0f, 2.0f};
-        vec1 *= vec2;
-
-        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
-        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
-    }
-
     {
         Vector2<float> vec1{1.0f, 2.0f};
 
@@ -275,19 +262,6 @@ TEST(Vector2, operators)
         EXPECT_FLOAT_EQ(0.5f, vec1[0]);
         EXPECT_FLOAT_EQ(1.0f, vec1[1]);
     }
-
-    {
-        Vector2<float> vec1{1.0f, 2.0f};
-
-        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
-        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
-
-        Vector2<float> vec2{1.0f, 2.0f};
-        vec1 /= vec2;
-
-        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
-        EXPECT_FLOAT_EQ(1.0f, vec1[1]);
-    }
 }
 
 /* ************************************************************************ */
@@ -348,32 +322,6 @@ TEST(Vector2, memberFunctions)
         EXPECT_FLOAT_EQ(5, vec.getLengthSquared());
     }
 
-    {
-        const Vector2<float> vec;
-
-        EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
-    }
-
-    {
-        const Vector2<float> vec{1.0f, 2.0f};
-
-        EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
-    }
-
-    {
-        const Vector2<float> vec1;
-        const Vector2<float> vec2;
-
-        EXPECT_FLOAT_EQ(0, vec1.dot(vec2));
-    }
-
-    {
-        const Vector2<float> vec1{1.0f, 2.0f};
-        const Vector2<float> vec2{5.0f, 4.0f};
-
-        EXPECT_FLOAT_EQ(13, vec1.dot(vec2));
-    }
-
     {
         const Vector2<float> vec;
 
@@ -503,8 +451,24 @@ TEST(Vector2, functions)
         EXPECT_EQ(0, rot.getY());
     }
 
+    {
+        Vector2<float> vec1(0.94333f, 0.73733f);
+        Vector2<float> vec2(0.16110f, 0.61872f);
+
+        EXPECT_FLOAT_EQ(0.94333f, vec1.getX());
+        EXPECT_FLOAT_EQ(0.73733f, vec1.getY());
+
+        EXPECT_FLOAT_EQ(0.16110f, vec2.getX());
+        EXPECT_FLOAT_EQ(0.61872f, vec2.getY());
 
-    // TODO: cross, dot
+        auto res = dot(vec1, vec2);
+
+        EXPECT_FLOAT_EQ(
+            0.94333f * 0.16110f +
+            0.73733f * 0.61872f,
+            res
+        );
+    }
 }
 
 /* ************************************************************************ */
@@ -551,46 +515,6 @@ TEST(Vector2, freeOperators)
         EXPECT_FLOAT_EQ(1.2f - 8.9f, vec4.getY());
     }
 
-    {
-        const Vector2<float> vec1(5.3f, 8.9f);
-        const Vector2<float> vec2(3.3f, 1.2f);
-
-        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
-        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
-
-        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
-        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
-
-        const auto vec3 = vec1 * vec2;
-        const auto vec4 = vec2 * vec1;
-
-        EXPECT_FLOAT_EQ(5.3f * 3.3f, vec3.getX());
-        EXPECT_FLOAT_EQ(8.9f * 1.2f, vec3.getY());
-
-        EXPECT_FLOAT_EQ(3.3f * 5.3f, vec4.getX());
-        EXPECT_FLOAT_EQ(1.2f * 8.9f, vec4.getY());
-    }
-
-    {
-        const Vector2<float> vec1(5.3f, 8.9f);
-        const Vector2<float> vec2(3.3f, 1.2f);
-
-        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
-        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
-
-        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
-        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
-
-        const auto vec3 = vec1 / vec2;
-        const auto vec4 = vec2 / vec1;
-
-        EXPECT_FLOAT_EQ(5.3f / 3.3f, vec3.getX());
-        EXPECT_FLOAT_EQ(8.9f / 1.2f, vec3.getY());
-
-        EXPECT_FLOAT_EQ(3.3f / 5.3f, vec4.getX());
-        EXPECT_FLOAT_EQ(1.2f / 8.9f, vec4.getY());
-    }
-
     {
         const Vector2<float> vec1(5.3f, 8.9f);
 
diff --git a/unittests/math/Vector3_test.cpp b/unittests/math/Vector3_test.cpp
index e300661..9d9e088 100644
--- a/unittests/math/Vector3_test.cpp
+++ b/unittests/math/Vector3_test.cpp
@@ -614,8 +614,36 @@ TEST(Vector3, assignmentMove)
 
 /* ************************************************************************ */
 
-TEST(Vector3, operators)
+TEST(Vector3, operatorUnaryPlus)
 {
+    {
+        Vector3<int> vec1{1, 2, -8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+        EXPECT_EQ(-8, vec1[2]);
+
+        Vector3<int> vec2 = +vec1;
+
+        EXPECT_EQ(1, vec2[0]);
+        EXPECT_EQ(2, vec2[1]);
+        EXPECT_EQ(-8, vec2[2]);
+    }
+
+    {
+        Vector3<unsigned int> vec1{1, 2, 8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+        EXPECT_EQ(8, vec1[2]);
+
+        Vector3<unsigned int> vec2 = +vec1;
+
+        EXPECT_EQ(1, vec2[0]);
+        EXPECT_EQ(2, vec2[1]);
+        EXPECT_EQ(8, vec2[2]);
+    }
+
     {
         Vector3<float> vec1{1.0f, 2.0f, -8.1f};
 
@@ -630,6 +658,53 @@ TEST(Vector3, operators)
         EXPECT_FLOAT_EQ(-8.1f, vec2[2]);
     }
 
+    {
+        Vector3<double> vec1{1.0, 2.0, -8.1};
+
+        EXPECT_DOUBLE_EQ(1.0, vec1[0]);
+        EXPECT_DOUBLE_EQ(2.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec1[2]);
+
+        Vector3<double> vec2 = +vec1;
+
+        EXPECT_DOUBLE_EQ(1.0, vec2[0]);
+        EXPECT_DOUBLE_EQ(2.0, vec2[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec2[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, operatorUnaryMinus)
+{
+    {
+        Vector3<int> vec1{1, 2, -8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+        EXPECT_EQ(-8, vec1[2]);
+
+        Vector3<int> vec2 = -vec1;
+
+        EXPECT_EQ(-1, vec2[0]);
+        EXPECT_EQ(-2, vec2[1]);
+        EXPECT_EQ(8, vec2[2]);
+    }
+
+    {
+        Vector3<unsigned int> vec1{1, 2, 8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+        EXPECT_EQ(8, vec1[2]);
+
+        Vector3<unsigned int> vec2 = -vec1;
+
+        EXPECT_EQ(-1, vec2[0]);
+        EXPECT_EQ(-2, vec2[1]);
+        EXPECT_EQ(-8, vec2[2]);
+    }
+
     {
         Vector3<float> vec1{1.0f, 2.0f, -8.1f};
 
@@ -644,6 +719,55 @@ TEST(Vector3, operators)
         EXPECT_FLOAT_EQ(8.1f, vec2[2]);
     }
 
+    {
+        Vector3<double> vec1{1.0, 2.0, -8.1};
+
+        EXPECT_DOUBLE_EQ(1.0, vec1[0]);
+        EXPECT_DOUBLE_EQ(2.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec1[2]);
+
+        Vector3<double> vec2 = -vec1;
+
+        EXPECT_DOUBLE_EQ(-1.0, vec2[0]);
+        EXPECT_DOUBLE_EQ(-2.0, vec2[1]);
+        EXPECT_DOUBLE_EQ(8.1, vec2[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, operatorPlus)
+{
+    {
+        Vector3<int> vec1{1, 2, -8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+        EXPECT_EQ(-8, vec1[2]);
+
+        Vector3<int> vec2{1, 2, -8};
+        vec1 += vec2;
+
+        EXPECT_EQ(2, vec1[0]);
+        EXPECT_EQ(4, vec1[1]);
+        EXPECT_EQ(-16, vec1[2]);
+    }
+
+    {
+        Vector3<unsigned int> vec1{1, 2, 8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+        EXPECT_EQ(8, vec1[2]);
+
+        Vector3<unsigned int> vec2{1, 2, 8};
+        vec1 += vec2;
+
+        EXPECT_EQ(2, vec1[0]);
+        EXPECT_EQ(4, vec1[1]);
+        EXPECT_EQ(16, vec1[2]);
+    }
+
     {
         Vector3<float> vec1{1.0f, 2.0f, -8.1f};
 
@@ -659,6 +783,56 @@ TEST(Vector3, operators)
         EXPECT_FLOAT_EQ(-16.2f, vec1[2]);
     }
 
+    {
+        Vector3<double> vec1{1.0, 2.0, -8.1};
+
+        EXPECT_DOUBLE_EQ(1.0, vec1[0]);
+        EXPECT_DOUBLE_EQ(2.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec1[2]);
+
+        Vector3<double> vec2{1.0, 2.0, -8.1};
+        vec1 += vec2;
+
+        EXPECT_DOUBLE_EQ(2.0, vec1[0]);
+        EXPECT_DOUBLE_EQ(4.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-16.2, vec1[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, operatorMinus)
+{
+    {
+        Vector3<int> vec1{1, 2, -8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+        EXPECT_EQ(-8, vec1[2]);
+
+        Vector3<int> vec2{1, 2, -8};
+        vec1 -= vec2;
+
+        EXPECT_EQ(0, vec1[0]);
+        EXPECT_EQ(0, vec1[1]);
+        EXPECT_EQ(0, vec1[2]);
+    }
+
+    {
+        Vector3<unsigned int> vec1{1, 2, 8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+        EXPECT_EQ(8, vec1[2]);
+
+        Vector3<unsigned int> vec2{1, 2, 8};
+        vec1 -= vec2;
+
+        EXPECT_EQ(0, vec1[0]);
+        EXPECT_EQ(0, vec1[1]);
+        EXPECT_EQ(0, vec1[2]);
+    }
+
     {
         Vector3<float> vec1{1.0f, 2.0f, -8.1f};
 
@@ -674,6 +848,54 @@ TEST(Vector3, operators)
         EXPECT_FLOAT_EQ(0.0f, vec1[2]);
     }
 
+    {
+        Vector3<double> vec1{1.0, 2.0, -8.1};
+
+        EXPECT_DOUBLE_EQ(1.0, vec1[0]);
+        EXPECT_DOUBLE_EQ(2.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec1[2]);
+
+        Vector3<double> vec2{1.0, 2.0, -8.1};
+        vec1 -= vec2;
+
+        EXPECT_DOUBLE_EQ(0.0, vec1[0]);
+        EXPECT_DOUBLE_EQ(0.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(0.0, vec1[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, operatorMult)
+{
+    {
+        Vector3<int> vec1{1, 2, -8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+        EXPECT_EQ(-8, vec1[2]);
+
+        vec1 *= 2.0;
+
+        EXPECT_EQ(2, vec1[0]);
+        EXPECT_EQ(4, vec1[1]);
+        EXPECT_EQ(-16, vec1[2]);
+    }
+
+    {
+        Vector3<unsigned int> vec1{1, 2, 8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+        EXPECT_EQ(8, vec1[2]);
+
+        vec1 *= 2.0;
+
+        EXPECT_EQ(2, vec1[0]);
+        EXPECT_EQ(4, vec1[1]);
+        EXPECT_EQ(16, vec1[2]);
+    }
+
     {
         Vector3<float> vec1{1.0f, 2.0f, -8.1f};
 
@@ -689,18 +911,50 @@ TEST(Vector3, operators)
     }
 
     {
-        Vector3<float> vec1{1.0f, 2.0f, -8.1f};
+        Vector3<double> vec1{1.0, 2.0, -8.1};
 
-        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
-        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
-        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+        EXPECT_DOUBLE_EQ(1.0, vec1[0]);
+        EXPECT_DOUBLE_EQ(2.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec1[2]);
 
-        Vector3<float> vec2{1.0f, 2.0f, -8.1f};
-        vec1 *= vec2;
+        vec1 *= 2.0;
 
-        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
-        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
-        EXPECT_FLOAT_EQ(-8.1f * -8.1f, vec1[2]);
+        EXPECT_DOUBLE_EQ(2.0, vec1[0]);
+        EXPECT_DOUBLE_EQ(4.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-16.2, vec1[2]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(Vector3, operatorDiv)
+{
+    {
+        Vector3<int> vec1{1, 2, -8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+        EXPECT_EQ(-8, vec1[2]);
+
+        vec1 /= 2.0;
+
+        EXPECT_EQ(0, vec1[0]);
+        EXPECT_EQ(1, vec1[1]);
+        EXPECT_EQ(-4, vec1[2]);
+    }
+
+    {
+        Vector3<unsigned int> vec1{1, 2, 8};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+        EXPECT_EQ(8, vec1[2]);
+
+        vec1 /= 2.0;
+
+        EXPECT_EQ(0, vec1[0]);
+        EXPECT_EQ(1, vec1[1]);
+        EXPECT_EQ(4, vec1[2]);
     }
 
     {
@@ -718,18 +972,17 @@ TEST(Vector3, operators)
     }
 
     {
-        Vector3<float> vec1{1.0f, 2.0f, -8.1f};
+        Vector3<double> vec1{1.0, 2.0, -8.1};
 
-        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
-        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
-        EXPECT_FLOAT_EQ(-8.1f, vec1[2]);
+        EXPECT_DOUBLE_EQ(1.0, vec1[0]);
+        EXPECT_DOUBLE_EQ(2.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-8.1, vec1[2]);
 
-        Vector3<float> vec2{1.0f, 2.0f, -8.1f};
-        vec1 /= vec2;
+        vec1 /= 2.0;
 
-        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
-        EXPECT_FLOAT_EQ(1.0f, vec1[1]);
-        EXPECT_FLOAT_EQ(1.0f, vec1[2]);
+        EXPECT_DOUBLE_EQ(0.5, vec1[0]);
+        EXPECT_DOUBLE_EQ(1.0, vec1[1]);
+        EXPECT_DOUBLE_EQ(-4.05, vec1[2]);
     }
 }
 
@@ -898,6 +1151,162 @@ TEST(Vector3, mutators)
         EXPECT_EQ(50, vec.y);
         EXPECT_EQ(10, vec.z);
     }
+
+    {
+        Vector3<unsigned int> vec;
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+
+        vec.setX(100);
+
+        EXPECT_EQ(100, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+
+        vec.setY(50);
+
+        EXPECT_EQ(100, vec.getX());
+        EXPECT_EQ(50, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+
+        vec.setZ(10);
+
+        EXPECT_EQ(100, vec.getX());
+        EXPECT_EQ(50, vec.getY());
+        EXPECT_EQ(10, vec.getZ());
+    }
+
+    {
+        Vector3<unsigned int> vec;
+
+        EXPECT_EQ(0, vec.x);
+        EXPECT_EQ(0, vec.y);
+        EXPECT_EQ(0, vec.z);
+
+        vec.x = 100;
+
+        EXPECT_EQ(100, vec.x);
+        EXPECT_EQ(0, vec.y);
+        EXPECT_EQ(0, vec.z);
+
+        vec.y = 50;
+
+        EXPECT_EQ(100, vec.x);
+        EXPECT_EQ(50, vec.y);
+        EXPECT_EQ(0, vec.z);
+
+        vec.z = 10;
+
+        EXPECT_EQ(100, vec.x);
+        EXPECT_EQ(50, vec.y);
+        EXPECT_EQ(10, vec.z);
+    }
+
+    {
+        Vector3<float> vec;
+
+        EXPECT_FLOAT_EQ(0, vec.getX());
+        EXPECT_FLOAT_EQ(0, vec.getY());
+        EXPECT_FLOAT_EQ(0, vec.getZ());
+
+        vec.setX(100.3f);
+
+        EXPECT_FLOAT_EQ(100.3f, vec.getX());
+        EXPECT_FLOAT_EQ(0, vec.getY());
+        EXPECT_FLOAT_EQ(0, vec.getZ());
+
+        vec.setY(50);
+
+        EXPECT_FLOAT_EQ(100.3f, vec.getX());
+        EXPECT_FLOAT_EQ(50, vec.getY());
+        EXPECT_FLOAT_EQ(0, vec.getZ());
+
+        vec.setZ(10);
+
+        EXPECT_FLOAT_EQ(100.3f, vec.getX());
+        EXPECT_FLOAT_EQ(50, vec.getY());
+        EXPECT_FLOAT_EQ(10, vec.getZ());
+    }
+
+    {
+        Vector3<float> vec;
+
+        EXPECT_FLOAT_EQ(0, vec.x);
+        EXPECT_FLOAT_EQ(0, vec.y);
+        EXPECT_FLOAT_EQ(0, vec.z);
+
+        vec.x = 100.3f;
+
+        EXPECT_FLOAT_EQ(100.3f, vec.x);
+        EXPECT_FLOAT_EQ(0, vec.y);
+        EXPECT_FLOAT_EQ(0, vec.z);
+
+        vec.y = 50;
+
+        EXPECT_FLOAT_EQ(100.3f, vec.x);
+        EXPECT_FLOAT_EQ(50, vec.y);
+        EXPECT_FLOAT_EQ(0, vec.z);
+
+        vec.z = 10;
+
+        EXPECT_FLOAT_EQ(100.3f, vec.x);
+        EXPECT_FLOAT_EQ(50, vec.y);
+        EXPECT_FLOAT_EQ(10, vec.z);
+    }
+
+    {
+        Vector3<double> vec;
+
+        EXPECT_DOUBLE_EQ(0, vec.getX());
+        EXPECT_DOUBLE_EQ(0, vec.getY());
+        EXPECT_DOUBLE_EQ(0, vec.getZ());
+
+        vec.setX(100.3);
+
+        EXPECT_DOUBLE_EQ(100.3, vec.getX());
+        EXPECT_DOUBLE_EQ(0, vec.getY());
+        EXPECT_DOUBLE_EQ(0, vec.getZ());
+
+        vec.setY(50);
+
+        EXPECT_DOUBLE_EQ(100.3, vec.getX());
+        EXPECT_DOUBLE_EQ(50, vec.getY());
+        EXPECT_DOUBLE_EQ(0, vec.getZ());
+
+        vec.setZ(10);
+
+        EXPECT_DOUBLE_EQ(100.3, vec.getX());
+        EXPECT_DOUBLE_EQ(50, vec.getY());
+        EXPECT_DOUBLE_EQ(10, vec.getZ());
+    }
+
+    {
+        Vector3<double> vec;
+
+        EXPECT_DOUBLE_EQ(0, vec.x);
+        EXPECT_DOUBLE_EQ(0, vec.y);
+        EXPECT_DOUBLE_EQ(0, vec.z);
+
+        vec.x = 100.3;
+
+        EXPECT_DOUBLE_EQ(100.3, vec.x);
+        EXPECT_DOUBLE_EQ(0, vec.y);
+        EXPECT_DOUBLE_EQ(0, vec.z);
+
+        vec.y = 50;
+
+        EXPECT_DOUBLE_EQ(100.3, vec.x);
+        EXPECT_DOUBLE_EQ(50, vec.y);
+        EXPECT_DOUBLE_EQ(0, vec.z);
+
+        vec.z = 10;
+
+        EXPECT_DOUBLE_EQ(100.3, vec.x);
+        EXPECT_DOUBLE_EQ(50, vec.y);
+        EXPECT_DOUBLE_EQ(10, vec.z);
+    }
 }
 
 /* ************************************************************************ */
@@ -998,54 +1407,6 @@ TEST(Vector3, freeOperators)
         EXPECT_FLOAT_EQ(2.5f - -8.1f, vec4.getZ());
     }
 
-    {
-        const Vector3<float> vec1(5.3f, 8.9f, -8.1f);
-        const Vector3<float> vec2(3.3f, 1.2f, 2.5f);
-
-        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
-        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
-        EXPECT_FLOAT_EQ(-8.1f, vec1.getZ());
-
-        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
-        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
-        EXPECT_FLOAT_EQ(2.5f, vec2.getZ());
-
-        const auto vec3 = vec1 * vec2;
-        const auto vec4 = vec2 * vec1;
-
-        EXPECT_FLOAT_EQ(5.3f * 3.3f, vec3.getX());
-        EXPECT_FLOAT_EQ(8.9f * 1.2f, vec3.getY());
-        EXPECT_FLOAT_EQ(-8.1f * 2.5f, vec3.getZ());
-
-        EXPECT_FLOAT_EQ(3.3f * 5.3f, vec4.getX());
-        EXPECT_FLOAT_EQ(1.2f * 8.9f, vec4.getY());
-        EXPECT_FLOAT_EQ(2.5f * -8.1f, vec4.getZ());
-    }
-
-    {
-        const Vector3<float> vec1(5.3f, 8.9f, -8.1f);
-        const Vector3<float> vec2(3.3f, 1.2f, 2.5f);
-
-        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
-        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
-        EXPECT_FLOAT_EQ(-8.1f, vec1.getZ());
-
-        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
-        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
-        EXPECT_FLOAT_EQ(2.5f, vec2.getZ());
-
-        const auto vec3 = vec1 / vec2;
-        const auto vec4 = vec2 / vec1;
-
-        EXPECT_FLOAT_EQ(5.3f / 3.3f, vec3.getX());
-        EXPECT_FLOAT_EQ(8.9f / 1.2f, vec3.getY());
-        EXPECT_FLOAT_EQ(-8.1f / 2.5f, vec3.getZ());
-
-        EXPECT_FLOAT_EQ(3.3f / 5.3f, vec4.getX());
-        EXPECT_FLOAT_EQ(1.2f / 8.9f, vec4.getY());
-        EXPECT_FLOAT_EQ(2.5f / -8.1f, vec4.getZ());
-    }
-
     {
         const Vector3<float> vec1(5.3f, 8.9f, -8.1f);
 

From 7e6a5e0002cad6f08b887342ad334d35b83734b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Fatka?= <fatkaj@ntis.zcu.cz>
Date: Mon, 5 Jun 2017 17:50:14 +0200
Subject: [PATCH 07/11] Created VectorBase.

VectorBase is base class for all Vector classes (BasicVector, Vector2,
Vector3).
---
 include/cece/math/Vector.hpp       | 1384 ++++------------------------
 include/cece/math/Vector2.hpp      |  729 ++-------------
 include/cece/math/Vector3.hpp      |  748 ++-------------
 include/cece/math/VectorBase.hpp   | 1117 ++++++++++++++++++++++
 include/cece/math/VectorRange.hpp  |    2 +-
 unittests/math/CMakeLists.txt      |    1 +
 unittests/math/Vector2_test.cpp    |  122 +--
 unittests/math/Vector3_test.cpp    |  156 ++--
 unittests/math/VectorBase_test.cpp |  431 +++++++++
 unittests/math/Vector_test.cpp     |   85 +-
 10 files changed, 2029 insertions(+), 2746 deletions(-)
 create mode 100644 include/cece/math/VectorBase.hpp
 create mode 100644 unittests/math/VectorBase_test.cpp

diff --git a/include/cece/math/Vector.hpp b/include/cece/math/Vector.hpp
index ab050e5..8d1167d 100644
--- a/include/cece/math/Vector.hpp
+++ b/include/cece/math/Vector.hpp
@@ -41,6 +41,7 @@
 #include "cece/io/OutStream.hpp"
 #include "cece/unit/math.hpp"
 #include "cece/unit/Units.hpp"
+#include "cece/math/VectorBase.hpp"
 #include "cece/math/Vector2.hpp"
 #include "cece/math/Vector3.hpp"
 
@@ -58,7 +59,7 @@ namespace math {
  * @tparam     N     Number of elements.
  */
 template<typename T, int N>
-class BasicVector
+class BasicVector : public VectorBase<BasicVector, T, N>
 {
     static_assert(N > 0, "Cannot create empty vector");
 
@@ -70,8 +71,13 @@ class BasicVector
     /// BasicVector value type.
     using ValueType = T;
 
-    /// Element type squared.
-    using ValueTypeSq = decltype(std::declval<T>() * std::declval<T>());
+
+// Public Data Members
+public:
+
+
+    // Member data.
+    StaticArray<T, N> m;
 
 
 // Public Ctors
@@ -89,7 +95,7 @@ class BasicVector
      *
      * @param      data  The source data.
      */
-    BasicVector(std::initializer_list<T> data) noexcept;
+    BasicVector(std::initializer_list<T> data);
 
 
     /**
@@ -97,7 +103,7 @@ class BasicVector
      *
      * @param      data  The source data.
      */
-    explicit BasicVector(T (&data)[N]) noexcept;
+    explicit BasicVector(T (&data)[N]);
 
 
     /**
@@ -105,7 +111,7 @@ class BasicVector
      *
      * @param      data  The source data.
      */
-    explicit BasicVector(StaticArray<T, N> data) noexcept;
+    explicit BasicVector(const StaticArray<T, N>& data);
 
 
     /**
@@ -113,7 +119,7 @@ class BasicVector
      *
      * @param[in]  zero  The zero value.
      */
-    BasicVector(Zero_t zero) noexcept;
+    BasicVector(Zero_t zero);
 
 
     /**
@@ -121,7 +127,7 @@ class BasicVector
      *
      * @param[in]  src   The source vector.
      */
-    BasicVector(const BasicVector& src) noexcept;
+    BasicVector(const BasicVector& src);
 
 
     /**
@@ -129,7 +135,7 @@ class BasicVector
      *
      * @param[in]  src   The source vector.
      */
-    BasicVector(BasicVector&& src) noexcept;
+    BasicVector(BasicVector&& src);
 
 
     /**
@@ -140,7 +146,7 @@ class BasicVector
      * @tparam     T2    The source vector element type.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    explicit BasicVector(const BasicVector<T2, N>& src) noexcept;
+    explicit BasicVector(const BasicVector<T2, N>& src);
 
 
 // Public Operators
@@ -154,7 +160,7 @@ class BasicVector
      *
      * @return     *this.
      */
-    BasicVector& operator=(Zero_t zero) noexcept;
+    BasicVector& operator=(Zero_t zero);
 
 
     /**
@@ -164,7 +170,7 @@ class BasicVector
      *
      * @return     *this.
      */
-    BasicVector& operator=(std::initializer_list<T> data) noexcept;
+    BasicVector& operator=(std::initializer_list<T> data);
 
 
     /**
@@ -174,7 +180,7 @@ class BasicVector
      *
      * @return     *this.
      */
-    BasicVector& operator=(T (&data)[N]) noexcept;
+    BasicVector& operator=(T (&data)[N]);
 
 
     /**
@@ -184,7 +190,7 @@ class BasicVector
      *
      * @return     *this.
      */
-    BasicVector& operator=(StaticArray<T, N> data) noexcept;
+    BasicVector& operator=(const StaticArray<T, N>& data);
 
 
     /**
@@ -194,7 +200,7 @@ class BasicVector
      *
      * @return     *this.
      */
-    BasicVector& operator=(const BasicVector& src) noexcept;
+    BasicVector& operator=(const BasicVector& src);
 
 
     /**
@@ -204,7 +210,7 @@ class BasicVector
      *
      * @return     *this.
      */
-    BasicVector& operator=(BasicVector&& src) noexcept;
+    BasicVector& operator=(BasicVector&& src);
 
 
     /**
@@ -217,131 +223,7 @@ class BasicVector
      * @return     *this.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    BasicVector& operator=(const BasicVector<T2, N>& src) noexcept;
-
-
-    /**
-     * @brief      Unary plus operator.
-     *
-     * @return     Vector.
-     */
-    BasicVector operator+() const noexcept;
-
-
-    /**
-     * @brief      Unary minus operator.
-     *
-     * @return     Vector.
-     */
-    BasicVector operator-() const noexcept;
-
-
-    /**
-     * @brief      Addition operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of right operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() + std::declval<T1>()),
-        T
-    >::value>::type* = nullptr>
-    BasicVector& operator+=(const BasicVector<T1, N>& rhs) noexcept;
-
-
-    /**
-     * @brief      Subtraction operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of value in BasicVector operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() - std::declval<T1>()),
-        T
-    >::value>::type* = nullptr>
-    BasicVector& operator-=(const BasicVector<T1, N>& rhs) noexcept;
-
-
-    /**
-     * @brief      Multiplication operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of right operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() * std::declval<T1>()),
-        T
-    >::value || std::is_constructible<
-        T,
-        decltype(std::declval<T>() * std::declval<T1>())
-    >::value>::type* = nullptr>
-    BasicVector& operator*=(T1 rhs) noexcept;
-
-
-    /**
-     * @brief      Multiplication operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of value in BasicVector operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() * std::declval<T1>()),
-        T
-    >::value || std::is_constructible<
-        T,
-        decltype(std::declval<T>() * std::declval<T1>())
-    >::value>::type* = nullptr>
-    BasicVector& operator*=(const BasicVector<T1, N>& rhs) noexcept;
-
-
-    /**
-     * @brief      Division operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of right operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() / std::declval<T1>()),
-        T
-    >::value || std::is_constructible<
-        T,
-        decltype(std::declval<T>() * std::declval<T1>())
-    >::value>::type* = nullptr>
-    BasicVector& operator/=(T1 rhs) noexcept;
-
-
-    /**
-     * @brief      Division operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of value in BasicVector operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() / std::declval<T1>()),
-        T
-    >::value || std::is_constructible<
-        T,
-        decltype(std::declval<T>() * std::declval<T1>())
-    >::value>::type* = nullptr>
-    BasicVector& operator/=(const BasicVector<T1, N>& rhs) noexcept;
+    BasicVector& operator=(const BasicVector<T2, N>& src);
 
 
     /**
@@ -375,122 +257,6 @@ class BasicVector
      */
     int getSize() const noexcept;
 
-
-    /**
-     * @brief      Check if given value is in given range.
-     *
-     * @param      value  Given value.
-     * @param      low    Minimum value (>=).
-     * @param      high   Maximum value (<).
-     *
-     * @return     If given value is in given range.
-     */
-    static bool inRange(T value, T low, T high) noexcept;
-
-
-    /**
-     * @brief      Check if current vector is in given range.
-     *
-     * @param      low   Minimum coordinates (>=).
-     * @param      high  Maximum coordinates (<).
-     *
-     * @return     If current value is in given range.
-     */
-    bool inRange(const BasicVector& low, const BasicVector& high) const noexcept;
-
-
-    /**
-     * @brief      Check if current vector is in given range where the low range
-     *             is Zero vector.
-     *
-     * @param      high  Maximum coordinates (<).
-     *
-     * @return     If current value is in given range.
-     */
-    bool inRange(const BasicVector& high) const noexcept;
-
-
-// Public Operations
-public:
-
-
-    /**
-     * @brief      Calculate vector length.
-     *
-     * @return     The length.
-     */
-    ValueType getLength() const noexcept;
-
-
-    /**
-     * @brief      Calculate vector length - squared.
-     *
-     * @return     The length squared.
-     */
-    ValueTypeSq getLengthSquared() const noexcept;
-
-
-    /**
-     * @brief      Calculate dot of two vectors.
-     *
-     * @param      rhs   Second vector.
-     *
-     * @return     Dot product.
-     */
-    ValueTypeSq dot(const BasicVector& rhs) const noexcept;
-
-
-    /**
-     * @brief      Calculate vectors squared distance.
-     *
-     * @param      rhs   Second vector.
-     *
-     * @return     Distance.
-     */
-    ValueTypeSq distanceSquared(const BasicVector& rhs) const noexcept;
-
-
-    /**
-     * @brief      Calculate vectors distance.
-     *
-     * @param      rhs   Second vector.
-     *
-     * @return     Distance.
-     */
-    ValueType distance(const BasicVector& rhs) const noexcept;
-
-
-    /**
-     * @brief      Inverse current vector (1 / *this).
-     *
-     * @tparam     T2    Type of result vector's element.
-     *
-     * @return     Inversed vector.
-     */
-    template<typename T2 = T>
-    BasicVector<T2, N> inversed() const noexcept;
-
-
-// Public Operations
-public:
-
-
-    /**
-     * @brief      Create from single value.
-     *
-     * @param      val   The value.
-     *
-     * @return     Vector of vals.
-     */
-    static BasicVector createSingle(T val) noexcept;
-
-
-// Private Data Members
-private:
-
-    /// BasicVector data.
-    StaticArray<T, N> m_data;
-
 };
 
 /* ************************************************************************ */
@@ -509,7 +275,41 @@ struct BasicVector<T, 2> : public Vector2<T>
     }
 
     const T& getWidth() const noexcept { return Vector2<T>::getX(); }
+
     const T& getHeight() const noexcept { return Vector2<T>::getY(); }
+
+    static bool inRange(T value, T low, T high) noexcept { return value >= low && value < high; }
+
+    bool inRange(const BasicVector& low, const BasicVector& high) const noexcept
+    {
+        bool res = true;
+
+        res = res && inRange(Vector2<T>::getX(), low.getX(), high.getX());
+        res = res && inRange(Vector2<T>::getY(), low.getY(), high.getY());
+
+        return res;
+    }
+
+    bool inRange(const BasicVector& high) const noexcept
+    {
+        return inRange(Zero, high);
+    }
+
+    static BasicVector createSingle(T val) noexcept { return BasicVector(val, val); }
+
+    template<typename T2 = T>
+    BasicVector inversed() const noexcept
+    {
+        return BasicVector(
+            T2(1) / Vector2<T>::getX(),
+            T2(1) / Vector2<T>::getY()
+        );
+    }
+
+    BasicVector rotated(unit::Angle angle) const noexcept
+    {
+        return rotate(*this, angle);
+    }
 };
 
 /* ************************************************************************ */
@@ -530,6 +330,36 @@ struct BasicVector<T, 3> : public Vector3<T>
     const T& getWidth() const noexcept { return Vector3<T>::getX(); }
     const T& getHeight() const noexcept { return Vector3<T>::getY(); }
     const T& getDepth() const noexcept { return Vector3<T>::getZ(); }
+
+    static bool inRange(T value, T low, T high) noexcept { return value >= low && value < high; }
+
+    bool inRange(const BasicVector& low, const BasicVector& high) const noexcept
+    {
+        bool res = true;
+
+        res = res && inRange(Vector3<T>::getX(), low.getX(), high.getX());
+        res = res && inRange(Vector3<T>::getY(), low.getY(), high.getY());
+        res = res && inRange(Vector3<T>::getZ(), low.getZ(), high.getZ());
+
+        return res;
+    }
+
+    bool inRange(const BasicVector& high) const noexcept
+    {
+        return inRange(Zero, high);
+    }
+
+    static BasicVector createSingle(T val) noexcept { return BasicVector(val, val, val); }
+
+    template<typename T2 = T>
+    BasicVector inversed() const noexcept
+    {
+        return BasicVector(
+            T2(1) / Vector3<T>::getX(),
+            T2(1) / Vector3<T>::getY(),
+            T2(1) / Vector3<T>::getZ()
+        );
+    }
 };
 
 /* ************************************************************************ */
@@ -592,776 +422,163 @@ using VectorReal = Vector<RealType>;
 /* ************************************************************************ */
 
 /**
- * @brief Addition operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of value in second BasicVector.
- * @tparam N  BasicVector size.
+ * @brief Input stream operator.
  *
- * @param lhs Left operand.
- * @param rhs Right operand.
+ * @param is     Input stream.
+ * @param vector Result value.
  *
- * @return Result vector.
+ * @return is.
  */
-template<typename T1, typename T2, int N>
-inline BasicVector<decltype(T1{} + T2{}), N> operator+(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
+template<typename T, int N>
+io::InStream& operator>>(io::InStream& is, BasicVector<T, N>& vector)
 {
-    BasicVector<decltype(T1{} + T2{}), N> res;
+    int i = 0;
 
-    for (int i = 0; i < N; ++i)
-        res[i] = lhs[i] + rhs[i];
+    for (; i < N; ++i)
+    {
+        if (!(is >> std::skipws >> vector[i]))
+            break;
+    }
 
-    return res;
+    if (i == 0)
+        return is;
+
+    // Copy missing values
+    // TODO: have this feature?
+    for (int j = i; j < N; ++j)
+        vector[j] = vector[i - 1];
+
+    return is;
 }
 
 /* ************************************************************************ */
 
 /**
- * @brief Addition operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of second operand.
- * @tparam N  BasicVector size.
+ * @brief Output stream operator.
  *
- * @param lhs Left operand.
- * @param rhs Right operand.
+ * @param os     Output stream.
+ * @param vector Input value.
  *
- * @return Result vector.
+ * @return os.
  */
-template<typename T1, typename T2, int N>
-inline BasicVector<decltype(T1{} + T2{}), N> operator+(const BasicVector<T1, N>& lhs, T2 rhs) noexcept
+template<typename T, int N>
+io::OutStream& operator<<(io::OutStream& os, const BasicVector<T, N>& vector) noexcept
 {
-    BasicVector<decltype(T1{} + T2{}), N> res;
-
     for (int i = 0; i < N; ++i)
-        res[i] = lhs[i] + rhs;
+    {
+        if (i != 0)
+            os << " ";
 
-    return res;
+        os << vector[i];
+    }
+
+    return os;
 }
 
 /* ************************************************************************ */
 
-/**
- * @brief Addition operator.
- *
- * @tparam T1 Type of first operand.
- * @tparam T2 Type of value in second BasicVector.
- * @tparam N  BasicVector size.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2, int N>
-inline BasicVector<decltype(T1{} + T2{}), N> operator+(T1 lhs, const BasicVector<T2, N>& rhs) noexcept
-{
-    BasicVector<decltype(T1{} + T2{}), N> res;
+extern template class BasicVector<RealType, DIMENSION>;
 
-    for (int i = 0; i < N; ++i)
-        res[i] = lhs + rhs[i];
+/* ************************************************************************ */
 
-    return res;
+}
 }
 
+/* ************************************************************************ */
+/* ************************************************************************ */
 /* ************************************************************************ */
 
-/**
- * @brief Substract operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2, int N>
-inline BasicVector<decltype(T1{} - T2{}), N> operator-(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
-{
-    BasicVector<decltype(T1{} - T2{}), N> res;
+namespace cece {
+namespace math {
 
-    for (int i = 0; i < N; ++i)
-        res[i] = lhs[i] - rhs[i];
+/* ************************************************************************ */
 
-    return res;
+template<typename T, int N>
+inline BasicVector<T, N>::BasicVector() noexcept
+    : m{}
+{
+    // Nothing to do
 }
 
 /* ************************************************************************ */
 
-/**
- * @brief Substract operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of second operand.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2, int N>
-inline BasicVector<decltype(T1{} - T2{}), N> operator-(const BasicVector<T1, N>& lhs, T2 rhs) noexcept
+template<typename T, int N>
+inline BasicVector<T, N>::BasicVector(std::initializer_list<T> data)
 {
-    BasicVector<decltype(T1{} - T2{}), N> res;
+    CECE_ASSERT(data.size() == getSize());
 
-    for (int i = 0; i < N; ++i)
-        res[i] = lhs[i] - rhs;
+    using std::begin;
+    auto it = begin(data);
 
-    return res;
+    for (int i = 0; i < getSize(); ++i, ++it)
+        m[i] = *it;
 }
 
 /* ************************************************************************ */
 
-/**
- * @brief Substract operator.
- *
- * @tparam T1 Type of first operand.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2, int N>
-inline BasicVector<decltype(T1{} - T2{}), N> operator-(T1 lhs, const BasicVector<T2, N>& rhs) noexcept
+template<typename T, int N>
+inline BasicVector<T, N>::BasicVector(T (&data)[N])
 {
-    BasicVector<decltype(T1{} - T2{}), N> res;
-
-    for (int i = 0; i < N; ++i)
-        res[i] = lhs - rhs[i];
+    using std::begin;
+    auto it = begin(data);
 
-    return res;
+    for (int i = 0; i < getSize(); ++i, ++it)
+        m[i] = *it;
 }
 
 /* ************************************************************************ */
 
-/**
- * @brief Multiplication operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2, int N>
-inline BasicVector<decltype(T1{} * T2{}), N> operator*(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
+template<typename T, int N>
+inline BasicVector<T, N>::BasicVector(const StaticArray<T, N>& data)
+    : m(data)
 {
-    BasicVector<decltype(T1{} * T2{}), N> res;
-
-    for (int i = 0; i < N; ++i)
-        res[i] = lhs[i] * rhs[i];
-
-    return res;
+    // Nothing to do
 }
 
 /* ************************************************************************ */
 
-/**
- * @brief Multiplication operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of second operand.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2, int N>
-inline BasicVector<decltype(T1{} * T2{}), N> operator*(const BasicVector<T1, N>& lhs, T2 rhs) noexcept
-{
-    BasicVector<decltype(T1{} * T2{}), N> res;
-
-    for (int i = 0; i < N; ++i)
-        res[i] = lhs[i] * rhs;
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Multiplication operator.
- *
- * @tparam T1 Type of first operand.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2, int N>
-inline BasicVector<decltype(T1{} * T2{}), N> operator*(T1 lhs, const BasicVector<T2, N>& rhs) noexcept
-{
-    BasicVector<decltype(T1{} * T2{}), N> res;
-
-    for (int i = 0; i < N; ++i)
-        res[i] = lhs * rhs[i];
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Division operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2, int N>
-inline BasicVector<decltype(T1{} / T2{}), N> operator/(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
-{
-    BasicVector<decltype(T1{} / T2{}), N> res;
-
-    for (int i = 0; i < N; ++i)
-        res[i] = lhs[i] / rhs[i];
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Division operator.
- *
- * @tparam T1 Type of value in first BasicVector.
- * @tparam T2 Type of second operand.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2, int N>
-inline BasicVector<decltype(T1{} / T2{}), N> operator/(const BasicVector<T1, N>& lhs, T2 rhs) noexcept
-{
-    BasicVector<decltype(T1{} / T2{}), N> res;
-
-    for (int i = 0; i < N; ++i)
-        res[i] = lhs[i] / rhs;
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Division operator.
- *
- * @tparam T1 Type of first operand.
- * @tparam T2 Type of value in second BasicVector.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Result vector.
- */
-template<typename T1, typename T2, int N>
-inline BasicVector<decltype(T1{} / T2{}), N> operator/(T1 lhs, const BasicVector<T2, N>& rhs) noexcept
-{
-    BasicVector<decltype(T1{} / T2{}), N> res;
-
-    for (int i = 0; i < N; ++i)
-        res[i] = lhs / rhs[i];
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, typename T2, int N>
-inline bool operator==(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
-{
-    bool res = true;
-
-    for (int i = 0; i < N; ++i)
-        res = res && lhs[i] == rhs[i];
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, int N>
-inline bool operator==(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
-{
-    return lhs == BasicVector<T1, N>(Zero);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, int N>
-inline bool operator==(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
-{
-    return BasicVector<T1, N>(Zero) == rhs;
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, typename T2, int N>
-inline bool operator!=(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
-{
-    return !operator==(lhs, rhs);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, int N>
-inline bool operator!=(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
-{
-    return !operator==(lhs, rhs);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, int N>
-inline bool operator!=(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
-{
-    return !operator==(lhs, rhs);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, typename T2, int N>
-inline bool operator<(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
-{
-    bool res = true;
-
-    for (int i = 0; i < N; ++i)
-        res = res && ((lhs[i] < rhs[i]) || !(rhs[i] < lhs[i]));
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, int N>
-inline bool operator<(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
-{
-    return lhs < BasicVector<T1, N>{Zero};
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, int N>
-inline bool operator<(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
-{
-    return BasicVector<T1, N>{Zero} < rhs;
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, typename T2, int N>
-inline bool operator<=(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
-{
-    return !operator>(lhs, rhs);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, int N>
-inline bool operator<=(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
-{
-    return !operator>(lhs, rhs);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, int N>
-inline bool operator<=(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
-{
-    return !operator>(lhs, rhs);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, typename T2, int N>
-inline bool operator>(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
-{
-    // Reversed operands
-    return operator<(rhs, lhs);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, int N>
-inline bool operator>(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
-{
-    // Reversed operands
-    return operator<(rhs, lhs);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, int N>
-inline bool operator>(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
-{
-    // Reversed operands
-    return operator<(rhs, lhs);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, typename T2, int N>
-inline bool operator>=(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
-{
-    return !operator<(lhs, rhs);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, int N>
-inline bool operator>=(const BasicVector<T1, N>& lhs, Zero_t rhs) noexcept
-{
-    return !operator<(lhs, rhs);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Compare vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return
- */
-template<typename T1, int N>
-inline bool operator>=(Zero_t lhs, const BasicVector<T1, N>& rhs) noexcept
-{
-    return !operator<(lhs, rhs);
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Calculate dot product of two vectors.
- *
- * @param lhs Left operand.
- * @param rhs Right operand.
- *
- * @return Dot product.
- */
-template<typename T1, typename T2, int N>
-inline decltype(T1{} * T2{}) dot(const BasicVector<T1, N>& lhs, const BasicVector<T2, N>& rhs) noexcept
-{
-    decltype(T1{} * T2{}) res{};
-
-    for (int i = 0; i < N; ++i)
-        res += lhs[i] * rhs[i];
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-/**
- * @brief Input stream operator.
- *
- * @param is     Input stream.
- * @param vector Result value.
- *
- * @return is.
- */
 template<typename T, int N>
-io::InStream& operator>>(io::InStream& is, BasicVector<T, N>& vector)
+inline BasicVector<T, N>::BasicVector(Zero_t zero)
 {
-    int i = 0;
-
-    for (; i < N; ++i)
-    {
-        if (!(is >> std::skipws >> vector[i]))
-            break;
-    }
-
-    if (i == 0)
-        return is;
-
-    // Copy missing values
-    // TODO: have this feature?
-    for (int j = i; j < N; ++j)
-        vector[j] = vector[i - 1];
-
-    return is;
+    for (int i = 0; i < getSize(); ++i)
+        m[i] = T{};
 }
 
 /* ************************************************************************ */
 
-/**
- * @brief Output stream operator.
- *
- * @param os     Output stream.
- * @param vector Input value.
- *
- * @return os.
- */
 template<typename T, int N>
-io::OutStream& operator<<(io::OutStream& os, const BasicVector<T, N>& vector) noexcept
+inline BasicVector<T, N>::BasicVector(const BasicVector& src)
 {
-    for (int i = 0; i < N; ++i)
-    {
-        if (i != 0)
-            os << " ";
-
-        os << vector[i];
-    }
-
-    return os;
+    for (int i = 0; i < getSize(); ++i)
+        m[i] = src.m[i];
 }
 
 /* ************************************************************************ */
 
-extern template class BasicVector<RealType, DIMENSION>;
-
-/* ************************************************************************ */
-
-}
-}
-
-/* ************************************************************************ */
-/* ************************************************************************ */
-/* ************************************************************************ */
-
-namespace cece {
-namespace math {
-
-/* ************************************************************************ */
-
 template<typename T, int N>
-inline BasicVector<T, N>::BasicVector() noexcept
-    : m_data{}
+inline BasicVector<T, N>::BasicVector(BasicVector&& src)
 {
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector(std::initializer_list<T> data) noexcept
-{
-    CECE_ASSERT(data.size() == N);
-
-    using std::begin;
-    auto it = begin(data);
-
-    for (int i = 0; i < N; ++i, ++it)
-        m_data[i] = *it;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector(T (&data)[N]) noexcept
-{
-    using std::begin;
-    auto it = begin(data);
-
-    for (int i = 0; i < N; ++i, ++it)
-        m_data[i] = *it;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector(StaticArray<T, N> data) noexcept
-    : m_data(data)
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector(Zero_t zero) noexcept
-{
-    for (int i = 0; i < N; ++i)
-        m_data[i] = T{};
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector(const BasicVector& src) noexcept
-{
-    for (int i = 0; i < N; ++i)
-        m_data[i] = src.m_data[i];
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector(BasicVector&& src) noexcept
-{
-    for (int i = 0; i < N; ++i)
-        m_data[i] = std::move(src.m_data[i]);
+    for (int i = 0; i < getSize(); ++i)
+        m[i] = std::move(src.m[i]);
 }
 
 /* ************************************************************************ */
 
 template<typename T, int N>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline BasicVector<T, N>::BasicVector(const BasicVector<T2, N>& src) noexcept
+inline BasicVector<T, N>::BasicVector(const BasicVector<T2, N>& src)
 {
-    for (int i = 0; i < N; ++i)
-        m_data[i] = T(src[i]);
+    for (int i = 0; i < getSize(); ++i)
+        m[i] = T(src[i]);
 }
 
 /* ************************************************************************ */
 
 template<typename T, int N>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(Zero_t zero) noexcept
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(Zero_t zero)
 {
-    for (int i = 0; i < N; ++i)
-        m_data[i] = T{};
+    for (int i = 0; i < getSize(); ++i)
+        m[i] = T{};
 
     return *this;
 }
@@ -1369,15 +586,15 @@ inline BasicVector<T, N>& BasicVector<T, N>::operator=(Zero_t zero) noexcept
 /* ************************************************************************ */
 
 template<typename T, int N>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(std::initializer_list<T> data) noexcept
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(std::initializer_list<T> data)
 {
-    CECE_ASSERT(data.size() == N);
+    CECE_ASSERT(data.size() == getSize());
 
     using std::begin;
     auto it = begin(data);
 
-    for (int i = 0; i < N; ++i, ++it)
-        m_data[i] = *it;
+    for (int i = 0; i < getSize(); ++i, ++it)
+        m[i] = *it;
 
     return *this;
 }
@@ -1385,13 +602,13 @@ inline BasicVector<T, N>& BasicVector<T, N>::operator=(std::initializer_list<T>
 /* ************************************************************************ */
 
 template<typename T, int N>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(T (&data)[N]) noexcept
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(T (&data)[N])
 {
     using std::begin;
     auto it = begin(data);
 
-    for (int i = 0; i < N; ++i, ++it)
-        m_data[i] = *it;
+    for (int i = 0; i < getSize(); ++i, ++it)
+        m[i] = *it;
 
     return *this;
 }
@@ -1399,9 +616,9 @@ inline BasicVector<T, N>& BasicVector<T, N>::operator=(T (&data)[N]) noexcept
 /* ************************************************************************ */
 
 template<typename T, int N>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(StaticArray<T, N> data) noexcept
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(const StaticArray<T, N>& data)
 {
-    m_data = data;
+    m = data;
 
     return *this;
 }
@@ -1409,10 +626,10 @@ inline BasicVector<T, N>& BasicVector<T, N>::operator=(StaticArray<T, N> data) n
 /* ************************************************************************ */
 
 template<typename T, int N>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(const BasicVector& src) noexcept
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(const BasicVector& src)
 {
-    for (int i = 0; i < N; ++i)
-        m_data[i] = src.m_data[i];
+    for (int i = 0; i < getSize(); ++i)
+        m[i] = src.m[i];
 
     return *this;
 }
@@ -1420,10 +637,10 @@ inline BasicVector<T, N>& BasicVector<T, N>::operator=(const BasicVector& src) n
 /* ************************************************************************ */
 
 template<typename T, int N>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(BasicVector&& src) noexcept
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(BasicVector&& src)
 {
-    for (int i = 0; i < N; ++i)
-        m_data[i] = std::move(src.m_data[i]);
+    for (int i = 0; i < getSize(); ++i)
+        m[i] = std::move(src.m[i]);
 
     return *this;
 }
@@ -1432,133 +649,10 @@ inline BasicVector<T, N>& BasicVector<T, N>::operator=(BasicVector&& src) noexce
 
 template<typename T, int N>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(const BasicVector<T2, N>& src) noexcept
-{
-    for (int i = 0; i < N; ++i)
-        m_data[i] = T(src[i]);
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline BasicVector<T, N> BasicVector<T, N>::operator+() const noexcept
-{
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline BasicVector<T, N> BasicVector<T, N>::operator-() const noexcept
-{
-    BasicVector res;
-
-    for (int i = 0; i < N; ++i)
-        res[i] = -m_data[i];
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() + std::declval<T1>()),
-    T
->::value>::type*>
-inline BasicVector<T, N>& BasicVector<T, N>::operator+=(const BasicVector<T1, N>& rhs) noexcept
-{
-    for (int i = 0; i < N; ++i)
-        m_data[i] += rhs[i];
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() - std::declval<T1>()),
-    T
->::value>::type*>
-inline BasicVector<T, N>& BasicVector<T, N>::operator-=(const BasicVector<T1, N>& rhs) noexcept
+inline BasicVector<T, N>& BasicVector<T, N>::operator=(const BasicVector<T2, N>& src)
 {
-    for (int i = 0; i < N; ++i)
-        m_data[i] -= rhs[i];
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() * std::declval<T1>()),
-    T
->::value || std::is_constructible<
-    T,
-    decltype(std::declval<T>() * std::declval<T1>())
->::value>::type*>
-inline BasicVector<T, N>& BasicVector<T, N>::operator*=(T1 rhs) noexcept
-{
-    for (int i = 0; i < N; ++i)
-        m_data[i] *= rhs;
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() * std::declval<T1>()),
-    T
->::value || std::is_constructible<
-    T,
-    decltype(std::declval<T>() * std::declval<T1>())
->::value>::type*>
-inline BasicVector<T, N>& BasicVector<T, N>::operator*=(const BasicVector<T1, N>& rhs) noexcept
-{
-    for (int i = 0; i < N; ++i)
-        m_data[i] *= rhs[i];
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() / std::declval<T1>()),
-    T
->::value || std::is_constructible<
-    T,
-    decltype(std::declval<T>() * std::declval<T1>())
->::value>::type*>
-inline BasicVector<T, N>& BasicVector<T, N>::operator/=(T1 rhs) noexcept
-{
-    for (int i = 0; i < N; ++i)
-        m_data[i] /= rhs;
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() / std::declval<T1>()),
-    T
->::value || std::is_constructible<
-    T,
-    decltype(std::declval<T>() * std::declval<T1>())
->::value>::type*>
-inline BasicVector<T, N>& BasicVector<T, N>::operator/=(const BasicVector<T1, N>& rhs) noexcept
-{
-    for (int i = 0; i < N; ++i)
-        m_data[i] /= rhs[i];
+    for (int i = 0; i < getSize(); ++i)
+        m[i] = T(src[i]);
 
     return *this;
 }
@@ -1569,8 +663,8 @@ template<typename T, int N>
 inline T& BasicVector<T, N>::operator[](int pos) noexcept
 {
     CECE_ASSERT(pos >= 0);
-    CECE_ASSERT(pos < N);
-    return m_data[pos];
+    CECE_ASSERT(pos < getSize());
+    return m[pos];
 }
 
 /* ************************************************************************ */
@@ -1579,8 +673,8 @@ template<typename T, int N>
 inline const T& BasicVector<T, N>::operator[](int pos) const noexcept
 {
     CECE_ASSERT(pos >= 0);
-    CECE_ASSERT(pos < N);
-    return m_data[pos];
+    CECE_ASSERT(pos < getSize());
+    return m[pos];
 }
 
 /* ************************************************************************ */
@@ -1593,108 +687,6 @@ int BasicVector<T, N>::getSize() const noexcept
 
 /* ************************************************************************ */
 
-template<typename T, int N>
-inline bool BasicVector<T, N>::inRange(T value, T low, T high) noexcept
-{
-    return value >= low && value < high;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline bool BasicVector<T, N>::inRange(const BasicVector& low, const BasicVector& high) const noexcept
-{
-    bool res = true;
-
-    for (int i = 0; i < N; ++i)
-        res = res && inRange(m_data[i], low[i], high[i]);
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline bool BasicVector<T, N>::inRange(const BasicVector& high) const noexcept
-{
-    return inRange(Zero, high);
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline typename BasicVector<T, N>::ValueType BasicVector<T, N>::getLength() const noexcept
-{
-    using std::sqrt;
-    return static_cast<T>(sqrt(getLengthSquared()));
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline typename BasicVector<T, N>::ValueTypeSq BasicVector<T, N>::getLengthSquared() const noexcept
-{
-    return dot(*this);
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline typename BasicVector<T, N>::ValueTypeSq BasicVector<T, N>::dot(const BasicVector& rhs) const noexcept
-{
-    ValueTypeSq res{};
-
-    for (int i = 0; i < N; ++i)
-        res += m_data[i] * rhs[i];
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline typename BasicVector<T, N>::ValueTypeSq BasicVector<T, N>::distanceSquared(const BasicVector& rhs) const noexcept
-{
-    return (*this - rhs).getLengthSquared();
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline typename BasicVector<T, N>::ValueType BasicVector<T, N>::distance(const BasicVector& rhs) const noexcept
-{
-    return (*this - rhs).getLength();
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-template<typename T2>
-inline BasicVector<T2, N> BasicVector<T, N>::inversed() const noexcept
-{
-    BasicVector<T2, N> res;
-
-    for (int i = 0; i < N; ++i)
-        res[i] = T2(1) / m_data[i];
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-template<typename T, int N>
-inline BasicVector<T, N> BasicVector<T, N>::createSingle(T val) noexcept
-{
-    BasicVector res;
-
-    for (int i = 0; i < N; ++i)
-        res[i] = val;
-
-    return res;
-}
-
-/* ************************************************************************ */
-
 }
 }
 
diff --git a/include/cece/math/Vector2.hpp b/include/cece/math/Vector2.hpp
index 2b2e376..4661074 100644
--- a/include/cece/math/Vector2.hpp
+++ b/include/cece/math/Vector2.hpp
@@ -28,14 +28,14 @@
 /* ************************************************************************ */
 
 // C++
-#include <cmath>
 #include <type_traits>
+#include <utility>
 
 // CeCe
 #include "cece/common.hpp"
 #include "cece/Assert.hpp"
 #include "cece/math/Zero.hpp"
-#include "cece/unit/math.hpp"
+#include "cece/math/VectorBase.hpp"
 #include "cece/unit/Units.hpp"
 
 /* ************************************************************************ */
@@ -51,7 +51,7 @@ namespace math {
  * @tparam     T     Element type.
  */
 template<typename T>
-class Vector2
+class Vector2 : public VectorBase<Vector2, T>
 {
 
 
@@ -62,18 +62,24 @@ class Vector2
     /// Vector2 value type.
     using ValueType = T;
 
-    /// Element type squared.
-    using ValueTypeSq = decltype(std::declval<T>() * std::declval<T>());
-
 
 // Public Data Members
 public:
 
-    /// X coordinate.
-    T x;
 
-    /// Y coordinate.
-    T y;
+    union
+    {
+        struct
+        {
+            /// X coordinate.
+            T x;
+
+            /// Y coordinate.
+            T y;
+        };
+
+        T m[2];
+    };
 
 
 // Public Ctors
@@ -83,7 +89,15 @@ class Vector2
     /**
      * @brief      Default constructor.
      */
-    Vector2() noexcept;
+    Vector2();
+
+
+    /**
+     * @brief      Constructor.
+     *
+     * @param      x     The X and Y coordinate.
+     */
+    explicit Vector2(T value);
 
 
     /**
@@ -92,7 +106,7 @@ class Vector2
      * @param      x     The X coordinate.
      * @param      y     The Y coordinate.
      */
-    Vector2(T x, T y) noexcept;
+    Vector2(T x, T y);
 
 
     /**
@@ -100,7 +114,7 @@ class Vector2
      *
      * @param[in]  zero  The zero value.
      */
-    Vector2(Zero_t zero) noexcept;
+    Vector2(Zero_t zero);
 
 
     /**
@@ -108,7 +122,7 @@ class Vector2
      *
      * @param[in]  src   The source vector.
      */
-    Vector2(const Vector2& src) noexcept;
+    Vector2(const Vector2& src);
 
 
     /**
@@ -116,7 +130,7 @@ class Vector2
      *
      * @param[in]  src   The source vector.
      */
-    Vector2(Vector2&& src) noexcept;
+    Vector2(Vector2&& src);
 
 
     /**
@@ -127,7 +141,7 @@ class Vector2
      * @tparam     T2    The source vector element type.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    Vector2(const Vector2<T2>& rhs) noexcept;
+    Vector2(const Vector2<T2>& rhs);
 
 
 // Public Operators
@@ -141,7 +155,7 @@ class Vector2
      *
      * @return     *this.
      */
-    Vector2& operator=(Zero_t zero) noexcept;
+    Vector2& operator=(Zero_t zero);
 
 
     /**
@@ -151,7 +165,7 @@ class Vector2
      *
      * @return     *this.
      */
-    Vector2& operator=(const Vector2& src) noexcept;
+    Vector2& operator=(const Vector2& src);
 
 
     /**
@@ -161,7 +175,7 @@ class Vector2
      *
      * @return     *this.
      */
-    Vector2& operator=(Vector2&& src) noexcept;
+    Vector2& operator=(Vector2&& src);
 
 
     /**
@@ -174,93 +188,7 @@ class Vector2
      * @return     *this.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    Vector2& operator=(const Vector2<T2>& src) noexcept;
-
-
-    /**
-     * @brief      Unary plus operator.
-     *
-     * @return     Vector.
-     */
-    Vector2 operator+() const noexcept;
-
-
-    /**
-     * @brief      Unary minus operator.
-     *
-     * @return     Vector.
-     */
-    Vector2 operator-() const noexcept;
-
-
-    /**
-     * @brief      Addition operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of right operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() + std::declval<T1>()),
-        T
-    >::value>::type* = nullptr>
-    Vector2& operator+=(const Vector2<T1>& rhs) noexcept;
-
-
-    /**
-     * @brief      Subtraction operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of value in Vector2 operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() - std::declval<T1>()),
-        T
-    >::value>::type* = nullptr>
-    Vector2& operator-=(const Vector2<T1>& rhs) noexcept;
-
-
-    /**
-     * @brief      Multiplication operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of right operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() * std::declval<T1>()),
-        T
-    >::value || std::is_constructible<
-        T,
-        decltype(std::declval<T>() * std::declval<T1>())
-    >::value>::type* = nullptr>
-    Vector2& operator*=(T1 rhs) noexcept;
-
-
-    /**
-     * @brief      Division operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of right operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() / std::declval<T1>()),
-        T
-    >::value || std::is_constructible<
-        T,
-        decltype(std::declval<T>() * std::declval<T1>())
-    >::value>::type* = nullptr>
-    Vector2& operator/=(T1 rhs) noexcept;
+    Vector2& operator=(const Vector2<T2>& src);
 
 
     /**
@@ -287,6 +215,14 @@ class Vector2
 public:
 
 
+    /**
+     * @brief      Returns vector size.
+     *
+     * @return     The size.
+     */
+    int getSize() const noexcept;
+
+
     /**
      * @brief      Returns X coordinate.
      *
@@ -300,7 +236,7 @@ class Vector2
      *
      * @param      x     The X coordinate.
      */
-    void setX(T x) noexcept;
+    void setX(T x);
 
 
     /**
@@ -316,273 +252,31 @@ class Vector2
      *
      * @param      y     The Y coordinate.
      */
-    void setY(T y) noexcept;
-
-
-    /**
-     * @brief      Check if given value is in given range.
-     *
-     * @param      value  Given value.
-     * @param      low    Minimum value (>=).
-     * @param      high   Maximum value (<).
-     *
-     * @return     If given value is in given range.
-     */
-    static bool inRange(T value, T low, T high) noexcept;
-
-
-    /**
-     * @brief      Check if current vector is in given range.
-     *
-     * @param      low   Minimum coordinates (>=).
-     * @param      high  Maximum coordinates (<).
-     *
-     * @return     If current value is in given range.
-     */
-    bool inRange(const Vector2& low, const Vector2& high) const noexcept;
-
-
-    /**
-     * @brief      Check if current vector is in given range where the low range
-     *             is Zero vector.
-     *
-     * @param      high  Maximum coordinates (<).
-     *
-     * @return     If current value is in given range.
-     */
-    bool inRange(const Vector2& high) const noexcept;
-
-
-// Public Operations
-public:
-
-
-    /**
-     * @brief      Calculate vector length.
-     *
-     * @return     The length.
-     */
-    ValueType getLength() const noexcept;
-
-
-    /**
-     * @brief      Calculate vector length - squared.
-     *
-     * @return     The length squared.
-     */
-    ValueTypeSq getLengthSquared() const noexcept;
-
-
-    /**
-     * @brief      Calculate vectors squared distance.
-     *
-     * @param      rhs   Second vector.
-     *
-     * @return     Distance.
-     */
-    ValueTypeSq distanceSquared(const Vector2& rhs) const noexcept;
-
-
-    /**
-     * @brief      Calculate vectors distance.
-     *
-     * @param      rhs   Second vector.
-     *
-     * @return     Distance.
-     */
-    ValueType distance(const Vector2& rhs) const noexcept;
-
-
-    /**
-     * @brief      Inverse current vector (1 / *this).
-     *
-     * @tparam     T2    Type of result vector's element.
-     *
-     * @return     Inversed vector.
-     */
-    template<typename T2 = T>
-    Vector2<T2> inversed() const noexcept;
-
-
-    /**
-     * @brief      Rotate current vector counter-clockwise and return rotated
-     *             version.
-     *
-     * @param      angle  Rotation angle.
-     *
-     * @return     Rotated vector.
-     */
-    Vector2 rotated(unit::Angle angle) const noexcept;
-
-
-    /**
-     * @brief      Create from single value.
-     *
-     * @param      val   The value
-     *
-     * @return     Vector of {val, val}.
-     */
-    static Vector2 createSingle(T val) noexcept;
+    void setY(T y);
 
 };
 
 /* ************************************************************************ */
 
-extern template class Vector2<float>;
-extern template class Vector2<double>;
-extern template class Vector2<unsigned int>;
-extern template class Vector2<int>;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Addition operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector2.
- * @tparam     T2    Type of value in second Vector2.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Substract operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector2.
- * @tparam     T2    Type of value in second Vector2.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Multiplication operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector2.
- * @tparam     T2    Type of second operand.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const Vector2<T1>& lhs, T2 rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Multiplication operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second Vector2.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(T1 lhs, const Vector2<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Division operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector2.
- * @tparam     T2    Type of second operand.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const Vector2<T1>& lhs, T2 rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Division operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second Vector2.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(T1 lhs, const Vector2<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Compare vectors.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    The first type.
- * @tparam     T2    The second type.
- *
- * @return     Comparision result.
- */
-template<typename T1, typename T2>
-bool operator==(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
 /**
- * @brief      Compare vectors.
+ * @brief      Rotate the vector counter-clockwise and return rotated version.
  *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
+ * @param[in]  vec    The vector.
+ * @param[in]  angle  Rotation angle.
  *
- * @tparam     T1    The first type.
- * @tparam     T2    The second type.
+ * @tparam     T      The vector element type.
  *
- * @return     Comparision result.
+ * @return     Rotated vector.
  */
-template<typename T1, typename T2>
-bool operator!=(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
+template<typename T>
+Vector2<T> rotate(const Vector2<T>& vec, unit::Angle angle) noexcept;
 
 /* ************************************************************************ */
 
-/**
- * @brief      Calculate dot product of two vectors.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    The first type.
- * @tparam     T2    The second type.
- *
- * @return     Dot product.
- */
-template<typename T1, typename T2>
-decltype(std::declval<T1>() * std::declval<T2>())
-dot(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept;
+extern template class Vector2<float>;
+extern template class Vector2<double>;
+extern template class Vector2<unsigned int>;
+extern template class Vector2<int>;
 
 /* ************************************************************************ */
 
@@ -599,7 +293,7 @@ namespace math {
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector2<T>::Vector2() noexcept
+inline Vector2<T>::Vector2()
     : x{}
     , y{}
 {
@@ -609,7 +303,17 @@ inline Vector2<T>::Vector2() noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector2<T>::Vector2(T x, T y) noexcept
+inline Vector2<T>::Vector2(T val)
+    : x{val}
+    , y{val}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector2<T>::Vector2(T x, T y)
     : x{std::move(x)}
     , y{std::move(y)}
 {
@@ -619,7 +323,7 @@ inline Vector2<T>::Vector2(T x, T y) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector2<T>::Vector2(Zero_t zero) noexcept
+inline Vector2<T>::Vector2(Zero_t zero)
     : x{}
     , y{}
 {
@@ -629,7 +333,7 @@ inline Vector2<T>::Vector2(Zero_t zero) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector2<T>::Vector2(const Vector2& src) noexcept
+inline Vector2<T>::Vector2(const Vector2& src)
     : x{src.getX()}
     , y{src.getY()}
 {
@@ -639,7 +343,7 @@ inline Vector2<T>::Vector2(const Vector2& src) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector2<T>::Vector2(Vector2&& src) noexcept
+inline Vector2<T>::Vector2(Vector2&& src)
     : x{std::move(src.x)}
     , y{std::move(src.y)}
 {
@@ -650,7 +354,7 @@ inline Vector2<T>::Vector2(Vector2&& src) noexcept
 
 template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline Vector2<T>::Vector2(const Vector2<T2>& rhs) noexcept
+inline Vector2<T>::Vector2(const Vector2<T2>& rhs)
     : x(rhs.getX())
     , y(rhs.getY())
 {
@@ -660,7 +364,7 @@ inline Vector2<T>::Vector2(const Vector2<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector2<T>& Vector2<T>::operator=(Zero_t zero) noexcept
+inline Vector2<T>& Vector2<T>::operator=(Zero_t zero)
 {
     x = T{};
     y = T{};
@@ -671,7 +375,7 @@ inline Vector2<T>& Vector2<T>::operator=(Zero_t zero) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector2<T>& Vector2<T>::operator=(const Vector2& src) noexcept
+inline Vector2<T>& Vector2<T>::operator=(const Vector2& src)
 {
     x = src.x;
     y = src.y;
@@ -682,7 +386,7 @@ inline Vector2<T>& Vector2<T>::operator=(const Vector2& src) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector2<T>& Vector2<T>::operator=(Vector2&& src) noexcept
+inline Vector2<T>& Vector2<T>::operator=(Vector2&& src)
 {
     x = std::move(src.x);
     y = std::move(src.y);
@@ -694,7 +398,7 @@ inline Vector2<T>& Vector2<T>::operator=(Vector2&& src) noexcept
 
 template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline Vector2<T>& Vector2<T>::operator=(const Vector2<T2>& src) noexcept
+inline Vector2<T>& Vector2<T>::operator=(const Vector2<T2>& src)
 {
     x = T(src.getX());
     y = T(src.getY());
@@ -705,103 +409,29 @@ inline Vector2<T>& Vector2<T>::operator=(const Vector2<T2>& src) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector2<T> Vector2<T>::operator+() const noexcept
-{
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T> Vector2<T>::operator-() const noexcept
-{
-    return {-x, -y};
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() + std::declval<T1>()),
-    T
->::value>::type*>
-inline Vector2<T>& Vector2<T>::operator+=(const Vector2<T1>& rhs) noexcept
-{
-    x += rhs.getX();
-    y += rhs.getY();
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() - std::declval<T1>()),
-    T
->::value>::type*>
-inline Vector2<T>& Vector2<T>::operator-=(const Vector2<T1>& rhs) noexcept
-{
-    x -= rhs.getX();
-    y -= rhs.getY();
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() * std::declval<T1>()),
-    T
->::value || std::is_constructible<
-    T,
-    decltype(std::declval<T>() * std::declval<T1>())
->::value>::type*>
-inline Vector2<T>& Vector2<T>::operator*=(T1 rhs) noexcept
-{
-    x *= rhs;
-    y *= rhs;
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() / std::declval<T1>()),
-    T
->::value || std::is_constructible<
-    T,
-    decltype(std::declval<T>() * std::declval<T1>())
->::value>::type*>
-inline Vector2<T>& Vector2<T>::operator/=(T1 rhs) noexcept
+inline T& Vector2<T>::operator[](int pos) noexcept
 {
-    x /= rhs;
-    y /= rhs;
-
-    return *this;
+    CECE_ASSERT(pos >= 0);
+    CECE_ASSERT(pos < getSize());
+    return (&x)[pos];
 }
 
 /* ************************************************************************ */
 
 template<typename T>
-inline T& Vector2<T>::operator[](int pos) noexcept
+inline const T& Vector2<T>::operator[](int pos) const noexcept
 {
     CECE_ASSERT(pos >= 0);
-    CECE_ASSERT(pos < 2);
+    CECE_ASSERT(pos < getSize());
     return (&x)[pos];
 }
 
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector2<T>::operator[](int pos) const noexcept
+inline int Vector2<T>::getSize() const noexcept
 {
-    CECE_ASSERT(pos >= 0);
-    CECE_ASSERT(pos < 2);
-    return (&x)[pos];
+    return 2;
 }
 
 /* ************************************************************************ */
@@ -815,7 +445,7 @@ inline const T& Vector2<T>::getX() const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline void Vector2<T>::setX(T x) noexcept
+inline void Vector2<T>::setX(T x)
 {
     this->x = std::move(x);
 }
@@ -831,7 +461,7 @@ inline const T& Vector2<T>::getY() const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline void Vector2<T>::setY(T y) noexcept
+inline void Vector2<T>::setY(T y)
 {
     this->y = std::move(y);
 }
@@ -839,194 +469,11 @@ inline void Vector2<T>::setY(T y) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline bool Vector2<T>::inRange(T value, T low, T high) noexcept
-{
-    return value >= low && value < high;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline bool Vector2<T>::inRange(const Vector2& low, const Vector2& high) const noexcept
-{
-    bool res = true;
-
-    res = res && inRange(getX(), low.getX(), high.getX());
-    res = res && inRange(getY(), low.getY(), high.getY());
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline bool Vector2<T>::inRange(const Vector2& high) const noexcept
-{
-    return inRange(Zero, high);
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline typename Vector2<T>::ValueType Vector2<T>::getLength() const noexcept
-{
-    using std::sqrt;
-    return static_cast<T>(sqrt(getLengthSquared()));
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline typename Vector2<T>::ValueTypeSq Vector2<T>::getLengthSquared() const noexcept
-{
-    return getX() * getX() + getY() * getY();
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline typename Vector2<T>::ValueTypeSq Vector2<T>::distanceSquared(const Vector2& rhs) const noexcept
-{
-    return (*this - rhs).getLengthSquared();
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline typename Vector2<T>::ValueType Vector2<T>::distance(const Vector2& rhs) const noexcept
-{
-    return (*this - rhs).getLength();
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T2>
-inline Vector2<T2> Vector2<T>::inversed() const noexcept
-{
-    return {T2(1) / getX(), T2(1) / getY()};
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T> Vector2<T>::rotated(unit::Angle angle) const noexcept
-{
-    return {
-        static_cast<T>(getX() * cos(static_cast<RealType>(angle)) - getY() * sin(static_cast<RealType>(angle))),
-        static_cast<T>(getX() * sin(static_cast<RealType>(angle)) + getY() * cos(static_cast<RealType>(angle)))
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T> Vector2<T>::createSingle(T val) noexcept
-{
-    return {val, val};
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
-{
-    return {
-        lhs.getX() + rhs.getX(),
-        lhs.getY() + rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
-{
-    return {
-        lhs.getX() - rhs.getX(),
-        lhs.getY() - rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const Vector2<T1>& lhs, T2 rhs) noexcept
-{
-    return {
-        lhs.getX() * rhs,
-        lhs.getY() * rhs
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(T1 lhs, const Vector2<T2>& rhs) noexcept
-{
-    return {
-        lhs * rhs.getX(),
-        lhs * rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const Vector2<T1>& lhs, T2 rhs) noexcept
-{
-    return {
-        lhs.getX() / rhs,
-        lhs.getY() / rhs
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector2<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(T1 lhs, const Vector2<T2>& rhs) noexcept
-{
-    return {
-        lhs / rhs.getX(),
-        lhs / rhs.getY()
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline bool operator==(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
-{
-    return
-        lhs.getX() == rhs.getX() &&
-        lhs.getY() == rhs.getY()
-    ;
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline bool operator!=(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
-{
-    return !operator==(lhs, rhs);
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline
-decltype(std::declval<T1>() * std::declval<T2>())
-dot(const Vector2<T1>& lhs, const Vector2<T2>& rhs) noexcept
+inline Vector2<T> rotate(const Vector2<T>& vec, unit::Angle angle) noexcept
 {
     return {
-        lhs.getX() * rhs.getX() +
-        lhs.getY() * rhs.getY()
+        static_cast<T>(vec.getX() * cos(static_cast<RealType>(angle)) - vec.getY() * sin(static_cast<RealType>(angle))),
+        static_cast<T>(vec.getX() * sin(static_cast<RealType>(angle)) + vec.getY() * cos(static_cast<RealType>(angle)))
     };
 }
 
diff --git a/include/cece/math/Vector3.hpp b/include/cece/math/Vector3.hpp
index 2fd79cc..bfaeeca 100644
--- a/include/cece/math/Vector3.hpp
+++ b/include/cece/math/Vector3.hpp
@@ -28,15 +28,14 @@
 /* ************************************************************************ */
 
 // C++
-#include <cmath>
 #include <type_traits>
+#include <utility>
 
 // CeCe
 #include "cece/common.hpp"
 #include "cece/Assert.hpp"
 #include "cece/math/Zero.hpp"
-#include "cece/unit/math.hpp"
-#include "cece/unit/Units.hpp"
+#include "cece/math/VectorBase.hpp"
 
 /* ************************************************************************ */
 
@@ -51,7 +50,7 @@ namespace math {
  * @tparam     T     Element type.
  */
 template<typename T>
-class Vector3
+class Vector3 : public VectorBase<Vector3, T>
 {
 
 
@@ -62,22 +61,27 @@ class Vector3
     /// Vector3 value type.
     using ValueType = T;
 
-    /// Element type squared.
-    using ValueTypeSq = decltype(std::declval<T>() * std::declval<T>());
-
 
 // Public Data Members
 public:
 
 
-    /// X coordinate.
-    T x;
+    union
+    {
+        struct
+        {
+            /// X coordinate.
+            T x;
+
+            /// Y coordinate.
+            T y;
 
-    /// Y coordinate.
-    T y;
+            /// Z coordinate.
+            T z;
+        };
 
-    /// Z coordinate.
-    T z;
+        T m[3];
+    };
 
 
 // Public Ctors
@@ -90,6 +94,14 @@ class Vector3
     Vector3() noexcept;
 
 
+    /**
+     * @brief      Constructor.
+     *
+     * @param      val   The X, Y and Z coordinate.
+     */
+    explicit Vector3(T val);
+
+
     /**
      * @brief      Constructor.
      *
@@ -97,7 +109,7 @@ class Vector3
      * @param      y     The Y coordinate.
      * @param      y     The Z coordinate.
      */
-    Vector3(T x, T y, T z) noexcept;
+    Vector3(T x, T y, T z);
 
 
     /**
@@ -105,7 +117,7 @@ class Vector3
      *
      * @param[in]  zero  The zero value.
      */
-    Vector3(Zero_t zero) noexcept;
+    Vector3(Zero_t zero);
 
 
     /**
@@ -113,7 +125,7 @@ class Vector3
      *
      * @param[in]  src   The source vector.
      */
-    Vector3(const Vector3& src) noexcept;
+    Vector3(const Vector3& src);
 
 
     /**
@@ -121,7 +133,7 @@ class Vector3
      *
      * @param[in]  src   The source vector.
      */
-    Vector3(Vector3&& src) noexcept;
+    Vector3(Vector3&& src);
 
 
     /**
@@ -132,7 +144,7 @@ class Vector3
      * @tparam     T2    The source vector element type.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    Vector3(const Vector3<T2>& rhs) noexcept;
+    Vector3(const Vector3<T2>& rhs);
 
 
 // Public Operators
@@ -146,7 +158,7 @@ class Vector3
      *
      * @return     *this.
      */
-    Vector3& operator=(Zero_t zero) noexcept;
+    Vector3& operator=(Zero_t zero);
 
 
     /**
@@ -156,7 +168,7 @@ class Vector3
      *
      * @return     *this.
      */
-    Vector3& operator=(const Vector3& src) noexcept;
+    Vector3& operator=(const Vector3& src);
 
 
     /**
@@ -166,7 +178,7 @@ class Vector3
      *
      * @return     *this.
      */
-    Vector3& operator=(Vector3&& src) noexcept;
+    Vector3& operator=(Vector3&& src);
 
 
     /**
@@ -179,93 +191,7 @@ class Vector3
      * @return     *this.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    Vector3& operator=(const Vector3<T2>& src) noexcept;
-
-
-    /**
-     * @brief      Unary plus operator.
-     *
-     * @return     Vector.
-     */
-    Vector3 operator+() const noexcept;
-
-
-    /**
-     * @brief      Unary minus operator.
-     *
-     * @return     Vector.
-     */
-    Vector3 operator-() const noexcept;
-
-
-    /**
-     * @brief      Addition operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of right operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() + std::declval<T1>()),
-        T
-    >::value>::type* = nullptr>
-    Vector3& operator+=(const Vector3<T1>& rhs) noexcept;
-
-
-    /**
-     * @brief      Subtraction operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of value in Vector3 operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() - std::declval<T1>()),
-        T
-    >::value>::type* = nullptr>
-    Vector3& operator-=(const Vector3<T1>& rhs) noexcept;
-
-
-    /**
-     * @brief      Multiplication operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of right operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() * std::declval<T1>()),
-        T
-    >::value || std::is_constructible<
-        T,
-        decltype(std::declval<T>() * std::declval<T1>())
-    >::value>::type* = nullptr>
-    Vector3& operator*=(T1 rhs) noexcept;
-
-
-    /**
-     * @brief      Division operator.
-     *
-     * @param      rhs        Right operand.
-     *
-     * @tparam     T1         Type of right operand.
-     *
-     * @return     *this.
-     */
-    template<typename T1, typename std::enable_if<std::is_same<
-        decltype(std::declval<T>() / std::declval<T1>()),
-        T
-    >::value || std::is_constructible<
-        T,
-        decltype(std::declval<T>() * std::declval<T1>())
-    >::value>::type* = nullptr>
-    Vector3& operator/=(T1 rhs) noexcept;
+    Vector3& operator=(const Vector3<T2>& src);
 
 
     /**
@@ -292,6 +218,14 @@ class Vector3
 public:
 
 
+    /**
+     * @brief      Returns vector size.
+     *
+     * @return     The size.
+     */
+    int getSize() const noexcept;
+
+
     /**
      * @brief      Returns X coordinate.
      *
@@ -305,7 +239,7 @@ class Vector3
      *
      * @param      x     The X coordinate.
      */
-    void setX(T x) noexcept;
+    void setX(T x);
 
 
     /**
@@ -321,7 +255,7 @@ class Vector3
      *
      * @param      y     The Y coordinate.
      */
-    void setY(T y) noexcept;
+    void setY(T y);
 
 
     /**
@@ -337,112 +271,7 @@ class Vector3
      *
      * @param      z     The Z coordinate.
      */
-    void setZ(T z) noexcept;
-
-
-    /**
-     * @brief      Check if given value is in given range.
-     *
-     * @param      value  Given value.
-     * @param      low    Minimum value (>=).
-     * @param      high   Maximum value (<).
-     *
-     * @return     If given value is in given range.
-     */
-    static bool inRange(T value, T low, T high) noexcept;
-
-
-    /**
-     * @brief      Check if current vector is in given range.
-     *
-     * @param      low   Minimum coordinates (>=).
-     * @param      high  Maximum coordinates (<).
-     *
-     * @return     If current value is in given range.
-     */
-    bool inRange(const Vector3& low, const Vector3& high) const noexcept;
-
-
-    /**
-     * @brief      Check if current vector is in given range where the low range
-     *             is Zero vector.
-     *
-     * @param      high  Maximum coordinates (<).
-     *
-     * @return     If current value is in given range.
-     */
-    bool inRange(const Vector3& high) const noexcept;
-
-
-// Public Operations
-public:
-
-
-    /**
-     * @brief      Calculate vector length.
-     *
-     * @return     The length.
-     */
-    ValueType getLength() const noexcept;
-
-
-    /**
-     * @brief      Calculate vector length - squared.
-     *
-     * @return     The length squared.
-     */
-    ValueTypeSq getLengthSquared() const noexcept;
-
-
-    /**
-     * @brief      Calculate vectors squared distance.
-     *
-     * @param      rhs   Second vector.
-     *
-     * @return     Distance.
-     */
-    ValueTypeSq distanceSquared(const Vector3& rhs) const noexcept;
-
-
-    /**
-     * @brief      Calculate vectors distance.
-     *
-     * @param      rhs   Second vector.
-     *
-     * @return     Distance.
-     */
-    ValueType distance(const Vector3& rhs) const noexcept;
-
-
-    /**
-     * @brief      Inverse current vector (1 / *this).
-     *
-     * @tparam     T2    Type of result vector's element.
-     *
-     * @return     Inversed vector.
-     */
-    template<typename T2 = T>
-    Vector3<T2> inversed() const noexcept;
-
-
-    /**
-     * @brief      Rotate current vector and return rotated version.
-     *
-     * @param      angle  Rotation angle.
-     *
-     * @return     Rotated vector.
-     */
-    Vector3 rotated(unit::Angle angle) const noexcept;
-
-
-    /**
-     * @brief      Create from single value.
-     *
-     * @param      val   The value
-     *
-     * @return     Vector of {val, val}.
-     */
-    static Vector3 createSingle(T val) noexcept;
+    void setZ(T z);
 
 };
 
@@ -455,140 +284,6 @@ extern template class Vector3<int>;
 
 /* ************************************************************************ */
 
-/**
- * @brief      Addition operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector3.
- * @tparam     T2    Type of value in second Vector3.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Substract operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector3.
- * @tparam     T2    Type of value in second Vector3.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Multiplication operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector3.
- * @tparam     T2    Type of second operand.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const Vector3<T1>& lhs, T2 rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Multiplication operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second Vector3.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(T1 lhs, const Vector3<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Division operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of value in first Vector3.
- * @tparam     T2    Type of second operand.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const Vector3<T1>& lhs, T2 rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Division operator.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    Type of first operand.
- * @tparam     T2    Type of value in second Vector3.
- *
- * @return     Result vector.
- */
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(T1 lhs, const Vector3<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Compare vectors.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    The first type.
- * @tparam     T2    The second type.
- *
- * @return     Comparision result.
- */
-template<typename T1, typename T2>
-inline bool operator==(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Compare vectors.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    The first type.
- * @tparam     T2    The second type.
- *
- * @return     Comparision result.
- */
-template<typename T1, typename T2>
-bool operator!=(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
 /**
  * @brief      Calculate cross product of two vectors.
  *
@@ -602,24 +297,7 @@ bool operator!=(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
  */
 template<typename T1, typename T2>
 Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Calculate dot product of two vectors.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    The first type.
- * @tparam     T2    The second type.
- *
- * @return     Dot product.
- */
-template<typename T1, typename T2>
-decltype(std::declval<T1>() * std::declval<T2>())
-dot(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept;
+cross(const Vector3<T1>& lhs, const Vector3<T2>& rhs);
 
 /* ************************************************************************ */
 
@@ -647,10 +325,21 @@ inline Vector3<T>::Vector3() noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector3<T>::Vector3(T x, T y, T z) noexcept
-    : x(x)
-    , y(y)
-    , z(z)
+inline Vector3<T>::Vector3(T val)
+    : x{val}
+    , y{val}
+    , z{val}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector3<T>::Vector3(T x, T y, T z)
+    : x{std::move(x)}
+    , y{std::move(y)}
+    , z{std::move(z)}
 {
     // Nothing to do
 }
@@ -658,7 +347,7 @@ inline Vector3<T>::Vector3(T x, T y, T z) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector3<T>::Vector3(Zero_t zero) noexcept
+inline Vector3<T>::Vector3(Zero_t zero)
     : x{}
     , y{}
     , z{}
@@ -669,7 +358,7 @@ inline Vector3<T>::Vector3(Zero_t zero) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector3<T>::Vector3(const Vector3& src) noexcept
+inline Vector3<T>::Vector3(const Vector3& src)
     : x{src.getX()}
     , y{src.getY()}
     , z{src.getZ()}
@@ -680,7 +369,7 @@ inline Vector3<T>::Vector3(const Vector3& src) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector3<T>::Vector3(Vector3&& src) noexcept
+inline Vector3<T>::Vector3(Vector3&& src)
     : x{std::move(src.x)}
     , y{std::move(src.y)}
     , z{std::move(src.z)}
@@ -692,7 +381,7 @@ inline Vector3<T>::Vector3(Vector3&& src) noexcept
 
 template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline Vector3<T>::Vector3(const Vector3<T2>& rhs) noexcept
+inline Vector3<T>::Vector3(const Vector3<T2>& rhs)
     : x(rhs.getX())
     , y(rhs.getY())
     , z(rhs.getZ())
@@ -703,7 +392,7 @@ inline Vector3<T>::Vector3(const Vector3<T2>& rhs) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector3<T>& Vector3<T>::operator=(Zero_t zero) noexcept
+inline Vector3<T>& Vector3<T>::operator=(Zero_t zero)
 {
     x = T{};
     y = T{};
@@ -715,7 +404,7 @@ inline Vector3<T>& Vector3<T>::operator=(Zero_t zero) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector3<T>& Vector3<T>::operator=(const Vector3& src) noexcept
+inline Vector3<T>& Vector3<T>::operator=(const Vector3& src)
 {
     x = src.x;
     y = src.y;
@@ -727,7 +416,7 @@ inline Vector3<T>& Vector3<T>::operator=(const Vector3& src) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector3<T>& Vector3<T>::operator=(Vector3&& src) noexcept
+inline Vector3<T>& Vector3<T>::operator=(Vector3&& src)
 {
     x = std::move(src.x);
     y = std::move(src.y);
@@ -740,7 +429,7 @@ inline Vector3<T>& Vector3<T>::operator=(Vector3&& src) noexcept
 
 template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline Vector3<T>& Vector3<T>::operator=(const Vector3<T2>& src) noexcept
+inline Vector3<T>& Vector3<T>::operator=(const Vector3<T2>& src)
 {
     x = T(src.getX());
     y = T(src.getY());
@@ -752,87 +441,9 @@ inline Vector3<T>& Vector3<T>::operator=(const Vector3<T2>& src) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector3<T> Vector3<T>::operator+() const noexcept
-{
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector3<T> Vector3<T>::operator-() const noexcept
+inline int Vector3<T>::getSize() const noexcept
 {
-    return {-x, -y, -z};
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() + std::declval<T1>()),
-    T
->::value>::type*>
-inline Vector3<T>& Vector3<T>::operator+=(const Vector3<T1>& rhs) noexcept
-{
-    x += rhs.getX();
-    y += rhs.getY();
-    z += rhs.getZ();
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() - std::declval<T1>()),
-    T
->::value>::type*>
-inline Vector3<T>& Vector3<T>::operator-=(const Vector3<T1>& rhs) noexcept
-{
-    x -= rhs.getX();
-    y -= rhs.getY();
-    z -= rhs.getZ();
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() * std::declval<T1>()),
-    T
->::value || std::is_constructible<
-    T,
-    decltype(std::declval<T>() * std::declval<T1>())
->::value>::type*>
-inline Vector3<T>& Vector3<T>::operator*=(T1 rhs) noexcept
-{
-    x *= rhs;
-    y *= rhs;
-    z *= rhs;
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T1, typename std::enable_if<std::is_same<
-    decltype(std::declval<T>() / std::declval<T1>()),
-    T
->::value || std::is_constructible<
-    T,
-    decltype(std::declval<T>() * std::declval<T1>())
->::value>::type*>
-inline Vector3<T>& Vector3<T>::operator/=(T1 rhs) noexcept
-{
-    x /= rhs;
-    y /= rhs;
-    z /= rhs;
-
-    return *this;
+    return 3;
 }
 
 /* ************************************************************************ */
@@ -841,7 +452,7 @@ template<typename T>
 inline T& Vector3<T>::operator[](int pos) noexcept
 {
     CECE_ASSERT(pos >= 0);
-    CECE_ASSERT(pos < 3);
+    CECE_ASSERT(pos < getSize());
     return (&x)[pos];
 }
 
@@ -851,7 +462,7 @@ template<typename T>
 inline const T& Vector3<T>::operator[](int pos) const noexcept
 {
     CECE_ASSERT(pos >= 0);
-    CECE_ASSERT(pos < 3);
+    CECE_ASSERT(pos < getSize());
     return (&x)[pos];
 }
 
@@ -866,7 +477,7 @@ inline const T& Vector3<T>::getX() const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline void Vector3<T>::setX(T x) noexcept
+inline void Vector3<T>::setX(T x)
 {
     this->x = std::move(x);
 }
@@ -882,7 +493,7 @@ inline const T& Vector3<T>::getY() const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline void Vector3<T>::setY(T y) noexcept
+inline void Vector3<T>::setY(T y)
 {
     this->y = std::move(y);
 }
@@ -898,203 +509,18 @@ inline const T& Vector3<T>::getZ() const noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline void Vector3<T>::setZ(T z) noexcept
+inline void Vector3<T>::setZ(T z)
 {
     this->z = std::move(z);
 }
 
 /* ************************************************************************ */
 
-template<typename T>
-inline bool Vector3<T>::inRange(T value, T low, T high) noexcept
-{
-    return value >= low && value < high;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline bool Vector3<T>::inRange(const Vector3& low, const Vector3& high) const noexcept
-{
-    bool res = true;
-
-    res = res && inRange(getX(), low.getX(), high.getX());
-    res = res && inRange(getY(), low.getY(), high.getY());
-    res = res && inRange(getZ(), low.getZ(), high.getZ());
-
-    return res;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline bool Vector3<T>::inRange(const Vector3& high) const noexcept
-{
-    return inRange(Zero, high);
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline typename Vector3<T>::ValueType Vector3<T>::getLength() const noexcept
-{
-    using std::sqrt;
-    return static_cast<T>(sqrt(getLengthSquared()));
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline typename Vector3<T>::ValueTypeSq Vector3<T>::getLengthSquared() const noexcept
-{
-    return
-        getX() * getX() +
-        getY() * getY() +
-        getZ() * getZ()
-    ;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline typename Vector3<T>::ValueTypeSq Vector3<T>::distanceSquared(const Vector3& rhs) const noexcept
-{
-    return (*this - rhs).getLengthSquared();
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline typename Vector3<T>::ValueType Vector3<T>::distance(const Vector3& rhs) const noexcept
-{
-    return (*this - rhs).getLength();
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T2>
-inline Vector3<T2> Vector3<T>::inversed() const noexcept
-{
-    return {
-        T2(1) / getX(),
-        T2(1) / getY(),
-        T2(1) / getZ()
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector3<T> Vector3<T>::createSingle(T val) noexcept
-{
-    return {val, val, val};
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() + std::declval<T2>())>
-operator+(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
-{
-    return {
-        lhs.getX() + rhs.getX(),
-        lhs.getY() + rhs.getY(),
-        lhs.getZ() + rhs.getZ()
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() - std::declval<T2>())>
-operator-(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
-{
-    return {
-        lhs.getX() - rhs.getX(),
-        lhs.getY() - rhs.getY(),
-        lhs.getZ() - rhs.getZ()
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(const Vector3<T1>& lhs, T2 rhs) noexcept
-{
-    return {
-        lhs.getX() * rhs,
-        lhs.getY() * rhs,
-        lhs.getZ() * rhs
-    };
-}
-
-/* ************************************************************************ */
-
 template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
-operator*(T1 lhs, const Vector3<T2>& rhs) noexcept
-{
-    return {
-        lhs * rhs.getX(),
-        lhs * rhs.getY(),
-        lhs * rhs.getZ()
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(const Vector3<T1>& lhs, T2 rhs) noexcept
-{
-    return {
-        lhs.getX() / rhs,
-        lhs.getY() / rhs,
-        lhs.getZ() / rhs
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() / std::declval<T2>())>
-operator/(T1 lhs, const Vector3<T2>& rhs) noexcept
-{
-    return {
-        lhs / rhs.getX(),
-        lhs / rhs.getY(),
-        lhs / rhs.getZ()
-    };
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline bool operator==(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
-{
-    return
-        lhs.getX() == rhs.getX() &&
-        lhs.getY() == rhs.getY() &&
-        lhs.getZ() == rhs.getZ()
-    ;
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline bool operator!=(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
-{
-    return !operator==(lhs, rhs);
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline
-Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
+inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())> cross(
+    const Vector3<T1>& lhs,
+    const Vector3<T2>& rhs
+)
 {
     return {
         lhs.getY() * rhs.getZ() - lhs.getZ() * rhs.getY(),
@@ -1105,20 +531,6 @@ cross(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
 
 /* ************************************************************************ */
 
-template<typename T1, typename T2>
-inline
-decltype(std::declval<T1>() * std::declval<T2>())
-dot(const Vector3<T1>& lhs, const Vector3<T2>& rhs) noexcept
-{
-    return {
-        lhs.getX() * rhs.getX() +
-        lhs.getY() * rhs.getY() +
-        lhs.getZ() * rhs.getZ()
-    };
-}
-
-/* ************************************************************************ */
-
 }
 }
 
diff --git a/include/cece/math/VectorBase.hpp b/include/cece/math/VectorBase.hpp
new file mode 100644
index 0000000..216169c
--- /dev/null
+++ b/include/cece/math/VectorBase.hpp
@@ -0,0 +1,1117 @@
+/* ************************************************************************ */
+/* Georgiev Lab (c) 2015-2017                                               */
+/* ************************************************************************ */
+/* Department of Cybernetics                                                */
+/* Faculty of Applied Sciences                                              */
+/* University of West Bohemia in Pilsen                                     */
+/* ************************************************************************ */
+/*                                                                          */
+/* This file is part of CeCe.                                               */
+/*                                                                          */
+/* CeCe is free software: you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by     */
+/* the Free Software Foundation, either version 3 of the License, or        */
+/* (at your option) any later version.                                      */
+/*                                                                          */
+/* CeCe is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/* GNU General Public License for more details.                             */
+/*                                                                          */
+/* You should have received a copy of the GNU General Public License        */
+/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
+/*                                                                          */
+/* ************************************************************************ */
+
+#pragma once
+
+/* ************************************************************************ */
+
+// C++
+#include <cmath>
+#include <type_traits>
+
+// CeCe
+#include "cece/common.hpp"
+#include "cece/Assert.hpp"
+#include "cece/math/Zero.hpp"
+
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector adaptor.
+ *
+ * @tparam     VectorType  The vector type.
+ * @tparam     T           Value type.
+ * @tparam     Tags        Additional tags.
+ */
+template<
+    template<typename, int...> typename VectorType,
+    typename T,
+    int... Tags
+>
+class VectorBase
+{
+
+// Public Types
+public:
+
+
+    /// VectorBase value type.
+    using ValueType = T;
+
+
+// Public Operators
+public:
+
+
+    /**
+     * @brief      Unary plus operator.
+     *
+     * @return     Vector.
+     */
+    VectorType<T, Tags...> operator+() const noexcept;
+
+
+    /**
+     * @brief      Unary minus operator.
+     *
+     * @return     Vector.
+     */
+    VectorType<T, Tags...> operator-() const noexcept;
+
+
+    /**
+     * @brief      Addition operator.
+     *
+     * @param      rhs        The right operand.
+     *
+     * @tparam     T1         The second type.
+     *
+     * @return     *this.
+     */
+    template<typename T1>
+    VectorType<T, Tags...>& operator+=(const VectorType<T1, Tags...>& rhs);
+
+
+    /**
+     * @brief      Subtraction operator.
+     *
+     * @param      rhs        The right operand.
+     *
+     * @tparam     T1         The second type.
+     *
+     * @return     *this.
+     */
+    template<typename T1>
+    VectorType<T, Tags...>& operator-=(const VectorType<T1, Tags...>& rhs);
+
+
+    /**
+     * @brief      Multiplication operator.
+     *
+     * @param      rhs        The right operand.
+     *
+     * @tparam     T1         Type of right operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1>
+    VectorType<T, Tags...>& operator*=(T1 rhs);
+
+
+    /**
+     * @brief      Multiplication operator.
+     *
+     * @param      rhs        The right operand.
+     *
+     * @tparam     T1         The second type.
+     *
+     * @return     *this.
+     */
+    template<typename T1>
+    VectorType<T, Tags...>& operator*=(const VectorType<T1, Tags...>& rhs);
+
+
+    /**
+     * @brief      Division operator.
+     *
+     * @param      rhs        The right operand.
+     *
+     * @tparam     T1         Type of right operand.
+     *
+     * @return     *this.
+     */
+    template<typename T1>
+    VectorType<T, Tags...>& operator/=(T1 rhs);
+
+
+    /**
+     * @brief      Division operator.
+     *
+     * @param      rhs        Right operand.
+     *
+     * @tparam     T1         The second type.
+     *
+     * @return     *this.
+     */
+    template<typename T1>
+    VectorType<T, Tags...>& operator/=(const VectorType<T1, Tags...>& rhs);
+
+
+    /**
+     * @brief      Access operator.
+     *
+     * @param      pos   The position.
+     *
+     * @return     Reference to the element.
+     */
+    T& operator[](int pos);
+
+
+    /**
+     * @brief      Access operator.
+     *
+     * @param      pos   The position.
+     *
+     * @return     Reference to the element.
+     */
+    const T& operator[](int pos) const;
+
+
+// Public Accessors
+public:
+
+
+    /**
+     * @brief      Returns vector size.
+     *
+     * @return     The size.
+     */
+    int getSize() const;
+
+
+// Public Operations
+public:
+
+
+    /**
+     * @brief      Calculate vector length.
+     *
+     * @return     The length.
+     */
+    T getLength() const;
+
+
+    /**
+     * @brief      Calculate vector length - squared.
+     *
+     * @return     The length squared.
+     */
+    decltype(std::declval<T>() * std::declval<T>()) getLengthSquared() const;
+
+};
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Addition operator.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Result vector.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+VectorType<decltype(std::declval<T1>() + std::declval<T2>()), Tags...> operator+(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Substract operator.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Result vector.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+VectorType<decltype(std::declval<T1>() - std::declval<T2>()), Tags...> operator-(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Multiplication operator.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Result vector.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Multiplication operator.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Result vector.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*(
+    const VectorType<T1, Tags...>& lhs,
+    const T2& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Multiplication operator.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Result vector.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*(
+    const T1& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Division operator.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Result vector.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Division operator.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Result vector.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/(
+    const VectorType<T1, Tags...>& lhs,
+    const T2& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Division operator.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Result vector.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/(
+    const T1& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Operation result.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+bool operator==(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Operation result.
+ */
+template<template<typename, int...> typename VectorType, typename T1, int... Tags>
+bool operator==(
+    const VectorType<T1, Tags...>& lhs,
+    const Zero_t& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Operation result.
+ */
+template<template<typename, int...> typename VectorType, typename T2, int... Tags>
+bool operator==(
+    const Zero_t& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Operation result.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+bool operator!=(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Operation result.
+ */
+template<template<typename, int...> typename VectorType, typename T1, int... Tags>
+bool operator!=(
+    const VectorType<T1, Tags...>& lhs,
+    const Zero_t& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Operation result.
+ */
+template<template<typename, int...> typename VectorType, typename T2, int... Tags>
+bool operator!=(
+    const Zero_t& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Operation result.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+bool operator<(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Operation result.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+bool operator<=(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Operation result.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+bool operator>(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Compare vectors.
+ *
+ * @param      lhs         The left operand.
+ * @param      rhs         The right operand.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T1          Type of value in first VectorBase.
+ * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Operation result.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+bool operator>=(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Calculate dot product of two vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @return     Dot product.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+decltype(std::declval<T1>() * std::declval<T2>()) dot(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Calculate distance of two vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @return     Distance.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+decltype(std::declval<decltype(std::declval<T1>() - std::declval<T2>())>() * std::declval<decltype(std::declval<T1>() - std::declval<T2>())>()) distanceSquared(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Calculate distance of two vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @return     Distance.
+ */
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+decltype(std::declval<T1>() - std::declval<T2>()) distance(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+);
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+inline VectorType<T, Tags...> VectorBase<VectorType, T, Tags...>::operator+() const noexcept
+{
+    return *static_cast<const VectorType<T, Tags...>*>(this);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+inline VectorType<T, Tags...> VectorBase<VectorType, T, Tags...>::operator-() const noexcept
+{
+    VectorType<T, Tags...> res;
+
+    for (int i = 0; i < getSize(); ++i)
+        res[i] = -(*this)[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+template<typename T1>
+inline VectorType<T, Tags...>& VectorBase<VectorType, T, Tags...>::operator+=(const VectorType<T1, Tags...>& rhs)
+{
+    for (int i = 0; i < getSize(); ++i)
+        (*this)[i] += rhs[i];
+
+    return *static_cast<VectorType<T, Tags...>*>(this);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+template<typename T1>
+inline VectorType<T, Tags...>& VectorBase<VectorType, T, Tags...>::operator-=(const VectorType<T1, Tags...>& rhs)
+{
+    for (int i = 0; i < getSize(); ++i)
+        (*this)[i] -= rhs[i];
+
+    return *static_cast<VectorType<T, Tags...>*>(this);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+template<typename T1>
+inline VectorType<T, Tags...>& VectorBase<VectorType, T, Tags...>::operator*=(T1 rhs)
+{
+    for (int i = 0; i < getSize(); ++i)
+        (*this)[i] *= rhs;
+
+    return *static_cast<VectorType<T, Tags...>*>(this);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+template<typename T1>
+inline VectorType<T, Tags...>& VectorBase<VectorType, T, Tags...>::operator*=(const VectorType<T1, Tags...>& rhs)
+{
+    for (int i = 0; i < getSize(); ++i)
+        (*this)[i] *= rhs[i];
+
+    return *static_cast<VectorType<T, Tags...>*>(this);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+template<typename T1>
+inline VectorType<T, Tags...>& VectorBase<VectorType, T, Tags...>::operator/=(T1 rhs)
+{
+    for (int i = 0; i < getSize(); ++i)
+        (*this)[i] /= rhs;
+
+    return *static_cast<VectorType<T, Tags...>*>(this);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+template<typename T1>
+inline VectorType<T, Tags...>& VectorBase<VectorType, T, Tags...>::operator/=(const VectorType<T1, Tags...>& rhs)
+{
+    for (int i = 0; i < getSize(); ++i)
+        (*this)[i] /= rhs[i];
+
+    return *static_cast<VectorType<T, Tags...>*>(this);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+inline T& VectorBase<VectorType, T, Tags...>::operator[](int pos)
+{
+    // TODO: recursion possibility
+    return (*static_cast<VectorType<T, Tags...>*>(this))[pos];
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+inline const T& VectorBase<VectorType, T, Tags...>::operator[](int pos) const
+{
+    // TODO: recursion possibility
+    return (*static_cast<const VectorType<T, Tags...>*>(this))[pos];
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+inline int VectorBase<VectorType, T, Tags...>::getSize() const
+{
+    // TODO: recursion possibility
+    return static_cast<const VectorType<T, Tags...>*>(this)->getSize();
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+inline T VectorBase<VectorType, T, Tags...>::getLength() const
+{
+    using std::sqrt;
+    return static_cast<T>(sqrt(getLengthSquared()));
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+inline decltype(std::declval<T>() * std::declval<T>()) VectorBase<VectorType, T, Tags...>::getLengthSquared() const
+{
+    decltype(std::declval<T>() * std::declval<T>()) res{};
+
+    for (int i = 0; i < getSize(); ++i)
+        res += (*this)[i] * (*this)[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline VectorType<decltype(std::declval<T1>() + std::declval<T2>()), Tags...> operator+(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    VectorType<decltype(std::declval<T1>() + std::declval<T2>()), Tags...> res;
+
+    CECE_ASSERT(lhs.getSize() == rhs.getSize());
+    CECE_ASSERT(res.getSize() == lhs.getSize());
+    CECE_ASSERT(res.getSize() == rhs.getSize());
+
+    for (int i = 0; i < res.getSize(); ++i)
+        res[i] = lhs[i] + rhs[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline VectorType<decltype(std::declval<T1>() - std::declval<T2>()), Tags...> operator-(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    VectorType<decltype(std::declval<T1>() - std::declval<T2>()), Tags...> res;
+
+    CECE_ASSERT(lhs.getSize() == rhs.getSize());
+    CECE_ASSERT(res.getSize() == lhs.getSize());
+    CECE_ASSERT(res.getSize() == rhs.getSize());
+
+    for (int i = 0; i < res.getSize(); ++i)
+        res[i] = lhs[i] - rhs[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> res;
+
+    CECE_ASSERT(lhs.getSize() == rhs.getSize());
+    CECE_ASSERT(res.getSize() == lhs.getSize());
+    CECE_ASSERT(res.getSize() == rhs.getSize());
+
+    for (int i = 0; i < res.getSize(); ++i)
+        res[i] = lhs[i] * rhs[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*(
+    const VectorType<T1, Tags...>& lhs,
+    const T2& rhs
+)
+{
+    VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> res;
+
+    CECE_ASSERT(res.getSize() == lhs.getSize());
+
+    for (int i = 0; i < res.getSize(); ++i)
+        res[i] = lhs[i] * rhs;
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*(
+    const T1& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> res;
+
+    CECE_ASSERT(res.getSize() == rhs.getSize());
+
+    for (int i = 0; i < res.getSize(); ++i)
+        res[i] = lhs * rhs[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> res;
+
+    CECE_ASSERT(lhs.getSize() == rhs.getSize());
+    CECE_ASSERT(res.getSize() == lhs.getSize());
+    CECE_ASSERT(res.getSize() == rhs.getSize());
+
+    for (int i = 0; i < res.getSize(); ++i)
+        res[i] = lhs[i] / rhs[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/(
+    const VectorType<T1, Tags...>& lhs,
+    const T2& rhs
+)
+{
+    VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> res;
+
+    CECE_ASSERT(res.getSize() == lhs.getSize());
+
+    for (int i = 0; i < res.getSize(); ++i)
+        res[i] = lhs[i] / rhs;
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/(
+    const T1& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> res;
+
+    CECE_ASSERT(res.getSize() == rhs.getSize());
+
+    for (int i = 0; i < res.getSize(); ++i)
+        res[i] = lhs / rhs[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline bool operator==(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    bool res = true;
+
+    CECE_ASSERT(lhs.getSize() == rhs.getSize());
+
+    for (int i = 0; i < lhs.getSize(); ++i)
+        res = res && lhs[i] == rhs[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, int... Tags>
+inline bool operator==(
+    const VectorType<T1, Tags...>& lhs,
+    const Zero_t& rhs
+)
+{
+    return operator==(lhs, VectorType<T1, Tags...>(Zero));
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T2, int... Tags>
+inline bool operator==(
+    const Zero_t& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    return operator==(VectorType<T2, Tags...>(lhs), rhs);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline bool operator!=(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    return !operator==(lhs, rhs);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, int... Tags>
+inline bool operator!=(
+    const VectorType<T1, Tags...>& lhs,
+    const Zero_t& rhs
+)
+{
+    return !operator==(lhs, rhs);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T2, int... Tags>
+inline bool operator!=(
+    const Zero_t& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    return !operator==(lhs, rhs);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline bool operator<(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    bool res = true;
+
+    CECE_ASSERT(lhs.getSize() == rhs.getSize());
+
+    for (int i = 0; i < lhs.getSize(); ++i)
+        res = res && (lhs[i] < rhs[i]);
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline bool operator<=(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    return !operator>(lhs, rhs);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline bool operator>(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    return operator<(rhs, lhs);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline bool operator>=(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    return !operator<(lhs, rhs);
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline decltype(std::declval<T1>() * std::declval<T2>()) dot(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    decltype(std::declval<T1>() * std::declval<T2>()) res{};
+
+    CECE_ASSERT(lhs.getSize() == rhs.getSize());
+
+    for (int i = 0; i < lhs.getSize(); ++i)
+        res += lhs[i] * rhs[i];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline decltype(std::declval<decltype(std::declval<T1>() - std::declval<T2>())>() * std::declval<decltype(std::declval<T1>() - std::declval<T2>())>()) distanceSquared(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    return (lhs - rhs).getLengthSquared();
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+inline decltype(std::declval<T1>() - std::declval<T2>()) distance(
+    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T2, Tags...>& rhs
+)
+{
+    return (lhs - rhs).getLength();
+}
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
diff --git a/include/cece/math/VectorRange.hpp b/include/cece/math/VectorRange.hpp
index e9f708e..4ef1912 100644
--- a/include/cece/math/VectorRange.hpp
+++ b/include/cece/math/VectorRange.hpp
@@ -203,7 +203,7 @@ template<typename T>
 constexpr IteratorRange<IteratorVector<T>> range(Vector<T> begin, Vector<T> end) noexcept
 {
     return makeRange(
-        IteratorVector<T>{begin, end - T{1}, begin},
+        IteratorVector<T>{begin, end - Vector<T>{1}, begin},
         IteratorVector<T>{Vector<T>{begin.getX(), end.getY()}, Zero, Zero}
     );
 }
diff --git a/unittests/math/CMakeLists.txt b/unittests/math/CMakeLists.txt
index 4893905..97ea6a5 100644
--- a/unittests/math/CMakeLists.txt
+++ b/unittests/math/CMakeLists.txt
@@ -25,6 +25,7 @@
 
 cece_add_test(math
     SOURCES
+        VectorBase_test.cpp
         Vector_test.cpp
         Vector2_test.cpp
         Vector3_test.cpp
diff --git a/unittests/math/Vector2_test.cpp b/unittests/math/Vector2_test.cpp
index 48aaa1d..e6bad88 100644
--- a/unittests/math/Vector2_test.cpp
+++ b/unittests/math/Vector2_test.cpp
@@ -28,6 +28,7 @@
 
 // CeCe
 #include "cece/math/Vector2.hpp"
+#include "cece/unit/math.hpp"
 
 /* ************************************************************************ */
 
@@ -56,6 +57,16 @@ TEST(Vector2, ctor)
         EXPECT_EQ(0, vec[1]);
     }
 
+    {
+        Vector2<float> vec(12.3f);
+
+        EXPECT_FLOAT_EQ(12.3f, vec.getX());
+        EXPECT_FLOAT_EQ(12.3f, vec.getY());
+        EXPECT_FLOAT_EQ(12.3f, vec[0]);
+        EXPECT_FLOAT_EQ(12.3f, vec[1]);
+    }
+
+
     {
         Vector2<float> vec = {1.2f, 3.0f};
 
@@ -266,36 +277,6 @@ TEST(Vector2, operators)
 
 /* ************************************************************************ */
 
-TEST(Vector2, inRange)
-{
-    {
-        const Vector2<float> vecMin{-10.0f, -5.0f};
-        const Vector2<float> vecMax{10.0f, 20.0f};
-
-        Vector2<float> vec1;
-        Vector2<float> vec2{-15.0f, 0.0f};
-        Vector2<float> vec3{5.0f, 0.0f};
-
-        EXPECT_TRUE(vec1.inRange(vecMin, vecMax));
-        EXPECT_FALSE(vec2.inRange(vecMin, vecMax));
-        EXPECT_TRUE(vec3.inRange(vecMin, vecMax));
-    }
-
-    {
-        const Vector2<float> vecMax{10.0f, 20.0f};
-
-        Vector2<float> vec1;
-        Vector2<float> vec2{-15.0f, 0.0f};
-        Vector2<float> vec3{5.0f, 0.0f};
-
-        EXPECT_TRUE(vec1.inRange(vecMax));
-        EXPECT_FALSE(vec2.inRange(vecMax));
-        EXPECT_TRUE(vec3.inRange(vecMax));
-    }
-}
-
-/* ************************************************************************ */
-
 TEST(Vector2, memberFunctions)
 {
     {
@@ -321,55 +302,6 @@ TEST(Vector2, memberFunctions)
 
         EXPECT_FLOAT_EQ(5, vec.getLengthSquared());
     }
-
-    {
-        const Vector2<float> vec;
-
-        EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
-    }
-
-    {
-        const Vector2<float> vec{1.0f, 2.0f};
-
-        EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
-    }
-
-    {
-        const Vector2<float> vec1{1.0f, 2.0f};
-        const Vector2<float> vec2{5.0f, 4.0f};
-
-        EXPECT_FLOAT_EQ(20.0f, vec1.distanceSquared(vec2));
-    }
-
-    {
-        const Vector2<float> vec1{1.0f, 2.0f};
-        const Vector2<float> vec2{5.0f, 4.0f};
-
-        EXPECT_FLOAT_EQ(4.4721360f, vec1.distance(vec2));
-    }
-
-    {
-        const Vector2<float> vec{1.0f, 2.0f};
-
-        auto inv = vec.inversed();
-
-        EXPECT_FLOAT_EQ(1.0f, inv[0]);
-        EXPECT_FLOAT_EQ(0.5f, inv[1]);
-    }
-
-    {
-        auto vec = Vector2<float>::createSingle(1);
-
-        EXPECT_FLOAT_EQ(1.0f, vec[0]);
-        EXPECT_FLOAT_EQ(1.0f, vec[1]);
-    }
-
-    {
-        auto vec = Vector2<float>::createSingle(375.1721f);
-
-        EXPECT_FLOAT_EQ(375.1721f, vec[0]);
-        EXPECT_FLOAT_EQ(375.1721f, vec[1]);
-    }
 }
 
 /* ************************************************************************ */
@@ -421,7 +353,7 @@ TEST(Vector2, functions)
         EXPECT_EQ(1, vec.getX());
         EXPECT_EQ(0, vec.getY());
 
-        auto rot = vec.rotated(unit::deg2rad(90));
+        auto rot = rotate(vec, unit::deg2rad(90));
 
         EXPECT_EQ(0, rot.getX());
         EXPECT_EQ(1, rot.getY());
@@ -433,7 +365,7 @@ TEST(Vector2, functions)
         EXPECT_EQ(1, vec.getX());
         EXPECT_EQ(0, vec.getY());
 
-        auto rot = vec.rotated(unit::deg2rad(-90));
+        auto rot = rotate(vec, unit::deg2rad(-90));
 
         EXPECT_EQ(0, rot.getX());
         EXPECT_EQ(-1, rot.getY());
@@ -445,7 +377,7 @@ TEST(Vector2, functions)
         EXPECT_EQ(1, vec.getX());
         EXPECT_EQ(0, vec.getY());
 
-        auto rot = vec.rotated(unit::deg2rad(180));
+        auto rot = rotate(vec, unit::deg2rad(180));
 
         EXPECT_EQ(-1, rot.getX());
         EXPECT_EQ(0, rot.getY());
@@ -469,6 +401,32 @@ TEST(Vector2, functions)
             res
         );
     }
+
+    {
+        const Vector2<float> vec;
+
+        EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec));
+    }
+
+    {
+        const Vector2<float> vec{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec));
+    }
+
+    {
+        const Vector2<float> vec1{1.0f, 2.0f};
+        const Vector2<float> vec2{5.0f, 4.0f};
+
+        EXPECT_FLOAT_EQ(20.0f, distanceSquared(vec1, vec2));
+    }
+
+    {
+        const Vector2<float> vec1{1.0f, 2.0f};
+        const Vector2<float> vec2{5.0f, 4.0f};
+
+        EXPECT_FLOAT_EQ(4.4721360f, distance(vec1, vec2));
+    }
 }
 
 /* ************************************************************************ */
diff --git a/unittests/math/Vector3_test.cpp b/unittests/math/Vector3_test.cpp
index 9d9e088..ddb7eee 100644
--- a/unittests/math/Vector3_test.cpp
+++ b/unittests/math/Vector3_test.cpp
@@ -134,6 +134,55 @@ TEST(Vector3, ctorZero)
 
 /* ************************************************************************ */
 
+TEST(Vector3, ctorSingle)
+{
+    {
+        Vector3<int> vec{1};
+
+        EXPECT_EQ(1, vec.getX());
+        EXPECT_EQ(1, vec.getY());
+        EXPECT_EQ(1, vec.getZ());
+        EXPECT_EQ(1, vec[0]);
+        EXPECT_EQ(1, vec[1]);
+        EXPECT_EQ(1, vec[2]);
+    }
+
+    {
+        Vector3<unsigned int> vec{3};
+
+        EXPECT_EQ(3, vec.getX());
+        EXPECT_EQ(3, vec.getY());
+        EXPECT_EQ(3, vec.getZ());
+        EXPECT_EQ(3, vec[0]);
+        EXPECT_EQ(3, vec[1]);
+        EXPECT_EQ(3, vec[2]);
+    }
+
+    {
+        Vector3<float> vec{1.2f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec.getX());
+        EXPECT_FLOAT_EQ(1.2f, vec.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec.getZ());
+        EXPECT_FLOAT_EQ(1.2f, vec[0]);
+        EXPECT_FLOAT_EQ(1.2f, vec[1]);
+        EXPECT_FLOAT_EQ(1.2f, vec[2]);
+    }
+
+    {
+        Vector3<double> vec{1.2};
+
+        EXPECT_DOUBLE_EQ(1.2, vec.getX());
+        EXPECT_DOUBLE_EQ(1.2, vec.getY());
+        EXPECT_DOUBLE_EQ(1.2, vec.getZ());
+        EXPECT_DOUBLE_EQ(1.2, vec[0]);
+        EXPECT_DOUBLE_EQ(1.2, vec[1]);
+        EXPECT_DOUBLE_EQ(1.2, vec[2]);
+    }
+}
+
+/* ************************************************************************ */
+
 TEST(Vector3, ctorElements)
 {
     {
@@ -988,36 +1037,6 @@ TEST(Vector3, operatorDiv)
 
 /* ************************************************************************ */
 
-TEST(Vector3, inRange)
-{
-    {
-        const Vector3<float> vecMin{-10.0f, -5.0f, -2.0f};
-        const Vector3<float> vecMax{10.0f, 20.0f, 5.0f};
-
-        Vector3<float> vec1;
-        Vector3<float> vec2{-15.0f, 0.0f, 0.0f};
-        Vector3<float> vec3{5.0f, 0.0f, 3.0f};
-
-        EXPECT_TRUE(vec1.inRange(vecMin, vecMax));
-        EXPECT_FALSE(vec2.inRange(vecMin, vecMax));
-        EXPECT_TRUE(vec3.inRange(vecMin, vecMax));
-    }
-
-    {
-        const Vector3<float> vecMax{10.0f, 20.0f, 8.0f};
-
-        Vector3<float> vec1;
-        Vector3<float> vec2{-15.0f, 0.0f, 3.0f};
-        Vector3<float> vec3{5.0f, 0.0f, 3.0f};
-
-        EXPECT_TRUE(vec1.inRange(vecMax));
-        EXPECT_FALSE(vec2.inRange(vecMax));
-        EXPECT_TRUE(vec3.inRange(vecMax));
-    }
-}
-
-/* ************************************************************************ */
-
 TEST(Vector3, memberFunctions)
 {
     {
@@ -1043,57 +1062,6 @@ TEST(Vector3, memberFunctions)
 
         EXPECT_FLOAT_EQ(14, vec.getLengthSquared());
     }
-
-    {
-        const Vector3<float> vec;
-
-        EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
-    }
-
-    {
-        const Vector3<float> vec{1.0f, 2.0f, 3.0f};
-
-        EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
-    }
-
-    {
-        const Vector3<float> vec1{1.0f, 2.0f, 3.0f};
-        const Vector3<float> vec2{5.0f, 4.0f, 3.0f};
-
-        EXPECT_FLOAT_EQ(20.0f, vec1.distanceSquared(vec2));
-    }
-
-    {
-        const Vector3<float> vec1{1.0f, 2.0f, 3.0f};
-        const Vector3<float> vec2{5.0f, 4.0f, 3.0f};
-
-        EXPECT_FLOAT_EQ(4.4721360f, vec1.distance(vec2));
-    }
-
-    {
-        const Vector3<float> vec{1.0f, 2.0f, 3.0f};
-
-        auto inv = vec.inversed();
-
-        EXPECT_FLOAT_EQ(1.0f, inv[0]);
-        EXPECT_FLOAT_EQ(0.5f, inv[1]);
-        EXPECT_FLOAT_EQ(1.0f / 3.0f, inv[2]);
-    }
-
-    {
-        auto vec = Vector3<float>::createSingle(1);
-
-        EXPECT_FLOAT_EQ(1.0f, vec[0]);
-        EXPECT_FLOAT_EQ(1.0f, vec[1]);
-        EXPECT_FLOAT_EQ(1.0f, vec[2]);
-    }
-
-    {
-        auto vec = Vector3<float>::createSingle(375.1721f);
-
-        EXPECT_FLOAT_EQ(375.1721f, vec[0]);
-        EXPECT_FLOAT_EQ(375.1721f, vec[1]);
-    }
 }
 
 /* ************************************************************************ */
@@ -1353,6 +1321,32 @@ TEST(Vector3, functions)
             res
         );
     }
+
+    {
+        const Vector3<float> vec;
+
+        EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec));
+    }
+
+    {
+        const Vector3<float> vec{1.0f, 2.0f, 3.0f};
+
+        EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec));
+    }
+
+    {
+        const Vector3<float> vec1{1.0f, 2.0f, 3.0f};
+        const Vector3<float> vec2{5.0f, 4.0f, 3.0f};
+
+        EXPECT_FLOAT_EQ(20.0f, distanceSquared(vec1, vec2));
+    }
+
+    {
+        const Vector3<float> vec1{1.0f, 2.0f, 3.0f};
+        const Vector3<float> vec2{5.0f, 4.0f, 3.0f};
+
+        EXPECT_FLOAT_EQ(4.4721360f, distance(vec1, vec2));
+    }
 }
 
 /* ************************************************************************ */
diff --git a/unittests/math/VectorBase_test.cpp b/unittests/math/VectorBase_test.cpp
new file mode 100644
index 0000000..770d3bf
--- /dev/null
+++ b/unittests/math/VectorBase_test.cpp
@@ -0,0 +1,431 @@
+/* ************************************************************************ */
+/* Georgiev Lab (c) 2015-2017                                               */
+/* ************************************************************************ */
+/* Department of Cybernetics                                                */
+/* Faculty of Applied Sciences                                              */
+/* University of West Bohemia in Pilsen                                     */
+/* ************************************************************************ */
+/*                                                                          */
+/* This file is part of CeCe.                                               */
+/*                                                                          */
+/* CeCe is free software: you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by     */
+/* the Free Software Foundation, either version 3 of the License, or        */
+/* (at your option) any later version.                                      */
+/*                                                                          */
+/* CeCe is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/* GNU General Public License for more details.                             */
+/*                                                                          */
+/* You should have received a copy of the GNU General Public License        */
+/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
+/*                                                                          */
+/* ************************************************************************ */
+
+// GTest
+#include "gtest/gtest.h"
+
+// CeCe
+#include "cece/math/VectorBase.hpp"
+
+/* ************************************************************************ */
+
+using namespace cece;
+using namespace cece::math;
+
+/* ************************************************************************ */
+
+template<typename T>
+struct Vec2 : public VectorBase<Vec2, T>
+{
+    Vec2() : x{}, y{} {}
+    Vec2(T x, T y) : x{x}, y{y} {}
+
+    T& operator[](int pos) { return (&x)[pos]; }
+    const T& operator[](int pos) const { return (&x)[pos]; }
+
+    int getSize() const noexcept { return 2; }
+    T getX() const noexcept { return x; }
+    void setX(T x) { this->x = x; }
+    T getY() const noexcept { return y; }
+    void setY(T y) { this->y = y; }
+
+    T x;
+    T y;
+};
+
+/* ************************************************************************ */
+
+template<typename T>
+std::ostream& operator<<(std::ostream& os, const Vec2<T>& vec)
+{
+    return os << "(x = " << vec.x << ", y = " << vec.y << ")";
+}
+
+/* ************************************************************************ */
+
+TEST(VectorBase, operators)
+{
+    {
+        Vec2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        Vec2<float> vec2 = +vec1;
+
+        EXPECT_FLOAT_EQ(1.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec2[1]);
+    }
+
+    {
+        Vec2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        Vec2<float> vec2 = -vec1;
+
+        EXPECT_FLOAT_EQ(-1.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(-2.0f, vec2[1]);
+    }
+
+    {
+        Vec2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        Vec2<float> vec2{1.0f, 2.0f};
+        vec1 += vec2;
+
+        EXPECT_FLOAT_EQ(2.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
+    }
+
+    {
+        Vec2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        Vec2<float> vec2{1.0f, 2.0f};
+        vec1 -= vec2;
+
+        EXPECT_FLOAT_EQ(0.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(0.0f, vec1[1]);
+    }
+
+    {
+        Vec2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        vec1 *= 2.0;
+
+        EXPECT_FLOAT_EQ(2.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(4.0f, vec1[1]);
+    }
+
+    {
+        Vec2<float> vec1{1.0f, 2.0f};
+        Vec2<float> vec2{5.0f, 3.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        EXPECT_FLOAT_EQ(5.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+
+        vec1 *= vec2;
+
+        EXPECT_FLOAT_EQ(1.0f * 5.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f * 3.0f, vec1[1]);
+    }
+
+    {
+        Vec2<float> vec1{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        vec1 /= 2.0;
+
+        EXPECT_FLOAT_EQ(0.5f, vec1[0]);
+        EXPECT_FLOAT_EQ(1.0f, vec1[1]);
+    }
+
+    {
+        Vec2<float> vec1{1.0f, 2.0f};
+        Vec2<float> vec2{2.0f, 6.0f};
+
+        EXPECT_FLOAT_EQ(1.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f, vec1[1]);
+
+        EXPECT_FLOAT_EQ(2.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(6.0f, vec2[1]);
+
+        vec1 /= vec2;
+
+        EXPECT_FLOAT_EQ(1.0f / 2.0f, vec1[0]);
+        EXPECT_FLOAT_EQ(2.0f / 6.0f, vec1[1]);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(VectorBase, memberFunctions)
+{
+    {
+        const Vec2<float> vec;
+
+        EXPECT_FLOAT_EQ(0, vec.getLength());
+    }
+
+    {
+        const Vec2<float> vec{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(2.2360680f, vec.getLength());
+    }
+
+    {
+        const Vec2<float> vec;
+
+        EXPECT_FLOAT_EQ(0, vec.getLengthSquared());
+    }
+
+    {
+        const Vec2<float> vec{1.0f, 2.0f};
+
+        EXPECT_FLOAT_EQ(5, vec.getLengthSquared());
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(VectorBase, mutators)
+{
+    {
+        Vec2<int> vec;
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+
+        vec.setX(100);
+
+        EXPECT_EQ(100, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+
+        vec.setY(50);
+
+        EXPECT_EQ(100, vec.getX());
+        EXPECT_EQ(50, vec.getY());
+    }
+
+    {
+        Vec2<int> vec;
+
+        EXPECT_EQ(0, vec.x);
+        EXPECT_EQ(0, vec.y);
+
+        vec.x = 100;
+
+        EXPECT_EQ(100, vec.x);
+        EXPECT_EQ(0, vec.y);
+
+        vec.y = 50;
+
+        EXPECT_EQ(100, vec.x);
+        EXPECT_EQ(50, vec.y);
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(VectorBase, functions)
+{
+    {
+        Vec2<float> vec1(0.94333f, 0.73733f);
+        Vec2<float> vec2(0.16110f, 0.61872f);
+
+        EXPECT_FLOAT_EQ(0.94333f, vec1.getX());
+        EXPECT_FLOAT_EQ(0.73733f, vec1.getY());
+
+        EXPECT_FLOAT_EQ(0.16110f, vec2.getX());
+        EXPECT_FLOAT_EQ(0.61872f, vec2.getY());
+
+        auto res = dot(vec1, vec2);
+
+        EXPECT_FLOAT_EQ(
+            0.94333f * 0.16110f +
+            0.73733f * 0.61872f,
+            res
+        );
+    }
+}
+
+/* ************************************************************************ */
+
+TEST(VectorBase, freeOperators)
+{
+    {
+        const Vec2<float> vec1(5.3f, 8.9f);
+        const Vec2<float> vec2(3.3f, 1.2f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+
+        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
+
+        const auto vec3 = vec1 + vec2;
+        const auto vec4 = vec2 + vec1;
+
+        EXPECT_FLOAT_EQ(5.3f + 3.3f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f + 1.2f, vec3.getY());
+
+        EXPECT_FLOAT_EQ(3.3f + 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(1.2f + 8.9f, vec4.getY());
+    }
+
+    {
+        const Vec2<float> vec1(5.3f, 8.9f);
+        const Vec2<float> vec2(3.3f, 1.2f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+
+        EXPECT_FLOAT_EQ(3.3f, vec2.getX());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getY());
+
+        const auto vec3 = vec1 - vec2;
+        const auto vec4 = vec2 - vec1;
+
+        EXPECT_FLOAT_EQ(5.3f - 3.3f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f - 1.2f, vec3.getY());
+
+        EXPECT_FLOAT_EQ(3.3f - 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(1.2f - 8.9f, vec4.getY());
+    }
+
+    {
+        const Vec2<float> vec1(5.3f, 8.9f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+
+        const auto vec3 = vec1 * 3.2f;
+        const auto vec4 = 3.2f * vec1;
+
+        EXPECT_FLOAT_EQ(5.3f * 3.2f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f * 3.2f, vec3.getY());
+
+        EXPECT_FLOAT_EQ(3.2f * 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(3.2f * 8.9f, vec4.getY());
+    }
+
+    {
+        const Vec2<float> vec1(5.3f, 8.9f);
+        const Vec2<float> vec2(1.8f, 3.5f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+
+        EXPECT_FLOAT_EQ(1.8f, vec2.getX());
+        EXPECT_FLOAT_EQ(3.5f, vec2.getY());
+
+        const auto vec3 = vec1 * vec2;
+        const auto vec4 = vec2 * vec1;
+
+        EXPECT_FLOAT_EQ(5.3f * 1.8f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f * 3.5f, vec3.getY());
+
+        EXPECT_FLOAT_EQ(1.8f * 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(3.5f * 8.9f, vec4.getY());
+    }
+
+    {
+        const Vec2<float> vec1(5.3f, 8.9f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+
+        const auto vec3 = vec1 / 3.2f;
+        const auto vec4 = 3.2f / vec1;
+
+        EXPECT_FLOAT_EQ(5.3f / 3.2f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f / 3.2f, vec3.getY());
+
+        EXPECT_FLOAT_EQ(3.2f / 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(3.2f / 8.9f, vec4.getY());
+    }
+
+    {
+        const Vec2<float> vec1(5.3f, 8.9f);
+        const Vec2<float> vec2(1.8f, 3.5f);
+
+        EXPECT_FLOAT_EQ(5.3f, vec1.getX());
+        EXPECT_FLOAT_EQ(8.9f, vec1.getY());
+
+        EXPECT_FLOAT_EQ(1.8f, vec2.getX());
+        EXPECT_FLOAT_EQ(3.5f, vec2.getY());
+
+        const auto vec3 = vec1 / vec2;
+        const auto vec4 = vec2 / vec1;
+
+        EXPECT_FLOAT_EQ(5.3f / 1.8f, vec3.getX());
+        EXPECT_FLOAT_EQ(8.9f / 3.5f, vec3.getY());
+
+        EXPECT_FLOAT_EQ(1.8f / 5.3f, vec4.getX());
+        EXPECT_FLOAT_EQ(3.5f / 8.9f, vec4.getY());
+    }
+
+    {
+        const Vec2<float> vec1(5.3f, 8.9f);
+        const Vec2<float> vec2(5.3f, 8.9f);
+        const Vec2<float> vec3(1.3f, 8.9f);
+        const Vec2<float> vec4(5.3f, 0.9f);
+        const Vec2<float> vec5(1.3f, 0.9f);
+
+        EXPECT_EQ(vec1, vec1);
+        EXPECT_EQ(vec1, vec2);
+        EXPECT_NE(vec1, vec3);
+        EXPECT_NE(vec1, vec4);
+
+        EXPECT_EQ(vec2, vec1);
+        EXPECT_EQ(vec2, vec2);
+        EXPECT_NE(vec2, vec3);
+        EXPECT_NE(vec2, vec4);
+
+        EXPECT_NE(vec3, vec1);
+        EXPECT_NE(vec3, vec2);
+        EXPECT_EQ(vec3, vec3);
+        EXPECT_NE(vec3, vec4);
+
+        EXPECT_NE(vec4, vec1);
+        EXPECT_NE(vec4, vec2);
+        EXPECT_NE(vec4, vec3);
+        EXPECT_EQ(vec4, vec4);
+
+        EXPECT_FALSE(vec1 < vec2);
+
+        EXPECT_GE(vec1, vec1);
+        EXPECT_GE(vec1, vec2);
+        EXPECT_GE(vec1, vec3);
+        EXPECT_GE(vec1, vec4);
+
+        EXPECT_GT(vec1, vec5);
+
+        EXPECT_LE(vec1, vec1);
+        EXPECT_LE(vec1, vec2);
+        EXPECT_LE(vec3, vec1);
+        EXPECT_LE(vec4, vec1);
+
+        EXPECT_LT(vec5, vec1);
+    }
+
+}
+
+/* ************************************************************************ */
diff --git a/unittests/math/Vector_test.cpp b/unittests/math/Vector_test.cpp
index e4ce1f2..e65f32d 100644
--- a/unittests/math/Vector_test.cpp
+++ b/unittests/math/Vector_test.cpp
@@ -499,40 +499,6 @@ TEST(Vector, operators)
 
 /* ************************************************************************ */
 
-TEST(Vector, inRange)
-{
-    {
-        const BasicVector<float, 5> vecMin{-10.0f, -5.0f, 0.0f, 5.0f, 10.0f};
-        const BasicVector<float, 5> vecMax{10.0f, 20.0f, 30.0f, 40.0f, 50.0f};
-
-        BasicVector<float, 5> vec1;
-        BasicVector<float, 5> vec2{-15.0f, 0.0f, 0.0f, 0.0f, 0.0f};
-        BasicVector<float, 5> vec3{5.0f, 0.0f, 0.0f, 10.0f, 40.0f};
-        BasicVector<float, 5> vec4{5.0f, 0.0f, 0.0f, 5.0f, 40.0f};
-
-        EXPECT_FALSE(vec1.inRange(vecMin, vecMax));
-        EXPECT_FALSE(vec2.inRange(vecMin, vecMax));
-        EXPECT_TRUE(vec3.inRange(vecMin, vecMax));
-        EXPECT_TRUE(vec4.inRange(vecMin, vecMax));
-    }
-
-    {
-        const BasicVector<float, 5> vecMax{10.0f, 20.0f, 30.0f, 40.0f, 50.0f};
-
-        BasicVector<float, 5> vec1;
-        BasicVector<float, 5> vec2{-15.0f, 0.0f, 0.0f, 0.0f, 0.0f};
-        BasicVector<float, 5> vec3{5.0f, 0.0f, -3.0f, 0.0f, 40.0f};
-        BasicVector<float, 5> vec4{5.0f, 0.0f, 0.0f, 5.0f, 40.0f};
-
-        EXPECT_TRUE(vec1.inRange(vecMax));
-        EXPECT_FALSE(vec2.inRange(vecMax));
-        EXPECT_FALSE(vec3.inRange(vecMax));
-        EXPECT_TRUE(vec4.inRange(vecMax));
-    }
-}
-
-/* ************************************************************************ */
-
 TEST(Vector, memberFunctions)
 {
     {
@@ -562,88 +528,53 @@ TEST(Vector, memberFunctions)
     {
         const BasicVector<float, 5> vec;
 
-        EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
+        EXPECT_FLOAT_EQ(vec.getLengthSquared(), dot(vec, vec));
     }
 
     {
         const BasicVector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
 
-        EXPECT_FLOAT_EQ(vec.getLengthSquared(), vec.dot(vec));
+        EXPECT_FLOAT_EQ(vec.getLengthSquared(), dot(vec, vec));
     }
 
     {
         const BasicVector<float, 5> vec1;
         const BasicVector<float, 5> vec2;
 
-        EXPECT_FLOAT_EQ(0, vec1.dot(vec2));
+        EXPECT_FLOAT_EQ(0, dot(vec1, vec2));
     }
 
     {
         const BasicVector<float, 5> vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
         const BasicVector<float, 5> vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
 
-        EXPECT_FLOAT_EQ(35, vec1.dot(vec2));
+        EXPECT_FLOAT_EQ(35, dot(vec1, vec2));
     }
 
     {
         const BasicVector<float, 5> vec;
 
-        EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
+        EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec));
     }
 
     {
         const BasicVector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
 
-        EXPECT_FLOAT_EQ(0.0f, vec.distanceSquared(vec));
+        EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec));
     }
 
     {
         const BasicVector<float, 5> vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
         const BasicVector<float, 5> vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
 
-        EXPECT_FLOAT_EQ(40.0f, vec1.distanceSquared(vec2));
+        EXPECT_FLOAT_EQ(40.0f, distanceSquared(vec1, vec2));
     }
 
     {
         const BasicVector<float, 5> vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
         const BasicVector<float, 5> vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
 
-        EXPECT_FLOAT_EQ(6.3245554f, vec1.distance(vec2));
-    }
-
-    {
-        const BasicVector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
-
-        auto inv = vec.inversed();
-
-        EXPECT_EQ(5, inv.getSize());
-        EXPECT_FLOAT_EQ(1.0f, inv[0]);
-        EXPECT_FLOAT_EQ(0.5f, inv[1]);
-        EXPECT_FLOAT_EQ(1.0f / 3.0f, inv[2]);
-        EXPECT_FLOAT_EQ(0.25f, inv[3]);
-        EXPECT_FLOAT_EQ(0.2f, inv[4]);
-    }
-
-    {
-        auto vec = BasicVector<float, 5>::createSingle(1);
-
-        EXPECT_EQ(5, vec.getSize());
-        EXPECT_FLOAT_EQ(1.0f, vec[0]);
-        EXPECT_FLOAT_EQ(1.0f, vec[1]);
-        EXPECT_FLOAT_EQ(1.0f, vec[2]);
-        EXPECT_FLOAT_EQ(1.0f, vec[3]);
-        EXPECT_FLOAT_EQ(1.0f, vec[4]);
-    }
-
-    {
-        auto vec = BasicVector<float, 5>::createSingle(375.1721f);
-
-        EXPECT_EQ(5, vec.getSize());
-        EXPECT_FLOAT_EQ(375.1721f, vec[0]);
-        EXPECT_FLOAT_EQ(375.1721f, vec[1]);
-        EXPECT_FLOAT_EQ(375.1721f, vec[2]);
-        EXPECT_FLOAT_EQ(375.1721f, vec[3]);
-        EXPECT_FLOAT_EQ(375.1721f, vec[4]);
+        EXPECT_FLOAT_EQ(6.3245554f, distance(vec1, vec2));
     }
 }
 

From 54760dfd3f7a1eea66ed65b5093aaf4f757ffc88 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Fatka?= <fatkaj@ntis.zcu.cz>
Date: Thu, 8 Jun 2017 16:50:24 +0200
Subject: [PATCH 08/11] Massive Vector refractoring.

---
 include/cece/math/Vector.hpp                  | 1606 +++++++++++++----
 include/cece/math/Vector2.hpp                 |  485 -----
 include/cece/math/Vector3.hpp                 |  537 ------
 include/cece/math/VectorBase.hpp              |  557 +++---
 include/cece/math/VectorIo.hpp                |  125 ++
 include/cece/unit/VectorUnits.hpp             |   11 +-
 src/math/CMakeLists.txt                       |    2 -
 src/math/Vector.cpp                           |   13 +-
 src/math/Vector3.cpp                          |   46 -
 src/simulation/DefaultSimulation.cpp          |    1 +
 src/simulation/Object.cpp                     |    1 +
 src/simulation/Simulation.cpp                 |    1 +
 src/unit/VectorUnits.cpp                      |   11 +-
 unittests/math/CMakeLists.txt                 |    1 +
 unittests/math/Vector2_test.cpp               |   45 +-
 unittests/math/Vector3_test.cpp               |    2 +-
 unittests/math/VectorBase_test.cpp            |   66 +-
 .../math/VectorIo_test.cpp                    |  108 +-
 18 files changed, 1886 insertions(+), 1732 deletions(-)
 delete mode 100644 include/cece/math/Vector2.hpp
 delete mode 100644 include/cece/math/Vector3.hpp
 create mode 100644 include/cece/math/VectorIo.hpp
 delete mode 100644 src/math/Vector3.cpp
 rename src/math/Vector2.cpp => unittests/math/VectorIo_test.cpp (53%)

diff --git a/include/cece/math/Vector.hpp b/include/cece/math/Vector.hpp
index 8d1167d..c4dd936 100644
--- a/include/cece/math/Vector.hpp
+++ b/include/cece/math/Vector.hpp
@@ -37,13 +37,9 @@
 #include "cece/Assert.hpp"
 #include "cece/StaticArray.hpp"
 #include "cece/math/Zero.hpp"
-#include "cece/io/InStream.hpp"
-#include "cece/io/OutStream.hpp"
 #include "cece/unit/math.hpp"
 #include "cece/unit/Units.hpp"
 #include "cece/math/VectorBase.hpp"
-#include "cece/math/Vector2.hpp"
-#include "cece/math/Vector3.hpp"
 
 /* ************************************************************************ */
 
@@ -58,8 +54,8 @@ namespace math {
  * @tparam     T     Element type.
  * @tparam     N     Number of elements.
  */
-template<typename T, int N>
-class BasicVector : public VectorBase<BasicVector, T, N>
+template<typename T, int N = DIMENSION>
+class Vector : public VectorBase<Vector, T, N>
 {
     static_assert(N > 0, "Cannot create empty vector");
 
@@ -68,7 +64,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
 public:
 
 
-    /// BasicVector value type.
+    /// Vector value type.
     using ValueType = T;
 
 
@@ -87,7 +83,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
     /**
      * @brief      Default constructor.
      */
-    BasicVector() noexcept;
+    Vector() noexcept;
 
 
     /**
@@ -95,7 +91,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      *
      * @param      data  The source data.
      */
-    BasicVector(std::initializer_list<T> data);
+    Vector(std::initializer_list<T> data);
 
 
     /**
@@ -103,7 +99,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      *
      * @param      data  The source data.
      */
-    explicit BasicVector(T (&data)[N]);
+    explicit Vector(T (&data)[N]);
 
 
     /**
@@ -111,7 +107,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      *
      * @param      data  The source data.
      */
-    explicit BasicVector(const StaticArray<T, N>& data);
+    explicit Vector(const StaticArray<T, N>& data);
 
 
     /**
@@ -119,7 +115,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      *
      * @param[in]  zero  The zero value.
      */
-    BasicVector(Zero_t zero);
+    Vector(Zero_t zero);
 
 
     /**
@@ -127,7 +123,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      *
      * @param[in]  src   The source vector.
      */
-    BasicVector(const BasicVector& src);
+    Vector(const Vector& src);
 
 
     /**
@@ -135,7 +131,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      *
      * @param[in]  src   The source vector.
      */
-    BasicVector(BasicVector&& src);
+    Vector(Vector&& src);
 
 
     /**
@@ -146,7 +142,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      * @tparam     T2    The source vector element type.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    explicit BasicVector(const BasicVector<T2, N>& src);
+    explicit Vector(const Vector<T2, N>& src);
 
 
 // Public Operators
@@ -160,7 +156,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      *
      * @return     *this.
      */
-    BasicVector& operator=(Zero_t zero);
+    Vector& operator=(Zero_t zero);
 
 
     /**
@@ -170,7 +166,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      *
      * @return     *this.
      */
-    BasicVector& operator=(std::initializer_list<T> data);
+    Vector& operator=(std::initializer_list<T> data);
 
 
     /**
@@ -180,7 +176,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      *
      * @return     *this.
      */
-    BasicVector& operator=(T (&data)[N]);
+    Vector& operator=(T (&data)[N]);
 
 
     /**
@@ -190,7 +186,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      *
      * @return     *this.
      */
-    BasicVector& operator=(const StaticArray<T, N>& data);
+    Vector& operator=(const StaticArray<T, N>& data);
 
 
     /**
@@ -200,7 +196,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      *
      * @return     *this.
      */
-    BasicVector& operator=(const BasicVector& src);
+    Vector& operator=(const Vector& src);
 
 
     /**
@@ -210,7 +206,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      *
      * @return     *this.
      */
-    BasicVector& operator=(BasicVector&& src);
+    Vector& operator=(Vector&& src);
 
 
     /**
@@ -223,7 +219,7 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      * @return     *this.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    BasicVector& operator=(const BasicVector<T2, N>& src);
+    Vector& operator=(const Vector<T2, N>& src);
 
 
     /**
@@ -245,444 +241,1446 @@ class BasicVector : public VectorBase<BasicVector, T, N>
      */
     const T& operator[](int pos) const noexcept;
 
-
-// Public Accessors
-public:
-
-
-    /**
-     * @brief      Returns vector size.
-     *
-     * @return     The size.
-     */
-    int getSize() const noexcept;
-
 };
 
 /* ************************************************************************ */
 
-// TODO: rework
+/**
+ * @brief      2D vector specialization.
+ *
+ * @tparam     T     Element type.
+ */
 template<typename T>
-struct BasicVector<T, 2> : public Vector2<T>
+struct Vector<T, 2> : public VectorBase<Vector, T, 2>
 {
-    using Vector2<T>::Vector2;
-
-    BasicVector() {};
-    BasicVector(const Vector2<T>& src)
-        : Vector2<T>(src)
-    {
-        //
-    }
 
-    const T& getWidth() const noexcept { return Vector2<T>::getX(); }
+// Public Types
+public:
 
-    const T& getHeight() const noexcept { return Vector2<T>::getY(); }
 
-    static bool inRange(T value, T low, T high) noexcept { return value >= low && value < high; }
+    /// Element type.
+    using ValueType = T;
 
-    bool inRange(const BasicVector& low, const BasicVector& high) const noexcept
-    {
-        bool res = true;
 
-        res = res && inRange(Vector2<T>::getX(), low.getX(), high.getX());
-        res = res && inRange(Vector2<T>::getY(), low.getY(), high.getY());
+// Public Data Members
+public:
 
-        return res;
-    }
 
-    bool inRange(const BasicVector& high) const noexcept
+    union
     {
-        return inRange(Zero, high);
-    }
+        struct
+        {
+            /// X coordinate.
+            T x;
 
-    static BasicVector createSingle(T val) noexcept { return BasicVector(val, val); }
+            /// Y coordinate.
+            T y;
+        };
 
-    template<typename T2 = T>
-    BasicVector inversed() const noexcept
-    {
-        return BasicVector(
-            T2(1) / Vector2<T>::getX(),
-            T2(1) / Vector2<T>::getY()
-        );
-    }
+        struct
+        {
+            /// Width
+            T width;
 
-    BasicVector rotated(unit::Angle angle) const noexcept
-    {
-        return rotate(*this, angle);
-    }
-};
+            /// Height.
+            T height;
+        };
 
-/* ************************************************************************ */
+        T m[2];
+    };
 
-// TODO: rework
-template<typename T>
-struct BasicVector<T, 3> : public Vector3<T>
-{
-    using Vector3<T>::Vector3;
 
-    BasicVector() {};
-    BasicVector(const Vector3<T>& src)
-        : Vector3<T>(src)
-    {
-        //
-    }
+// Public Ctors
+public:
 
-    const T& getWidth() const noexcept { return Vector3<T>::getX(); }
-    const T& getHeight() const noexcept { return Vector3<T>::getY(); }
-    const T& getDepth() const noexcept { return Vector3<T>::getZ(); }
 
-    static bool inRange(T value, T low, T high) noexcept { return value >= low && value < high; }
+    /**
+     * @brief      Default constructor.
+     */
+    Vector();
 
-    bool inRange(const BasicVector& low, const BasicVector& high) const noexcept
-    {
-        bool res = true;
 
-        res = res && inRange(Vector3<T>::getX(), low.getX(), high.getX());
-        res = res && inRange(Vector3<T>::getY(), low.getY(), high.getY());
-        res = res && inRange(Vector3<T>::getZ(), low.getZ(), high.getZ());
+    /**
+     * @brief      Constructor.
+     *
+     * @param      x     The X and Y coordinate.
+     */
+    explicit Vector(T value);
 
-        return res;
-    }
 
-    bool inRange(const BasicVector& high) const noexcept
-    {
-        return inRange(Zero, high);
-    }
+    /**
+     * @brief      Constructor.
+     *
+     * @param      x     The X coordinate.
+     * @param      y     The Y coordinate.
+     */
+    Vector(T x, T y);
 
-    static BasicVector createSingle(T val) noexcept { return BasicVector(val, val, val); }
 
-    template<typename T2 = T>
-    BasicVector inversed() const noexcept
-    {
-        return BasicVector(
-            T2(1) / Vector3<T>::getX(),
-            T2(1) / Vector3<T>::getY(),
-            T2(1) / Vector3<T>::getZ()
-        );
-    }
-};
+    /**
+     * @brief      Zero value constructor.
+     *
+     * @param[in]  zero  The zero value.
+     */
+    Vector(Zero_t zero);
 
-/* ************************************************************************ */
 
-/**
- * @brief Basic vector.
- */
-template<typename T>
-using Vector = BasicVector<T, DIMENSION>;
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  src   The source vector.
+     */
+    Vector(const Vector& src);
 
-/* ************************************************************************ */
 
-/**
- * @brief Vector for integer size.
- */
-using Size = Vector<unsigned int>;
+    /**
+     * @brief      Move constructor.
+     *
+     * @param[in]  src   The source vector.
+     */
+    Vector(Vector&& src);
 
-/* ************************************************************************ */
 
-/**
- * @brief Vector for coordinates.
- */
-using Coordinate = Vector<unsigned int>;
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param      rhs   Source vector.
+     *
+     * @tparam     T2    The source vector element type.
+     */
+    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
+    Vector(const Vector<T2, 2>& rhs);
 
-/* ************************************************************************ */
 
-/**
- * @brief Vector of int.
- */
-using VectorInt = Vector<int>;
+// Public Operators
+public:
 
-/* ************************************************************************ */
 
-/**
- * @brief Vector of float.
- */
-using VectorFloat = Vector<float>;
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  zero  The zero value.
+     *
+     * @return     *this.
+     */
+    Vector& operator=(Zero_t zero);
 
-/* ************************************************************************ */
 
-/**
- * @brief Vector of float.
- */
-using VectorDouble = Vector<float>;
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  src   The source vector.
+     *
+     * @return     *this.
+     */
+    Vector& operator=(const Vector& src);
 
-/* ************************************************************************ */
 
-/**
- * @brief Vector of float.
- */
-using VectorLongDouble = Vector<float>;
+    /**
+     * @brief      Move constructor.
+     *
+     * @param[in]  src   The source vector.
+     *
+     * @return     *this.
+     */
+    Vector& operator=(Vector&& src);
 
-/* ************************************************************************ */
 
-/**
- * @brief Vector of float.
- */
-using VectorReal = Vector<RealType>;
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param      v     The source vector.
+     *
+     * @tparam     T2    The source vector element type.
+     *
+     * @return     *this.
+     */
+    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
+    Vector& operator=(const Vector<T2, 2>& src);
 
-/* ************************************************************************ */
 
-/**
- * @brief Input stream operator.
- *
- * @param is     Input stream.
- * @param vector Result value.
- *
- * @return is.
- */
-template<typename T, int N>
-io::InStream& operator>>(io::InStream& is, BasicVector<T, N>& vector)
-{
-    int i = 0;
+    /**
+     * @brief      Access operator.
+     *
+     * @param      pos   The position.
+     *
+     * @return     Reference to the element.
+     */
+    T& operator[](int pos) noexcept;
 
-    for (; i < N; ++i)
-    {
-        if (!(is >> std::skipws >> vector[i]))
-            break;
-    }
 
-    if (i == 0)
-        return is;
+    /**
+     * @brief      Access operator.
+     *
+     * @param      pos   The position.
+     *
+     * @return     Reference to the element.
+     */
+    const T& operator[](int pos) const noexcept;
 
-    // Copy missing values
-    // TODO: have this feature?
-    for (int j = i; j < N; ++j)
-        vector[j] = vector[i - 1];
 
-    return is;
-}
+// Public Accessors
+public:
 
-/* ************************************************************************ */
 
-/**
- * @brief Output stream operator.
- *
- * @param os     Output stream.
- * @param vector Input value.
- *
- * @return os.
- */
-template<typename T, int N>
-io::OutStream& operator<<(io::OutStream& os, const BasicVector<T, N>& vector) noexcept
-{
-    for (int i = 0; i < N; ++i)
-    {
-        if (i != 0)
-            os << " ";
+    /**
+     * @brief      Returns X coordinate.
+     *
+     * @return     The X coordinate.
+     */
+    const T& getX() const noexcept;
 
-        os << vector[i];
-    }
 
-    return os;
-}
+    /**
+     * @brief      Set X coordinate.
+     *
+     * @param[in]  x     The X coordinate.
+     */
+    void setX(T x);
 
-/* ************************************************************************ */
 
-extern template class BasicVector<RealType, DIMENSION>;
+    /**
+     * @brief      Returns Y coordinate.
+     *
+     * @return     The Y coordinate.
+     */
+    const T& getY() const noexcept;
 
-/* ************************************************************************ */
 
-}
-}
+    /**
+     * @brief      Set Y coordinate.
+     *
+     * @param[in]  y     The Y coordinate.
+     */
+    void setY(T y);
 
-/* ************************************************************************ */
-/* ************************************************************************ */
-/* ************************************************************************ */
 
-namespace cece {
-namespace math {
+    /**
+     * @brief      Gets the width.
+     *
+     * @return     The width.
+     */
+    const T& getWidth() const noexcept;
 
-/* ************************************************************************ */
 
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector() noexcept
-    : m{}
-{
-    // Nothing to do
-}
+    /**
+     * @brief      Set the width.
+     *
+     * @param[in]  width  The width.
+     */
+    void setWidth(T width);
 
-/* ************************************************************************ */
 
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector(std::initializer_list<T> data)
-{
-    CECE_ASSERT(data.size() == getSize());
+    /**
+     * @brief      Gets the height.
+     *
+     * @return     The height.
+     */
+    const T& getHeight() const noexcept;
 
-    using std::begin;
-    auto it = begin(data);
 
-    for (int i = 0; i < getSize(); ++i, ++it)
-        m[i] = *it;
-}
+    /**
+     * @brief      Sets the height.
+     *
+     * @param[in]  height  The height
+     */
+    void setHeight(T height);
 
-/* ************************************************************************ */
 
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector(T (&data)[N])
-{
-    using std::begin;
-    auto it = begin(data);
+// Public Deprecated
+public:
 
-    for (int i = 0; i < getSize(); ++i, ++it)
-        m[i] = *it;
-}
 
-/* ************************************************************************ */
+    // @deprecated
+    bool inRange(const Vector& low, const Vector& high) const noexcept
+    {
+        return math::inRange(*this, low, high);
+    }
 
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector(const StaticArray<T, N>& data)
-    : m(data)
-{
-    // Nothing to do
-}
 
-/* ************************************************************************ */
+    // @deprecated
+    bool inRange(const Vector& high) const noexcept
+    {
+        return math::inRange(*this, high);
+    }
 
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector(Zero_t zero)
-{
-    for (int i = 0; i < getSize(); ++i)
-        m[i] = T{};
-}
 
-/* ************************************************************************ */
+    // @deprecated
+    static Vector createSingle(T val) noexcept
+    {
+        return Vector(val, val);
+    }
 
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector(const BasicVector& src)
-{
-    for (int i = 0; i < getSize(); ++i)
+
+    // @deprecated
+    template<typename T2 = T>
+    Vector inversed() const noexcept
+    {
+        return T2(1) / *this;
+    }
+
+
+    // @deprecated
+    Vector rotated(unit::Angle angle) const noexcept
+    {
+        return rotate(*this, angle);
+    }
+};
+
+/* ************************************************************************ */
+
+/**
+ * @brief      3D vector specialization.
+ *
+ * @tparam     T     Element type.
+ */
+template<typename T>
+struct Vector<T, 3> : public VectorBase<Vector, T, 3>
+{
+
+
+// Public Types
+public:
+
+
+    /// Vector element type.
+    using ValueType = T;
+
+
+// Public Data Members
+public:
+
+
+    union
+    {
+        struct
+        {
+            /// X coordinate.
+            T x;
+
+            /// Y coordinate.
+            T y;
+
+            /// Z coordinate.
+            T z;
+        };
+
+        struct
+        {
+            /// Width.
+            T width;
+
+            /// Height.
+            T height;
+
+            /// Depth.
+            T depth;
+        };
+
+        T m[3];
+    };
+
+
+// Public Ctors
+public:
+
+
+    /**
+     * @brief      Default constructor.
+     */
+    Vector() noexcept;
+
+
+    /**
+     * @brief      Constructor.
+     *
+     * @param      val   The X, Y and Z coordinate.
+     */
+    explicit Vector(T val);
+
+
+    /**
+     * @brief      Constructor.
+     *
+     * @param      x     The X coordinate.
+     * @param      y     The Y coordinate.
+     * @param      y     The Z coordinate.
+     */
+    Vector(T x, T y, T z);
+
+
+    /**
+     * @brief      Zero value constructor.
+     *
+     * @param[in]  zero  The zero value.
+     */
+    Vector(Zero_t zero);
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  src   The source vector.
+     */
+    Vector(const Vector& src);
+
+
+    /**
+     * @brief      Move constructor.
+     *
+     * @param[in]  src   The source vector.
+     */
+    Vector(Vector&& src);
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param      rhs   Source vector.
+     *
+     * @tparam     T2    The source vector element type.
+     */
+    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
+    Vector(const Vector<T2, 3>& rhs);
+
+
+// Public Operators
+public:
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  zero  The zero value.
+     *
+     * @return     *this.
+     */
+    Vector& operator=(Zero_t zero);
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param[in]  src   The source vector.
+     *
+     * @return     *this.
+     */
+    Vector& operator=(const Vector& src);
+
+
+    /**
+     * @brief      Move constructor.
+     *
+     * @param[in]  src   The source vector.
+     *
+     * @return     *this.
+     */
+    Vector& operator=(Vector&& src);
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param      v     The source vector.
+     *
+     * @tparam     T2    The source vector element type.
+     *
+     * @return     *this.
+     */
+    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
+    Vector& operator=(const Vector<T2, 3>& src);
+
+
+    /**
+     * @brief      Access operator.
+     *
+     * @param      pos   The position.
+     *
+     * @return     Reference to the element.
+     */
+    T& operator[](int pos) noexcept;
+
+
+    /**
+     * @brief      Access operator.
+     *
+     * @param      pos   The position.
+     *
+     * @return     Reference to the element.
+     */
+    const T& operator[](int pos) const noexcept;
+
+
+// Public Accessors
+public:
+
+
+    /**
+     * @brief      Returns X coordinate.
+     *
+     * @return     The X coordinate.
+     */
+    const T& getX() const noexcept;
+
+
+    /**
+     * @brief      Set X coordinate.
+     *
+     * @param      x     The X coordinate.
+     */
+    void setX(T x);
+
+
+    /**
+     * @brief      Returns Y coordinate.
+     *
+     * @return     The Y coordinate.
+     */
+    const T& getY() const noexcept;
+
+
+    /**
+     * @brief      Set Y coordinate.
+     *
+     * @param      y     The Y coordinate.
+     */
+    void setY(T y);
+
+
+    /**
+     * @brief      Returns Z coordinate.
+     *
+     * @return     The Z coordinate.
+     */
+    const T& getZ() const noexcept;
+
+
+    /**
+     * @brief      Set Z coordinate.
+     *
+     * @param      z     The Z coordinate.
+     */
+    void setZ(T z);
+
+
+    /**
+     * @brief      Gets the width.
+     *
+     * @return     The width.
+     */
+    const T& getWidth() const noexcept;
+
+
+    /**
+     * @brief      Set the width.
+     *
+     * @param[in]  width  The width.
+     */
+    void setWidth(T width);
+
+
+    /**
+     * @brief      Gets the height.
+     *
+     * @return     The height.
+     */
+    const T& getHeight() const noexcept;
+
+
+    /**
+     * @brief      Sets the height.
+     *
+     * @param[in]  height  The height
+     */
+    void setHeight(T height);
+
+
+    /**
+     * @brief      Gets the depth.
+     *
+     * @return     The depth.
+     */
+    const T& getDepth() const noexcept;
+
+
+    /**
+     * @brief      Sets the depth.
+     *
+     * @param[in]  depth  The depth
+     */
+    void setDepth(T depth);
+
+
+// Public Deprecated
+public:
+
+
+    // @deprecated
+    bool inRange(const Vector& low, const Vector& high) const noexcept
+    {
+        return math::inRange(*this, low, high);
+    }
+
+
+    // @deprecated
+    bool inRange(const Vector& high) const noexcept
+    {
+        return math::inRange(*this, high);
+    }
+
+
+    // @deprecated
+    static Vector createSingle(T val) noexcept
+    {
+        return Vector(val, val, val);
+    }
+
+
+    // @deprecated
+    template<typename T2 = T>
+    Vector inversed() const noexcept
+    {
+        return T2(1) / *this;
+    }
+};
+
+/* ************************************************************************ */
+
+/**
+ * @brief      2D vector alias.
+ */
+template<typename T>
+using Vector2 = Vector<T, 2>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      3D vector alias.
+ */
+template<typename T>
+using Vector3 = Vector<T, 3>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector for integer size.
+ * @deprecated
+ */
+using Size = Vector<unsigned int>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector for coordinates.
+ * @deprecated
+ */
+using Coordinate = Vector<unsigned int>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector of int.
+ * @deprecated
+ */
+using VectorInt = Vector<int>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector of float.
+ * @deprecated
+ */
+using VectorFloat = Vector<float>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector of double.
+ * @deprecated
+ */
+using VectorDouble = Vector<double>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector of long double.
+ * @deprecated
+ */
+using VectorLongDouble = Vector<long double>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector of float.
+ * @deprecated
+ */
+using VectorReal = Vector<RealType>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector of integers.
+ */
+using IntVector = Vector<int>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector of float.
+ */
+using FloatVector = Vector<float>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector of double.
+ */
+using DoubleVector = Vector<double>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector of long double.
+ */
+using LongDoubleVector = Vector<long double>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector of float.
+ */
+using RealVector = Vector<RealType>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector for indices.
+ */
+using IndexVector = Vector<unsigned long>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Vector for sizes.
+ */
+using SizeVector = Vector<unsigned long>;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Rotate the vector counter-clockwise and return rotated version.
+ *
+ * @param[in]  vec    The vector.
+ * @param[in]  angle  Rotation angle.
+ *
+ * @tparam     T      The vector element type.
+ *
+ * @return     Rotated vector.
+ */
+template<typename T>
+Vector<T, 2> rotate(const Vector<T, 2>& vec, unit::Angle angle) noexcept;
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Calculate cross product of two vectors.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    The first type.
+ * @tparam     T2    The second type.
+ *
+ * @return     Cross product.
+ */
+template<typename T1, typename T2>
+Vector<decltype(std::declval<T1>() * std::declval<T2>()), 3>
+cross(const Vector<T1, 3>& lhs, const Vector<T2, 3>& rhs);
+
+/* ************************************************************************ */
+
+extern template class Vector<int, 2>;
+extern template class Vector<int, 3>;
+extern template class Vector<unsigned int, 2>;
+extern template class Vector<unsigned int, 3>;
+extern template class Vector<unsigned long, 2>;
+extern template class Vector<unsigned long, 3>;
+extern template class Vector<float, 2>;
+extern template class Vector<float, 3>;
+extern template class Vector<double, 2>;
+extern template class Vector<double, 3>;
+
+/* ************************************************************************ */
+
+/// @deprecated
+template<typename T, int N>
+using BasicVector = Vector<T, N>;
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>::Vector() noexcept
+    : m{}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>::Vector(std::initializer_list<T> data)
+{
+    CECE_ASSERT(data.size() == N);
+
+    using std::begin;
+    auto it = begin(data);
+
+    for (int i = 0; i < N; ++i, ++it)
+        m[i] = *it;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>::Vector(T (&data)[N])
+{
+    using std::begin;
+    auto it = begin(data);
+
+    for (int i = 0; i < N; ++i, ++it)
+        m[i] = *it;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>::Vector(const StaticArray<T, N>& data)
+    : m(data)
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>::Vector(Zero_t zero)
+{
+    for (int i = 0; i < N; ++i)
+        m[i] = T{};
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>::Vector(const Vector& src)
+{
+    for (int i = 0; i < N; ++i)
+        m[i] = src.m[i];
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>::Vector(Vector&& src)
+{
+    for (int i = 0; i < N; ++i)
+        m[i] = std::move(src.m[i]);
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
+inline Vector<T, N>::Vector(const Vector<T2, N>& src)
+{
+    for (int i = 0; i < N; ++i)
+        m[i] = T(src[i]);
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>& Vector<T, N>::operator=(Zero_t zero)
+{
+    for (int i = 0; i < N; ++i)
+        m[i] = T{};
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>& Vector<T, N>::operator=(std::initializer_list<T> data)
+{
+    CECE_ASSERT(data.size() == N);
+
+    using std::begin;
+    auto it = begin(data);
+
+    for (int i = 0; i < N; ++i, ++it)
+        m[i] = *it;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>& Vector<T, N>::operator=(T (&data)[N])
+{
+    using std::begin;
+    auto it = begin(data);
+
+    for (int i = 0; i < N; ++i, ++it)
+        m[i] = *it;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>& Vector<T, N>::operator=(const StaticArray<T, N>& data)
+{
+    m = data;
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>& Vector<T, N>::operator=(const Vector& src)
+{
+    for (int i = 0; i < N; ++i)
         m[i] = src.m[i];
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline Vector<T, N>& Vector<T, N>::operator=(Vector&& src)
+{
+    for (int i = 0; i < N; ++i)
+        m[i] = std::move(src.m[i]);
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
+inline Vector<T, N>& Vector<T, N>::operator=(const Vector<T2, N>& src)
+{
+    for (int i = 0; i < N; ++i)
+        m[i] = T(src[i]);
+
+    return *this;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline T& Vector<T, N>::operator[](int pos) noexcept
+{
+    CECE_ASSERT(pos >= 0);
+    CECE_ASSERT(pos < N);
+    return m[pos];
+}
+
+/* ************************************************************************ */
+
+template<typename T, int N>
+inline const T& Vector<T, N>::operator[](int pos) const noexcept
+{
+    CECE_ASSERT(pos >= 0);
+    CECE_ASSERT(pos < N);
+    return m[pos];
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 2>::Vector()
+    : x{}
+    , y{}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 2>::Vector(T val)
+    : x{val}
+    , y{val}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 2>::Vector(T x, T y)
+    : x{std::move(x)}
+    , y{std::move(y)}
+{
+    // Nothing to do
 }
 
 /* ************************************************************************ */
 
-template<typename T, int N>
-inline BasicVector<T, N>::BasicVector(BasicVector&& src)
+template<typename T>
+inline Vector<T, 2>::Vector(Zero_t zero)
+    : x{}
+    , y{}
 {
-    for (int i = 0; i < getSize(); ++i)
-        m[i] = std::move(src.m[i]);
+    // Nothing to do
 }
 
 /* ************************************************************************ */
 
-template<typename T, int N>
+template<typename T>
+inline Vector<T, 2>::Vector(const Vector& src)
+    : x{src.getX()}
+    , y{src.getY()}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 2>::Vector(Vector&& src)
+    : x{std::move(src.x)}
+    , y{std::move(src.y)}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline BasicVector<T, N>::BasicVector(const BasicVector<T2, N>& src)
+inline Vector<T, 2>::Vector(const Vector<T2, 2>& rhs)
+    : x(rhs.getX())
+    , y(rhs.getY())
 {
-    for (int i = 0; i < getSize(); ++i)
-        m[i] = T(src[i]);
+    // Nothing to do
 }
 
 /* ************************************************************************ */
 
-template<typename T, int N>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(Zero_t zero)
+template<typename T>
+inline Vector<T, 2>& Vector<T, 2>::operator=(Zero_t zero)
 {
-    for (int i = 0; i < getSize(); ++i)
-        m[i] = T{};
+    x = T{};
+    y = T{};
 
     return *this;
 }
 
 /* ************************************************************************ */
 
-template<typename T, int N>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(std::initializer_list<T> data)
+template<typename T>
+inline Vector<T, 2>& Vector<T, 2>::operator=(const Vector& src)
 {
-    CECE_ASSERT(data.size() == getSize());
+    x = src.x;
+    y = src.y;
 
-    using std::begin;
-    auto it = begin(data);
+    return *this;
+}
 
-    for (int i = 0; i < getSize(); ++i, ++it)
-        m[i] = *it;
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 2>& Vector<T, 2>::operator=(Vector&& src)
+{
+    x = std::move(src.x);
+    y = std::move(src.y);
 
     return *this;
 }
 
 /* ************************************************************************ */
 
-template<typename T, int N>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(T (&data)[N])
+template<typename T>
+template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
+inline Vector<T, 2>& Vector<T, 2>::operator=(const Vector<T2, 2>& src)
 {
-    using std::begin;
-    auto it = begin(data);
-
-    for (int i = 0; i < getSize(); ++i, ++it)
-        m[i] = *it;
+    x = T(src.getX());
+    y = T(src.getY());
 
     return *this;
 }
 
 /* ************************************************************************ */
 
-template<typename T, int N>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(const StaticArray<T, N>& data)
+template<typename T>
+inline T& Vector<T, 2>::operator[](int pos) noexcept
 {
-    m = data;
+    CECE_ASSERT(pos >= 0);
+    CECE_ASSERT(pos < 2);
+    return (&x)[pos];
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& Vector<T, 2>::operator[](int pos) const noexcept
+{
+    CECE_ASSERT(pos >= 0);
+    CECE_ASSERT(pos < 2);
+    return (&x)[pos];
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& Vector<T, 2>::getX() const noexcept
+{
+    return x;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void Vector<T, 2>::setX(T x)
+{
+    this->x = std::move(x);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& Vector<T, 2>::getY() const noexcept
+{
+    return y;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void Vector<T, 2>::setY(T y)
+{
+    this->y = std::move(y);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& Vector<T, 2>::getWidth() const noexcept
+{
+    return width;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void Vector<T, 2>::setWidth(T width)
+{
+    this->width = std::move(width);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& Vector<T, 2>::getHeight() const noexcept
+{
+    return height;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void Vector<T, 2>::setHeight(T height)
+{
+    this->height = std::move(height);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 3>::Vector() noexcept
+    : x{}
+    , y{}
+    , z{}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 3>::Vector(T val)
+    : x{val}
+    , y{val}
+    , z{val}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 3>::Vector(T x, T y, T z)
+    : x{std::move(x)}
+    , y{std::move(y)}
+    , z{std::move(z)}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 3>::Vector(Zero_t zero)
+    : x{}
+    , y{}
+    , z{}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 3>::Vector(const Vector& src)
+    : x{src.getX()}
+    , y{src.getY()}
+    , z{src.getZ()}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 3>::Vector(Vector&& src)
+    : x{std::move(src.x)}
+    , y{std::move(src.y)}
+    , z{std::move(src.z)}
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
+inline Vector<T, 3>::Vector(const Vector<T2, 3>& rhs)
+    : x(rhs.getX())
+    , y(rhs.getY())
+    , z(rhs.getZ())
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 3>& Vector<T, 3>::operator=(Zero_t zero)
+{
+    x = T{};
+    y = T{};
+    z = T{};
 
     return *this;
 }
 
 /* ************************************************************************ */
 
-template<typename T, int N>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(const BasicVector& src)
+template<typename T>
+inline Vector<T, 3>& Vector<T, 3>::operator=(const Vector& src)
 {
-    for (int i = 0; i < getSize(); ++i)
-        m[i] = src.m[i];
+    x = src.x;
+    y = src.y;
+    z = src.z;
 
     return *this;
 }
 
 /* ************************************************************************ */
 
-template<typename T, int N>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(BasicVector&& src)
+template<typename T>
+inline Vector<T, 3>& Vector<T, 3>::operator=(Vector&& src)
 {
-    for (int i = 0; i < getSize(); ++i)
-        m[i] = std::move(src.m[i]);
+    x = std::move(src.x);
+    y = std::move(src.y);
+    z = std::move(src.z);
 
     return *this;
 }
 
 /* ************************************************************************ */
 
-template<typename T, int N>
+template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline BasicVector<T, N>& BasicVector<T, N>::operator=(const BasicVector<T2, N>& src)
+inline Vector<T, 3>& Vector<T, 3>::operator=(const Vector<T2, 3>& src)
 {
-    for (int i = 0; i < getSize(); ++i)
-        m[i] = T(src[i]);
+    x = T(src.getX());
+    y = T(src.getY());
+    z = T(src.getZ());
 
     return *this;
 }
 
 /* ************************************************************************ */
 
-template<typename T, int N>
-inline T& BasicVector<T, N>::operator[](int pos) noexcept
+template<typename T>
+inline T& Vector<T, 3>::operator[](int pos) noexcept
 {
     CECE_ASSERT(pos >= 0);
-    CECE_ASSERT(pos < getSize());
-    return m[pos];
+    CECE_ASSERT(pos < 3);
+    return (&x)[pos];
 }
 
 /* ************************************************************************ */
 
-template<typename T, int N>
-inline const T& BasicVector<T, N>::operator[](int pos) const noexcept
+template<typename T>
+inline const T& Vector<T, 3>::operator[](int pos) const noexcept
 {
     CECE_ASSERT(pos >= 0);
-    CECE_ASSERT(pos < getSize());
-    return m[pos];
+    CECE_ASSERT(pos < 3);
+    return (&x)[pos];
 }
 
 /* ************************************************************************ */
 
-template<typename T, int N>
-int BasicVector<T, N>::getSize() const noexcept
+template<typename T>
+inline const T& Vector<T, 3>::getX() const noexcept
+{
+    return x;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void Vector<T, 3>::setX(T x)
+{
+    this->x = std::move(x);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& Vector<T, 3>::getY() const noexcept
+{
+    return y;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void Vector<T, 3>::setY(T y)
+{
+    this->y = std::move(y);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& Vector<T, 3>::getZ() const noexcept
+{
+    return z;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void Vector<T, 3>::setZ(T z)
+{
+    this->z = std::move(z);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& Vector<T, 3>::getWidth() const noexcept
+{
+    return width;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void Vector<T, 3>::setWidth(T width)
+{
+    this->width = std::move(width);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& Vector<T, 3>::getHeight() const noexcept
+{
+    return height;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void Vector<T, 3>::setHeight(T height)
+{
+    this->height = std::move(height);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline const T& Vector<T, 3>::getDepth() const noexcept
+{
+    return depth;
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline void Vector<T, 3>::setDepth(T depth)
+{
+    this->depth = std::move(depth);
+}
+
+/* ************************************************************************ */
+
+template<typename T>
+inline Vector<T, 2> rotate(const Vector<T, 2>& vec, unit::Angle angle) noexcept
+{
+    return {
+        static_cast<T>(vec.getX() * cos(static_cast<RealType>(angle)) - vec.getY() * sin(static_cast<RealType>(angle))),
+        static_cast<T>(vec.getX() * sin(static_cast<RealType>(angle)) + vec.getY() * cos(static_cast<RealType>(angle)))
+    };
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2>
+inline Vector<decltype(std::declval<T1>() * std::declval<T2>()), 3> cross(
+    const Vector<T1, 3>& lhs,
+    const Vector<T2, 3>& rhs
+)
 {
-    return N;
+    return {
+        lhs.getY() * rhs.getZ() - lhs.getZ() * rhs.getY(),
+        lhs.getZ() * rhs.getX() - lhs.getX() * rhs.getZ(),
+        lhs.getX() * rhs.getY() - lhs.getY() * rhs.getX()
+    };
 }
 
 /* ************************************************************************ */
diff --git a/include/cece/math/Vector2.hpp b/include/cece/math/Vector2.hpp
deleted file mode 100644
index 4661074..0000000
--- a/include/cece/math/Vector2.hpp
+++ /dev/null
@@ -1,485 +0,0 @@
-/* ************************************************************************ */
-/* Georgiev Lab (c) 2015-2017                                               */
-/* ************************************************************************ */
-/* Department of Cybernetics                                                */
-/* Faculty of Applied Sciences                                              */
-/* University of West Bohemia in Pilsen                                     */
-/* ************************************************************************ */
-/*                                                                          */
-/* This file is part of CeCe.                                               */
-/*                                                                          */
-/* CeCe is free software: you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by     */
-/* the Free Software Foundation, either version 3 of the License, or        */
-/* (at your option) any later version.                                      */
-/*                                                                          */
-/* CeCe is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
-/* GNU General Public License for more details.                             */
-/*                                                                          */
-/* You should have received a copy of the GNU General Public License        */
-/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
-/*                                                                          */
-/* ************************************************************************ */
-
-#pragma once
-
-/* ************************************************************************ */
-
-// C++
-#include <type_traits>
-#include <utility>
-
-// CeCe
-#include "cece/common.hpp"
-#include "cece/Assert.hpp"
-#include "cece/math/Zero.hpp"
-#include "cece/math/VectorBase.hpp"
-#include "cece/unit/Units.hpp"
-
-/* ************************************************************************ */
-
-namespace cece {
-namespace math {
-
-/* ************************************************************************ */
-
-/**
- * @brief      Two dimensional vector.
- *
- * @tparam     T     Element type.
- */
-template<typename T>
-class Vector2 : public VectorBase<Vector2, T>
-{
-
-
-// Public Types
-public:
-
-
-    /// Vector2 value type.
-    using ValueType = T;
-
-
-// Public Data Members
-public:
-
-
-    union
-    {
-        struct
-        {
-            /// X coordinate.
-            T x;
-
-            /// Y coordinate.
-            T y;
-        };
-
-        T m[2];
-    };
-
-
-// Public Ctors
-public:
-
-
-    /**
-     * @brief      Default constructor.
-     */
-    Vector2();
-
-
-    /**
-     * @brief      Constructor.
-     *
-     * @param      x     The X and Y coordinate.
-     */
-    explicit Vector2(T value);
-
-
-    /**
-     * @brief      Constructor.
-     *
-     * @param      x     The X coordinate.
-     * @param      y     The Y coordinate.
-     */
-    Vector2(T x, T y);
-
-
-    /**
-     * @brief      Zero value constructor.
-     *
-     * @param[in]  zero  The zero value.
-     */
-    Vector2(Zero_t zero);
-
-
-    /**
-     * @brief      Copy constructor.
-     *
-     * @param[in]  src   The source vector.
-     */
-    Vector2(const Vector2& src);
-
-
-    /**
-     * @brief      Move constructor.
-     *
-     * @param[in]  src   The source vector.
-     */
-    Vector2(Vector2&& src);
-
-
-    /**
-     * @brief      Copy constructor.
-     *
-     * @param      rhs   Source vector.
-     *
-     * @tparam     T2    The source vector element type.
-     */
-    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    Vector2(const Vector2<T2>& rhs);
-
-
-// Public Operators
-public:
-
-
-    /**
-     * @brief      Copy constructor.
-     *
-     * @param[in]  zero  The zero value.
-     *
-     * @return     *this.
-     */
-    Vector2& operator=(Zero_t zero);
-
-
-    /**
-     * @brief      Copy constructor.
-     *
-     * @param[in]  src   The source vector.
-     *
-     * @return     *this.
-     */
-    Vector2& operator=(const Vector2& src);
-
-
-    /**
-     * @brief      Move constructor.
-     *
-     * @param[in]  src   The source vector.
-     *
-     * @return     *this.
-     */
-    Vector2& operator=(Vector2&& src);
-
-
-    /**
-     * @brief      Copy constructor.
-     *
-     * @param      v     The source vector.
-     *
-     * @tparam     T2    The source vector element type.
-     *
-     * @return     *this.
-     */
-    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    Vector2& operator=(const Vector2<T2>& src);
-
-
-    /**
-     * @brief      Access operator.
-     *
-     * @param      pos   The position.
-     *
-     * @return     Reference to the element.
-     */
-    T& operator[](int pos) noexcept;
-
-
-    /**
-     * @brief      Access operator.
-     *
-     * @param      pos   The position.
-     *
-     * @return     Reference to the element.
-     */
-    const T& operator[](int pos) const noexcept;
-
-
-// Public Accessors
-public:
-
-
-    /**
-     * @brief      Returns vector size.
-     *
-     * @return     The size.
-     */
-    int getSize() const noexcept;
-
-
-    /**
-     * @brief      Returns X coordinate.
-     *
-     * @return     The X coordinate.
-     */
-    const T& getX() const noexcept;
-
-
-    /**
-     * @brief      Set X coordinate.
-     *
-     * @param      x     The X coordinate.
-     */
-    void setX(T x);
-
-
-    /**
-     * @brief      Returns Y coordinate.
-     *
-     * @return     The Y coordinate.
-     */
-    const T& getY() const noexcept;
-
-
-    /**
-     * @brief      Set Y coordinate.
-     *
-     * @param      y     The Y coordinate.
-     */
-    void setY(T y);
-
-};
-
-/* ************************************************************************ */
-
-/**
- * @brief      Rotate the vector counter-clockwise and return rotated version.
- *
- * @param[in]  vec    The vector.
- * @param[in]  angle  Rotation angle.
- *
- * @tparam     T      The vector element type.
- *
- * @return     Rotated vector.
- */
-template<typename T>
-Vector2<T> rotate(const Vector2<T>& vec, unit::Angle angle) noexcept;
-
-/* ************************************************************************ */
-
-extern template class Vector2<float>;
-extern template class Vector2<double>;
-extern template class Vector2<unsigned int>;
-extern template class Vector2<int>;
-
-/* ************************************************************************ */
-
-}
-}
-
-/* ************************************************************************ */
-/* ************************************************************************ */
-/* ************************************************************************ */
-
-namespace cece {
-namespace math {
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T>::Vector2()
-    : x{}
-    , y{}
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T>::Vector2(T val)
-    : x{val}
-    , y{val}
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T>::Vector2(T x, T y)
-    : x{std::move(x)}
-    , y{std::move(y)}
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T>::Vector2(Zero_t zero)
-    : x{}
-    , y{}
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T>::Vector2(const Vector2& src)
-    : x{src.getX()}
-    , y{src.getY()}
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T>::Vector2(Vector2&& src)
-    : x{std::move(src.x)}
-    , y{std::move(src.y)}
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline Vector2<T>::Vector2(const Vector2<T2>& rhs)
-    : x(rhs.getX())
-    , y(rhs.getY())
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T>& Vector2<T>::operator=(Zero_t zero)
-{
-    x = T{};
-    y = T{};
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T>& Vector2<T>::operator=(const Vector2& src)
-{
-    x = src.x;
-    y = src.y;
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T>& Vector2<T>::operator=(Vector2&& src)
-{
-    x = std::move(src.x);
-    y = std::move(src.y);
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline Vector2<T>& Vector2<T>::operator=(const Vector2<T2>& src)
-{
-    x = T(src.getX());
-    y = T(src.getY());
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline T& Vector2<T>::operator[](int pos) noexcept
-{
-    CECE_ASSERT(pos >= 0);
-    CECE_ASSERT(pos < getSize());
-    return (&x)[pos];
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline const T& Vector2<T>::operator[](int pos) const noexcept
-{
-    CECE_ASSERT(pos >= 0);
-    CECE_ASSERT(pos < getSize());
-    return (&x)[pos];
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline int Vector2<T>::getSize() const noexcept
-{
-    return 2;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline const T& Vector2<T>::getX() const noexcept
-{
-    return x;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline void Vector2<T>::setX(T x)
-{
-    this->x = std::move(x);
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline const T& Vector2<T>::getY() const noexcept
-{
-    return y;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline void Vector2<T>::setY(T y)
-{
-    this->y = std::move(y);
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector2<T> rotate(const Vector2<T>& vec, unit::Angle angle) noexcept
-{
-    return {
-        static_cast<T>(vec.getX() * cos(static_cast<RealType>(angle)) - vec.getY() * sin(static_cast<RealType>(angle))),
-        static_cast<T>(vec.getX() * sin(static_cast<RealType>(angle)) + vec.getY() * cos(static_cast<RealType>(angle)))
-    };
-}
-
-/* ************************************************************************ */
-
-}
-}
-
-/* ************************************************************************ */
diff --git a/include/cece/math/Vector3.hpp b/include/cece/math/Vector3.hpp
deleted file mode 100644
index bfaeeca..0000000
--- a/include/cece/math/Vector3.hpp
+++ /dev/null
@@ -1,537 +0,0 @@
-/* ************************************************************************ */
-/* Georgiev Lab (c) 2015-2017                                               */
-/* ************************************************************************ */
-/* Department of Cybernetics                                                */
-/* Faculty of Applied Sciences                                              */
-/* University of West Bohemia in Pilsen                                     */
-/* ************************************************************************ */
-/*                                                                          */
-/* This file is part of CeCe.                                               */
-/*                                                                          */
-/* CeCe is free software: you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by     */
-/* the Free Software Foundation, either version 3 of the License, or        */
-/* (at your option) any later version.                                      */
-/*                                                                          */
-/* CeCe is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
-/* GNU General Public License for more details.                             */
-/*                                                                          */
-/* You should have received a copy of the GNU General Public License        */
-/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
-/*                                                                          */
-/* ************************************************************************ */
-
-#pragma once
-
-/* ************************************************************************ */
-
-// C++
-#include <type_traits>
-#include <utility>
-
-// CeCe
-#include "cece/common.hpp"
-#include "cece/Assert.hpp"
-#include "cece/math/Zero.hpp"
-#include "cece/math/VectorBase.hpp"
-
-/* ************************************************************************ */
-
-namespace cece {
-namespace math {
-
-/* ************************************************************************ */
-
-/**
- * @brief      Three dimensional vector.
- *
- * @tparam     T     Element type.
- */
-template<typename T>
-class Vector3 : public VectorBase<Vector3, T>
-{
-
-
-// Public Types
-public:
-
-
-    /// Vector3 value type.
-    using ValueType = T;
-
-
-// Public Data Members
-public:
-
-
-    union
-    {
-        struct
-        {
-            /// X coordinate.
-            T x;
-
-            /// Y coordinate.
-            T y;
-
-            /// Z coordinate.
-            T z;
-        };
-
-        T m[3];
-    };
-
-
-// Public Ctors
-public:
-
-
-    /**
-     * @brief      Default constructor.
-     */
-    Vector3() noexcept;
-
-
-    /**
-     * @brief      Constructor.
-     *
-     * @param      val   The X, Y and Z coordinate.
-     */
-    explicit Vector3(T val);
-
-
-    /**
-     * @brief      Constructor.
-     *
-     * @param      x     The X coordinate.
-     * @param      y     The Y coordinate.
-     * @param      y     The Z coordinate.
-     */
-    Vector3(T x, T y, T z);
-
-
-    /**
-     * @brief      Zero value constructor.
-     *
-     * @param[in]  zero  The zero value.
-     */
-    Vector3(Zero_t zero);
-
-
-    /**
-     * @brief      Copy constructor.
-     *
-     * @param[in]  src   The source vector.
-     */
-    Vector3(const Vector3& src);
-
-
-    /**
-     * @brief      Move constructor.
-     *
-     * @param[in]  src   The source vector.
-     */
-    Vector3(Vector3&& src);
-
-
-    /**
-     * @brief      Copy constructor.
-     *
-     * @param      rhs   Source vector.
-     *
-     * @tparam     T2    The source vector element type.
-     */
-    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    Vector3(const Vector3<T2>& rhs);
-
-
-// Public Operators
-public:
-
-
-    /**
-     * @brief      Copy constructor.
-     *
-     * @param[in]  zero  The zero value.
-     *
-     * @return     *this.
-     */
-    Vector3& operator=(Zero_t zero);
-
-
-    /**
-     * @brief      Copy constructor.
-     *
-     * @param[in]  src   The source vector.
-     *
-     * @return     *this.
-     */
-    Vector3& operator=(const Vector3& src);
-
-
-    /**
-     * @brief      Move constructor.
-     *
-     * @param[in]  src   The source vector.
-     *
-     * @return     *this.
-     */
-    Vector3& operator=(Vector3&& src);
-
-
-    /**
-     * @brief      Copy constructor.
-     *
-     * @param      v     The source vector.
-     *
-     * @tparam     T2    The source vector element type.
-     *
-     * @return     *this.
-     */
-    template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    Vector3& operator=(const Vector3<T2>& src);
-
-
-    /**
-     * @brief      Access operator.
-     *
-     * @param      pos   The position.
-     *
-     * @return     Reference to the element.
-     */
-    T& operator[](int pos) noexcept;
-
-
-    /**
-     * @brief      Access operator.
-     *
-     * @param      pos   The position.
-     *
-     * @return     Reference to the element.
-     */
-    const T& operator[](int pos) const noexcept;
-
-
-// Public Accessors
-public:
-
-
-    /**
-     * @brief      Returns vector size.
-     *
-     * @return     The size.
-     */
-    int getSize() const noexcept;
-
-
-    /**
-     * @brief      Returns X coordinate.
-     *
-     * @return     The X coordinate.
-     */
-    const T& getX() const noexcept;
-
-
-    /**
-     * @brief      Set X coordinate.
-     *
-     * @param      x     The X coordinate.
-     */
-    void setX(T x);
-
-
-    /**
-     * @brief      Returns Y coordinate.
-     *
-     * @return     The Y coordinate.
-     */
-    const T& getY() const noexcept;
-
-
-    /**
-     * @brief      Set Y coordinate.
-     *
-     * @param      y     The Y coordinate.
-     */
-    void setY(T y);
-
-
-    /**
-     * @brief      Returns Z coordinate.
-     *
-     * @return     The Z coordinate.
-     */
-    const T& getZ() const noexcept;
-
-
-    /**
-     * @brief      Set Z coordinate.
-     *
-     * @param      z     The Z coordinate.
-     */
-    void setZ(T z);
-
-};
-
-/* ************************************************************************ */
-
-extern template class Vector3<float>;
-extern template class Vector3<double>;
-extern template class Vector3<unsigned int>;
-extern template class Vector3<int>;
-
-/* ************************************************************************ */
-
-/**
- * @brief      Calculate cross product of two vectors.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
- *
- * @tparam     T1    The first type.
- * @tparam     T2    The second type.
- *
- * @return     Cross product.
- */
-template<typename T1, typename T2>
-Vector3<decltype(std::declval<T1>() * std::declval<T2>())>
-cross(const Vector3<T1>& lhs, const Vector3<T2>& rhs);
-
-/* ************************************************************************ */
-
-}
-}
-
-/* ************************************************************************ */
-/* ************************************************************************ */
-/* ************************************************************************ */
-
-namespace cece {
-namespace math {
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector3<T>::Vector3() noexcept
-    : x{}
-    , y{}
-    , z{}
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector3<T>::Vector3(T val)
-    : x{val}
-    , y{val}
-    , z{val}
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector3<T>::Vector3(T x, T y, T z)
-    : x{std::move(x)}
-    , y{std::move(y)}
-    , z{std::move(z)}
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector3<T>::Vector3(Zero_t zero)
-    : x{}
-    , y{}
-    , z{}
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector3<T>::Vector3(const Vector3& src)
-    : x{src.getX()}
-    , y{src.getY()}
-    , z{src.getZ()}
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector3<T>::Vector3(Vector3&& src)
-    : x{std::move(src.x)}
-    , y{std::move(src.y)}
-    , z{std::move(src.z)}
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline Vector3<T>::Vector3(const Vector3<T2>& rhs)
-    : x(rhs.getX())
-    , y(rhs.getY())
-    , z(rhs.getZ())
-{
-    // Nothing to do
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector3<T>& Vector3<T>::operator=(Zero_t zero)
-{
-    x = T{};
-    y = T{};
-    z = T{};
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector3<T>& Vector3<T>::operator=(const Vector3& src)
-{
-    x = src.x;
-    y = src.y;
-    z = src.z;
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline Vector3<T>& Vector3<T>::operator=(Vector3&& src)
-{
-    x = std::move(src.x);
-    y = std::move(src.y);
-    z = std::move(src.z);
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline Vector3<T>& Vector3<T>::operator=(const Vector3<T2>& src)
-{
-    x = T(src.getX());
-    y = T(src.getY());
-    z = T(src.getZ());
-
-    return *this;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline int Vector3<T>::getSize() const noexcept
-{
-    return 3;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline T& Vector3<T>::operator[](int pos) noexcept
-{
-    CECE_ASSERT(pos >= 0);
-    CECE_ASSERT(pos < getSize());
-    return (&x)[pos];
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline const T& Vector3<T>::operator[](int pos) const noexcept
-{
-    CECE_ASSERT(pos >= 0);
-    CECE_ASSERT(pos < getSize());
-    return (&x)[pos];
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline const T& Vector3<T>::getX() const noexcept
-{
-    return x;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline void Vector3<T>::setX(T x)
-{
-    this->x = std::move(x);
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline const T& Vector3<T>::getY() const noexcept
-{
-    return y;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline void Vector3<T>::setY(T y)
-{
-    this->y = std::move(y);
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline const T& Vector3<T>::getZ() const noexcept
-{
-    return z;
-}
-
-/* ************************************************************************ */
-
-template<typename T>
-inline void Vector3<T>::setZ(T z)
-{
-    this->z = std::move(z);
-}
-
-/* ************************************************************************ */
-
-template<typename T1, typename T2>
-inline Vector3<decltype(std::declval<T1>() * std::declval<T2>())> cross(
-    const Vector3<T1>& lhs,
-    const Vector3<T2>& rhs
-)
-{
-    return {
-        lhs.getY() * rhs.getZ() - lhs.getZ() * rhs.getY(),
-        lhs.getZ() * rhs.getX() - lhs.getX() * rhs.getZ(),
-        lhs.getX() * rhs.getY() - lhs.getY() * rhs.getX()
-    };
-}
-
-/* ************************************************************************ */
-
-}
-}
-
-/* ************************************************************************ */
diff --git a/include/cece/math/VectorBase.hpp b/include/cece/math/VectorBase.hpp
index 216169c..a9f5ee1 100644
--- a/include/cece/math/VectorBase.hpp
+++ b/include/cece/math/VectorBase.hpp
@@ -48,12 +48,12 @@ namespace math {
  *
  * @tparam     VectorType  The vector type.
  * @tparam     T           Value type.
- * @tparam     Tags        Additional tags.
+ * @tparam     N           Vector size.
  */
 template<
-    template<typename, int...> typename VectorType,
+    template<typename, int> typename VectorType,
     typename T,
-    int... Tags
+    int N
 >
 class VectorBase
 {
@@ -75,7 +75,7 @@ class VectorBase
      *
      * @return     Vector.
      */
-    VectorType<T, Tags...> operator+() const noexcept;
+    VectorType<T, N> operator+() const noexcept;
 
 
     /**
@@ -83,7 +83,7 @@ class VectorBase
      *
      * @return     Vector.
      */
-    VectorType<T, Tags...> operator-() const noexcept;
+    VectorType<T, N> operator-() const noexcept;
 
 
     /**
@@ -96,7 +96,7 @@ class VectorBase
      * @return     *this.
      */
     template<typename T1>
-    VectorType<T, Tags...>& operator+=(const VectorType<T1, Tags...>& rhs);
+    VectorType<T, N>& operator+=(const VectorType<T1, N>& rhs);
 
 
     /**
@@ -109,7 +109,7 @@ class VectorBase
      * @return     *this.
      */
     template<typename T1>
-    VectorType<T, Tags...>& operator-=(const VectorType<T1, Tags...>& rhs);
+    VectorType<T, N>& operator-=(const VectorType<T1, N>& rhs);
 
 
     /**
@@ -122,7 +122,7 @@ class VectorBase
      * @return     *this.
      */
     template<typename T1>
-    VectorType<T, Tags...>& operator*=(T1 rhs);
+    VectorType<T, N>& operator*=(T1 rhs);
 
 
     /**
@@ -135,7 +135,7 @@ class VectorBase
      * @return     *this.
      */
     template<typename T1>
-    VectorType<T, Tags...>& operator*=(const VectorType<T1, Tags...>& rhs);
+    VectorType<T, N>& operator*=(const VectorType<T1, N>& rhs);
 
 
     /**
@@ -148,7 +148,7 @@ class VectorBase
      * @return     *this.
      */
     template<typename T1>
-    VectorType<T, Tags...>& operator/=(T1 rhs);
+    VectorType<T, N>& operator/=(T1 rhs);
 
 
     /**
@@ -161,7 +161,7 @@ class VectorBase
      * @return     *this.
      */
     template<typename T1>
-    VectorType<T, Tags...>& operator/=(const VectorType<T1, Tags...>& rhs);
+    VectorType<T, N>& operator/=(const VectorType<T1, N>& rhs);
 
 
     /**
@@ -193,7 +193,7 @@ class VectorBase
      *
      * @return     The size.
      */
-    int getSize() const;
+    constexpr int getSize() const noexcept;
 
 
 // Public Operations
@@ -232,10 +232,10 @@ class VectorBase
  *
  * @return     Result vector.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-VectorType<decltype(std::declval<T1>() + std::declval<T2>()), Tags...> operator+(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+VectorType<decltype(std::declval<T1>() + std::declval<T2>()), N> operator+(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
@@ -253,10 +253,10 @@ VectorType<decltype(std::declval<T1>() + std::declval<T2>()), Tags...> operator+
  *
  * @return     Result vector.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-VectorType<decltype(std::declval<T1>() - std::declval<T2>()), Tags...> operator-(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+VectorType<decltype(std::declval<T1>() - std::declval<T2>()), N> operator-(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
@@ -274,10 +274,10 @@ VectorType<decltype(std::declval<T1>() - std::declval<T2>()), Tags...> operator-
  *
  * @return     Result vector.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+VectorType<decltype(std::declval<T1>() * std::declval<T2>()), N> operator*(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
@@ -295,9 +295,9 @@ VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*
  *
  * @return     Result vector.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*(
-    const VectorType<T1, Tags...>& lhs,
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+VectorType<decltype(std::declval<T1>() * std::declval<T2>()), N> operator*(
+    const VectorType<T1, N>& lhs,
     const T2& rhs
 );
 
@@ -316,10 +316,10 @@ VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*
  *
  * @return     Result vector.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*(
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+VectorType<decltype(std::declval<T1>() * std::declval<T2>()), N> operator*(
     const T1& lhs,
-    const VectorType<T2, Tags...>& rhs
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
@@ -337,10 +337,10 @@ VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*
  *
  * @return     Result vector.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+VectorType<decltype(std::declval<T1>() / std::declval<T2>()), N> operator/(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
@@ -358,9 +358,9 @@ VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/
  *
  * @return     Result vector.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/(
-    const VectorType<T1, Tags...>& lhs,
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+VectorType<decltype(std::declval<T1>() / std::declval<T2>()), N> operator/(
+    const VectorType<T1, N>& lhs,
     const T2& rhs
 );
 
@@ -379,10 +379,10 @@ VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/
  *
  * @return     Result vector.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/(
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+VectorType<decltype(std::declval<T1>() / std::declval<T2>()), N> operator/(
     const T1& lhs,
-    const VectorType<T2, Tags...>& rhs
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
@@ -400,10 +400,10 @@ VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/
  *
  * @return     Operation result.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
 bool operator==(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
@@ -420,9 +420,9 @@ bool operator==(
  *
  * @return     Operation result.
  */
-template<template<typename, int...> typename VectorType, typename T1, int... Tags>
+template<template<typename, int> typename VectorType, typename T1, int N>
 bool operator==(
-    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T1, N>& lhs,
     const Zero_t& rhs
 );
 
@@ -440,10 +440,10 @@ bool operator==(
  *
  * @return     Operation result.
  */
-template<template<typename, int...> typename VectorType, typename T2, int... Tags>
+template<template<typename, int> typename VectorType, typename T2, int N>
 bool operator==(
     const Zero_t& lhs,
-    const VectorType<T2, Tags...>& rhs
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
@@ -461,10 +461,10 @@ bool operator==(
  *
  * @return     Operation result.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
 bool operator!=(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
@@ -481,9 +481,9 @@ bool operator!=(
  *
  * @return     Operation result.
  */
-template<template<typename, int...> typename VectorType, typename T1, int... Tags>
+template<template<typename, int> typename VectorType, typename T1, int N>
 bool operator!=(
-    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T1, N>& lhs,
     const Zero_t& rhs
 );
 
@@ -501,142 +501,123 @@ bool operator!=(
  *
  * @return     Operation result.
  */
-template<template<typename, int...> typename VectorType, typename T2, int... Tags>
+template<template<typename, int> typename VectorType, typename T2, int N>
 bool operator!=(
     const Zero_t& lhs,
-    const VectorType<T2, Tags...>& rhs
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
 
 /**
- * @brief      Compare vectors.
+ * @brief      Calculate dot product of two vectors.
  *
- * @param      lhs         The left operand.
- * @param      rhs         The right operand.
+ * @param      lhs         Left operand.
+ * @param      rhs         Right operand.
  *
  * @tparam     VectorType  Vector type.
  * @tparam     T1          Type of value in first VectorBase.
  * @tparam     T2          Type of value in second VectorBase.
  * @tparam     Tags        Vector type tags.
  *
- * @return     Operation result.
+ * @return     Dot product.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-bool operator<(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+decltype(std::declval<T1>() * std::declval<T2>()) dot(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
 
 /**
- * @brief      Compare vectors.
+ * @brief      Calculate distance of two vectors.
  *
- * @param      lhs         The left operand.
- * @param      rhs         The right operand.
+ * @param      lhs         Left operand.
+ * @param      rhs         Right operand.
  *
  * @tparam     VectorType  Vector type.
  * @tparam     T1          Type of value in first VectorBase.
  * @tparam     T2          Type of value in second VectorBase.
  * @tparam     Tags        Vector type tags.
  *
- * @return     Operation result.
+ * @return     Distance.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-bool operator<=(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+decltype(std::declval<decltype(std::declval<T1>() - std::declval<T2>())>() * std::declval<decltype(std::declval<T1>() - std::declval<T2>())>()) distanceSquared(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
 
 /**
- * @brief      Compare vectors.
+ * @brief      Calculate distance of two vectors.
  *
- * @param      lhs         The left operand.
- * @param      rhs         The right operand.
+ * @param      lhs         Left operand.
+ * @param      rhs         Right operand.
  *
  * @tparam     VectorType  Vector type.
  * @tparam     T1          Type of value in first VectorBase.
  * @tparam     T2          Type of value in second VectorBase.
  * @tparam     Tags        Vector type tags.
  *
- * @return     Operation result.
+ * @return     Distance.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-bool operator>(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+decltype(std::declval<T1>() - std::declval<T2>()) distance(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 );
 
 /* ************************************************************************ */
 
 /**
- * @brief      Compare vectors.
+ * @brief      Check if value is in given range.
  *
- * @param      lhs         The left operand.
- * @param      rhs         The right operand.
+ * @code
+ *  value >= low && value < high;
+ * @endcode
+ *
+ * @param[in]  value       The tested value.
+ * @param[in]  low         The low value.
+ * @param[in]  high        The high value.
  *
  * @tparam     VectorType  Vector type.
- * @tparam     T1          Type of value in first VectorBase.
- * @tparam     T2          Type of value in second VectorBase.
+ * @tparam     T           Type of value.
  * @tparam     Tags        Vector type tags.
  *
- * @return     Operation result.
+ * @return     If value is in range.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-bool operator>=(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T, int N>
+bool inRange(
+    const VectorType<T, N>& value,
+    const VectorType<T, N>& low,
+    const VectorType<T, N>& high
 );
 
 /* ************************************************************************ */
 
 /**
- * @brief      Calculate dot product of two vectors.
+ * @brief      Check if value is in given range.
  *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
+ * @code
+ *  value >= Zero && value < high;
+ * @endcode
  *
- * @return     Dot product.
- */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-decltype(std::declval<T1>() * std::declval<T2>()) dot(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
-);
-
-/* ************************************************************************ */
-
-/**
- * @brief      Calculate distance of two vectors.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
+ * @param[in]  value       The tested value.
+ * @param[in]  high        The high value.
  *
- * @return     Distance.
- */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-decltype(std::declval<decltype(std::declval<T1>() - std::declval<T2>())>() * std::declval<decltype(std::declval<T1>() - std::declval<T2>())>()) distanceSquared(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
-);
-
-/* ************************************************************************ */
-
-/**
- * @brief      Calculate distance of two vectors.
- *
- * @param      lhs   Left operand.
- * @param      rhs   Right operand.
+ * @tparam     VectorType  Vector type.
+ * @tparam     T           Type of value.
+ * @tparam     Tags        Vector type tags.
  *
- * @return     Distance.
+ * @return     If value is in range.
  */
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-decltype(std::declval<T1>() - std::declval<T2>()) distance(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T, int N>
+bool inRange(
+    const VectorType<T, N>& value,
+    const VectorType<T, N>& high
 );
 
 /* ************************************************************************ */
@@ -653,20 +634,20 @@ namespace math {
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
-inline VectorType<T, Tags...> VectorBase<VectorType, T, Tags...>::operator+() const noexcept
+template<template<typename, int> typename VectorType, typename T, int N>
+inline VectorType<T, N> VectorBase<VectorType, T, N>::operator+() const noexcept
 {
-    return *static_cast<const VectorType<T, Tags...>*>(this);
+    return *static_cast<const VectorType<T, N>*>(this);
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
-inline VectorType<T, Tags...> VectorBase<VectorType, T, Tags...>::operator-() const noexcept
+template<template<typename, int> typename VectorType, typename T, int N>
+inline VectorType<T, N> VectorBase<VectorType, T, N>::operator-() const noexcept
 {
-    VectorType<T, Tags...> res;
+    VectorType<T, N> res;
 
-    for (int i = 0; i < getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = -(*this)[i];
 
     return res;
@@ -674,107 +655,106 @@ inline VectorType<T, Tags...> VectorBase<VectorType, T, Tags...>::operator-() co
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
+template<template<typename, int> typename VectorType, typename T, int N>
 template<typename T1>
-inline VectorType<T, Tags...>& VectorBase<VectorType, T, Tags...>::operator+=(const VectorType<T1, Tags...>& rhs)
+inline VectorType<T, N>& VectorBase<VectorType, T, N>::operator+=(const VectorType<T1, N>& rhs)
 {
-    for (int i = 0; i < getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         (*this)[i] += rhs[i];
 
-    return *static_cast<VectorType<T, Tags...>*>(this);
+    return *static_cast<VectorType<T, N>*>(this);
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
+template<template<typename, int> typename VectorType, typename T, int N>
 template<typename T1>
-inline VectorType<T, Tags...>& VectorBase<VectorType, T, Tags...>::operator-=(const VectorType<T1, Tags...>& rhs)
+inline VectorType<T, N>& VectorBase<VectorType, T, N>::operator-=(const VectorType<T1, N>& rhs)
 {
-    for (int i = 0; i < getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         (*this)[i] -= rhs[i];
 
-    return *static_cast<VectorType<T, Tags...>*>(this);
+    return *static_cast<VectorType<T, N>*>(this);
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
+template<template<typename, int> typename VectorType, typename T, int N>
 template<typename T1>
-inline VectorType<T, Tags...>& VectorBase<VectorType, T, Tags...>::operator*=(T1 rhs)
+inline VectorType<T, N>& VectorBase<VectorType, T, N>::operator*=(T1 rhs)
 {
-    for (int i = 0; i < getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         (*this)[i] *= rhs;
 
-    return *static_cast<VectorType<T, Tags...>*>(this);
+    return *static_cast<VectorType<T, N>*>(this);
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
+template<template<typename, int> typename VectorType, typename T, int N>
 template<typename T1>
-inline VectorType<T, Tags...>& VectorBase<VectorType, T, Tags...>::operator*=(const VectorType<T1, Tags...>& rhs)
+inline VectorType<T, N>& VectorBase<VectorType, T, N>::operator*=(const VectorType<T1, N>& rhs)
 {
-    for (int i = 0; i < getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         (*this)[i] *= rhs[i];
 
-    return *static_cast<VectorType<T, Tags...>*>(this);
+    return *static_cast<VectorType<T, N>*>(this);
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
+template<template<typename, int> typename VectorType, typename T, int N>
 template<typename T1>
-inline VectorType<T, Tags...>& VectorBase<VectorType, T, Tags...>::operator/=(T1 rhs)
+inline VectorType<T, N>& VectorBase<VectorType, T, N>::operator/=(T1 rhs)
 {
-    for (int i = 0; i < getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         (*this)[i] /= rhs;
 
-    return *static_cast<VectorType<T, Tags...>*>(this);
+    return *static_cast<VectorType<T, N>*>(this);
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
+template<template<typename, int> typename VectorType, typename T, int N>
 template<typename T1>
-inline VectorType<T, Tags...>& VectorBase<VectorType, T, Tags...>::operator/=(const VectorType<T1, Tags...>& rhs)
+inline VectorType<T, N>& VectorBase<VectorType, T, N>::operator/=(const VectorType<T1, N>& rhs)
 {
-    for (int i = 0; i < getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         (*this)[i] /= rhs[i];
 
-    return *static_cast<VectorType<T, Tags...>*>(this);
+    return *static_cast<VectorType<T, N>*>(this);
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
-inline T& VectorBase<VectorType, T, Tags...>::operator[](int pos)
+template<template<typename, int> typename VectorType, typename T, int N>
+inline T& VectorBase<VectorType, T, N>::operator[](int pos)
 {
     // TODO: recursion possibility
-    return (*static_cast<VectorType<T, Tags...>*>(this))[pos];
+    return (*static_cast<VectorType<T, N>*>(this))[pos];
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
-inline const T& VectorBase<VectorType, T, Tags...>::operator[](int pos) const
+template<template<typename, int> typename VectorType, typename T, int N>
+inline const T& VectorBase<VectorType, T, N>::operator[](int pos) const
 {
     // TODO: recursion possibility
-    return (*static_cast<const VectorType<T, Tags...>*>(this))[pos];
+    return (*static_cast<const VectorType<T, N>*>(this))[pos];
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
-inline int VectorBase<VectorType, T, Tags...>::getSize() const
+template<template<typename, int> typename VectorType, typename T, int N>
+inline constexpr int VectorBase<VectorType, T, N>::getSize() const noexcept
 {
-    // TODO: recursion possibility
-    return static_cast<const VectorType<T, Tags...>*>(this)->getSize();
+    return N;
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
-inline T VectorBase<VectorType, T, Tags...>::getLength() const
+template<template<typename, int> typename VectorType, typename T, int N>
+inline T VectorBase<VectorType, T, N>::getLength() const
 {
     using std::sqrt;
     return static_cast<T>(sqrt(getLengthSquared()));
@@ -782,12 +762,12 @@ inline T VectorBase<VectorType, T, Tags...>::getLength() const
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T, int... Tags>
-inline decltype(std::declval<T>() * std::declval<T>()) VectorBase<VectorType, T, Tags...>::getLengthSquared() const
+template<template<typename, int> typename VectorType, typename T, int N>
+inline decltype(std::declval<T>() * std::declval<T>()) VectorBase<VectorType, T, N>::getLengthSquared() const
 {
     decltype(std::declval<T>() * std::declval<T>()) res{};
 
-    for (int i = 0; i < getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         res += (*this)[i] * (*this)[i];
 
     return res;
@@ -795,19 +775,15 @@ inline decltype(std::declval<T>() * std::declval<T>()) VectorBase<VectorType, T,
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline VectorType<decltype(std::declval<T1>() + std::declval<T2>()), Tags...> operator+(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+inline VectorType<decltype(std::declval<T1>() + std::declval<T2>()), N> operator+(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 )
 {
-    VectorType<decltype(std::declval<T1>() + std::declval<T2>()), Tags...> res;
-
-    CECE_ASSERT(lhs.getSize() == rhs.getSize());
-    CECE_ASSERT(res.getSize() == lhs.getSize());
-    CECE_ASSERT(res.getSize() == rhs.getSize());
+    VectorType<decltype(std::declval<T1>() + std::declval<T2>()), N> res;
 
-    for (int i = 0; i < res.getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] + rhs[i];
 
     return res;
@@ -815,19 +791,15 @@ inline VectorType<decltype(std::declval<T1>() + std::declval<T2>()), Tags...> op
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline VectorType<decltype(std::declval<T1>() - std::declval<T2>()), Tags...> operator-(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+inline VectorType<decltype(std::declval<T1>() - std::declval<T2>()), N> operator-(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 )
 {
-    VectorType<decltype(std::declval<T1>() - std::declval<T2>()), Tags...> res;
-
-    CECE_ASSERT(lhs.getSize() == rhs.getSize());
-    CECE_ASSERT(res.getSize() == lhs.getSize());
-    CECE_ASSERT(res.getSize() == rhs.getSize());
+    VectorType<decltype(std::declval<T1>() - std::declval<T2>()), N> res;
 
-    for (int i = 0; i < res.getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] - rhs[i];
 
     return res;
@@ -835,19 +807,15 @@ inline VectorType<decltype(std::declval<T1>() - std::declval<T2>()), Tags...> op
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+inline VectorType<decltype(std::declval<T1>() * std::declval<T2>()), N> operator*(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 )
 {
-    VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> res;
+    VectorType<decltype(std::declval<T1>() * std::declval<T2>()), N> res;
 
-    CECE_ASSERT(lhs.getSize() == rhs.getSize());
-    CECE_ASSERT(res.getSize() == lhs.getSize());
-    CECE_ASSERT(res.getSize() == rhs.getSize());
-
-    for (int i = 0; i < res.getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] * rhs[i];
 
     return res;
@@ -855,17 +823,15 @@ inline VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> op
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*(
-    const VectorType<T1, Tags...>& lhs,
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+inline VectorType<decltype(std::declval<T1>() * std::declval<T2>()), N> operator*(
+    const VectorType<T1, N>& lhs,
     const T2& rhs
 )
 {
-    VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> res;
-
-    CECE_ASSERT(res.getSize() == lhs.getSize());
+    VectorType<decltype(std::declval<T1>() * std::declval<T2>()), N> res;
 
-    for (int i = 0; i < res.getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] * rhs;
 
     return res;
@@ -873,17 +839,15 @@ inline VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> op
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> operator*(
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+inline VectorType<decltype(std::declval<T1>() * std::declval<T2>()), N> operator*(
     const T1& lhs,
-    const VectorType<T2, Tags...>& rhs
+    const VectorType<T2, N>& rhs
 )
 {
-    VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> res;
-
-    CECE_ASSERT(res.getSize() == rhs.getSize());
+    VectorType<decltype(std::declval<T1>() * std::declval<T2>()), N> res;
 
-    for (int i = 0; i < res.getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs * rhs[i];
 
     return res;
@@ -891,19 +855,15 @@ inline VectorType<decltype(std::declval<T1>() * std::declval<T2>()), Tags...> op
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+inline VectorType<decltype(std::declval<T1>() / std::declval<T2>()), N> operator/(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 )
 {
-    VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> res;
+    VectorType<decltype(std::declval<T1>() / std::declval<T2>()), N> res;
 
-    CECE_ASSERT(lhs.getSize() == rhs.getSize());
-    CECE_ASSERT(res.getSize() == lhs.getSize());
-    CECE_ASSERT(res.getSize() == rhs.getSize());
-
-    for (int i = 0; i < res.getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] / rhs[i];
 
     return res;
@@ -911,17 +871,15 @@ inline VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> op
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/(
-    const VectorType<T1, Tags...>& lhs,
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+inline VectorType<decltype(std::declval<T1>() / std::declval<T2>()), N> operator/(
+    const VectorType<T1, N>& lhs,
     const T2& rhs
 )
 {
-    VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> res;
-
-    CECE_ASSERT(res.getSize() == lhs.getSize());
+    VectorType<decltype(std::declval<T1>() / std::declval<T2>()), N> res;
 
-    for (int i = 0; i < res.getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs[i] / rhs;
 
     return res;
@@ -929,17 +887,15 @@ inline VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> op
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> operator/(
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+inline VectorType<decltype(std::declval<T1>() / std::declval<T2>()), N> operator/(
     const T1& lhs,
-    const VectorType<T2, Tags...>& rhs
+    const VectorType<T2, N>& rhs
 )
 {
-    VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> res;
-
-    CECE_ASSERT(res.getSize() == rhs.getSize());
+    VectorType<decltype(std::declval<T1>() / std::declval<T2>()), N> res;
 
-    for (int i = 0; i < res.getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         res[i] = lhs / rhs[i];
 
     return res;
@@ -947,17 +903,15 @@ inline VectorType<decltype(std::declval<T1>() / std::declval<T2>()), Tags...> op
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
 inline bool operator==(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 )
 {
     bool res = true;
 
-    CECE_ASSERT(lhs.getSize() == rhs.getSize());
-
-    for (int i = 0; i < lhs.getSize(); ++i)
+    for (int i = 0; i < N; ++i)
         res = res && lhs[i] == rhs[i];
 
     return res;
@@ -965,32 +919,32 @@ inline bool operator==(
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, int... Tags>
+template<template<typename, int> typename VectorType, typename T1, int N>
 inline bool operator==(
-    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T1, N>& lhs,
     const Zero_t& rhs
 )
 {
-    return operator==(lhs, VectorType<T1, Tags...>(Zero));
+    return operator==(lhs, VectorType<T1, N>(Zero));
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T2, int... Tags>
+template<template<typename, int> typename VectorType, typename T2, int N>
 inline bool operator==(
     const Zero_t& lhs,
-    const VectorType<T2, Tags...>& rhs
+    const VectorType<T2, N>& rhs
 )
 {
-    return operator==(VectorType<T2, Tags...>(lhs), rhs);
+    return operator==(VectorType<T2, N>(lhs), rhs);
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
 inline bool operator!=(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 )
 {
     return !operator==(lhs, rhs);
@@ -998,9 +952,9 @@ inline bool operator!=(
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, int... Tags>
+template<template<typename, int> typename VectorType, typename T1, int N>
 inline bool operator!=(
-    const VectorType<T1, Tags...>& lhs,
+    const VectorType<T1, N>& lhs,
     const Zero_t& rhs
 )
 {
@@ -1009,10 +963,10 @@ inline bool operator!=(
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T2, int... Tags>
+template<template<typename, int> typename VectorType, typename T2, int N>
 inline bool operator!=(
     const Zero_t& lhs,
-    const VectorType<T2, Tags...>& rhs
+    const VectorType<T2, N>& rhs
 )
 {
     return !operator==(lhs, rhs);
@@ -1020,93 +974,68 @@ inline bool operator!=(
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline bool operator<(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+inline decltype(std::declval<T1>() * std::declval<T2>()) dot(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 )
 {
-    bool res = true;
-
-    CECE_ASSERT(lhs.getSize() == rhs.getSize());
+    decltype(std::declval<T1>() * std::declval<T2>()) res{};
 
-    for (int i = 0; i < lhs.getSize(); ++i)
-        res = res && (lhs[i] < rhs[i]);
+    for (int i = 0; i < N; ++i)
+        res += lhs[i] * rhs[i];
 
     return res;
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline bool operator<=(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
-)
-{
-    return !operator>(lhs, rhs);
-}
-
-/* ************************************************************************ */
-
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline bool operator>(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+inline decltype(std::declval<decltype(std::declval<T1>() - std::declval<T2>())>() * std::declval<decltype(std::declval<T1>() - std::declval<T2>())>()) distanceSquared(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 )
 {
-    return operator<(rhs, lhs);
+    return (lhs - rhs).getLengthSquared();
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline bool operator>=(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T1, typename T2, int N>
+inline decltype(std::declval<T1>() - std::declval<T2>()) distance(
+    const VectorType<T1, N>& lhs,
+    const VectorType<T2, N>& rhs
 )
 {
-    return !operator<(lhs, rhs);
+    return (lhs - rhs).getLength();
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline decltype(std::declval<T1>() * std::declval<T2>()) dot(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T, int N>
+inline bool inRange(
+    const VectorType<T, N>& value,
+    const VectorType<T, N>& low,
+    const VectorType<T, N>& high
 )
 {
-    decltype(std::declval<T1>() * std::declval<T2>()) res{};
+    bool res = true;
 
-    CECE_ASSERT(lhs.getSize() == rhs.getSize());
-
-    for (int i = 0; i < lhs.getSize(); ++i)
-        res += lhs[i] * rhs[i];
+    for (int i = 0; i < N; ++i)
+        res = res && (value[i] >= low[i] && value[i] < high[i]);
 
     return res;
 }
 
 /* ************************************************************************ */
 
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline decltype(std::declval<decltype(std::declval<T1>() - std::declval<T2>())>() * std::declval<decltype(std::declval<T1>() - std::declval<T2>())>()) distanceSquared(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
+template<template<typename, int> typename VectorType, typename T, int N>
+inline bool inRange(
+    const VectorType<T, N>& value,
+    const VectorType<T, N>& high
 )
 {
-    return (lhs - rhs).getLengthSquared();
-}
-
-/* ************************************************************************ */
-
-template<template<typename, int...> typename VectorType, typename T1, typename T2, int... Tags>
-inline decltype(std::declval<T1>() - std::declval<T2>()) distance(
-    const VectorType<T1, Tags...>& lhs,
-    const VectorType<T2, Tags...>& rhs
-)
-{
-    return (lhs - rhs).getLength();
+    return inRange(value, VectorType<T, N>(Zero), high);
 }
 
 /* ************************************************************************ */
diff --git a/include/cece/math/VectorIo.hpp b/include/cece/math/VectorIo.hpp
new file mode 100644
index 0000000..a4ae960
--- /dev/null
+++ b/include/cece/math/VectorIo.hpp
@@ -0,0 +1,125 @@
+/* ************************************************************************ */
+/* Georgiev Lab (c) 2015-2017                                               */
+/* ************************************************************************ */
+/* Department of Cybernetics                                                */
+/* Faculty of Applied Sciences                                              */
+/* University of West Bohemia in Pilsen                                     */
+/* ************************************************************************ */
+/*                                                                          */
+/* This file is part of CeCe.                                               */
+/*                                                                          */
+/* CeCe is free software: you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by     */
+/* the Free Software Foundation, either version 3 of the License, or        */
+/* (at your option) any later version.                                      */
+/*                                                                          */
+/* CeCe is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/* GNU General Public License for more details.                             */
+/*                                                                          */
+/* You should have received a copy of the GNU General Public License        */
+/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
+/*                                                                          */
+/* ************************************************************************ */
+
+#pragma once
+
+/* ************************************************************************ */
+
+// CeCe
+#include "cece/common.hpp"
+#include "cece/Assert.hpp"
+#include "cece/io/InStream.hpp"
+#include "cece/io/OutStream.hpp"
+#include "cece/math/VectorBase.hpp"
+
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Input stream operator.
+ *
+ * @param      is          Input stream.
+ * @param      vector      Result value.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T           Type of value.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Input stream.
+ */
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+io::InStream& operator>>(io::InStream& is, VectorType<T, Tags...>& vector);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Output stream operator.
+ *
+ * @param      os          Output stream.
+ * @param      vector      Input value.
+ *
+ * @tparam     VectorType  Vector type.
+ * @tparam     T           Type of value.
+ * @tparam     Tags        Vector type tags.
+ *
+ * @return     Output stream.
+ */
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+io::OutStream& operator<<(io::OutStream& os, const VectorType<T, Tags...>& vector);
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+inline io::InStream& operator>>(io::InStream& is, VectorType<T, Tags...>& vector)
+{
+    // Read all elements
+    for (int i = 0; i < vector.getSize(); ++i)
+    {
+        // Unable to read element
+        if (!(is >> std::skipws >> vector[i]))
+            break;
+    }
+
+    return is;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int...> typename VectorType, typename T, int... Tags>
+inline io::OutStream& operator<<(io::OutStream& os, const VectorType<T, Tags...>& vector)
+{
+    for (int i = 0; i < vector.getSize(); ++i)
+    {
+        if (i != 0)
+            os << " ";
+
+        os << vector[i];
+    }
+
+    return os;
+}
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
diff --git a/include/cece/unit/VectorUnits.hpp b/include/cece/unit/VectorUnits.hpp
index 2cecbdd..bd06b2a 100644
--- a/include/cece/unit/VectorUnits.hpp
+++ b/include/cece/unit/VectorUnits.hpp
@@ -106,12 +106,11 @@ namespace math {
 
 /* ************************************************************************ */
 
-extern template class BasicVector<unit::Length, DIMENSION>;
-extern template class BasicVector<unit::Velocity, DIMENSION>;
-extern template class BasicVector<unit::Acceleration, DIMENSION>;
-extern template class BasicVector<unit::Force, DIMENSION>;
-extern template class BasicVector<unit::Impulse, DIMENSION>;
-extern template class BasicVector<RealType, DIMENSION>;
+extern template class Vector<unit::Length, DIMENSION>;
+extern template class Vector<unit::Velocity, DIMENSION>;
+extern template class Vector<unit::Acceleration, DIMENSION>;
+extern template class Vector<unit::Force, DIMENSION>;
+extern template class Vector<unit::Impulse, DIMENSION>;
 
 /* ************************************************************************ */
 
diff --git a/src/math/CMakeLists.txt b/src/math/CMakeLists.txt
index ca0401b..5aac37e 100644
--- a/src/math/CMakeLists.txt
+++ b/src/math/CMakeLists.txt
@@ -25,8 +25,6 @@
 
 set(SRCS
     Vector.cpp
-    Vector2.cpp
-    Vector3.cpp
     Grid.cpp
 )
 
diff --git a/src/math/Vector.cpp b/src/math/Vector.cpp
index 4e89d5d..2cfb36e 100644
--- a/src/math/Vector.cpp
+++ b/src/math/Vector.cpp
@@ -33,9 +33,16 @@ namespace math {
 
 /* ************************************************************************ */
 
-template class BasicVector<RealType, DIMENSION>;
-template class BasicVector<unsigned int, DIMENSION>;
-template class BasicVector<int, DIMENSION>;
+template class Vector<int, 2>;
+template class Vector<int, 3>;
+template class Vector<unsigned int, 2>;
+template class Vector<unsigned int, 3>;
+template class Vector<unsigned long, 2>;
+template class Vector<unsigned long, 3>;
+template class Vector<float, 2>;
+template class Vector<float, 3>;
+template class Vector<double, 2>;
+template class Vector<double, 3>;
 
 /* ************************************************************************ */
 
diff --git a/src/math/Vector3.cpp b/src/math/Vector3.cpp
deleted file mode 100644
index 8904c16..0000000
--- a/src/math/Vector3.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/* ************************************************************************ */
-/* Georgiev Lab (c) 2015-2017                                               */
-/* ************************************************************************ */
-/* Department of Cybernetics                                                */
-/* Faculty of Applied Sciences                                              */
-/* University of West Bohemia in Pilsen                                     */
-/* ************************************************************************ */
-/*                                                                          */
-/* This file is part of CeCe.                                               */
-/*                                                                          */
-/* CeCe is free software: you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by     */
-/* the Free Software Foundation, either version 3 of the License, or        */
-/* (at your option) any later version.                                      */
-/*                                                                          */
-/* CeCe is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
-/* GNU General Public License for more details.                             */
-/*                                                                          */
-/* You should have received a copy of the GNU General Public License        */
-/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
-/*                                                                          */
-/* ************************************************************************ */
-
-// Declaration
-#include "cece/math/Vector3.hpp"
-
-/* ************************************************************************ */
-
-namespace cece {
-namespace math {
-
-/* ************************************************************************ */
-
-template class Vector3<float>;
-template class Vector3<double>;
-template class Vector3<unsigned int>;
-template class Vector3<int>;
-
-/* ************************************************************************ */
-
-}
-}
-
-/* ************************************************************************ */
diff --git a/src/simulation/DefaultSimulation.cpp b/src/simulation/DefaultSimulation.cpp
index fb1556b..4caa039 100644
--- a/src/simulation/DefaultSimulation.cpp
+++ b/src/simulation/DefaultSimulation.cpp
@@ -41,6 +41,7 @@
 #include "cece/Exception.hpp"
 #include "cece/log/Log.hpp"
 #include "cece/unit/UnitIo.hpp"
+#include "cece/math/VectorIo.hpp"
 #include "cece/io/FileStream.hpp"
 #include "cece/io/OutStream.hpp"
 #include "cece/plugin/Api.hpp"
diff --git a/src/simulation/Object.cpp b/src/simulation/Object.cpp
index cee26c1..44931d0 100644
--- a/src/simulation/Object.cpp
+++ b/src/simulation/Object.cpp
@@ -37,6 +37,7 @@
 #include "cece/Assert.hpp"
 #include "cece/log/Log.hpp"
 #include "cece/unit/UnitIo.hpp"
+#include "cece/math/VectorIo.hpp"
 #include "cece/io/FileStream.hpp"
 #include "cece/config/Configuration.hpp"
 #include "cece/plugin/Context.hpp"
diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp
index 9f2e197..4b04f75 100644
--- a/src/simulation/Simulation.cpp
+++ b/src/simulation/Simulation.cpp
@@ -31,6 +31,7 @@
 
 // CeCe
 #include "cece/unit/UnitIo.hpp"
+#include "cece/math/VectorIo.hpp"
 #include "cece/plugin/Api.hpp"
 #include "cece/simulation/Initializer.hpp"
 #include "cece/simulation/Module.hpp"
diff --git a/src/unit/VectorUnits.cpp b/src/unit/VectorUnits.cpp
index 7972d18..af6e05e 100644
--- a/src/unit/VectorUnits.cpp
+++ b/src/unit/VectorUnits.cpp
@@ -33,12 +33,11 @@ namespace math {
 
 /* ************************************************************************ */
 
-template class BasicVector<unit::Length, DIMENSION>;
-template class BasicVector<unit::Velocity, DIMENSION>;
-template class BasicVector<unit::Acceleration, DIMENSION>;
-template class BasicVector<unit::Force, DIMENSION>;
-template class BasicVector<unit::Impulse, DIMENSION>;
-template class BasicVector<RealType, DIMENSION>;
+template class Vector<unit::Length, DIMENSION>;
+template class Vector<unit::Velocity, DIMENSION>;
+template class Vector<unit::Acceleration, DIMENSION>;
+template class Vector<unit::Force, DIMENSION>;
+template class Vector<unit::Impulse, DIMENSION>;
 
 /* ************************************************************************ */
 
diff --git a/unittests/math/CMakeLists.txt b/unittests/math/CMakeLists.txt
index 97ea6a5..1e1fc3f 100644
--- a/unittests/math/CMakeLists.txt
+++ b/unittests/math/CMakeLists.txt
@@ -30,6 +30,7 @@ cece_add_test(math
         Vector2_test.cpp
         Vector3_test.cpp
         VectorRangeTest.cpp
+        VectorIo_test.cpp
 )
 
 # ######################################################################### #
diff --git a/unittests/math/Vector2_test.cpp b/unittests/math/Vector2_test.cpp
index e6bad88..03dadcc 100644
--- a/unittests/math/Vector2_test.cpp
+++ b/unittests/math/Vector2_test.cpp
@@ -27,7 +27,7 @@
 #include "gtest/gtest.h"
 
 // CeCe
-#include "cece/math/Vector2.hpp"
+#include "cece/math/Vector.hpp"
 #include "cece/unit/math.hpp"
 
 /* ************************************************************************ */
@@ -44,6 +44,8 @@ TEST(Vector2, ctor)
 
         EXPECT_EQ(0, vec.getX());
         EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getWidth());
+        EXPECT_EQ(0, vec.getHeight());
         EXPECT_EQ(0, vec[0]);
         EXPECT_EQ(0, vec[1]);
     }
@@ -53,6 +55,8 @@ TEST(Vector2, ctor)
 
         EXPECT_EQ(0, vec.getX());
         EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getWidth());
+        EXPECT_EQ(0, vec.getHeight());
         EXPECT_EQ(0, vec[0]);
         EXPECT_EQ(0, vec[1]);
     }
@@ -62,6 +66,8 @@ TEST(Vector2, ctor)
 
         EXPECT_FLOAT_EQ(12.3f, vec.getX());
         EXPECT_FLOAT_EQ(12.3f, vec.getY());
+        EXPECT_FLOAT_EQ(12.3f, vec.getWidth());
+        EXPECT_FLOAT_EQ(12.3f, vec.getHeight());
         EXPECT_FLOAT_EQ(12.3f, vec[0]);
         EXPECT_FLOAT_EQ(12.3f, vec[1]);
     }
@@ -72,6 +78,8 @@ TEST(Vector2, ctor)
 
         EXPECT_FLOAT_EQ(1.2f, vec.getX());
         EXPECT_FLOAT_EQ(3.0f, vec.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec.getWidth());
+        EXPECT_FLOAT_EQ(3.0f, vec.getHeight());
         EXPECT_FLOAT_EQ(1.2f, vec[0]);
         EXPECT_FLOAT_EQ(3.0f, vec[1]);
     }
@@ -81,6 +89,8 @@ TEST(Vector2, ctor)
 
         EXPECT_FLOAT_EQ(1.2f, vec1.getX());
         EXPECT_FLOAT_EQ(3.0f, vec1.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec1.getWidth());
+        EXPECT_FLOAT_EQ(3.0f, vec1.getHeight());
         EXPECT_FLOAT_EQ(1.2f, vec1[0]);
         EXPECT_FLOAT_EQ(3.0f, vec1[1]);
 
@@ -88,6 +98,8 @@ TEST(Vector2, ctor)
 
         EXPECT_FLOAT_EQ(1.2f, vec2.getX());
         EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getWidth());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getHeight());
         EXPECT_FLOAT_EQ(1.2f, vec2[0]);
         EXPECT_FLOAT_EQ(3.0f, vec2[1]);
     }
@@ -97,6 +109,8 @@ TEST(Vector2, ctor)
 
         EXPECT_FLOAT_EQ(1.2f, vec1.getX());
         EXPECT_FLOAT_EQ(3.0f, vec1.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec1.getWidth());
+        EXPECT_FLOAT_EQ(3.0f, vec1.getHeight());
         EXPECT_FLOAT_EQ(1.2f, vec1[0]);
         EXPECT_FLOAT_EQ(3.0f, vec1[1]);
 
@@ -104,6 +118,8 @@ TEST(Vector2, ctor)
 
         EXPECT_FLOAT_EQ(1.2f, vec2.getX());
         EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getWidth());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getHeight());
         EXPECT_FLOAT_EQ(1.2f, vec2[0]);
         EXPECT_FLOAT_EQ(3.0f, vec2[1]);
     }
@@ -113,6 +129,8 @@ TEST(Vector2, ctor)
 
         EXPECT_EQ(1, vec1.getX());
         EXPECT_EQ(3, vec1.getY());
+        EXPECT_EQ(1, vec1.getWidth());
+        EXPECT_EQ(3, vec1.getHeight());
         EXPECT_EQ(1, vec1[0]);
         EXPECT_EQ(3, vec1[1]);
 
@@ -120,6 +138,8 @@ TEST(Vector2, ctor)
 
         EXPECT_FLOAT_EQ(1.0f, vec2.getX());
         EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(1.0f, vec2.getWidth());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getHeight());
         EXPECT_FLOAT_EQ(1.0f, vec2[0]);
         EXPECT_FLOAT_EQ(3.0f, vec2[1]);
     }
@@ -341,6 +361,29 @@ TEST(Vector2, mutators)
         EXPECT_EQ(100, vec.x);
         EXPECT_EQ(50, vec.y);
     }
+
+    {
+        Vector2<int> vec;
+
+        EXPECT_EQ(0, vec.x);
+        EXPECT_EQ(0, vec.y);
+        EXPECT_EQ(0, vec.width);
+        EXPECT_EQ(0, vec.height);
+
+        vec.width = 100;
+
+        EXPECT_EQ(100, vec.x);
+        EXPECT_EQ(0, vec.y);
+        EXPECT_EQ(100, vec.width);
+        EXPECT_EQ(0, vec.height);
+
+        vec.height = 50;
+
+        EXPECT_EQ(100, vec.x);
+        EXPECT_EQ(50, vec.y);
+        EXPECT_EQ(100, vec.width);
+        EXPECT_EQ(50, vec.height);
+    }
 }
 
 /* ************************************************************************ */
diff --git a/unittests/math/Vector3_test.cpp b/unittests/math/Vector3_test.cpp
index ddb7eee..e57c107 100644
--- a/unittests/math/Vector3_test.cpp
+++ b/unittests/math/Vector3_test.cpp
@@ -27,7 +27,7 @@
 #include "gtest/gtest.h"
 
 // CeCe
-#include "cece/math/Vector3.hpp"
+#include "cece/math/Vector.hpp"
 
 /* ************************************************************************ */
 
diff --git a/unittests/math/VectorBase_test.cpp b/unittests/math/VectorBase_test.cpp
index 770d3bf..d963584 100644
--- a/unittests/math/VectorBase_test.cpp
+++ b/unittests/math/VectorBase_test.cpp
@@ -27,6 +27,7 @@
 #include "gtest/gtest.h"
 
 // CeCe
+#include "cece/math/Zero.hpp"
 #include "cece/math/VectorBase.hpp"
 
 /* ************************************************************************ */
@@ -36,10 +37,11 @@ using namespace cece::math;
 
 /* ************************************************************************ */
 
-template<typename T>
-struct Vec2 : public VectorBase<Vec2, T>
+template<typename T, int N = 2>
+struct Vec2 : public VectorBase<Vec2, T, 2>
 {
     Vec2() : x{}, y{} {}
+    Vec2(Zero_t) : x{}, y{} {}
     Vec2(T x, T y) : x{x}, y{y} {}
 
     T& operator[](int pos) { return (&x)[pos]; }
@@ -104,6 +106,19 @@ TEST(VectorBase, operators)
         EXPECT_FLOAT_EQ(4.0f, vec1[1]);
     }
 
+    {
+        Vec2<int> vec1{1, 2};
+
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(2, vec1[1]);
+
+        Vec2<float> vec2{1.0f, 2.0f};
+        vec1 += vec2;
+
+        EXPECT_EQ(2, vec1[0]);
+        EXPECT_EQ(4, vec1[1]);
+    }
+
     {
         Vec2<float> vec1{1.0f, 2.0f};
 
@@ -264,6 +279,33 @@ TEST(VectorBase, functions)
             res
         );
     }
+
+    {
+        const Vec2<float> vecMin{-10.0f, -5.0f};
+        const Vec2<float> vecMax{10.0f, 20.0f};
+
+        Vec2<float> vec1;
+        Vec2<float> vec2{-15.0f, 0.0f};
+        Vec2<float> vec3{5.0f, 0.0f};
+        Vec2<float> vec4{5.0f, 25.0f};
+
+        EXPECT_TRUE(inRange(vec1, vecMin, vecMax));
+        EXPECT_FALSE(inRange(vec2, vecMin, vecMax));
+        EXPECT_TRUE(inRange(vec3, vecMin, vecMax));
+        EXPECT_FALSE(inRange(vec4, vecMin, vecMax));
+    }
+
+    {
+        const Vec2<float> vecMax{10.0f, 20.0f};
+
+        Vec2<float> vec1;
+        Vec2<float> vec2{-15.0f, 0.0f};
+        Vec2<float> vec3{5.0f, 0.0f};
+
+        EXPECT_TRUE(inRange(vec1, vecMax));
+        EXPECT_FALSE(inRange(vec2, vecMax));
+        EXPECT_TRUE(inRange(vec3, vecMax));
+    }
 }
 
 /* ************************************************************************ */
@@ -383,12 +425,16 @@ TEST(VectorBase, freeOperators)
     }
 
     {
+        const Vec2<float> vec0(Zero);
         const Vec2<float> vec1(5.3f, 8.9f);
         const Vec2<float> vec2(5.3f, 8.9f);
         const Vec2<float> vec3(1.3f, 8.9f);
         const Vec2<float> vec4(5.3f, 0.9f);
         const Vec2<float> vec5(1.3f, 0.9f);
 
+        EXPECT_EQ(vec0, Zero);
+        EXPECT_EQ(Zero, vec0);
+
         EXPECT_EQ(vec1, vec1);
         EXPECT_EQ(vec1, vec2);
         EXPECT_NE(vec1, vec3);
@@ -408,22 +454,6 @@ TEST(VectorBase, freeOperators)
         EXPECT_NE(vec4, vec2);
         EXPECT_NE(vec4, vec3);
         EXPECT_EQ(vec4, vec4);
-
-        EXPECT_FALSE(vec1 < vec2);
-
-        EXPECT_GE(vec1, vec1);
-        EXPECT_GE(vec1, vec2);
-        EXPECT_GE(vec1, vec3);
-        EXPECT_GE(vec1, vec4);
-
-        EXPECT_GT(vec1, vec5);
-
-        EXPECT_LE(vec1, vec1);
-        EXPECT_LE(vec1, vec2);
-        EXPECT_LE(vec3, vec1);
-        EXPECT_LE(vec4, vec1);
-
-        EXPECT_LT(vec5, vec1);
     }
 
 }
diff --git a/src/math/Vector2.cpp b/unittests/math/VectorIo_test.cpp
similarity index 53%
rename from src/math/Vector2.cpp
rename to unittests/math/VectorIo_test.cpp
index 824623e..bcff064 100644
--- a/src/math/Vector2.cpp
+++ b/unittests/math/VectorIo_test.cpp
@@ -1,5 +1,5 @@
 /* ************************************************************************ */
-/* Georgiev Lab (c) 2015-2017                                               */
+/* Georgiev Lab (c) 2015-2016                                               */
 /* ************************************************************************ */
 /* Department of Cybernetics                                                */
 /* Faculty of Applied Sciences                                              */
@@ -23,24 +23,114 @@
 /*                                                                          */
 /* ************************************************************************ */
 
-// Declaration
-#include "cece/math/Vector2.hpp"
+// GTest
+#include "gtest/gtest.h"
+
+// CeCe
+#include "cece/io/StringStream.hpp"
+#include "cece/math/VectorIo.hpp"
+#include "cece/math/Vector.hpp"
 
 /* ************************************************************************ */
 
-namespace cece {
-namespace math {
+using namespace cece;
+using namespace cece::math;
 
 /* ************************************************************************ */
 
-template class Vector2<float>;
-template class Vector2<double>;
-template class Vector2<unsigned int>;
-template class Vector2<int>;
+TEST(VectorIo, read)
+{
+    {
+        io::InStringStream iss("200 100");
+
+        Vector2<int> vec;
+        iss >> vec;
+
+        EXPECT_EQ(200, vec.x);
+        EXPECT_EQ(100, vec.y);
+    }
+
+    {
+        io::InStringStream iss("200 100");
+
+        Vector2<float> vec;
+        iss >> vec;
+
+        EXPECT_FLOAT_EQ(200.f, vec.x);
+        EXPECT_FLOAT_EQ(100.f, vec.y);
+    }
+
+    {
+        io::InStringStream iss("2.3 100.15");
+
+        Vector2<float> vec;
+        iss >> vec;
+
+        EXPECT_FLOAT_EQ(2.3f, vec.x);
+        EXPECT_FLOAT_EQ(100.15f, vec.y);
+    }
+}
 
 /* ************************************************************************ */
 
+TEST(VectorIo, readFail)
+{
+    {
+        io::InStringStream iss("200");
+
+        Vector2<int> vec;
+        iss >> vec;
+        EXPECT_FALSE(iss);
+    }
+
+    {
+        io::InStringStream iss("23.3");
+
+        Vector2<float> vec;
+        iss >> vec;
+        EXPECT_FALSE(iss);
+    }
 }
+
+/* ************************************************************************ */
+
+TEST(VectorIo, write)
+{
+    {
+        io::OutStringStream oss;
+
+        Vector2<int> vec{200, 100};
+        EXPECT_EQ(200, vec.x);
+        EXPECT_EQ(100, vec.y);
+
+        oss << vec;
+
+        EXPECT_EQ("200 100", oss.str());
+    }
+
+    {
+        io::OutStringStream oss;
+
+        Vector2<float> vec{200.f, 100.f};
+        EXPECT_FLOAT_EQ(200.f, vec.x);
+        EXPECT_FLOAT_EQ(100.f, vec.y);
+
+        oss << vec;
+
+        EXPECT_EQ("200 100", oss.str());
+    }
+
+    {
+        io::OutStringStream oss;
+
+        Vector2<float> vec{2.3f, 100.15f};
+        EXPECT_FLOAT_EQ(2.3f, vec.x);
+        EXPECT_FLOAT_EQ(100.15f, vec.y);
+
+        oss << vec;
+
+        EXPECT_EQ("2.3 100.15", oss.str());
+    }
 }
 
 /* ************************************************************************ */

From 53beb29141ae53f57503c49ef5244d7c335ff0db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Fatka?= <fatkaj@ntis.zcu.cz>
Date: Thu, 8 Jun 2017 17:27:54 +0200
Subject: [PATCH 09/11] Added constexpr to math::Vector classes.

---
 include/cece/math/Vector.hpp     | 126 +++++++++++++++-------------
 include/cece/math/VectorBase.hpp |   4 +-
 unittests/math/Vector2_test.cpp  | 139 ++++++++++++++++++++++++++++++-
 unittests/math/Vector3_test.cpp  |  73 ++++++++++++++++
 unittests/math/Vector_test.cpp   | 102 +++++++++++------------
 5 files changed, 329 insertions(+), 115 deletions(-)

diff --git a/include/cece/math/Vector.hpp b/include/cece/math/Vector.hpp
index c4dd936..cd01f0e 100644
--- a/include/cece/math/Vector.hpp
+++ b/include/cece/math/Vector.hpp
@@ -83,7 +83,7 @@ class Vector : public VectorBase<Vector, T, N>
     /**
      * @brief      Default constructor.
      */
-    Vector() noexcept;
+    constexpr Vector() noexcept;
 
 
     /**
@@ -239,7 +239,7 @@ class Vector : public VectorBase<Vector, T, N>
      *
      * @return     Reference to the element.
      */
-    const T& operator[](int pos) const noexcept;
+    constexpr const T& operator[](int pos) const noexcept;
 
 };
 
@@ -297,7 +297,7 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
     /**
      * @brief      Default constructor.
      */
-    Vector();
+    constexpr Vector();
 
 
     /**
@@ -305,7 +305,7 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
      *
      * @param      x     The X and Y coordinate.
      */
-    explicit Vector(T value);
+    explicit constexpr Vector(T value);
 
 
     /**
@@ -314,7 +314,7 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
      * @param      x     The X coordinate.
      * @param      y     The Y coordinate.
      */
-    Vector(T x, T y);
+    constexpr Vector(T x, T y);
 
 
     /**
@@ -322,7 +322,7 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
      *
      * @param[in]  zero  The zero value.
      */
-    Vector(Zero_t zero);
+    constexpr Vector(Zero_t zero);
 
 
     /**
@@ -330,7 +330,7 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
      *
      * @param[in]  src   The source vector.
      */
-    Vector(const Vector& src);
+    constexpr Vector(const Vector& src);
 
 
     /**
@@ -338,7 +338,7 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
      *
      * @param[in]  src   The source vector.
      */
-    Vector(Vector&& src);
+    constexpr Vector(Vector&& src);
 
 
     /**
@@ -349,7 +349,7 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
      * @tparam     T2    The source vector element type.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    Vector(const Vector<T2, 2>& rhs);
+    constexpr Vector(const Vector<T2, 2>& rhs);
 
 
 // Public Operators
@@ -416,7 +416,7 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
      *
      * @return     Reference to the element.
      */
-    const T& operator[](int pos) const noexcept;
+    constexpr const T& operator[](int pos) const noexcept;
 
 
 // Public Accessors
@@ -428,7 +428,7 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
      *
      * @return     The X coordinate.
      */
-    const T& getX() const noexcept;
+    constexpr const T& getX() const noexcept;
 
 
     /**
@@ -444,7 +444,7 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
      *
      * @return     The Y coordinate.
      */
-    const T& getY() const noexcept;
+    constexpr const T& getY() const noexcept;
 
 
     /**
@@ -460,7 +460,7 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
      *
      * @return     The width.
      */
-    const T& getWidth() const noexcept;
+    constexpr const T& getWidth() const noexcept;
 
 
     /**
@@ -476,7 +476,7 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
      *
      * @return     The height.
      */
-    const T& getHeight() const noexcept;
+    constexpr const T& getHeight() const noexcept;
 
 
     /**
@@ -588,7 +588,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
     /**
      * @brief      Default constructor.
      */
-    Vector() noexcept;
+    constexpr Vector() noexcept;
 
 
     /**
@@ -596,7 +596,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      *
      * @param      val   The X, Y and Z coordinate.
      */
-    explicit Vector(T val);
+    explicit constexpr Vector(T val);
 
 
     /**
@@ -606,7 +606,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      * @param      y     The Y coordinate.
      * @param      y     The Z coordinate.
      */
-    Vector(T x, T y, T z);
+    constexpr Vector(T x, T y, T z);
 
 
     /**
@@ -614,7 +614,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      *
      * @param[in]  zero  The zero value.
      */
-    Vector(Zero_t zero);
+    constexpr Vector(Zero_t zero);
 
 
     /**
@@ -622,7 +622,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      *
      * @param[in]  src   The source vector.
      */
-    Vector(const Vector& src);
+    constexpr Vector(const Vector& src);
 
 
     /**
@@ -630,7 +630,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      *
      * @param[in]  src   The source vector.
      */
-    Vector(Vector&& src);
+    constexpr Vector(Vector&& src);
 
 
     /**
@@ -641,7 +641,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      * @tparam     T2    The source vector element type.
      */
     template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type* = nullptr>
-    Vector(const Vector<T2, 3>& rhs);
+    constexpr Vector(const Vector<T2, 3>& rhs);
 
 
 // Public Operators
@@ -708,7 +708,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      *
      * @return     Reference to the element.
      */
-    const T& operator[](int pos) const noexcept;
+    constexpr const T& operator[](int pos) const noexcept;
 
 
 // Public Accessors
@@ -720,7 +720,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      *
      * @return     The X coordinate.
      */
-    const T& getX() const noexcept;
+    constexpr const T& getX() const noexcept;
 
 
     /**
@@ -736,7 +736,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      *
      * @return     The Y coordinate.
      */
-    const T& getY() const noexcept;
+    constexpr const T& getY() const noexcept;
 
 
     /**
@@ -752,7 +752,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      *
      * @return     The Z coordinate.
      */
-    const T& getZ() const noexcept;
+    constexpr const T& getZ() const noexcept;
 
 
     /**
@@ -768,7 +768,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      *
      * @return     The width.
      */
-    const T& getWidth() const noexcept;
+    constexpr const T& getWidth() const noexcept;
 
 
     /**
@@ -784,7 +784,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      *
      * @return     The height.
      */
-    const T& getHeight() const noexcept;
+    constexpr const T& getHeight() const noexcept;
 
 
     /**
@@ -800,7 +800,7 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
      *
      * @return     The depth.
      */
-    const T& getDepth() const noexcept;
+    constexpr const T& getDepth() const noexcept;
 
 
     /**
@@ -978,7 +978,7 @@ using SizeVector = Vector<unsigned long>;
  * @return     Rotated vector.
  */
 template<typename T>
-Vector<T, 2> rotate(const Vector<T, 2>& vec, unit::Angle angle) noexcept;
+constexpr Vector<T, 2> rotate(const Vector<T, 2>& vec, unit::Angle angle) noexcept;
 
 /* ************************************************************************ */
 
@@ -994,7 +994,7 @@ Vector<T, 2> rotate(const Vector<T, 2>& vec, unit::Angle angle) noexcept;
  * @return     Cross product.
  */
 template<typename T1, typename T2>
-Vector<decltype(std::declval<T1>() * std::declval<T2>()), 3>
+constexpr Vector<decltype(std::declval<T1>() * std::declval<T2>()), 3>
 cross(const Vector<T1, 3>& lhs, const Vector<T2, 3>& rhs);
 
 /* ************************************************************************ */
@@ -1031,7 +1031,7 @@ namespace math {
 /* ************************************************************************ */
 
 template<typename T, int N>
-inline Vector<T, N>::Vector() noexcept
+inline constexpr Vector<T, N>::Vector() noexcept
     : m{}
 {
     // Nothing to do
@@ -1207,17 +1207,19 @@ inline T& Vector<T, N>::operator[](int pos) noexcept
 /* ************************************************************************ */
 
 template<typename T, int N>
-inline const T& Vector<T, N>::operator[](int pos) const noexcept
+inline constexpr const T& Vector<T, N>::operator[](int pos) const noexcept
 {
+#if __cplusplus >= 201402L
     CECE_ASSERT(pos >= 0);
     CECE_ASSERT(pos < N);
+#endif
     return m[pos];
 }
 
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 2>::Vector()
+inline constexpr Vector<T, 2>::Vector()
     : x{}
     , y{}
 {
@@ -1227,7 +1229,7 @@ inline Vector<T, 2>::Vector()
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 2>::Vector(T val)
+inline constexpr Vector<T, 2>::Vector(T val)
     : x{val}
     , y{val}
 {
@@ -1237,7 +1239,7 @@ inline Vector<T, 2>::Vector(T val)
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 2>::Vector(T x, T y)
+inline constexpr Vector<T, 2>::Vector(T x, T y)
     : x{std::move(x)}
     , y{std::move(y)}
 {
@@ -1247,7 +1249,7 @@ inline Vector<T, 2>::Vector(T x, T y)
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 2>::Vector(Zero_t zero)
+inline constexpr Vector<T, 2>::Vector(Zero_t zero)
     : x{}
     , y{}
 {
@@ -1257,7 +1259,7 @@ inline Vector<T, 2>::Vector(Zero_t zero)
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 2>::Vector(const Vector& src)
+inline constexpr Vector<T, 2>::Vector(const Vector& src)
     : x{src.getX()}
     , y{src.getY()}
 {
@@ -1267,7 +1269,7 @@ inline Vector<T, 2>::Vector(const Vector& src)
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 2>::Vector(Vector&& src)
+inline constexpr Vector<T, 2>::Vector(Vector&& src)
     : x{std::move(src.x)}
     , y{std::move(src.y)}
 {
@@ -1278,7 +1280,7 @@ inline Vector<T, 2>::Vector(Vector&& src)
 
 template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline Vector<T, 2>::Vector(const Vector<T2, 2>& rhs)
+inline constexpr Vector<T, 2>::Vector(const Vector<T2, 2>& rhs)
     : x(rhs.getX())
     , y(rhs.getY())
 {
@@ -1343,17 +1345,19 @@ inline T& Vector<T, 2>::operator[](int pos) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector<T, 2>::operator[](int pos) const noexcept
+inline constexpr const T& Vector<T, 2>::operator[](int pos) const noexcept
 {
+#if __cplusplus >= 201402L
     CECE_ASSERT(pos >= 0);
     CECE_ASSERT(pos < 2);
+#endif
     return (&x)[pos];
 }
 
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector<T, 2>::getX() const noexcept
+inline constexpr const T& Vector<T, 2>::getX() const noexcept
 {
     return x;
 }
@@ -1369,7 +1373,7 @@ inline void Vector<T, 2>::setX(T x)
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector<T, 2>::getY() const noexcept
+inline constexpr const T& Vector<T, 2>::getY() const noexcept
 {
     return y;
 }
@@ -1385,7 +1389,7 @@ inline void Vector<T, 2>::setY(T y)
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector<T, 2>::getWidth() const noexcept
+inline constexpr const T& Vector<T, 2>::getWidth() const noexcept
 {
     return width;
 }
@@ -1401,7 +1405,7 @@ inline void Vector<T, 2>::setWidth(T width)
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector<T, 2>::getHeight() const noexcept
+inline constexpr const T& Vector<T, 2>::getHeight() const noexcept
 {
     return height;
 }
@@ -1417,7 +1421,7 @@ inline void Vector<T, 2>::setHeight(T height)
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 3>::Vector() noexcept
+inline constexpr Vector<T, 3>::Vector() noexcept
     : x{}
     , y{}
     , z{}
@@ -1428,7 +1432,7 @@ inline Vector<T, 3>::Vector() noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 3>::Vector(T val)
+inline constexpr Vector<T, 3>::Vector(T val)
     : x{val}
     , y{val}
     , z{val}
@@ -1439,7 +1443,7 @@ inline Vector<T, 3>::Vector(T val)
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 3>::Vector(T x, T y, T z)
+inline constexpr Vector<T, 3>::Vector(T x, T y, T z)
     : x{std::move(x)}
     , y{std::move(y)}
     , z{std::move(z)}
@@ -1450,7 +1454,7 @@ inline Vector<T, 3>::Vector(T x, T y, T z)
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 3>::Vector(Zero_t zero)
+inline constexpr Vector<T, 3>::Vector(Zero_t zero)
     : x{}
     , y{}
     , z{}
@@ -1461,7 +1465,7 @@ inline Vector<T, 3>::Vector(Zero_t zero)
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 3>::Vector(const Vector& src)
+inline constexpr Vector<T, 3>::Vector(const Vector& src)
     : x{src.getX()}
     , y{src.getY()}
     , z{src.getZ()}
@@ -1472,7 +1476,7 @@ inline Vector<T, 3>::Vector(const Vector& src)
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 3>::Vector(Vector&& src)
+inline constexpr Vector<T, 3>::Vector(Vector&& src)
     : x{std::move(src.x)}
     , y{std::move(src.y)}
     , z{std::move(src.z)}
@@ -1484,7 +1488,7 @@ inline Vector<T, 3>::Vector(Vector&& src)
 
 template<typename T>
 template<typename T2, typename std::enable_if<std::is_constructible<T, T2>::value>::type*>
-inline Vector<T, 3>::Vector(const Vector<T2, 3>& rhs)
+inline constexpr Vector<T, 3>::Vector(const Vector<T2, 3>& rhs)
     : x(rhs.getX())
     , y(rhs.getY())
     , z(rhs.getZ())
@@ -1554,17 +1558,19 @@ inline T& Vector<T, 3>::operator[](int pos) noexcept
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector<T, 3>::operator[](int pos) const noexcept
+inline constexpr const T& Vector<T, 3>::operator[](int pos) const noexcept
 {
+#if __cplusplus >= 201402L
     CECE_ASSERT(pos >= 0);
     CECE_ASSERT(pos < 3);
+#endif
     return (&x)[pos];
 }
 
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector<T, 3>::getX() const noexcept
+inline constexpr const T& Vector<T, 3>::getX() const noexcept
 {
     return x;
 }
@@ -1580,7 +1586,7 @@ inline void Vector<T, 3>::setX(T x)
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector<T, 3>::getY() const noexcept
+inline constexpr const T& Vector<T, 3>::getY() const noexcept
 {
     return y;
 }
@@ -1596,7 +1602,7 @@ inline void Vector<T, 3>::setY(T y)
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector<T, 3>::getZ() const noexcept
+inline constexpr const T& Vector<T, 3>::getZ() const noexcept
 {
     return z;
 }
@@ -1612,7 +1618,7 @@ inline void Vector<T, 3>::setZ(T z)
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector<T, 3>::getWidth() const noexcept
+inline constexpr const T& Vector<T, 3>::getWidth() const noexcept
 {
     return width;
 }
@@ -1628,7 +1634,7 @@ inline void Vector<T, 3>::setWidth(T width)
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector<T, 3>::getHeight() const noexcept
+inline constexpr const T& Vector<T, 3>::getHeight() const noexcept
 {
     return height;
 }
@@ -1644,7 +1650,7 @@ inline void Vector<T, 3>::setHeight(T height)
 /* ************************************************************************ */
 
 template<typename T>
-inline const T& Vector<T, 3>::getDepth() const noexcept
+inline constexpr const T& Vector<T, 3>::getDepth() const noexcept
 {
     return depth;
 }
@@ -1660,7 +1666,7 @@ inline void Vector<T, 3>::setDepth(T depth)
 /* ************************************************************************ */
 
 template<typename T>
-inline Vector<T, 2> rotate(const Vector<T, 2>& vec, unit::Angle angle) noexcept
+inline constexpr Vector<T, 2> rotate(const Vector<T, 2>& vec, unit::Angle angle) noexcept
 {
     return {
         static_cast<T>(vec.getX() * cos(static_cast<RealType>(angle)) - vec.getY() * sin(static_cast<RealType>(angle))),
@@ -1671,7 +1677,7 @@ inline Vector<T, 2> rotate(const Vector<T, 2>& vec, unit::Angle angle) noexcept
 /* ************************************************************************ */
 
 template<typename T1, typename T2>
-inline Vector<decltype(std::declval<T1>() * std::declval<T2>()), 3> cross(
+inline constexpr Vector<decltype(std::declval<T1>() * std::declval<T2>()), 3> cross(
     const Vector<T1, 3>& lhs,
     const Vector<T2, 3>& rhs
 )
diff --git a/include/cece/math/VectorBase.hpp b/include/cece/math/VectorBase.hpp
index a9f5ee1..18ed4d5 100644
--- a/include/cece/math/VectorBase.hpp
+++ b/include/cece/math/VectorBase.hpp
@@ -181,7 +181,7 @@ class VectorBase
      *
      * @return     Reference to the element.
      */
-    const T& operator[](int pos) const;
+    constexpr const T& operator[](int pos) const;
 
 
 // Public Accessors
@@ -737,7 +737,7 @@ inline T& VectorBase<VectorType, T, N>::operator[](int pos)
 /* ************************************************************************ */
 
 template<template<typename, int> typename VectorType, typename T, int N>
-inline const T& VectorBase<VectorType, T, N>::operator[](int pos) const
+inline constexpr const T& VectorBase<VectorType, T, N>::operator[](int pos) const
 {
     // TODO: recursion possibility
     return (*static_cast<const VectorType<T, N>*>(this))[pos];
diff --git a/unittests/math/Vector2_test.cpp b/unittests/math/Vector2_test.cpp
index 03dadcc..ec9cb93 100644
--- a/unittests/math/Vector2_test.cpp
+++ b/unittests/math/Vector2_test.cpp
@@ -50,6 +50,17 @@ TEST(Vector2, ctor)
         EXPECT_EQ(0, vec[1]);
     }
 
+    {
+        constexpr Vector2<int> vec;
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getWidth());
+        EXPECT_EQ(0, vec.getHeight());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+    }
+
     {
         Vector2<int> vec(Zero);
 
@@ -61,6 +72,17 @@ TEST(Vector2, ctor)
         EXPECT_EQ(0, vec[1]);
     }
 
+    {
+        constexpr Vector2<int> vec(Zero);
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getWidth());
+        EXPECT_EQ(0, vec.getHeight());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+    }
+
     {
         Vector2<float> vec(12.3f);
 
@@ -72,6 +94,16 @@ TEST(Vector2, ctor)
         EXPECT_FLOAT_EQ(12.3f, vec[1]);
     }
 
+    {
+        constexpr Vector2<float> vec(12.3f);
+
+        EXPECT_FLOAT_EQ(12.3f, vec.getX());
+        EXPECT_FLOAT_EQ(12.3f, vec.getY());
+        EXPECT_FLOAT_EQ(12.3f, vec.getWidth());
+        EXPECT_FLOAT_EQ(12.3f, vec.getHeight());
+        EXPECT_FLOAT_EQ(12.3f, vec[0]);
+        EXPECT_FLOAT_EQ(12.3f, vec[1]);
+    }
 
     {
         Vector2<float> vec = {1.2f, 3.0f};
@@ -84,6 +116,17 @@ TEST(Vector2, ctor)
         EXPECT_FLOAT_EQ(3.0f, vec[1]);
     }
 
+    {
+        constexpr Vector2<float> vec = {1.2f, 3.0f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec.getWidth());
+        EXPECT_FLOAT_EQ(3.0f, vec.getHeight());
+        EXPECT_FLOAT_EQ(1.2f, vec[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec[1]);
+    }
+
     {
         const Vector2<float> vec1 = {1.2f, 3.0f};
 
@@ -104,6 +147,26 @@ TEST(Vector2, ctor)
         EXPECT_FLOAT_EQ(3.0f, vec2[1]);
     }
 
+    {
+        constexpr const Vector2<float> vec1 = {1.2f, 3.0f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec1.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec1.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec1.getWidth());
+        EXPECT_FLOAT_EQ(3.0f, vec1.getHeight());
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+
+        constexpr Vector2<float> vec2(vec1);
+
+        EXPECT_FLOAT_EQ(1.2f, vec2.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getWidth());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getHeight());
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+    }
+
     {
         Vector2<float> vec1 = {1.2f, 3.0f};
 
@@ -124,6 +187,26 @@ TEST(Vector2, ctor)
         EXPECT_FLOAT_EQ(3.0f, vec2[1]);
     }
 
+    {
+        constexpr Vector2<float> vec1 = {1.2f, 3.0f};
+
+        EXPECT_FLOAT_EQ(1.2f, vec1.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec1.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec1.getWidth());
+        EXPECT_FLOAT_EQ(3.0f, vec1.getHeight());
+        EXPECT_FLOAT_EQ(1.2f, vec1[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec1[1]);
+
+        constexpr Vector2<float> vec2(std::move(vec1));
+
+        EXPECT_FLOAT_EQ(1.2f, vec2.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(1.2f, vec2.getWidth());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getHeight());
+        EXPECT_FLOAT_EQ(1.2f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+    }
+
     {
         const Vector2<int> vec1 = {1, 3};
 
@@ -143,6 +226,26 @@ TEST(Vector2, ctor)
         EXPECT_FLOAT_EQ(1.0f, vec2[0]);
         EXPECT_FLOAT_EQ(3.0f, vec2[1]);
     }
+
+    {
+        constexpr const Vector2<int> vec1 = {1, 3};
+
+        EXPECT_EQ(1, vec1.getX());
+        EXPECT_EQ(3, vec1.getY());
+        EXPECT_EQ(1, vec1.getWidth());
+        EXPECT_EQ(3, vec1.getHeight());
+        EXPECT_EQ(1, vec1[0]);
+        EXPECT_EQ(3, vec1[1]);
+
+        constexpr Vector2<float> vec2(vec1);
+
+        EXPECT_FLOAT_EQ(1.0f, vec2.getX());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getY());
+        EXPECT_FLOAT_EQ(1.0f, vec2.getWidth());
+        EXPECT_FLOAT_EQ(3.0f, vec2.getHeight());
+        EXPECT_FLOAT_EQ(1.0f, vec2[0]);
+        EXPECT_FLOAT_EQ(3.0f, vec2[1]);
+    }
 }
 
 /* ************************************************************************ */
@@ -370,14 +473,14 @@ TEST(Vector2, mutators)
         EXPECT_EQ(0, vec.width);
         EXPECT_EQ(0, vec.height);
 
-        vec.width = 100;
+        vec.setWidth(100);
 
         EXPECT_EQ(100, vec.x);
         EXPECT_EQ(0, vec.y);
         EXPECT_EQ(100, vec.width);
         EXPECT_EQ(0, vec.height);
 
-        vec.height = 50;
+        vec.setHeight(50);
 
         EXPECT_EQ(100, vec.x);
         EXPECT_EQ(50, vec.y);
@@ -426,6 +529,18 @@ TEST(Vector2, functions)
         EXPECT_EQ(0, rot.getY());
     }
 
+    {
+        constexpr Vector2<int> vec(1, 0);
+
+        EXPECT_EQ(1, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+
+        /*constexpr*/ auto rot = rotate(vec, unit::deg2rad(180));
+
+        EXPECT_EQ(-1, rot.getX());
+        EXPECT_EQ(0, rot.getY());
+    }
+
     {
         Vector2<float> vec1(0.94333f, 0.73733f);
         Vector2<float> vec2(0.16110f, 0.61872f);
@@ -445,6 +560,26 @@ TEST(Vector2, functions)
         );
     }
 
+    {
+        constexpr Vector2<float> vec1(0.94333f, 0.73733f);
+        constexpr Vector2<float> vec2(0.16110f, 0.61872f);
+
+        EXPECT_FLOAT_EQ(0.94333f, vec1.getX());
+        EXPECT_FLOAT_EQ(0.73733f, vec1.getY());
+
+        EXPECT_FLOAT_EQ(0.16110f, vec2.getX());
+        EXPECT_FLOAT_EQ(0.61872f, vec2.getY());
+
+        /*constexpr*/ auto res = dot(vec1, vec2);
+
+        EXPECT_FLOAT_EQ(
+            0.94333f * 0.16110f +
+            0.73733f * 0.61872f,
+            res
+        );
+    }
+
+
     {
         const Vector2<float> vec;
 
diff --git a/unittests/math/Vector3_test.cpp b/unittests/math/Vector3_test.cpp
index e57c107..b997726 100644
--- a/unittests/math/Vector3_test.cpp
+++ b/unittests/math/Vector3_test.cpp
@@ -49,6 +49,17 @@ TEST(Vector3, ctorDefault)
         EXPECT_EQ(0, vec[2]);
     }
 
+    {
+        constexpr Vector3<int> vec;
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+    }
+
     {
         Vector3<unsigned int> vec;
 
@@ -60,6 +71,17 @@ TEST(Vector3, ctorDefault)
         EXPECT_EQ(0, vec[2]);
     }
 
+    {
+        constexpr Vector3<unsigned int> vec;
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+    }
+
     {
         Vector3<float> vec;
 
@@ -98,6 +120,17 @@ TEST(Vector3, ctorZero)
         EXPECT_EQ(0, vec[2]);
     }
 
+    {
+        constexpr Vector3<int> vec(Zero);
+
+        EXPECT_EQ(0, vec.getX());
+        EXPECT_EQ(0, vec.getY());
+        EXPECT_EQ(0, vec.getZ());
+        EXPECT_EQ(0, vec[0]);
+        EXPECT_EQ(0, vec[1]);
+        EXPECT_EQ(0, vec[2]);
+    }
+
     {
         Vector3<unsigned int> vec(Zero);
 
@@ -147,6 +180,17 @@ TEST(Vector3, ctorSingle)
         EXPECT_EQ(1, vec[2]);
     }
 
+    {
+        constexpr Vector3<int> vec{1};
+
+        EXPECT_EQ(1, vec.getX());
+        EXPECT_EQ(1, vec.getY());
+        EXPECT_EQ(1, vec.getZ());
+        EXPECT_EQ(1, vec[0]);
+        EXPECT_EQ(1, vec[1]);
+        EXPECT_EQ(1, vec[2]);
+    }
+
     {
         Vector3<unsigned int> vec{3};
 
@@ -1250,6 +1294,35 @@ TEST(Vector3, mutators)
         EXPECT_DOUBLE_EQ(10, vec.getZ());
     }
 
+    {
+        Vector3<double> vec;
+
+        EXPECT_DOUBLE_EQ(0, vec.getX());
+        EXPECT_DOUBLE_EQ(0, vec.getY());
+        EXPECT_DOUBLE_EQ(0, vec.getZ());
+
+        vec.setWidth(100.3);
+
+        EXPECT_DOUBLE_EQ(100.3, vec.getX());
+        EXPECT_DOUBLE_EQ(0, vec.getY());
+        EXPECT_DOUBLE_EQ(0, vec.getZ());
+
+        vec.setHeight(50);
+
+        EXPECT_DOUBLE_EQ(100.3, vec.getX());
+        EXPECT_DOUBLE_EQ(50, vec.getY());
+        EXPECT_DOUBLE_EQ(0, vec.getZ());
+
+        vec.setDepth(10);
+
+        EXPECT_DOUBLE_EQ(100.3, vec.getX());
+        EXPECT_DOUBLE_EQ(50, vec.getY());
+        EXPECT_DOUBLE_EQ(10, vec.getZ());
+        EXPECT_DOUBLE_EQ(100.3, vec.getWidth());
+        EXPECT_DOUBLE_EQ(50, vec.getHeight());
+        EXPECT_DOUBLE_EQ(10, vec.getDepth());
+    }
+
     {
         Vector3<double> vec;
 
diff --git a/unittests/math/Vector_test.cpp b/unittests/math/Vector_test.cpp
index e65f32d..4f18e8c 100644
--- a/unittests/math/Vector_test.cpp
+++ b/unittests/math/Vector_test.cpp
@@ -39,7 +39,7 @@ using namespace cece::math;
 TEST(Vector, ctor)
 {
     {
-        BasicVector<int, 5> vec;
+        Vector<int, 5> vec;
 
         EXPECT_EQ(5, vec.getSize());
         EXPECT_EQ(0, vec[0]);
@@ -50,7 +50,7 @@ TEST(Vector, ctor)
     }
 
     {
-        BasicVector<int, 10> vec(Zero);
+        Vector<int, 10> vec(Zero);
 
         EXPECT_EQ(10, vec.getSize());
         EXPECT_EQ(0, vec[0]);
@@ -66,7 +66,7 @@ TEST(Vector, ctor)
     }
 
     {
-        BasicVector<float, 5> vec = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+        Vector<float, 5> vec = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
 
         EXPECT_EQ(5, vec.getSize());
         EXPECT_FLOAT_EQ(1.2f, vec[0]);
@@ -79,7 +79,7 @@ TEST(Vector, ctor)
     {
         float data[5] = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
 
-        BasicVector<float, 5> vec(data);
+        Vector<float, 5> vec(data);
 
         EXPECT_EQ(5, vec.getSize());
         EXPECT_FLOAT_EQ(1.2f, vec[0]);
@@ -92,7 +92,7 @@ TEST(Vector, ctor)
     {
         StaticArray<float, 5> data = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
 
-        BasicVector<float, 5> vec(data);
+        Vector<float, 5> vec(data);
 
         EXPECT_EQ(5, vec.getSize());
         EXPECT_FLOAT_EQ(1.2f, vec[0]);
@@ -103,7 +103,7 @@ TEST(Vector, ctor)
     }
 
     {
-        const BasicVector<float, 5> vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+        const Vector<float, 5> vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_FLOAT_EQ(1.2f, vec1[0]);
@@ -112,7 +112,7 @@ TEST(Vector, ctor)
         EXPECT_FLOAT_EQ(45.1f, vec1[3]);
         EXPECT_FLOAT_EQ(-34.0f, vec1[4]);
 
-        BasicVector<float, 5> vec2(vec1);
+        Vector<float, 5> vec2(vec1);
 
         EXPECT_EQ(5, vec2.getSize());
         EXPECT_FLOAT_EQ(1.2f, vec2[0]);
@@ -123,7 +123,7 @@ TEST(Vector, ctor)
     }
 
     {
-        BasicVector<float, 5> vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+        Vector<float, 5> vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_FLOAT_EQ(1.2f, vec1[0]);
@@ -132,7 +132,7 @@ TEST(Vector, ctor)
         EXPECT_FLOAT_EQ(45.1f, vec1[3]);
         EXPECT_FLOAT_EQ(-34.0f, vec1[4]);
 
-        BasicVector<float, 5> vec2(std::move(vec1));
+        Vector<float, 5> vec2(std::move(vec1));
 
         EXPECT_EQ(5, vec2.getSize());
         EXPECT_FLOAT_EQ(1.2f, vec2[0]);
@@ -143,7 +143,7 @@ TEST(Vector, ctor)
     }
 
     {
-        const BasicVector<int, 5> vec1 = {1, 3, 0, 45, -34};
+        const Vector<int, 5> vec1 = {1, 3, 0, 45, -34};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_EQ(1, vec1[0]);
@@ -152,7 +152,7 @@ TEST(Vector, ctor)
         EXPECT_EQ(45, vec1[3]);
         EXPECT_EQ(-34, vec1[4]);
 
-        BasicVector<float, 5> vec2(vec1);
+        Vector<float, 5> vec2(vec1);
 
         EXPECT_EQ(5, vec2.getSize());
         EXPECT_FLOAT_EQ(1.0, vec2[0]);
@@ -168,7 +168,7 @@ TEST(Vector, ctor)
 TEST(Vector, assignment)
 {
     {
-        BasicVector<int, 10> vec{1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+        Vector<int, 10> vec{1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
 
         EXPECT_EQ(10, vec.getSize());
         EXPECT_EQ(1, vec[0]);
@@ -198,7 +198,7 @@ TEST(Vector, assignment)
     }
 
     {
-        BasicVector<float, 5> vec;
+        Vector<float, 5> vec;
 
         EXPECT_EQ(5, vec.getSize());
         EXPECT_EQ(0, vec[0]);
@@ -218,7 +218,7 @@ TEST(Vector, assignment)
     }
 
     {
-        BasicVector<float, 5> vec;
+        Vector<float, 5> vec;
 
         EXPECT_EQ(5, vec.getSize());
         EXPECT_EQ(0, vec[0]);
@@ -240,7 +240,7 @@ TEST(Vector, assignment)
     }
 
     {
-        BasicVector<float, 5> vec;
+        Vector<float, 5> vec;
 
         EXPECT_EQ(5, vec.getSize());
         EXPECT_EQ(0, vec[0]);
@@ -262,7 +262,7 @@ TEST(Vector, assignment)
     }
 
     {
-        const BasicVector<float, 5> vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+        const Vector<float, 5> vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_FLOAT_EQ(1.2f, vec1[0]);
@@ -271,7 +271,7 @@ TEST(Vector, assignment)
         EXPECT_FLOAT_EQ(45.1f, vec1[3]);
         EXPECT_FLOAT_EQ(-34.0f, vec1[4]);
 
-        BasicVector<float, 5> vec2;
+        Vector<float, 5> vec2;
 
         vec2 = vec1;
 
@@ -284,7 +284,7 @@ TEST(Vector, assignment)
     }
 
     {
-        BasicVector<float, 5> vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
+        Vector<float, 5> vec1 = {1.2f, 3.0f, 0.0f, 45.1f, -34.f};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_FLOAT_EQ(1.2f, vec1[0]);
@@ -293,7 +293,7 @@ TEST(Vector, assignment)
         EXPECT_FLOAT_EQ(45.1f, vec1[3]);
         EXPECT_FLOAT_EQ(-34.0f, vec1[4]);
 
-        BasicVector<float, 5> vec2;
+        Vector<float, 5> vec2;
 
         vec2 = std::move(vec1);
 
@@ -306,7 +306,7 @@ TEST(Vector, assignment)
     }
 
     {
-        const BasicVector<int, 5> vec1 = {1, 3, 0, 45, -34};
+        const Vector<int, 5> vec1 = {1, 3, 0, 45, -34};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_EQ(1, vec1[0]);
@@ -315,7 +315,7 @@ TEST(Vector, assignment)
         EXPECT_EQ(45, vec1[3]);
         EXPECT_EQ(-34, vec1[4]);
 
-        BasicVector<float, 5> vec2;
+        Vector<float, 5> vec2;
 
         vec2 = vec1;
 
@@ -333,7 +333,7 @@ TEST(Vector, assignment)
 TEST(Vector, operators)
 {
     {
-        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -300.8f};
+        Vector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -300.8f};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
@@ -342,7 +342,7 @@ TEST(Vector, operators)
         EXPECT_FLOAT_EQ(0.0f, vec1[3]);
         EXPECT_FLOAT_EQ(-300.8f, vec1[4]);
 
-        BasicVector<float, 5> vec2 = +vec1;
+        Vector<float, 5> vec2 = +vec1;
 
         EXPECT_EQ(5, vec2.getSize());
         EXPECT_FLOAT_EQ(1.0f, vec2[0]);
@@ -353,7 +353,7 @@ TEST(Vector, operators)
     }
 
     {
-        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -300.8f};
+        Vector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -300.8f};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
@@ -362,7 +362,7 @@ TEST(Vector, operators)
         EXPECT_FLOAT_EQ(0.0f, vec1[3]);
         EXPECT_FLOAT_EQ(-300.8f, vec1[4]);
 
-        BasicVector<float, 5> vec2 = -vec1;
+        Vector<float, 5> vec2 = -vec1;
 
         EXPECT_EQ(5, vec2.getSize());
         EXPECT_FLOAT_EQ(-1.0f, vec2[0]);
@@ -373,7 +373,7 @@ TEST(Vector, operators)
     }
 
     {
-        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
+        Vector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
@@ -382,7 +382,7 @@ TEST(Vector, operators)
         EXPECT_FLOAT_EQ(0.0f, vec1[3]);
         EXPECT_FLOAT_EQ(-3.8f, vec1[4]);
 
-        BasicVector<float, 5> vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        Vector<float, 5> vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
         vec1 += vec2;
 
         EXPECT_EQ(5, vec1.getSize());
@@ -394,7 +394,7 @@ TEST(Vector, operators)
     }
 
     {
-        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
+        Vector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
@@ -403,7 +403,7 @@ TEST(Vector, operators)
         EXPECT_FLOAT_EQ(0.0f, vec1[3]);
         EXPECT_FLOAT_EQ(-3.8f, vec1[4]);
 
-        BasicVector<float, 5> vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        Vector<float, 5> vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
         vec1 -= vec2;
 
         EXPECT_EQ(5, vec1.getSize());
@@ -415,7 +415,7 @@ TEST(Vector, operators)
     }
 
     {
-        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
+        Vector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
@@ -435,7 +435,7 @@ TEST(Vector, operators)
     }
 
     {
-        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
+        Vector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
@@ -444,7 +444,7 @@ TEST(Vector, operators)
         EXPECT_FLOAT_EQ(0.0f, vec1[3]);
         EXPECT_FLOAT_EQ(-3.8f, vec1[4]);
 
-        BasicVector<float, 5> vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        Vector<float, 5> vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
         vec1 *= vec2;
 
         EXPECT_EQ(5, vec1.getSize());
@@ -456,7 +456,7 @@ TEST(Vector, operators)
     }
 
     {
-        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
+        Vector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
@@ -476,7 +476,7 @@ TEST(Vector, operators)
     }
 
     {
-        BasicVector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
+        Vector<float, 5> vec1{1.0f, 2.0f, -5.0f, 0.0f, -3.8f};
 
         EXPECT_EQ(5, vec1.getSize());
         EXPECT_FLOAT_EQ(1.0f, vec1[0]);
@@ -485,7 +485,7 @@ TEST(Vector, operators)
         EXPECT_FLOAT_EQ(0.0f, vec1[3]);
         EXPECT_FLOAT_EQ(-3.8f, vec1[4]);
 
-        BasicVector<float, 5> vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        Vector<float, 5> vec2{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
         vec1 /= vec2;
 
         EXPECT_EQ(5, vec1.getSize());
@@ -502,77 +502,77 @@ TEST(Vector, operators)
 TEST(Vector, memberFunctions)
 {
     {
-        const BasicVector<float, 5> vec;
+        const Vector<float, 5> vec;
 
         EXPECT_FLOAT_EQ(0, vec.getLength());
     }
 
     {
-        const BasicVector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        const Vector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
 
         EXPECT_FLOAT_EQ(7.4162f, vec.getLength());
     }
 
     {
-        const BasicVector<float, 5> vec;
+        const Vector<float, 5> vec;
 
         EXPECT_FLOAT_EQ(0, vec.getLengthSquared());
     }
 
     {
-        const BasicVector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        const Vector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
 
         EXPECT_FLOAT_EQ(55, vec.getLengthSquared());
     }
 
     {
-        const BasicVector<float, 5> vec;
+        const Vector<float, 5> vec;
 
         EXPECT_FLOAT_EQ(vec.getLengthSquared(), dot(vec, vec));
     }
 
     {
-        const BasicVector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        const Vector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
 
         EXPECT_FLOAT_EQ(vec.getLengthSquared(), dot(vec, vec));
     }
 
     {
-        const BasicVector<float, 5> vec1;
-        const BasicVector<float, 5> vec2;
+        const Vector<float, 5> vec1;
+        const Vector<float, 5> vec2;
 
         EXPECT_FLOAT_EQ(0, dot(vec1, vec2));
     }
 
     {
-        const BasicVector<float, 5> vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
-        const BasicVector<float, 5> vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
+        const Vector<float, 5> vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        const Vector<float, 5> vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
 
         EXPECT_FLOAT_EQ(35, dot(vec1, vec2));
     }
 
     {
-        const BasicVector<float, 5> vec;
+        const Vector<float, 5> vec;
 
         EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec));
     }
 
     {
-        const BasicVector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        const Vector<float, 5> vec{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
 
         EXPECT_FLOAT_EQ(0.0f, distanceSquared(vec, vec));
     }
 
     {
-        const BasicVector<float, 5> vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
-        const BasicVector<float, 5> vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
+        const Vector<float, 5> vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        const Vector<float, 5> vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
 
         EXPECT_FLOAT_EQ(40.0f, distanceSquared(vec1, vec2));
     }
 
     {
-        const BasicVector<float, 5> vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
-        const BasicVector<float, 5> vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
+        const Vector<float, 5> vec1{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+        const Vector<float, 5> vec2{5.0f, 4.0f, 3.0f, 2.0f, 1.0f};
 
         EXPECT_FLOAT_EQ(6.3245554f, distance(vec1, vec2));
     }

From 34e225ae0df67857086fdb3372568632a6b5536c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Fatka?= <fatkaj@ntis.zcu.cz>
Date: Wed, 14 Jun 2017 16:07:22 +0200
Subject: [PATCH 10/11] Vector changes to prevent CRTP function call recusion.

---
 include/cece/math/Vector.hpp     |  52 +++++++++++++++
 include/cece/math/VectorBase.hpp | 110 +++++++++++--------------------
 2 files changed, 90 insertions(+), 72 deletions(-)

diff --git a/include/cece/math/Vector.hpp b/include/cece/math/Vector.hpp
index cd01f0e..3a8bba9 100644
--- a/include/cece/math/Vector.hpp
+++ b/include/cece/math/Vector.hpp
@@ -241,6 +241,18 @@ class Vector : public VectorBase<Vector, T, N>
      */
     constexpr const T& operator[](int pos) const noexcept;
 
+
+// Public Accessors
+public:
+
+
+    /**
+     * @brief      Returns vector size.
+     *
+     * @return     The size.
+     */
+    constexpr int getSize() const noexcept;
+
 };
 
 /* ************************************************************************ */
@@ -423,6 +435,14 @@ struct Vector<T, 2> : public VectorBase<Vector, T, 2>
 public:
 
 
+    /**
+     * @brief      Returns vector size.
+     *
+     * @return     The size.
+     */
+    constexpr int getSize() const noexcept;
+
+
     /**
      * @brief      Returns X coordinate.
      *
@@ -715,6 +735,14 @@ struct Vector<T, 3> : public VectorBase<Vector, T, 3>
 public:
 
 
+    /**
+     * @brief      Returns vector size.
+     *
+     * @return     The size.
+     */
+    constexpr int getSize() const noexcept;
+
+
     /**
      * @brief      Returns X coordinate.
      *
@@ -1218,6 +1246,14 @@ inline constexpr const T& Vector<T, N>::operator[](int pos) const noexcept
 
 /* ************************************************************************ */
 
+template<typename T, int N>
+inline constexpr int Vector<T, N>::getSize() const noexcept
+{
+    return N;
+}
+
+/* ************************************************************************ */
+
 template<typename T>
 inline constexpr Vector<T, 2>::Vector()
     : x{}
@@ -1356,6 +1392,14 @@ inline constexpr const T& Vector<T, 2>::operator[](int pos) const noexcept
 
 /* ************************************************************************ */
 
+template<typename T>
+inline constexpr int Vector<T, 2>::getSize() const noexcept
+{
+    return 2;
+}
+
+/* ************************************************************************ */
+
 template<typename T>
 inline constexpr const T& Vector<T, 2>::getX() const noexcept
 {
@@ -1577,6 +1621,14 @@ inline constexpr const T& Vector<T, 3>::getX() const noexcept
 
 /* ************************************************************************ */
 
+template<typename T>
+inline constexpr int Vector<T, 3>::getSize() const noexcept
+{
+    return 3;
+}
+
+/* ************************************************************************ */
+
 template<typename T>
 inline void Vector<T, 3>::setX(T x)
 {
diff --git a/include/cece/math/VectorBase.hpp b/include/cece/math/VectorBase.hpp
index 18ed4d5..e55c2d4 100644
--- a/include/cece/math/VectorBase.hpp
+++ b/include/cece/math/VectorBase.hpp
@@ -164,38 +164,6 @@ class VectorBase
     VectorType<T, N>& operator/=(const VectorType<T1, N>& rhs);
 
 
-    /**
-     * @brief      Access operator.
-     *
-     * @param      pos   The position.
-     *
-     * @return     Reference to the element.
-     */
-    T& operator[](int pos);
-
-
-    /**
-     * @brief      Access operator.
-     *
-     * @param      pos   The position.
-     *
-     * @return     Reference to the element.
-     */
-    constexpr const T& operator[](int pos) const;
-
-
-// Public Accessors
-public:
-
-
-    /**
-     * @brief      Returns vector size.
-     *
-     * @return     The size.
-     */
-    constexpr int getSize() const noexcept;
-
-
 // Public Operations
 public:
 
@@ -647,8 +615,11 @@ inline VectorType<T, N> VectorBase<VectorType, T, N>::operator-() const noexcept
 {
     VectorType<T, N> res;
 
+    // Typed alias
+    auto& self = *static_cast<const VectorType<T, N>*>(this);
+
     for (int i = 0; i < N; ++i)
-        res[i] = -(*this)[i];
+        res[i] = -self[i];
 
     return res;
 }
@@ -659,10 +630,13 @@ template<template<typename, int> typename VectorType, typename T, int N>
 template<typename T1>
 inline VectorType<T, N>& VectorBase<VectorType, T, N>::operator+=(const VectorType<T1, N>& rhs)
 {
+    // Typed alias
+    auto& self = *static_cast<VectorType<T, N>*>(this);
+
     for (int i = 0; i < N; ++i)
-        (*this)[i] += rhs[i];
+        self[i] += rhs[i];
 
-    return *static_cast<VectorType<T, N>*>(this);
+    return self;
 }
 
 /* ************************************************************************ */
@@ -671,10 +645,13 @@ template<template<typename, int> typename VectorType, typename T, int N>
 template<typename T1>
 inline VectorType<T, N>& VectorBase<VectorType, T, N>::operator-=(const VectorType<T1, N>& rhs)
 {
+    // Typed alias
+    auto& self = *static_cast<VectorType<T, N>*>(this);
+
     for (int i = 0; i < N; ++i)
-        (*this)[i] -= rhs[i];
+        self[i] -= rhs[i];
 
-    return *static_cast<VectorType<T, N>*>(this);
+    return self;
 }
 
 /* ************************************************************************ */
@@ -683,10 +660,13 @@ template<template<typename, int> typename VectorType, typename T, int N>
 template<typename T1>
 inline VectorType<T, N>& VectorBase<VectorType, T, N>::operator*=(T1 rhs)
 {
+    // Typed alias
+    auto& self = *static_cast<VectorType<T, N>*>(this);
+
     for (int i = 0; i < N; ++i)
-        (*this)[i] *= rhs;
+        self[i] *= rhs;
 
-    return *static_cast<VectorType<T, N>*>(this);
+    return self;
 }
 
 /* ************************************************************************ */
@@ -695,10 +675,13 @@ template<template<typename, int> typename VectorType, typename T, int N>
 template<typename T1>
 inline VectorType<T, N>& VectorBase<VectorType, T, N>::operator*=(const VectorType<T1, N>& rhs)
 {
+    // Typed alias
+    auto& self = *static_cast<VectorType<T, N>*>(this);
+
     for (int i = 0; i < N; ++i)
-        (*this)[i] *= rhs[i];
+        self[i] *= rhs[i];
 
-    return *static_cast<VectorType<T, N>*>(this);
+    return self;
 }
 
 /* ************************************************************************ */
@@ -707,10 +690,13 @@ template<template<typename, int> typename VectorType, typename T, int N>
 template<typename T1>
 inline VectorType<T, N>& VectorBase<VectorType, T, N>::operator/=(T1 rhs)
 {
+    // Typed alias
+    auto& self = *static_cast<VectorType<T, N>*>(this);
+
     for (int i = 0; i < N; ++i)
-        (*this)[i] /= rhs;
+        self[i] /= rhs;
 
-    return *static_cast<VectorType<T, N>*>(this);
+    return self;
 }
 
 /* ************************************************************************ */
@@ -719,36 +705,13 @@ template<template<typename, int> typename VectorType, typename T, int N>
 template<typename T1>
 inline VectorType<T, N>& VectorBase<VectorType, T, N>::operator/=(const VectorType<T1, N>& rhs)
 {
-    for (int i = 0; i < N; ++i)
-        (*this)[i] /= rhs[i];
-
-    return *static_cast<VectorType<T, N>*>(this);
-}
-
-/* ************************************************************************ */
-
-template<template<typename, int> typename VectorType, typename T, int N>
-inline T& VectorBase<VectorType, T, N>::operator[](int pos)
-{
-    // TODO: recursion possibility
-    return (*static_cast<VectorType<T, N>*>(this))[pos];
-}
+    // Typed alias
+    auto& self = *static_cast<VectorType<T, N>*>(this);
 
-/* ************************************************************************ */
-
-template<template<typename, int> typename VectorType, typename T, int N>
-inline constexpr const T& VectorBase<VectorType, T, N>::operator[](int pos) const
-{
-    // TODO: recursion possibility
-    return (*static_cast<const VectorType<T, N>*>(this))[pos];
-}
-
-/* ************************************************************************ */
+    for (int i = 0; i < N; ++i)
+        self[i] /= rhs[i];
 
-template<template<typename, int> typename VectorType, typename T, int N>
-inline constexpr int VectorBase<VectorType, T, N>::getSize() const noexcept
-{
-    return N;
+    return self;
 }
 
 /* ************************************************************************ */
@@ -767,8 +730,11 @@ inline decltype(std::declval<T>() * std::declval<T>()) VectorBase<VectorType, T,
 {
     decltype(std::declval<T>() * std::declval<T>()) res{};
 
+    // Typed alias
+    auto& self = *static_cast<const VectorType<T, N>*>(this);
+
     for (int i = 0; i < N; ++i)
-        res += (*this)[i] * (*this)[i];
+        res += self[i] * self[i];
 
     return res;
 }

From 591c7c809ecc4039257ca372573f5fea81702646 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Fatka?= <fatkaj@ntis.zcu.cz>
Date: Mon, 1 Jul 2019 19:28:43 +0200
Subject: [PATCH 11/11] Added Matrix classes.

---
 .clang-format                    |  86 +++++++
 .clang_complete                  |   5 +
 include/cece/math/Matrix.hpp     | 316 +++++++++++++++++++++++++
 include/cece/math/MatrixBase.hpp | 390 +++++++++++++++++++++++++++++++
 4 files changed, 797 insertions(+)
 create mode 100644 .clang-format
 create mode 100644 .clang_complete
 create mode 100644 include/cece/math/Matrix.hpp
 create mode 100644 include/cece/math/MatrixBase.hpp

diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..d9cf81d
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,86 @@
+---
+Language:        Cpp
+AccessModifierOffset: -4
+AlignAfterOpenBracket: AlwaysBreak
+AlignConsecutiveAssignments: true
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: false
+AlignOperands:   true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: true
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: false
+BinPackParameters: false
+BraceWrapping:
+  AfterClass:      true
+  AfterControlStatement: true
+  AfterEnum:       true
+  AfterFunction:   true
+  AfterNamespace:  false
+  AfterStruct:     true
+  AfterUnion:      true
+  BeforeCatch:     true
+  BeforeElse:      true
+  IndentBraces:    false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: true
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit:     80
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat:   false
+ExperimentalAutoDetectBinPacking: false
+IncludeCategories:
+  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
+    Priority:        2
+  - Regex:           '^(<|"(gtest|isl|json)/)'
+    Priority:        3
+  - Regex:           '.*'
+    Priority:        1
+IncludeIsMainRegex: '$'
+IndentCaseLabels: false
+IndentWidth:     4
+IndentWrappedFunctionNames: false
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd:   ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PointerAlignment: Left
+ReflowComments:  true
+SortIncludes:    true
+SpaceAfterCStyleCast: true
+SpaceAfterTemplateKeyword: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles:  false
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard:        Cpp11
+TabWidth:        4
+UseTab:          Never
+...
+
diff --git a/.clang_complete b/.clang_complete
new file mode 100644
index 0000000..25ea966
--- /dev/null
+++ b/.clang_complete
@@ -0,0 +1,5 @@
+-I.
+-Iinclude
+-Ibuild-debug/src
+-Ivendor/Box2D/Box2D/include
+-Ivendor/googletest/include
\ No newline at end of file
diff --git a/include/cece/math/Matrix.hpp b/include/cece/math/Matrix.hpp
new file mode 100644
index 0000000..b11861f
--- /dev/null
+++ b/include/cece/math/Matrix.hpp
@@ -0,0 +1,316 @@
+/* ************************************************************************ */
+/* Georgiev Lab (c) 2015-2017                                               */
+/* ************************************************************************ */
+/* Department of Cybernetics                                                */
+/* Faculty of Applied Sciences                                              */
+/* University of West Bohemia in Pilsen                                     */
+/* ************************************************************************ */
+/*                                                                          */
+/* This file is part of CeCe.                                               */
+/*                                                                          */
+/* CeCe is free software: you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by     */
+/* the Free Software Foundation, either version 3 of the License, or        */
+/* (at your option) any later version.                                      */
+/*                                                                          */
+/* CeCe is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/* GNU General Public License for more details.                             */
+/*                                                                          */
+/* You should have received a copy of the GNU General Public License        */
+/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
+/*                                                                          */
+/* ************************************************************************ */
+
+#pragma once
+
+/* ************************************************************************ */
+
+// CeCe
+#include "cece/math/Zero.hpp"
+#include "cece/math/MatrixBase.hpp"
+#include "cece/math/Vector.hpp"
+#include "cece/unit/Units.hpp"
+
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+/**
+ * @brief      2D matrix implementation.
+ *
+ * @tparam     T     Type of stored value.
+ * @tparam     R     Number of rows.
+ * @tparam     C     Number of columns.
+ */
+template<typename T, int R, int C = R>
+struct Matrix : public MatrixBase<Matrix, R, C>
+{
+
+// Public Types
+public:
+
+
+    /// Row type.
+    using RowType = Vector<T, C>;
+
+    /// Column type.
+    using ColumnType = Vector<T, R>;
+
+
+// Public Data Members
+public:
+
+
+    /// Matrix data.
+    Vector<RowType, R> m;
+
+
+// Public Ctors
+public:
+
+
+    /**
+     * @brief      Default constructor.
+     */
+    Matrix();
+
+
+    /**
+     * @brief      Zero constructor.
+     *
+     * @param[in]  zero  Zero value.
+     */
+    Matrix(Zero_t zero);
+
+
+    /**
+     * @brief      Constructor.
+     *
+     * @param      src   Initial data
+     */
+    Matrix(const T (&src)[R][C]);
+
+
+    /**
+     * @brief      Constructor.
+     *
+     * @param      src   Initial data
+     */
+    Matrix(const RowType (&src)[R]);
+
+
+    /**
+     * @brief      Copy constructor.
+     *
+     * @param      src   Source matrix.
+     */
+    Matrix(const Matrix& src);
+
+
+    /**
+     * @brief      Move constructor.
+     *
+     * @param      src   Source matrix.
+     */
+    Matrix(Matrix&& src);
+
+
+// Public Operators
+public:
+
+
+    /**
+     * @brief      Copy assignment operator.
+     *
+     * @param      src   The source matrix.
+     *
+     * @return     *this.
+     */
+    Matrix& operator=(const Matrix& src);
+
+
+    /**
+     * @brief      Move assignment operator.
+     *
+     * @param      src   The source matrix.
+     *
+     * @return     *this.
+     */
+    Matrix& operator=(Matrix&& src);
+
+
+    /**
+     * @brief      Row access operator.
+     *
+     * @param[in]  pos   The row number.
+     *
+     * @return     Row.
+     */
+    RowType& operator[](int pos) noexcept;
+
+
+    /**
+     * @brief      Row access operator.
+     *
+     * @param      pos   The row number.
+     *
+     * @return     Row.
+     */
+    const RowType& operator[](int pos) const noexcept;
+
+
+    /**
+     * @brief      Element access operator.
+     *
+     * @param      coord  Coordinates.
+     *
+     * @return     Element.
+     */
+    T& operator[](Vector2<int> coord) noexcept;
+
+
+    /**
+     * @brief      Element access operator.
+     *
+     * @param      coord  Coordinates.
+     *
+     * @return     Element.
+     */
+    const T& operator[](Vector2<int> coord) const noexcept;
+
+};
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+template<typename T, int R, int C>
+inline Matrix<T, R, C>::Matrix()
+{
+    // Nothing to do
+}
+
+/* ************************************************************************ */
+
+template<typename T, int R, int C>
+inline Matrix<T, R, C>::Matrix(Zero_t zero)
+{
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            m[row][col] = Zero;
+}
+
+/* ************************************************************************ */
+
+template<typename T, int R, int C>
+inline Matrix<T, R, C>::Matrix(const T (&src)[R][C])
+{
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            m[row][col] = src[row][col];
+}
+
+/* ************************************************************************ */
+
+template<typename T, int R, int C>
+inline Matrix<T, R, C>::Matrix(const RowType (&src)[R])
+{
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            m[row][col] = src[row][col];
+}
+
+/* ************************************************************************ */
+
+template<typename T, int R, int C>
+inline Matrix<T, R, C>::Matrix(const Matrix& src)
+{
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            m[row][col] = src[row][col];
+}
+
+/* ************************************************************************ */
+
+template<typename T, int R, int C>
+inline Matrix<T, R, C>::Matrix(Matrix&& src)
+{
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            m[row][col] = std::move(src[row][col]);
+}
+
+/* ************************************************************************ */
+
+template<typename T, int R, int C>
+inline Matrix<T, R, C>& Matrix<T, R, C>::operator=(const Matrix& src)
+{
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            m[row][col] = src[row][col];
+}
+
+/* ************************************************************************ */
+
+template<typename T, int R, int C>
+inline Matrix<T, R, C>& Matrix<T, R, C>::operator=(Matrix&& src)
+{
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            m[row][col] = std::move(src[row][col]);
+}
+
+/* ************************************************************************ */
+
+template<typename T, int R, int C>
+inline Matrix<T, R, C>::RowType& Matrix<T, R, C>::operator[](int pos) noexcept
+{
+    return m[pos];
+}
+
+/* ************************************************************************ */
+
+template<typename T, int R, int C>
+inline const Matrix<T, R, C>::RowType& Matrix<T, R, C>::operator[](int pos) const noexcept
+{
+    return m[pos];
+}
+
+/* ************************************************************************ */
+
+template<typename T, int R, int C>
+inline T& Matrix<T, R, C>::operator[](Vector2<int> coord) noexcept
+{
+    return m[coord.x][coord.y];
+}
+
+/* ************************************************************************ */
+
+template<typename T, int R, int C>
+inline const T& Matrix<T, R, C>::operator[](Vector2<int> coord) const noexcept
+{
+    return m[coord.x][coord.y];
+}
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
+
diff --git a/include/cece/math/MatrixBase.hpp b/include/cece/math/MatrixBase.hpp
new file mode 100644
index 0000000..13785c3
--- /dev/null
+++ b/include/cece/math/MatrixBase.hpp
@@ -0,0 +1,390 @@
+/* ************************************************************************ */
+/* Georgiev Lab (c) 2015-2017                                               */
+/* ************************************************************************ */
+/* Department of Cybernetics                                                */
+/* Faculty of Applied Sciences                                              */
+/* University of West Bohemia in Pilsen                                     */
+/* ************************************************************************ */
+/*                                                                          */
+/* This file is part of CeCe.                                               */
+/*                                                                          */
+/* CeCe is free software: you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by     */
+/* the Free Software Foundation, either version 3 of the License, or        */
+/* (at your option) any later version.                                      */
+/*                                                                          */
+/* CeCe is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/* GNU General Public License for more details.                             */
+/*                                                                          */
+/* You should have received a copy of the GNU General Public License        */
+/* along with CeCe.  If not, see <http://www.gnu.org/licenses/>.            */
+/*                                                                          */
+/* ************************************************************************ */
+
+#pragma once
+
+/* ************************************************************************ */
+
+// CeCe
+#include "cece/math/Vector.hpp"
+
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+/**
+ * @brief      2D fixed size matrix base class.
+ *
+ * @tparam     MatrixType  Matrix type.
+ * @tparam     T           Type of stored value.
+ * @tparam     R           Number of rows.
+ * @tparam     C           Number of cols.
+ */
+template<
+    template<typename, int, int> typename MatrixType,
+    typename T,
+    int R,
+    int C
+>
+struct MatrixBase
+{
+
+// Public Types
+public:
+
+
+    /// VectorBase value type.
+    using ValueType = T;
+
+
+// Public Operators
+public:
+
+
+    /**
+     * @brief      Addition operator.
+     *
+     * @param      rhs   Right operand.
+     *
+     * @tparam     T1    The second type.
+     *
+     * @return     *this.
+     */
+    template<typename T1>
+    MatrixType<T, R, C>& operator+=(const MatrixType<T1, R, C>& rhs);
+
+
+    /**
+     * @brief      Substraction operator.
+     *
+     * @param      rhs   Right operand.
+     *
+     * @tparam     T1    The second type.
+     *
+     * @return     *this.
+     */
+    template<typename T1>
+    MatrixType<T, R, C>& operator-=(const MatrixType<T2, R, C>& rhs);
+
+
+    /**
+     * @brief      Multiplication operator.
+     *
+     * @param      rhs   Right operand.
+     *
+     * @tparam     T1    The second type.
+     *
+     * @return     *this.
+     */
+    template<typename T1>
+    MatrixType<T, R, C>& operator*=(const T1& rhs);
+
+
+    /**
+     * @brief      Division operator.
+     *
+     * @param      rhs   Right operand.
+     *
+     * @tparam     T1    The second type.
+     *
+     * @return     *this.
+     */
+    template<typename T1>
+    MatrixType<T, R, C>& operator/=(const T1& rhs);
+
+};
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Addition operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first matrix.
+ * @tparam     T2    Type of value in second matrix.
+ * @tparam     R     Number of rows.
+ * @tparam     C     Number of columns.
+ *
+ * @return     Result matrix.
+ */
+template<typename T1, typename T2, int R, int C>
+MatrixBase<decltype(std::declval<T1>() + std::declval<T2>()), R, C> operator+(
+    const MatrixBase<T1, R, C>& lhs,
+    const MatrixBase<T2, R, C>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Substraction operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first matrix.
+ * @tparam     T2    Type of value in second matrix.
+ * @tparam     R     Number of rows.
+ * @tparam     C     Number of columns.
+ *
+ * @return     Result matrix.
+ */
+template<typename T1, typename T2, int R, int C>
+MatrixBase<decltype(std::declval<T1>() - std::declval<T2>()), R, C> operator-(
+    const MatrixBase<T1, R, C>& lhs,
+    const MatrixBase<T2, R, C>& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Multiplication operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first matrix.
+ * @tparam     T2    Type of value in second matrix.
+ * @tparam     R     Number of rows.
+ * @tparam     C     Number of columns.
+ *
+ * @return     Result matrix.
+ */
+template<typename T1, typename T2, int R, int C>
+MatrixBase<decltype(std::declval<T1>() * std::declval<T2>()), R, C> operator*(
+    const MatrixBase<T1, R, C>& lhs,
+    const T2& rhs
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Multiplication operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first matrix.
+ * @tparam     T2    Type of value in second matrix.
+ * @tparam     R     Number of rows.
+ * @tparam     C     Number of columns.
+ *
+ * @return     Result matrix.
+ */
+template<typename T1, typename T2, int R, int C>
+MatrixBase<decltype(std::declval<T1>() * std::declval<T2>()), R, C> operator*(
+    const T2& lhs
+    const MatrixBase<T1, R, C>& rhs,
+);
+
+/* ************************************************************************ */
+
+/**
+ * @brief      Multiplication operator.
+ *
+ * @param      lhs   Left operand.
+ * @param      rhs   Right operand.
+ *
+ * @tparam     T1    Type of value in first matrix.
+ * @tparam     T2    Type of value in second matrix.
+ * @tparam     R     Number of rows.
+ * @tparam     C     Number of columns.
+ *
+ * @return     Result matrix.
+ */
+template<typename T1, typename T2, int R, int C>
+MatrixBase<decltype(std::declval<T1>() / std::declval<T2>()), R, C> operator/(
+    const MatrixBase<T1, R, C>& lhs,
+    const T2& rhs
+);
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
+
+namespace cece {
+namespace math {
+
+/* ************************************************************************ */
+
+template<template<typename, int, int> typename MatrixType, typename T, int R, int C>
+template<typename T1>
+inline MatrixType<T, R, C>& MatrixBase<MatrixType, T, R, C>::operator+=(const MatrixType<T1, R, C>& rhs)
+{
+    auto& self = *static_cast<MatrixType<T, R, C>*>(this);
+
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            self[row][col] += rhs[row][col];
+
+    return self;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int, int> typename MatrixType, typename T, int R, int C>
+template<typename T1>
+inline MatrixType<T, R, C>& MatrixBase<MatrixType, T, R, C>::operator-=(const MatrixType<T2, R, C>& rhs)
+{
+    auto& self = *static_cast<MatrixType<T, R, C>*>(this);
+
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            self[row][col] -= rhs[row][col];
+
+    return self;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int, int> typename MatrixType, typename T, int R, int C>
+template<typename T1>
+inline MatrixType<T, R, C>& MatrixBase<MatrixType, T, R, C>::operator*=(const T1& rhs)
+{
+    auto& self = *static_cast<MatrixType<T, R, C>*>(this);
+
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            self[row][col] *= rhs;
+
+    return self;
+}
+
+/* ************************************************************************ */
+
+template<template<typename, int, int> typename MatrixType, typename T, int R, int C>
+template<typename T1>
+inline MatrixType<T, R, C>& MatrixBase<MatrixType, T, R, C>::operator/=(const T1& rhs)
+{
+    auto& self = *static_cast<MatrixType<T, R, C>*>(this);
+
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            self[row][col] /= rhs;
+
+    return self;
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2, int R, int C>
+inline MatrixBase<decltype(std::declval<T1>() + std::declval<T2>()), R, C> operator+(
+    const MatrixBase<T1, R, C>& lhs,
+    const MatrixBase<T2, R, C>& rhs
+)
+{
+    MatrixBase<decltype(std::declval<T1>() + std::declval<T2>()), R, C> res;
+
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            res[row][col] = lhs[row][col] + rhs[row][col];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2, int R, int C>
+inline MatrixBase<decltype(std::declval<T1>() - std::declval<T2>()), R, C> operator-(
+    const MatrixBase<T1, R, C>& lhs,
+    const MatrixBase<T2, R, C>& rhs
+)
+{
+    MatrixBase<decltype(std::declval<T1>() + std::declval<T2>()), R, C> res;
+
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            res[row][col] = lhs[row][col] - rhs[row][col];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2, int R, int C>
+inline MatrixBase<decltype(std::declval<T1>() * std::declval<T2>()), R, C> operator*(
+    const MatrixBase<T1, R, C>& lhs,
+    const T2& rhs
+)
+{
+    MatrixBase<decltype(std::declval<T1>() * std::declval<T2>()), R, C> res;
+
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            res[row][col] = lhs[row][col] * rhs;
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2, int R, int C>
+inline MatrixBase<decltype(std::declval<T1>() * std::declval<T2>()), R, C> operator*(
+    const T2& lhs
+    const MatrixBase<T1, R, C>& rhs,
+)
+{
+    MatrixBase<decltype(std::declval<T1>() * std::declval<T2>()), R, C> res;
+
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            res[row][col] = rhs * lhs[row][col];
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+template<typename T1, typename T2, int R, int C>
+inline MatrixBase<decltype(std::declval<T1>() / std::declval<T2>()), R, C> operator/(
+    const MatrixBase<T1, R, C>& lhs,
+    const T2& rhs
+)
+{
+    MatrixBase<decltype(std::declval<T1>() + std::declval<T2>()), R, C> res;
+
+    for (int row = 0; row < R; ++row)
+        for (int col = 0; col < C; ++col)
+            res[row][col] = lhs[row][col] / rhs;
+
+    return res;
+}
+
+/* ************************************************************************ */
+
+}
+}
+
+/* ************************************************************************ */
+