vecx.h File Reference

Go to the documentation of this file. Source: include/ffw/graphics/vecx.h

/* This file is part of FineFramework project */
#ifndef FFW_VEC_X
#define FFW_VEC_X

#include <ostream>
#include <array>
#include <cmath>
#include "config.h"

namespace ffw{
    template<class T, size_t S>
    class Vec {
    public:
        Vec() {
            for(size_t i = 0; i < S; i++) {
                arr[i] = (T)0;
            }
        }

        Vec(T val) {
            for (size_t i = 0; i < S; i++) {
                arr[i] = val;
            }
        }

        Vec(const std::initializer_list<T>& list) {
            if (S == list.size()) {
                for (size_t i = 0; i < S; i++) {
                    arr[i] = *(list.begin() + i);
                }
            } else {
                for (size_t i = 0; i < S; i++) {
                    arr[i] = (T)0;
                }
            }
        }

        Vec(const Vec<T, S>& other):arr(other.arr) {
        }

        Vec(Vec<T, S>&& other) NOEXCEPT :arr(std::move(other.arr)) {
        }

        void set(T val) {
            for (size_t i = 0; i < S; i++) {
                arr[i] = val;
            }
        }

        void set(const std::initializer_list<T>& list) {
            if (S == list.size()) {
                for (size_t i = 0; i < S; i++) {
                    arr[i] = *(list.begin() + i);
                }
            }
        }

        void set(const Vec<T, S>& other) {
            arr = other.arr;
        }

        ffw::Vec<T, S>  operator - () const {
            auto copy = *this;
            for(size_t i = 0; i < S; i++) {
                copy.arr[i] = -arr[i];
            }
            return copy;
        }

        ffw::Vec<T, S>& operator =  (const Vec<T, S>& vec) {
            for (size_t i = 0; i < S; i++) {
                arr[i] = vec.arr[i];
            }
            return *this;
        }

        ffw::Vec<T, S>  operator +  (const Vec<T, S>& vec) const {
            auto copy = *this;
            for (size_t i = 0; i < S; i++) {
                copy.arr[i] += vec.arr[i];
            }
            return copy;
        }

        ffw::Vec<T, S>& operator += (const Vec<T, S>& vec) {
            for (size_t i = 0; i < S; i++) {
                arr[i] += vec.arr[i];
            }
            return *this;
        }

        ffw::Vec<T, S>  operator -  (const Vec<T, S>& vec) const {
            auto copy = *this;
            for (size_t i = 0; i < S; i++) {
                copy.arr[i] -= vec.arr[i];
            }
            return copy;
        }

        ffw::Vec<T, S>& operator -= (const Vec<T, S>& vec) {
            for (size_t i = 0; i < S; i++) {
                arr[i] -= vec.arr[i];
            }
            return *this;
        }

        ffw::Vec<T, S>  operator /  (const Vec<T, S>& vec) const {
            auto copy = *this;
            for (size_t i = 0; i < S; i++) {
                copy.arr[i] /= vec.arr[i];
            }
            return copy;
        }

        ffw::Vec<T, S>& operator /= (const Vec<T, S>& vec) {
            for (size_t i = 0; i < S; i++) {
                arr[i] /= vec.arr[i];
            }
            return *this;
        }

        ffw::Vec<T, S>  operator *  (const Vec<T, S>& vec) const {
            auto copy = *this;
            for (size_t i = 0; i < S; i++) {
                copy.arr[i] *= vec.arr[i];
            }
            return copy;
        }

        ffw::Vec<T, S>& operator *= (const Vec<T, S>& vec) {
            for (size_t i = 0; i < S; i++) {
                arr[i] *= vec.arr[i];
            }
            return *this;
        }

        ffw::Vec<T, S>& operator =  (const T& val) {
            for (size_t i = 0; i < S; i++) {
                arr[i] = val;
            }
            return *this;
        }

        ffw::Vec<T, S>  operator +  (const T& val) const {
            auto copy = *this;
            for (size_t i = 0; i < S; i++) {
                copy.arr[i] += val;
            }
            return copy;
        }

        ffw::Vec<T, S>& operator += (const T& val) {
            for (size_t i = 0; i < S; i++) {
                arr[i] += val;
            }
            return *this;
        }

        ffw::Vec<T, S>  operator -  (const T& val) const {
            auto copy = *this;
            for (size_t i = 0; i < S; i++) {
                copy.arr[i] -= val;
            }
            return copy;
        }

        ffw::Vec<T, S>& operator -= (const T& val) {
            for (size_t i = 0; i < S; i++) {
                arr[i] -= val;
            }
            return *this;
        }

        ffw::Vec<T, S>  operator /  (const T& val) const {
            auto copy = *this;
            for (size_t i = 0; i < S; i++) {
                copy.arr[i] /= val;
            }
            return copy;
        }

        ffw::Vec<T, S>& operator /= (const T& val) {
            for (size_t i = 0; i < S; i++) {
                arr[i] /= val;
            }
            return *this;
        }

        ffw::Vec<T, S>  operator *  (const T& val) const {
            auto copy = *this;
            for (size_t i = 0; i < S; i++) {
                copy.arr[i] *= val;
            }
            return copy;
        }

        ffw::Vec<T, S>& operator *= (const T& val) {
            for (size_t i = 0; i < S; i++) {
                arr[i] *= val;
            }
            return *this;
        }

        bool operator != (const Vec<T, S>& vec) const {
            return !(*this == vec);
        }

        bool operator == (const Vec<T, S>& vec) const {
            for(size_t i = 0; i < S; i++) {
                if (arr[i] != vec.arr[i])return false;
            }
            return true;
        }

        ffw::Vec<T, S>& normalize() {
            double l = 0.0;
            for(size_t i = 0; i < S; i++) {
                l += arr[i] * arr[i];
            }
            l = sqrt(l);
            for(size_t i = 0; i < S; i++) {
                arr[i] = T(arr[i] / l);
            }
            return *this;
        }

        ffw::Vec<T, S>& scale(T factor) {
            for (size_t i = 0; i < S; i++) {
                arr[i] = arr[i] * factor;
            }
            return *this;
        }

        float lengthf() const {
            return sqrtf(lengthSqrd());
        }

        double length() const {
            return sqrt(lengthSqrd());
        }

        T lengthSqrd() const {
            T val = (T)0;
            for (size_t i = 0; i < S; i++) {
                val += arr[i] * arr[i];
            }
            return val;
        }

        T& operator [] (size_t i){
            return arr[i];
        }

        const T& operator [] (size_t i) const  {
            return arr[i];
        }

        template <class X>
        operator ffw::Vec<X, S>() const {
            Vec<X, S> copy;
            for(size_t i = 0; i < S; i++) {
                copy.arr[i] = static_cast<X>(arr[i]);
            }
            return copy;
        }

        inline Vec<T, S> round() const {
            Vec<T, S> ret;
            for (size_t i = 0; i < S; i++) {
                ret[i] = std::round(arr[i]);
            }
            return ret;
        }

        inline Vec<T, S> floor() const {
            Vec<T, S> ret;
            for (size_t i = 0; i < S; i++) {
                ret[i] = std::floor(arr[i]);
            }
            return ret;
        }

        inline Vec<T, S> ceil() const {
            Vec<T, S> ret;
            for (size_t i = 0; i < S; i++) {
                ret[i] = std::ceil(arr[i]);
            }
            return ret;
        }

        std::array<T, S> arr;
    };
    template <class T, size_t S>
    inline T dot(const ffw::Vec<T, S>& V1, const ffw::Vec<T, S>& V2) {
        T ret = 0;
        for(size_t i = 0; i < S; i++){
            ret += V1[i] * V2[i];
        }
        return ret;
    }
    template <class T, size_t S>
    inline T distance(const Vec<T, S>& v1, const Vec<T, S>& v2) {
        return static_cast<T>(ffw::Vec<T, S>(v2 - v1).length());
    }
    template <class T, size_t S>
    inline Vec<T, S> middle(const Vec<T, S>& v1, const Vec<T, S>& v2) {
        return ffw::Vec<T, S>((v1 + v2) / 2);
    }
    template <class T, size_t S>
    inline ffw::Vec<T, S> normalize(const Vec<T, S>& vec) {
        return ffw::Vec<T, S>(vec).normalize();
    }
    template <class T, size_t S>
    inline std::ostream& operator << (std::ostream& os, const ffw::Vec<T, S>& vec) {
        os << vec[0];
        for(size_t i = 1; i < S; i++){
            os << ", " << vec[i];
        }
        return os;
    }
};
#endif