Source

neglect / neglect / cpplib / include / neglect / _vector2.hpp

Full commit
#ifndef _INC_NEGLECT__VECTOR2_HPP_
#define _INC_NEGLECT__VECTOR2_HPP_

#include <neglect/vector.hpp>

namespace neglect {

    /* two dimensional vector */
    template <typename T>
    class vector<T, 2> {
    public:
        union {
            struct { T x, y; };
            struct { T r, g; };
            struct { T s, t; };
        };

        typedef T value_type;
        static const size_t size = 2;

        // -- constructors

        vector() {}

        template <class Sequence>
        explicit vector(Sequence seq) : x(seq[0]), y(seq[1])
        {
        }

        vector(T x, T y) : x(x), y(y)
        {
        }

        static vector<T, 2> zero()
        {
            vector<T, 2> rv;
            rv.set_zero();
            return rv;
        }

        void set_zero()
        {
            x = T();
            y = T();
        }

        // -- pointer access

        T* ptr() { return &x; }
        const T* ptr() const { return &x; }

        // -- boolean checks

        operator bool() const
        {
            return x || y;
        }

        bool operator!() const
        {
            return !static_cast<bool>(*this);
        }

        // -- subscript operators

        T &operator[](const size_t idx)
        {
            assert(idx < 2);
            return *(&x + idx);
        }

        T operator[](const size_t idx) const
        {
            assert(idx < 2);
            return *(&x + idx);
        }

        // -- arithmetic operators

        vector<T, 2> operator+(const vector<T, 2> &other) const
        {
            return vector<T, 2>(x + other.x, y + other.y);
        }

        vector<T, 2> operator-(const vector<T, 2> &other) const
        {
            return vector<T, 2>(x - other.x, y - other.y);
        }

        vector<T, 2> operator*(const vector<T, 2> &other) const
        {
            return vector<T, 2>(x * other.x, y * other.y);
        }

        template <class ScalarType>
        vector<T, 2> operator*(ScalarType scalar) const
        {
            return vector<T, 2>(x * scalar, y * scalar);
        }

        vector<T, 2> operator/(const vector<T, 2> &other) const
        {
            assert(other.x && other.y);
            return vector<T, 2>(x / other.x, y / other.y);
        }

        template <class ScalarType>
        vector<T, 2> operator/(ScalarType scalar) const
        {
            assert(scalar);
            return vector<T, 2>(x / scalar, y / scalar);
        }

        const vector<T, 2> &operator+() const
        {
            return *this;
        }

        vector<T, 2> operator-() const
        {
            return vector<T, 2>(-x, -y);
        }

        template <class ScalarType>
        friend vector<T, 2> operator*(ScalarType scalar,
                                      const vector<T, 2> &vec)
        {
            return vector<T, 2>(vec.x * scalar, vec.y * scalar);
        }

        template <class ScalarType>
        friend vector<T, 2> operator/(ScalarType scalar,
                                      const vector<T, 2> &vec)
        {
            assert(scalar);
            return vector<T, 2>(vec.x / scalar, vec.y / scalar);
        }

        // -- arithmetic assignment operators

        vector<T, 2> &operator+=(const vector<T, 2> &other)
        {
            x += other.x;
            y += other.y;
            return *this;
        }

        vector<T, 2> &operator-=(const vector<T, 2> &other)
        {
            x -= other.x;
            y -= other.y;
            return *this;
        }

        vector<T, 2> &operator*=(const vector<T, 2> &other)
        {
            x *= other.x;
            y *= other.y;
            return *this;
        }

        template <class ScalarType>
        vector<T, 2> &operator*=(ScalarType scalar)
        {
            x *= scalar;
            y *= scalar;
            return *this;
        }

        vector<T, 2> &operator/=(const vector<T, 2> &other)
        {
            assert(other.x && other.y);
            x /= other.x;
            y /= other.y;
            return *this;
        }

        template <class ScalarType>
        vector<T, 2> &operator/=(ScalarType scalar)
        {
            assert(scalar);
            x /= scalar;
            y /= scalar;
            return *this;
        }

        // -- helper methods

        T norm() const
        {
            return x * x + y * y;
        }

        T length() const
        {
            return math::sqrt(norm());
        }

        // include the swizzling functions
#       include <neglect/_vector2_swizzle.inc>
    };
}

#endif