diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 86957a4..1c48908 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -14,7 +14,7 @@ jobs: - { os: "windows-2016", vs: "Visual Studio 2017", arch: "x64" } - { os: "windows-2019", vs: "Visual Studio 2019", arch: "x86" } - { os: "windows-2019", vs: "Visual Studio 2019", arch: "x64" } - name: "${{matrix.config.vs}}" + name: "${{matrix.config.vs}} ${{matrix.config.arch}}" steps: - uses: actions/checkout@v2 - name: Build && Test diff --git a/README.md b/README.md index 2b7fa5a..53a0e31 100644 --- a/README.md +++ b/README.md @@ -85,48 +85,57 @@ class vec_base; template < typename T > class vec_base { public: - T x{}, y{}; + T x = T{0}; + T y = T{0}; - constexpr vec_base() = default; - constexpr explicit vec_base(T v); - constexpr vec_base(T x, T y); - constexpr explicit vec_base(const vec_base& xy); - constexpr explicit vec_base(const vec_base& xy); + vec_base() = default; + explicit vec_base(T v); + vec_base(T x, T y); }; template < typename T > class vec_base { public: - T x{}, y{}, z{}; + T x = T{0}; + T y = T{0}; + T z = T{0}; - constexpr vec_base() = default; - constexpr explicit vec_base(T v); - constexpr vec_base(T x, T y, T z); - constexpr vec_base(const vec_base& xy, T z); - constexpr vec_base(T x, const vec_base& yz); - constexpr explicit vec_base(const vec_base& xyz); + vec_base() = default; + explicit vec_base(T v); + vec_base(T x, T y, T z); + vec_base(const vec_base& xy, T z); + vec_base(T x, const vec_base& yz); + + explicit operator vec() const; }; template < typename T > class vec_base { public: - T x{}, y{}, z{}, w{}; + T x = T{0}; + T y = T{0}; + T z = T{0}; + T w = T{0}; - constexpr vec_base() = default; - constexpr explicit vec_base(T v); - constexpr vec_base(T x, T y, T z, T w); - constexpr vec_base(const vec_base& xy, T z, T w); - constexpr vec_base(T x, const vec_base& yz, T w); - constexpr vec_base(T x, T y, const vec_base& zw); - constexpr vec_base(const vec_base& xy, const vec_base& zw); - constexpr vec_base(const vec_base& xyz, T w); - constexpr vec_base(T x, const vec_base& yzw); + vec_base() = default; + explicit vec_base(T v); + vec_base(T x, T y, T z, T w); + vec_base(const vec_base& xy, T z, T w); + vec_base(T x, const vec_base& yz, T w); + vec_base(T x, T y, const vec_base& zw); + vec_base(const vec_base& xy, const vec_base& zw); + vec_base(const vec_base& xyz, T w); + vec_base(T x, const vec_base& yzw); + + explicit operator vec() const; + explicit operator vec() const; }; template < typename T, size_t Size > class vec final : public vec_base { public: using self_type = vec; + using base_type = vec_base; using component_type = T; using pointer = component_type*; @@ -140,33 +149,37 @@ public: using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - static constexpr size_t size = Size; + static inline size_t size = Size; - void swap(vec& other) noexcept(is_nothrow_swappable_v); + vec() = default; + vec(const vec&) = default; + vec& operator=(const vec&) = default; - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; + void swap(vec& other); - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + reverse_iterator rend(); + const_reverse_iterator rend() const; - pointer data() noexcept; - const_pointer data() const noexcept; + const_iterator cbegin() const; + const_iterator cend() const; + const_reverse_iterator crbegin() const; + const_reverse_iterator crend() const; - constexpr reference at(size_t index); - constexpr const_reference at(size_t index) const; + pointer data(); + const_pointer data() const; - constexpr reference operator[](size_t index) noexcept; - constexpr const_reference operator[](size_t index) const noexcept; + reference at(size_t index); + const_reference at(size_t index) const; + + reference operator[](size_t index); + const_reference operator[](size_t index) const; }; using bool2 = vec; @@ -210,23 +223,20 @@ public: using row_type = vec; row_type rows[2] = { - {1, 0}, - {0, 1}}; + row_type{T{1}, T{0}}, + row_type{T{0}, T{1}}}; - constexpr mat_base() = default; - constexpr explicit mat_base(T d); - constexpr explicit mat_base(const row_type& d); + mat_base() = default; + explicit mat_base(T d); + explicit mat_base(const row_type& d); - constexpr mat_base( + mat_base( T m11, T m12, T m21, T m22); - constexpr mat_base( + mat_base( const row_type& row0, const row_type& row1); - - constexpr explicit mat_base(const mat_base& other); - constexpr explicit mat_base(const mat_base& other); }; template < typename T > @@ -235,30 +245,31 @@ public: using row_type = vec; row_type rows[3] = { - {1, 0, 0}, - {0, 1, 0}, - {0, 0, 1}}; + row_type{T{1}, T{0}, T{0}}, + row_type{T{0}, T{1}, T{0}}, + row_type{T{0}, T{0}, T{1}}}; - constexpr mat_base() = default; - constexpr explicit mat_base(T d); - constexpr explicit mat_base(const row_type& d); + mat_base() = default; + explicit mat_base(T d); + explicit mat_base(const row_type& d); - constexpr mat_base( + mat_base( T m11, T m12, T m13, T m21, T m22, T m23, T m31, T m32, T m33); - constexpr mat_base( + mat_base( const row_type& row0, const row_type& row1, const row_type& row2); - constexpr mat_base( + mat_base( const mat_base& m, const vec_base& v); - constexpr explicit mat_base(const mat_base& other); - constexpr explicit mat_base(const mat_base& other); + explicit mat_base(const mat_base& other); + + explicit operator mat() const; }; template < typename T > @@ -267,39 +278,45 @@ public: using row_type = vec; row_type rows[4] = { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}}; + row_type{T{1}, T{0}, T{0}, T{0}}, + row_type{T{0}, T{1}, T{0}, T{0}}, + row_type{T{0}, T{0}, T{1}, T{0}}, + row_type{T{0}, T{0}, T{0}, T{1}}}; - constexpr mat_base() = default; - constexpr explicit mat_base(T d); - constexpr explicit mat_base(const row_type& d); + mat_base() = default; + explicit mat_base(T d); + explicit mat_base(const row_type& d); - constexpr mat_base( + mat_base( T m11, T m12, T m13, T m14, T m21, T m22, T m23, T m24, T m31, T m32, T m33, T m34, T m41, T m42, T m43, T m44); - constexpr mat_base( + mat_base( const row_type& row0, const row_type& row1, const row_type& row2, const row_type& row3); - constexpr mat_base( + mat_base( const mat_base& m, const vec_base& v); - constexpr explicit mat_base(const mat_base& other); - constexpr explicit mat_base(const mat_base& other); + explicit mat_base(const mat_base& other); + explicit mat_base(const mat_base& other); + + explicit operator mat() const; + explicit operator mat() const; }; template < typename T, size_t Size > class mat final : public mat_base { public: using self_type = mat; + using base_type = mat_base; + using component_type = T; + using row_type = vec; using pointer = row_type*; @@ -313,33 +330,37 @@ public: using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - static constexpr size_t size = Size; + static inline size_t size = Size; - void swap(mat& other) noexcept(is_nothrow_swappable_v); + mat() = default; + mat(const mat&) = default; + mat& operator=(const mat&) = default; - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; + void swap(mat& other); - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + reverse_iterator rend(); + const_reverse_iterator rend() const; - pointer data() noexcept; - const_pointer data() const noexcept; + const_iterator cbegin() const; + const_iterator cend() const; + const_reverse_iterator crbegin() const; + const_reverse_iterator crend() const; - constexpr reference at(size_t index); - constexpr const_reference at(size_t index) const; + pointer data(); + const_pointer data() const; - constexpr reference operator[](size_t index) noexcept; - constexpr const_reference operator[](size_t index) const noexcept; + reference at(size_t index); + const_reference at(size_t index) const; + + reference operator[](size_t index); + const_reference operator[](size_t index) const; }; using bool2x2 = mat; @@ -374,15 +395,30 @@ using ptrdiff4x4_t = mat; ### Quaternion Types ```cpp +template < typename T > +class qua_base { +public: + vec v = vec{T{0}}; + T s = T{1}; + + qua_base(); + qua_base(T vx, T vy, T vz, T s); + qua_base(const vec& v, T s); + + explicit qua_base(const vec& vs); + explicit operator vec() const; +}; + template < typename T > class qua final { -public: - vec v{0}; - T s{1}; public: using self_type = qua; + using base_type = qua_base; using component_type = T; + using imag_type = vec; + using real_type = T; + using pointer = component_type*; using const_pointer = const component_type*; @@ -394,43 +430,37 @@ public: using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - static constexpr size_t size = 4; -public: - constexpr qua() = default; - constexpr qua(const qua&) = default; - constexpr qua& operator=(const qua&) = default; + static inline size_t size = 4; - constexpr qua(T vx, T vy, T vz, T s); - constexpr qua(const vec& v, T s); - constexpr explicit qua(const vec& vs); + qua() = default; + qua(const qua&) = default; + qua& operator=(const qua&) = default; - constexpr explicit operator vec() const; + void swap(qua& other); - void swap(qua& other) noexcept(is_nothrow_swappable_v); + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + reverse_iterator rend(); + const_reverse_iterator rend() const; - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; + const_iterator cbegin() const; + const_iterator cend() const; + const_reverse_iterator crbegin() const; + const_reverse_iterator crend() const; - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; + pointer data(); + const_pointer data() const; - pointer data() noexcept; - const_pointer data() const noexcept; + reference at(size_t index); + const_reference at(size_t index) const; - constexpr reference at(size_t index); - constexpr const_reference at(size_t index) const; - - constexpr reference operator[](size_t index) noexcept; - constexpr const_reference operator[](size_t index) const noexcept; + reference operator[](size_t index); + const_reference operator[](size_t index) const; }; using qfloat = qua; @@ -443,192 +473,192 @@ using qdouble = qua; // +operator template < typename T, size_t Size > -constexpr vec operator+(const vec& xs); +auto operator+(const vec& xs); // -operator template < typename T, size_t Size > -constexpr vec operator-(const vec& xs); +auto operator-(const vec& xs); // ~operator template < typename T, size_t Size > -constexpr vec operator~(const vec& xs); +auto operator~(const vec& xs); // !operator template < typename T, size_t Size > -constexpr vec operator!(const vec& xs); +auto operator!(const vec& xs); // operator+ template < typename T, size_t Size > -constexpr vec operator+(const vec& xs, T y); +auto operator+(const vec& xs, T y); template < typename T, size_t Size > -constexpr vec operator+(T x, const vec& ys); +auto operator+(T x, const vec& ys); template < typename T, size_t Size > -constexpr vec operator+(const vec& xs, const vec& ys); +auto operator+(const vec& xs, const vec& ys); // operator+= template < typename T, size_t Size > -constexpr vec& operator+=(vec& xs, T y); +vec& operator+=(vec& xs, T y); template < typename T, size_t Size > -constexpr vec& operator+=(vec& xs, const vec& ys); +vec& operator+=(vec& xs, const vec& ys); // operator- template < typename T, size_t Size > -constexpr vec operator-(const vec& xs, T y); +auto operator-(const vec& xs, T y); template < typename T, size_t Size > -constexpr vec operator-(T x, const vec& ys); +auto operator-(T x, const vec& ys); template < typename T, size_t Size > -constexpr vec operator-(const vec& xs, const vec& ys); +auto operator-(const vec& xs, const vec& ys); // operator-= template < typename T, size_t Size > -constexpr vec& operator-=(vec& xs, T y); +vec& operator-=(vec& xs, T y); template < typename T, size_t Size > -constexpr vec& operator-=(vec& xs, const vec& ys); +vec& operator-=(vec& xs, const vec& ys); // operator* template < typename T, size_t Size > -constexpr vec operator*(const vec& xs, T y); +auto operator*(const vec& xs, T y); template < typename T, size_t Size > -constexpr vec operator*(T x, const vec& ys); +auto operator*(T x, const vec& ys); template < typename T, size_t Size > -constexpr vec operator*(const vec& xs, const vec& ys); +auto operator*(const vec& xs, const vec& ys); // operator*= template < typename T, size_t Size > -constexpr vec& operator*=(vec& xs, T y); +vec& operator*=(vec& xs, T y); template < typename T, size_t Size > -constexpr vec& operator*=(vec& xs, const vec& ys); +vec& operator*=(vec& xs, const vec& ys); // operator/ template < typename T, size_t Size > -constexpr vec operator/(const vec& xs, T y); +auto operator/(const vec& xs, T y); template < typename T, size_t Size > -constexpr vec operator/(T x, const vec& ys); +auto operator/(T x, const vec& ys); template < typename T, size_t Size > -constexpr vec operator/(const vec& xs, const vec& ys); +auto operator/(const vec& xs, const vec& ys); // operator/= template < typename T, size_t Size > -constexpr vec& operator/=(vec& xs, T y); +vec& operator/=(vec& xs, T y); template < typename T, size_t Size > -constexpr vec& operator/=(vec& xs, const vec& ys); +vec& operator/=(vec& xs, const vec& ys); // operator& template < typename T, size_t Size > -constexpr vec operator&(const vec& xs, T y); +auto operator&(const vec& xs, T y); template < typename T, size_t Size > -constexpr vec operator&(T x, const vec& ys); +auto operator&(T x, const vec& ys); template < typename T, size_t Size > -constexpr vec operator&(const vec& xs, const vec& ys); +auto operator&(const vec& xs, const vec& ys); // operator&= template < typename T, size_t Size > -constexpr vec& operator&=(vec& xs, T y); +vec& operator&=(vec& xs, T y); template < typename T, size_t Size > -constexpr vec& operator&=(vec& xs, const vec& ys); +vec& operator&=(vec& xs, const vec& ys); // operator| template < typename T, size_t Size > -constexpr vec operator|(const vec& xs, T y); +auto operator|(const vec& xs, T y); template < typename T, size_t Size > -constexpr vec operator|(T x, const vec& ys); +auto operator|(T x, const vec& ys); template < typename T, size_t Size > -constexpr vec operator|(const vec& xs, const vec& ys); +auto operator|(const vec& xs, const vec& ys); // operator|= template < typename T, size_t Size > -constexpr vec& operator|=(vec& xs, T y); +vec& operator|=(vec& xs, T y); template < typename T, size_t Size > -constexpr vec& operator|=(vec& xs, const vec& ys); +vec& operator|=(vec& xs, const vec& ys); // operator^ template < typename T, size_t Size > -constexpr vec operator^(const vec& xs, T y); +auto operator^(const vec& xs, T y); template < typename T, size_t Size > -constexpr vec operator^(T x, const vec& ys); +auto operator^(T x, const vec& ys); template < typename T, size_t Size > -constexpr vec operator^(const vec& xs, const vec& ys); +auto operator^(const vec& xs, const vec& ys); // operator^= template < typename T, size_t Size > -constexpr vec& operator^=(vec& xs, T y); +vec& operator^=(vec& xs, T y); template < typename T, size_t Size > -constexpr vec& operator^=(vec& xs, const vec& ys); +vec& operator^=(vec& xs, const vec& ys); // operator&& template < typename T, size_t Size > -constexpr vec operator&&(const vec& xs, T y); +auto operator&&(const vec& xs, T y); template < typename T, size_t Size > -constexpr vec operator&&(T x, const vec& ys); +auto operator&&(T x, const vec& ys); template < typename T, size_t Size > -constexpr vec operator&&(const vec& xs, const vec& ys); +auto operator&&(const vec& xs, const vec& ys); // operator|| template < typename T, size_t Size > -constexpr vec operator||(const vec& xs, T y); +auto operator||(const vec& xs, T y); template < typename T, size_t Size > -constexpr vec operator||(T x, const vec& ys); +auto operator||(T x, const vec& ys); template < typename T, size_t Size > -constexpr vec operator||(const vec& xs, const vec& ys); +auto operator||(const vec& xs, const vec& ys); // operator== template < typename T, size_t Size > -constexpr bool operator==(const vec& xs, const vec& ys); +bool operator==(const vec& xs, const vec& ys); // operator!= template < typename T, size_t Size > -constexpr bool operator!=(const vec& xs, const vec& ys); +bool operator!=(const vec& xs, const vec& ys); // operator< template < typename T, size_t Size > -constexpr bool operator<(const vec& xs, const vec& ys); +bool operator<(const vec& xs, const vec& ys); ``` ### Matrix Operators @@ -637,192 +667,192 @@ constexpr bool operator<(const vec& xs, const vec& ys); // +operator template < typename T, size_t Size > -constexpr mat operator+(const mat& xs); +auto operator+(const mat& xs); // -operator template < typename T, size_t Size > -constexpr mat operator-(const mat& xs); +auto operator-(const mat& xs); // ~operator template < typename T, size_t Size > -constexpr mat operator~(const mat& xs); +auto operator~(const mat& xs); // !operator template < typename T, size_t Size > -constexpr mat operator!(const mat& xs); +auto operator!(const mat& xs); // operator+ template < typename T, size_t Size > -constexpr mat operator+(const mat& xs, T y); +auto operator+(const mat& xs, T y); template < typename T, size_t Size > -constexpr mat operator+(T x, const mat& ys); +auto operator+(T x, const mat& ys); template < typename T, size_t Size > -constexpr mat operator+(const mat& xs, const mat& ys); +auto operator+(const mat& xs, const mat& ys); // operator+= template < typename T, size_t Size > -constexpr mat& operator+=(mat& xs, T y); +mat& operator+=(mat& xs, T y); template < typename T, size_t Size > -constexpr mat& operator+=(mat& xs, const mat& ys); +mat& operator+=(mat& xs, const mat& ys); // operator- template < typename T, size_t Size > -constexpr mat operator-(const mat& xs, T y); +auto operator-(const mat& xs, T y); template < typename T, size_t Size > -constexpr mat operator-(T x, const mat& ys); +auto operator-(T x, const mat& ys); template < typename T, size_t Size > -constexpr mat operator-(const mat& xs, const mat& ys); +auto operator-(const mat& xs, const mat& ys); // operator-= template < typename T, size_t Size > -constexpr mat& operator-=(mat& xs, T y); +mat& operator-=(mat& xs, T y); template < typename T, size_t Size > -constexpr mat& operator-=(mat& xs, const mat& ys); +mat& operator-=(mat& xs, const mat& ys); // operator* template < typename T, size_t Size > -constexpr mat operator*(const mat& xs, T y); +auto operator*(const mat& xs, T y); template < typename T, size_t Size > -constexpr mat operator*(T x, const mat& ys); +auto operator*(T x, const mat& ys); template < typename T, size_t Size > -constexpr vec operator*(const vec& xs, const mat& ys); +auto operator*(const vec& xs, const mat& ys); template < typename T, size_t Size > -constexpr mat operator*(const mat& xs, const mat& ys); +auto operator*(const mat& xs, const mat& ys); // operator*= template < typename T, size_t Size > -constexpr mat& operator*=(mat& xs, T y); +mat& operator*=(mat& xs, T y); template < typename T, size_t Size > -constexpr vec& operator*=(vec& xs, const mat& ys); +vec& operator*=(vec& xs, const mat& ys); template < typename T, size_t Size > -constexpr mat& operator*=(mat& xs, const mat& ys); +mat& operator*=(mat& xs, const mat& ys); // operator/ template < typename T, size_t Size > -constexpr mat operator/(const mat& xs, T y); +auto operator/(const mat& xs, T y); template < typename T, size_t Size > -constexpr mat operator/(T x, const mat& ys); +auto operator/(T x, const mat& ys); // operator/= template < typename T, size_t Size > -constexpr mat& operator/=(mat& xs, T y); +mat& operator/=(mat& xs, T y); // operator& template < typename T, size_t Size > -constexpr mat operator&(const mat& xs, T y); +auto operator&(const mat& xs, T y); template < typename T, size_t Size > -constexpr mat operator&(T x, const mat& ys); +auto operator&(T x, const mat& ys); template < typename T, size_t Size > -constexpr mat operator&(const mat& xs, const mat& ys); +auto operator&(const mat& xs, const mat& ys); // operator&= template < typename T, size_t Size > -constexpr mat& operator&=(mat& xs, T y); +mat& operator&=(mat& xs, T y); template < typename T, size_t Size > -constexpr mat& operator&=(mat& xs, const mat& ys); +mat& operator&=(mat& xs, const mat& ys); // operator| template < typename T, size_t Size > -constexpr mat operator|(const mat& xs, T y); +auto operator|(const mat& xs, T y); template < typename T, size_t Size > -constexpr mat operator|(T x, const mat& ys); +auto operator|(T x, const mat& ys); template < typename T, size_t Size > -constexpr mat operator|(const mat& xs, const mat& ys); +auto operator|(const mat& xs, const mat& ys); // operator|= template < typename T, size_t Size > -constexpr mat& operator|=(mat& xs, T y); +mat& operator|=(mat& xs, T y); template < typename T, size_t Size > -constexpr mat& operator|=(mat& xs, const mat& ys); +mat& operator|=(mat& xs, const mat& ys); // operator^ template < typename T, size_t Size > -constexpr mat operator^(const mat& xs, T y); +auto operator^(const mat& xs, T y); template < typename T, size_t Size > -constexpr mat operator^(T x, const mat& ys); +auto operator^(T x, const mat& ys); template < typename T, size_t Size > -constexpr mat operator^(const mat& xs, const mat& ys); +auto operator^(const mat& xs, const mat& ys); // operator^= template < typename T, size_t Size > -constexpr mat& operator^=(mat& xs, T y); +mat& operator^=(mat& xs, T y); template < typename T, size_t Size > -constexpr mat& operator^=(mat& xs, const mat& ys); +mat& operator^=(mat& xs, const mat& ys); // operator&& template < typename T, size_t Size > -constexpr mat operator&&(const mat& xs, T y); +auto operator&&(const mat& xs, T y); template < typename T, size_t Size > -constexpr mat operator&&(T x, const mat& ys); +auto operator&&(T x, const mat& ys); template < typename T, size_t Size > -constexpr mat operator&&(const mat& xs, const mat& ys); +auto operator&&(const mat& xs, const mat& ys); // operator|| template < typename T, size_t Size > -constexpr mat operator||(const mat& xs, T y); +auto operator||(const mat& xs, T y); template < typename T, size_t Size > -constexpr mat operator||(T x, const mat& ys); +auto operator||(T x, const mat& ys); template < typename T, size_t Size > -constexpr mat operator||(const mat& xs, const mat& ys); +auto operator||(const mat& xs, const mat& ys); // operator== template < typename T, size_t Size > -constexpr bool operator==(const mat& xs, const mat& ys); +bool operator==(const mat& xs, const mat& ys); // operator!= template < typename T, size_t Size > -constexpr bool operator!=(const mat& xs, const mat& ys); +bool operator!=(const mat& xs, const mat& ys); // operator< template < typename T, size_t Size > -constexpr bool operator<(const mat& xs, const mat& ys); +bool operator<(const mat& xs, const mat& ys); ``` ### Quaternion Operators @@ -831,85 +861,85 @@ constexpr bool operator<(const mat& xs, const mat& ys); // +operator template < typename T > -constexpr qua operator+(const qua& xs); +auto operator+(const qua& xs); // -operator template < typename T > -constexpr qua operator-(const qua& xs); +auto operator-(const qua& xs); // operator+ template < typename T > -constexpr qua operator+(const qua& xs, const qua& ys); +auto operator+(const qua& xs, const qua& ys); // operator+= template < typename T > -constexpr qua& operator+=(qua& xs, const qua& ys); +qua& operator+=(qua& xs, const qua& ys); // operator- template < typename T > -constexpr qua operator-(const qua& xs, const qua& ys); +auto operator-(const qua& xs, const qua& ys); // operator-= template < typename T > -constexpr qua& operator-=(qua& xs, const qua& ys); +qua& operator-=(qua& xs, const qua& ys); // operator* template < typename T > -constexpr qua operator*(const qua& xs, T y); +auto operator*(const qua& xs, T y); template < typename T > -constexpr qua operator*(T x, const qua& ys); +auto operator*(T x, const qua& ys); template < typename T > -constexpr vec operator*(const vec& xs, const qua& ys); +auto operator*(const vec& xs, const qua& ys); template < typename T > -constexpr qua operator*(const qua& xs, const qua& ys); +auto operator*(const qua& xs, const qua& ys); // operator*= template < typename T > -constexpr qua& operator*=(qua& xs, T y); +qua& operator*=(qua& xs, T y); template < typename T > -constexpr vec& operator*=(vec& xs, const qua& ys); +vec& operator*=(vec& xs, const qua& ys); template < typename T > -constexpr qua& operator*=(qua& xs, const qua& ys); +qua& operator*=(qua& xs, const qua& ys); // operator/ template < typename T > -constexpr qua operator/(const qua& xs, T y); +auto operator/(const qua& xs, T y); template < typename T > -constexpr qua operator/(T x, const qua& ys); +auto operator/(T x, const qua& ys); // operator/= template < typename T > -constexpr qua& operator/=(qua& xs, T y); +qua& operator/=(qua& xs, T y); // operator== template < typename T > -constexpr bool operator==(const qua& xs, const qua& ys); +bool operator==(const qua& xs, const qua& ys); // operator!= template < typename T > -constexpr bool operator!=(const qua& xs, const qua& ys); +bool operator!=(const qua& xs, const qua& ys); // operator< template < typename T > -constexpr bool operator<(const qua& xs, const qua& ys); +bool operator<(const qua& xs, const qua& ys); ``` ### Common Functions @@ -918,98 +948,80 @@ constexpr bool operator<(const qua& xs, const qua& ys); ```cpp template < arithmetic T > -constexpr T abs(T x) noexcept; +T abs(T x); template < arithmetic T > -constexpr T sqr(T x) noexcept; +T sqr(T x); template < arithmetic T > -constexpr T sign(T x) noexcept; +T sign(T x); template < floating_point T > -constexpr T rcp(T x) noexcept; +T rcp(T x); template < floating_point T > -T floor(T x) noexcept; +T floor(T x); template < floating_point T > -T trunc(T x) noexcept; +T trunc(T x); template < floating_point T > -T round(T x) noexcept; +T round(T x); template < floating_point T > -T ceil(T x) noexcept; +T ceil(T x); template < floating_point T > -T fract(T x) noexcept; +T fract(T x); template < floating_point T > -T fmod(T x, T y) noexcept; +T fmod(T x, T y); template < floating_point T > -T modf(T x, T* y) noexcept; +T modf(T x, T* y); template < floating_point T > -T copysign(T x, T s) noexcept; +T copysign(T x, T s); template < arithmetic T > -constexpr T min(T x, T y) noexcept; +T min(T x, T y); template < arithmetic T > -constexpr T max(T x, T y) noexcept; +T max(T x, T y); template < arithmetic T > -constexpr T clamp(T x, T min_x, T max_x) noexcept; +T clamp(T x, T min_x, T max_x); template < arithmetic T > -constexpr T saturate(T x) noexcept; +T saturate(T x); template < floating_point T > -constexpr T lerp(T x, T y, T a) noexcept; +T lerp(T x, T y, T a); template < floating_point T > -constexpr T lerp(T x, T y, T x_a, T y_a) noexcept; +T lerp(T x, T y, T x_a, T y_a); template < floating_point T > -constexpr T step(T edge, T x) noexcept; +T step(T edge, T x); template < floating_point T > -constexpr T smoothstep(T edge0, T edge1, T x) noexcept; - -template < arithmetic T > -bool isnan(T x) noexcept; - -template < arithmetic T > -bool isinf(T x) noexcept; - -template < arithmetic T > -bool isfinite(T x) noexcept; - -template < floating_point T > -T fma(T x, T y, T z) noexcept; - -template < floating_point T > -T frexp(T x, int* exp) noexcept; - -template < floating_point T > -T ldexp(T x, int exp) noexcept; +T smoothstep(T edge0, T edge1, T x); ``` #### Vector ```cpp template < typename T, size_t Size > -constexpr vec abs(const vec& xs); +vec abs(const vec& xs); template < typename T, size_t Size > -constexpr vec sqr(const vec& xs); +vec sqr(const vec& xs); template < typename T, size_t Size > -constexpr vec sign(const vec& xs); +vec sign(const vec& xs); template < typename T, size_t Size > -constexpr vec rcp(const vec& xs); +vec rcp(const vec& xs); template < typename T, size_t Size > vec floor(const vec& xs); @@ -1042,79 +1054,61 @@ template < typename T, size_t Size > vec copysign(const vec& xs, const vec& ss); template < typename T, size_t Size > -constexpr T min(const vec& xs); +T min(const vec& xs); template < typename T, size_t Size > -constexpr vec min(const vec& xs, T y); +vec min(const vec& xs, T y); template < typename T, size_t Size > -constexpr vec min(T x, const vec& ys); +vec min(T x, const vec& ys); template < typename T, size_t Size > -constexpr vec min(const vec& xs, const vec& ys); +vec min(const vec& xs, const vec& ys); template < typename T, size_t Size > -constexpr T max(const vec& xs); +T max(const vec& xs); template < typename T, size_t Size > -constexpr vec max(const vec& xs, T y); +vec max(const vec& xs, T y); template < typename T, size_t Size > -constexpr vec max(T x, const vec& ys); +vec max(T x, const vec& ys); template < typename T, size_t Size > -constexpr vec max(const vec& xs, const vec& ys); +vec max(const vec& xs, const vec& ys); template < typename T, size_t Size > -constexpr vec clamp(const vec& xs, T min_x, T max_x); +vec clamp(const vec& xs, T min_x, T max_x); template < typename T, size_t Size > -constexpr vec clamp(const vec& xs, const vec& min_xs, const vec& max_xs); +vec clamp(const vec& xs, const vec& min_xs, const vec& max_xs); template < typename T, size_t Size > -constexpr vec saturate(const vec& xs); +vec saturate(const vec& xs); template < typename T, size_t Size > -constexpr vec lerp(const vec& xs, const vec& ys, T a); +vec lerp(const vec& xs, const vec& ys, T a); template < typename T, size_t Size > -constexpr vec lerp(const vec& xs, const vec& ys, T x_a, T y_a); +vec lerp(const vec& xs, const vec& ys, T x_a, T y_a); template < typename T, size_t Size > -constexpr vec lerp(const vec& xs, const vec& ys, const vec& as); +vec lerp(const vec& xs, const vec& ys, const vec& as); template < typename T, size_t Size > -constexpr vec lerp(const vec& xs, const vec& ys, const vec& xs_a, const vec& ys_a); +vec lerp(const vec& xs, const vec& ys, const vec& xs_a, const vec& ys_a); template < typename T, size_t Size > -constexpr vec step(T edge, const vec& xs); +vec step(T edge, const vec& xs); template < typename T, size_t Size > -constexpr vec step(const vec& edges, const vec& xs); +vec step(const vec& edges, const vec& xs); template < typename T, size_t Size > -constexpr vec smoothstep(T edge0, T edge1, const vec& xs); +vec smoothstep(T edge0, T edge1, const vec& xs); template < typename T, size_t Size > -constexpr vec smoothstep(const vec& edges0, const vec& edges1, const vec& xs); - -template < typename T, size_t Size > -vec isnan(const vec& xs); - -template < typename T, size_t Size > -vec isinf(const vec& xs); - -template < typename T, size_t Size > -vec isfinite(const vec& xs); - -template < typename T, size_t Size > -vec fma(const vec& as, const vec& bs, const vec& cs); - -template < typename T, size_t Size > -vec frexp(const vec& xs, vec* exps); - -template < typename T, size_t Size > -vec ldexp(const vec& xs, const vec& exps); +vec smoothstep(const vec& edges0, const vec& edges1, const vec& xs); ``` #### Quaternion @@ -1131,15 +1125,6 @@ qua nlerp(const qua& unit_xs, const qua& unit_ys, T a); template < typename T > qua slerp(const qua& unit_xs, const qua& unit_ys, T a); - -template < typename T > -vec isnan(const qua& xs); - -template < typename T > -vec isinf(const qua& xs); - -template < typename T > -vec isfinite(const qua& xs); ``` ### Angle and Trigonometric Functions @@ -1148,65 +1133,65 @@ vec isfinite(const qua& xs); ```cpp template < floating_point T > -constexpr T radians(T degrees) noexcept; +T radians(T degrees); template < floating_point T > -constexpr T degrees(T radians) noexcept; +T degrees(T radians); template < floating_point T > -T sin(T x) noexcept; +T sin(T x); template < floating_point T > -T cos(T x) noexcept; +T cos(T x); template < floating_point T > -T tan(T x) noexcept; +T tan(T x); template < floating_point T > -T asin(T x) noexcept; +T asin(T x); template < floating_point T > -T acos(T x) noexcept; +T acos(T x); template < floating_point T > -T atan(T x) noexcept; +T atan(T x); template < floating_point T > -T atan2(T y, T x) noexcept; +T atan2(T y, T x); template < floating_point T > -T sinh(T x) noexcept; +T sinh(T x); template < floating_point T > -T cosh(T x) noexcept; +T cosh(T x); template < floating_point T > -T tanh(T x) noexcept; +T tanh(T x); template < floating_point T > -T asinh(T x) noexcept; +T asinh(T x); template < floating_point T > -T acosh(T x) noexcept; +T acosh(T x); template < floating_point T > -T atanh(T x) noexcept; +T atanh(T x); template < floating_point T > -pair sincos(T x) noexcept; +pair sincos(T x); template < floating_point T > -void sincos(T x, T* s, T* c) noexcept; +void sincos(T x, T* s, T* c); ``` #### Vector ```cpp template < typename T, size_t Size > -constexpr vec radians(const vec& degrees); +vec radians(const vec& degrees); template < typename T, size_t Size > -constexpr vec degrees(const vec& radians); +vec degrees(const vec& radians); template < typename T, size_t Size > vec sin(const vec& xs); @@ -1260,25 +1245,25 @@ void sincos(const vec& xs, vec* ss, vec* cs); ```cpp template < floating_point T > -T pow(T x, T y) noexcept; +T pow(T x, T y); template < floating_point T > -T exp(T x) noexcept; +T exp(T x); template < floating_point T > -T log(T x) noexcept; +T log(T x); template < floating_point T > -T exp2(T x) noexcept; +T exp2(T x); template < floating_point T > -T log2(T x) noexcept; +T log2(T x); template < floating_point T > -T sqrt(T x) noexcept; +T sqrt(T x); template < floating_point T > -T rsqrt(T x) noexcept; +T rsqrt(T x); ``` #### Vector @@ -1312,65 +1297,77 @@ vec rsqrt(const vec& xs); ```cpp template < arithmetic T > -constexpr T dot(T x, T y) noexcept; +T dot(T x, T y); template < arithmetic T > -constexpr T length(T x) noexcept; +T length(T x); template < arithmetic T > -constexpr T length2(T x) noexcept; +T rlength(T x); template < arithmetic T > -constexpr T distance(T x, T y) noexcept; +T length2(T x); template < arithmetic T > -constexpr T distance2(T x, T y) noexcept; +T rlength2(T x); + +template < arithmetic T > +T distance(T x, T y); + +template < arithmetic T > +T distance2(T x, T y); template < floating_point T > -T normalize(T x) noexcept; +T normalize(T x); template < floating_point T > -constexpr T faceforward(T n, T i, T nref) noexcept; +T faceforward(T n, T i, T nref); template < floating_point T > -constexpr T reflect(T i, T n) noexcept; +T reflect(T i, T n); template < floating_point T > -T refract(T i, T n, T eta) noexcept; +T refract(T i, T n, T eta); ``` #### Vector ```cpp template < typename T, size_t Size > -constexpr T dot(const vec& xs, const vec& ys); +T dot(const vec& xs, const vec& ys); template < typename T, size_t Size > T length(const vec& xs); template < typename T, size_t Size > -constexpr T length2(const vec& xs); +T rlength(const vec& xs); + +template < typename T, size_t Size > +T length2(const vec& xs); + +template < typename T, size_t Size > +T rlength2(const vec& xs); template < typename T, size_t Size > T distance(const vec& xs, const vec& ys); template < typename T, size_t Size > -constexpr T distance2(const vec& xs, const vec& ys); +T distance2(const vec& xs, const vec& ys); template < typename T > -constexpr T cross(const vec& xs, const vec& ys); +T cross(const vec& xs, const vec& ys); template < typename T > -constexpr vec cross(const vec& xs, const vec& ys); +vec cross(const vec& xs, const vec& ys); template < typename T, size_t Size > vec normalize(const vec& xs); template < typename T, size_t Size > -constexpr vec faceforward(const vec& n, const vec& i, const vec& nref); +vec faceforward(const vec& n, const vec& i, const vec& nref); template < typename T, size_t Size > -constexpr vec reflect(const vec& i, const vec& n); +vec reflect(const vec& i, const vec& n); template < typename T, size_t Size > vec refract(const vec& i, const vec& n, T eta); @@ -1380,13 +1377,19 @@ vec refract(const vec& i, const vec& n, T eta); ```cpp template < typename T > -constexpr T dot(const qua& xs, const qua& ys); +T dot(const qua& xs, const qua& ys); template < typename T > T length(const qua& xs); template < typename T > -constexpr T length2(const qua& xs); +T rlength(const qua& xs); + +template < typename T > +T length2(const qua& xs); + +template < typename T > +T rlength2(const qua& xs); template < typename T > T distance(const qua& xs, const qua& ys); @@ -1401,273 +1404,362 @@ qua normalize(const qua& xs); ```cpp template < arithmetic T > -constexpr bool any(T x) noexcept; +bool any(T x); template < arithmetic T > -constexpr bool all(T x) noexcept; +bool all(T x); template < arithmetic T > -constexpr bool approx(T x, T y) noexcept; +bool approx(T x, T y); template < arithmetic T > -constexpr bool approx(T x, T y, T epsilon) noexcept; +bool approx(T x, T y, T epsilon); template < arithmetic T > -constexpr bool less(T x, T y) noexcept; +bool less(T x, T y); template < arithmetic T > -constexpr bool less_equal(T x, T y) noexcept; +bool less_equal(T x, T y); template < arithmetic T > -constexpr bool greater(T x, T y) noexcept; +bool greater(T x, T y); template < arithmetic T > -constexpr bool greater_equal(T x, T y) noexcept; +bool greater_equal(T x, T y); template < arithmetic T > -constexpr bool equal_to(T x, T y) noexcept; +bool equal_to(T x, T y); template < arithmetic T > -constexpr bool not_equal_to(T x, T y) noexcept; +bool not_equal_to(T x, T y); ``` #### Vector ```cpp -template < typename T, size_t Size > -constexpr bool any(const vec& xs); +template < typename T, size_t Size + , typename U = decltype(any(declval())) > +U any(const vec& xs); -template < typename T, size_t Size > -constexpr bool all(const vec& xs); +template < typename T, size_t Size + , typename U = decltype(all(declval())) > +U all(const vec& xs); -template < typename T, size_t Size > -constexpr vec approx(const vec& xs, const vec& ys); +template < typename T, size_t Size + , typename U = decltype(approx( + declval(), + declval())) > +vec approx(const vec& xs, const vec& ys); -template < typename T, size_t Size > -constexpr vec approx(const vec& xs, const vec& ys, T epsilon); +template < typename T, size_t Size + , typename U = decltype(approx( + declval(), + declval(), + declval())) > +vec approx(const vec& xs, const vec& ys, T epsilon); -template < typename T, size_t Size > -constexpr vec less(const vec& xs, const vec& ys); +template < typename T, size_t Size + , typename U = decltype(less( + declval(), + declval())) > +vec less(const vec& xs, const vec& ys); -template < typename T, size_t Size > -constexpr vec less_equal(const vec& xs, const vec& ys); +template < typename T, size_t Size + , typename U = decltype(less_equal( + declval(), + declval())) > +vec less_equal(const vec& xs, const vec& ys); -template < typename T, size_t Size > -constexpr vec greater(const vec& xs, const vec& ys); +template < typename T, size_t Size + , typename U = decltype(greater( + declval(), + declval())) > +vec greater(const vec& xs, const vec& ys); -template < typename T, size_t Size > -constexpr vec greater_equal(const vec& xs, const vec& ys); +template < typename T, size_t Size + , typename U = decltype(greater_equal( + declval(), + declval())) > +vec greater_equal(const vec& xs, const vec& ys); -template < typename T, size_t Size > -constexpr vec equal_to(const vec& xs, const vec& ys); +template < typename T, size_t Size + , typename U = decltype(equal_to( + declval(), + declval())) > +vec equal_to(const vec& xs, const vec& ys); -template < typename T, size_t Size > -constexpr vec not_equal_to(const vec& xs, const vec& ys); +template < typename T, size_t Size + , typename U = decltype(not_equal_to( + declval(), + declval())) > +vec not_equal_to(const vec& xs, const vec& ys); ``` #### Matrix ```cpp -template < typename T, size_t Size > -constexpr bool any(const mat& xs); +template < typename T, size_t Size + , typename U = decltype(any(declval>())) > +U any(const mat& xs); -template < typename T, size_t Size > -constexpr bool all(const mat& xs); +template < typename T, size_t Size + , typename U = decltype(all(declval>())) > +U all(const mat& xs); -template < typename T, size_t Size > -constexpr mat approx(const mat& xs, const mat& ys); +template < typename T, size_t Size + , typename U = typename decltype(approx( + declval>(), + declval>()))::component_type > +mat approx(const mat& xs, const mat& ys); -template < typename T, size_t Size > -constexpr mat approx(const mat& xs, const mat& ys, T epsilon); +template < typename T, size_t Size + , typename U = typename decltype(approx( + declval>(), + declval>(), + declval()))::component_type > +mat approx(const mat& xs, const mat& ys, T epsilon); -template < typename T, size_t Size > -constexpr mat less(const mat& xs, const mat& ys); +template < typename T, size_t Size + , typename U = typename decltype(less( + declval>(), + declval>()))::component_type > +mat less(const mat& xs, const mat& ys); -template < typename T, size_t Size > -constexpr mat less_equal(const mat& xs, const mat& ys); +template < typename T, size_t Size + , typename U = typename decltype(less_equal( + declval>(), + declval>()))::component_type > +mat less_equal(const mat& xs, const mat& ys); -template < typename T, size_t Size > -constexpr mat greater(const mat& xs, const mat& ys); +template < typename T, size_t Size + , typename U = typename decltype(greater( + declval>(), + declval>()))::component_type > +mat greater(const mat& xs, const mat& ys); -template < typename T, size_t Size > -constexpr mat greater_equal(const mat& xs, const mat& ys); +template < typename T, size_t Size + , typename U = typename decltype(greater_equal( + declval>(), + declval>()))::component_type > +mat greater_equal(const mat& xs, const mat& ys); -template < typename T, size_t Size > -constexpr mat equal_to(const mat& xs, const mat& ys); +template < typename T, size_t Size + , typename U = typename decltype(equal_to( + declval>(), + declval>()))::component_type > +mat equal_to(const mat& xs, const mat& ys); -template < typename T, size_t Size > -constexpr mat not_equal_to(const mat& xs, const mat& ys); +template < typename T, size_t Size + , typename U = typename decltype(not_equal_to( + declval>(), + declval>()))::component_type > +mat not_equal_to(const mat& xs, const mat& ys); ``` #### Quaternion ```cpp -template < typename T > -constexpr vec approx(const qua& xs, const qua& ys); +template < typename T + , typename U = decltype(any(declval>())) > +U any(const qua& xs); -template < typename T > -constexpr vec approx(const qua& xs, const qua& ys, T epsilon); +template < typename T + , typename U = decltype(all(declval>())) > +U all(const qua& xs); -template < typename T > -constexpr vec less(const qua& xs, const qua& ys); +template < typename T + , typename U = typename decltype(approx( + declval>(), + declval>()))::component_type > +vec approx(const qua& xs, const qua& ys); -template < typename T > -constexpr vec less_equal(const qua& xs, const qua& ys); +template < typename T + , typename U = typename decltype(approx( + declval>(), + declval>(), + declval()))::component_type > +vec approx(const qua& xs, const qua& ys, T epsilon); -template < typename T > -constexpr vec greater(const qua& xs, const qua& ys); +template < typename T + , typename U = typename decltype(less( + declval>(), + declval>()))::component_type > +vec less(const qua& xs, const qua& ys); -template < typename T > -constexpr vec greater_equal(const qua& xs, const qua& ys); +template < typename T + , typename U = typename decltype(less_equal( + declval>(), + declval>()))::component_type > +vec less_equal(const qua& xs, const qua& ys); -template < typename T > -constexpr vec equal_to(const qua& xs, const qua& ys); +template < typename T + , typename U = typename decltype(greater( + declval>(), + declval>()))::component_type > +vec greater(const qua& xs, const qua& ys); -template < typename T > -constexpr vec not_equal_to(const qua& xs, const qua& ys); +template < typename T + , typename U = typename decltype(greater_equal( + declval>(), + declval>()))::component_type > +vec greater_equal(const qua& xs, const qua& ys); + +template < typename T + , typename U = typename decltype(equal_to( + declval>(), + declval>()))::component_type > +vec equal_to(const qua& xs, const qua& ys); + +template < typename T + , typename U = typename decltype(not_equal_to( + declval>(), + declval>()))::component_type > +vec not_equal_to(const qua& xs, const qua& ys); ``` ### Matrix Functions ```cpp template < typename T > -constexpr mat transpose(const mat& m); +mat transpose(const mat& m); template < typename T > -constexpr mat transpose(const mat& m); +mat transpose(const mat& m); template < typename T > -constexpr mat transpose(const mat& m); +mat transpose(const mat& m); template < typename T > -constexpr T determinant(const mat& m); +T determinant(const mat& m); template < typename T > -constexpr T determinant(const mat& m); +T determinant(const mat& m); template < typename T > -constexpr T determinant(const mat& m); +T determinant(const mat& m); template < typename T > -constexpr mat inverse(const mat& m); +mat inverse(const mat& m); template < typename T > -constexpr mat inverse(const mat& m); +mat inverse(const mat& m); template < typename T > -constexpr mat inverse(const mat& m); +mat inverse(const mat& m); ``` ### Quaternion Functions ```cpp template < typename T > -constexpr qua conjugate(const qua& q); +qua conjugate(const qua& q); template < typename T > -constexpr qua inverse(const qua& q); +qua inverse(const qua& q); ``` ### Units ```cpp -template < typename T > inline constexpr vec zero2; -template < typename T > inline constexpr vec zero3; -template < typename T > inline constexpr vec zero4; +template < typename T > inline vec zero2; +template < typename T > inline vec zero3; +template < typename T > inline vec zero4; -template < typename T > inline constexpr vec unit2; -template < typename T > inline constexpr vec unit3; -template < typename T > inline constexpr vec unit4; +template < typename T > inline vec unit2; +template < typename T > inline vec unit3; +template < typename T > inline vec unit4; -template < typename T > inline constexpr vec unit2_x; -template < typename T > inline constexpr vec unit2_y; +template < typename T > inline vec unit2_x; +template < typename T > inline vec unit2_y; -template < typename T > inline constexpr vec unit3_x; -template < typename T > inline constexpr vec unit3_y; -template < typename T > inline constexpr vec unit3_z; +template < typename T > inline vec unit3_x; +template < typename T > inline vec unit3_y; +template < typename T > inline vec unit3_z; -template < typename T > inline constexpr vec unit4_x; -template < typename T > inline constexpr vec unit4_y; -template < typename T > inline constexpr vec unit4_z; -template < typename T > inline constexpr vec unit4_w; +template < typename T > inline vec unit4_x; +template < typename T > inline vec unit4_y; +template < typename T > inline vec unit4_z; +template < typename T > inline vec unit4_w; -template < typename T > inline constexpr mat zero2x2; -template < typename T > inline constexpr mat zero3x3; -template < typename T > inline constexpr mat zero4x4; +template < typename T > inline mat zero2x2; +template < typename T > inline mat zero3x3; +template < typename T > inline mat zero4x4; -template < typename T > inline constexpr mat unit2x2; -template < typename T > inline constexpr mat unit3x3; -template < typename T > inline constexpr mat unit4x4; +template < typename T > inline mat unit2x2; +template < typename T > inline mat unit3x3; +template < typename T > inline mat unit4x4; -template < typename T > inline constexpr mat identity2x2; -template < typename T > inline constexpr mat identity3x3; -template < typename T > inline constexpr mat identity4x4; +template < typename T > inline mat identity2x2; +template < typename T > inline mat identity3x3; +template < typename T > inline mat identity4x4; + +template < typename T > inline qua qidentity; ``` ### Cast ```cpp template < arithmetic To, arithmetic From > -constexpr To cast_to(From x) noexcept; +To cast_to(From x); template < typename To, typename From, size_t Size > -constexpr vec cast_to(const vec& v); +vec cast_to(const vec& v); template < typename To, typename From, size_t Size > -constexpr mat cast_to(const mat& m); +mat cast_to(const mat& m); template < typename To, typename From > -constexpr qua cast_to(const qua& q); +qua cast_to(const qua& q); ``` ### Access ```cpp template < typename T, size_t Size > -constexpr T component(const vec& v, size_t index); +T component(const vec& v, size_t index); template < typename T, size_t Size > -constexpr vec component(vec v, size_t index, T x); +vec component(vec v, size_t index, T x); template < typename T, size_t Size > -constexpr vec row(const mat& m, size_t index); +vec row(const mat& m, size_t index); template < typename T, size_t Size > -constexpr mat row(mat m, size_t index, const vec& v); +mat row(mat m, size_t index, const vec& v); template < typename T, size_t Size > -constexpr vec column(const mat& m, size_t index); +vec column(const mat& m, size_t index); template < typename T, size_t Size > -constexpr mat column(const mat& m, size_t index, const vec& v); +mat column(const mat& m, size_t index, const vec& v); template < typename T > -constexpr T real(const qua& q); +T real(const qua& q); template < typename T > -constexpr qua real(qua q, T real); +qua real(qua q, T real); template < typename T > -constexpr vec imag(const qua& q); +vec imag(const qua& q); template < typename T > -constexpr qua imag(qua q, const vec& imag); +qua imag(qua q, const vec& imag); ``` ### Matrix Transform 3D ```cpp template < typename T > -constexpr mat translate(T x, T y, T z); +mat translate(T x, T y, T z); template < typename T > -constexpr mat translate(const mat& m, T x, T y, T z); +mat translate(const mat& m, T x, T y, T z); template < typename T > -constexpr mat translate(const vec& v); +mat translate(const vec& v); template < typename T > -constexpr mat translate(const mat& m, const vec& v); +mat translate(const mat& m, const vec& v); template < typename T > mat rotate(const qua& q); @@ -1700,16 +1792,16 @@ template < typename T > mat rotate_z(const mat& m, T angle); template < typename T > -constexpr mat scale(T x, T y, T z); +mat scale(T x, T y, T z); template < typename T > -constexpr mat scale(const mat& m, T x, T y, T z); +mat scale(const mat& m, T x, T y, T z); template < typename T > -constexpr mat scale(const vec& v); +mat scale(const vec& v); template < typename T > -constexpr mat scale(const mat& m, const vec& v); +mat scale(const mat& m, const vec& v); template < typename T > mat look_at_lh(const vec& eye, const vec& at, const vec& up); @@ -1722,16 +1814,16 @@ mat look_at_rh(const vec& eye, const vec& at, const vec& ```cpp template < typename T > -constexpr mat translate(T x, T y); +mat translate(T x, T y); template < typename T > -constexpr mat translate(const mat& m, T x, T y); +mat translate(const mat& m, T x, T y); template < typename T > -constexpr mat translate(const vec& v); +mat translate(const vec& v); template < typename T > -constexpr mat translate(const mat& m, const vec& v); +mat translate(const mat& m, const vec& v); template < typename T > mat rotate(T angle); @@ -1740,40 +1832,40 @@ template < typename T > mat rotate(const mat& m, T angle); template < typename T > -constexpr mat scale(T x, T y); +mat scale(T x, T y); template < typename T > -constexpr mat scale(const mat& m, T x, T y); +mat scale(const mat& m, T x, T y); template < typename T > -constexpr mat scale(const vec& v); +mat scale(const vec& v); template < typename T > -constexpr mat scale(const mat& m, const vec& v); +mat scale(const mat& m, const vec& v); template < typename T > -constexpr mat shear(T x, T y); +mat shear(T x, T y); template < typename T > -constexpr mat shear(const mat& m, T x, T y); +mat shear(const mat& m, T x, T y); template < typename T > -constexpr mat shear(const vec& v); +mat shear(const vec& v); template < typename T > -constexpr mat shear(const mat& m, const vec& v); +mat shear(const mat& m, const vec& v); template < typename T > -constexpr mat shear_x(T y); +mat shear_x(T y); template < typename T > -constexpr mat shear_x(const mat& m, T y); +mat shear_x(const mat& m, T y); template < typename T > -constexpr mat shear_y(T x); +mat shear_y(T x); template < typename T > -constexpr mat shear_y(const mat& m, T x); +mat shear_y(const mat& m, T x); ``` ### Matrix Projections @@ -1835,10 +1927,10 @@ template < typename T > vec rotate(const vec& v, T angle, const vec& axis); template < typename T, size_t Size > -constexpr vec project(const vec& v, const vec& normal); +vec project(const vec& v, const vec& normal); template < typename T, size_t Size > -constexpr vec perpendicular(const vec& v, const vec& normal); +vec perpendicular(const vec& v, const vec& normal); ``` ### Quaternion Transform diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index a80cfe4..6762382 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -19,37 +19,72 @@ namespace vmath_hpp { - template < typename T > inline constexpr vec zero2{0, 0}; - template < typename T > inline constexpr vec zero3{0, 0, 0}; - template < typename T > inline constexpr vec zero4{0, 0, 0, 0}; + template < typename T > inline constexpr vec zero2{T{0}, T{0}}; + template < typename T > inline constexpr vec zero3{T{0}, T{0}, T{0}}; + template < typename T > inline constexpr vec zero4{T{0}, T{0}, T{0}, T{0}}; - template < typename T > inline constexpr vec unit2{1, 1}; - template < typename T > inline constexpr vec unit3{1, 1, 1}; - template < typename T > inline constexpr vec unit4{1, 1, 1, 1}; + template < typename T > inline constexpr vec unit2{T{1}, T{1}}; + template < typename T > inline constexpr vec unit3{T{1}, T{1}, T{1}}; + template < typename T > inline constexpr vec unit4{T{1}, T{1}, T{1}, T{1}}; - template < typename T > inline constexpr vec unit2_x{1, 0}; - template < typename T > inline constexpr vec unit2_y{0, 1}; + template < typename T > inline constexpr vec unit2_x{T{1}, T{0}}; + template < typename T > inline constexpr vec unit2_y{T{0}, T{1}}; - template < typename T > inline constexpr vec unit3_x{1, 0, 0}; - template < typename T > inline constexpr vec unit3_y{0, 1, 0}; - template < typename T > inline constexpr vec unit3_z{0, 0, 1}; + template < typename T > inline constexpr vec unit3_x{T{1}, T{0}, T{0}}; + template < typename T > inline constexpr vec unit3_y{T{0}, T{1}, T{0}}; + template < typename T > inline constexpr vec unit3_z{T{0}, T{0}, T{1}}; - template < typename T > inline constexpr vec unit4_x{1, 0, 0, 0}; - template < typename T > inline constexpr vec unit4_y{0, 1, 0, 0}; - template < typename T > inline constexpr vec unit4_z{0, 0, 1, 0}; - template < typename T > inline constexpr vec unit4_w{0, 0, 0, 1}; + template < typename T > inline constexpr vec unit4_x{T{1}, T{0}, T{0}, T{0}}; + template < typename T > inline constexpr vec unit4_y{T{0}, T{1}, T{0}, T{0}}; + template < typename T > inline constexpr vec unit4_z{T{0}, T{0}, T{1}, T{0}}; + template < typename T > inline constexpr vec unit4_w{T{0}, T{0}, T{0}, T{1}}; - template < typename T > inline constexpr mat zero2x2{0, 0, 0, 0}; - template < typename T > inline constexpr mat zero3x3{0, 0, 0, 0, 0, 0, 0, 0, 0}; - template < typename T > inline constexpr mat zero4x4{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + template < typename T > inline constexpr mat zero2x2{ + T{0}, T{0}, + T{0}, T{0}}; - template < typename T > inline constexpr mat unit2x2{1, 1, 1, 1}; - template < typename T > inline constexpr mat unit3x3{1, 1, 1, 1, 1, 1, 1, 1, 1}; - template < typename T > inline constexpr mat unit4x4{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + template < typename T > inline constexpr mat zero3x3{ + T{0}, T{0}, T{0}, + T{0}, T{0}, T{0}, + T{0}, T{0}, T{0}}; - template < typename T > inline constexpr mat identity2x2{1, 0, 0, 1}; - template < typename T > inline constexpr mat identity3x3{1, 0, 0, 0, 1, 0, 0, 0, 1}; - template < typename T > inline constexpr mat identity4x4{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; + template < typename T > inline constexpr mat zero4x4{ + T{0}, T{0}, T{0}, T{0}, + T{0}, T{0}, T{0}, T{0}, + T{0}, T{0}, T{0}, T{0}, + T{0}, T{0}, T{0}, T{0}}; + + template < typename T > inline constexpr mat unit2x2{ + T{1}, T{1}, + T{1}, T{1}}; + + template < typename T > inline constexpr mat unit3x3{ + T{1}, T{1}, T{1}, + T{1}, T{1}, T{1}, + T{1}, T{1}, T{1}}; + + template < typename T > inline constexpr mat unit4x4{ + T{1}, T{1}, T{1}, T{1}, + T{1}, T{1}, T{1}, T{1}, + T{1}, T{1}, T{1}, T{1}, + T{1}, T{1}, T{1}, T{1}}; + + template < typename T > inline constexpr mat identity2x2{ + T{1}, T{0}, + T{0}, T{1}}; + + template < typename T > inline constexpr mat identity3x3{ + T{1}, T{0}, T{0}, + T{0}, T{1}, T{0}, + T{0}, T{0}, T{1}}; + + template < typename T > inline constexpr mat identity4x4{ + T{1}, T{0}, T{0}, T{0}, + T{0}, T{1}, T{0}, T{0}, + T{0}, T{0}, T{1}, T{0}, + T{0}, T{0}, T{0}, T{1}}; + + template < typename T > inline constexpr qua qidentity{T{0}, T{0}, T{0}, T{1}}; } // @@ -77,7 +112,7 @@ namespace vmath_hpp::detail template < typename T > [[nodiscard]] std::size_t hash(const qua& q) noexcept { - return hash(vec{q}); + return fold_join(hash_combiner{}, std::size_t{}, q); } } @@ -121,17 +156,17 @@ namespace vmath_hpp template < typename To, typename From, std::size_t Size > [[nodiscard]] constexpr vec cast_to(const vec& v) { - return detail::map_join([](From x){ return cast_to(x); }, v); + return map_join([](From x){ return cast_to(x); }, v); } template < typename To, typename From, std::size_t Size > [[nodiscard]] constexpr mat cast_to(const mat& m) { - return detail::map_join([](const vec& v){ return cast_to(v); }, m); + return map_join([](const vec& v){ return cast_to(v); }, m); } template < typename To, typename From > [[nodiscard]] constexpr qua cast_to(const qua& q) { - return qua(cast_to(vec{q})); + return map_join([](From x){ return cast_to(x); }, q); } } @@ -235,10 +270,10 @@ namespace vmath_hpp /// https://en.wikipedia.org/wiki/Translation_(geometry) return { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {x, y, z, 1}}; + {T{1}, T{0}, T{0}, T{0}}, + {T{0}, T{1}, T{0}, T{0}}, + {T{0}, T{0}, T{1}, T{0}}, + { x, y, z, T{1}}}; } template < typename T > @@ -259,15 +294,15 @@ namespace vmath_hpp // rotate template < typename T > - [[nodiscard]] mat rotate(const qua& q) { + [[nodiscard]] constexpr mat rotate(const qua& q) { /// REFERENCE: /// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/ const auto [qv, qs] = normalize(q); - const T x2 = qv.x * T(2); - const T y2 = qv.y * T(2); - const T z2 = qv.z * T(2); + const T x2 = qv.x * T{2}; + const T y2 = qv.y * T{2}; + const T z2 = qv.z * T{2}; const T sx2 = qs * x2; const T sy2 = qs * y2; @@ -282,19 +317,19 @@ namespace vmath_hpp const T zz2 = qv.z * z2; return { - T(1) - (yy2 + zz2), (xy2 + sz2), (xz2 - sy2), 0, - (xy2 - sz2), T(1) - (xx2 + zz2), (yz2 + sx2), 0, - (xz2 + sy2), (yz2 - sx2), T(1) - (xx2 + yy2), 0, - 0, 0, 0, 1}; + T{1} - (yy2 + zz2), (xy2 + sz2), (xz2 - sy2), T{0}, + (xy2 - sz2), T{1} - (xx2 + zz2), (yz2 + sx2), T{0}, + (xz2 + sy2), (yz2 - sx2), T{1} - (xx2 + yy2), T{0}, + T{0}, T{0}, T{0}, T{1}}; } template < typename T > - [[nodiscard]] mat rotate(const mat& m, const qua& q) { + [[nodiscard]] constexpr mat rotate(const mat& m, const qua& q) { return m * rotate(q); } template < typename T > - [[nodiscard]] mat rotate(T angle, const vec& axis) { + [[nodiscard]] constexpr mat rotate(T angle, const vec& axis) { /// REFERENCE: /// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/ @@ -309,7 +344,7 @@ namespace vmath_hpp const T ys = y * s; const T zs = z * s; - const T ic = T(1) - c; + const T ic = T{1} - c; const T xxm = xx * ic; const T yym = yy * ic; @@ -320,71 +355,71 @@ namespace vmath_hpp const T yzm = y * z * ic; return { - xxm + c, xym + zs, xzm - ys, 0, - xym - zs, yym + c, yzm + xs, 0, - xzm + ys, yzm - xs, zzm + c, 0, - 0, 0, 0, 1}; + xxm + c, xym + zs, xzm - ys, T{0}, + xym - zs, yym + c, yzm + xs, T{0}, + xzm + ys, yzm - xs, zzm + c, T{0}, + T{0}, T{0}, T{0}, T{1}}; } template < typename T > - [[nodiscard]] mat rotate(const mat& m, T angle, const vec& axis) { + [[nodiscard]] constexpr mat rotate(const mat& m, T angle, const vec& axis) { return m * rotate(angle, axis); } template < typename T > - [[nodiscard]] mat rotate_x(T angle) { + [[nodiscard]] constexpr mat rotate_x(T angle) { /// REFERENCE: /// http://www.euclideanspace.com/maths/algebra/matrix/orthogonal/rotation/ const auto [s, c] = sincos(angle); return { - 1, 0, 0, 0, - 0, c, s, 0, - 0, -s, c, 0, - 0, 0, 0, 1}; + T{1}, T{0}, T{0}, T{0}, + T{0}, c, s, T{0}, + T{0}, -s, c, T{0}, + T{0}, T{0}, T{0}, T{1}}; } template < typename T > - [[nodiscard]] mat rotate_x(const mat& m, T angle) { + [[nodiscard]] constexpr mat rotate_x(const mat& m, T angle) { return m * rotate_x(angle); } template < typename T > - [[nodiscard]] mat rotate_y(T angle) { + [[nodiscard]] constexpr mat rotate_y(T angle) { /// REFERENCE: /// http://www.euclideanspace.com/maths/algebra/matrix/orthogonal/rotation/ const auto [s, c] = sincos(angle); return { - c, 0, -s, 0, - 0, 1, 0, 0, - s, 0, c, 0, - 0, 0, 0, 1}; + c, T{0}, -s, T{0}, + T{0}, T{1}, T{0}, T{0}, + s, T{0}, c, T{0}, + T{0}, T{0}, T{0}, T{1}}; } template < typename T > - [[nodiscard]] mat rotate_y(const mat& m, T angle) { + [[nodiscard]] constexpr mat rotate_y(const mat& m, T angle) { return m * rotate_y(angle); } template < typename T > - [[nodiscard]] mat rotate_z(T angle) { + [[nodiscard]] constexpr mat rotate_z(T angle) { /// REFERENCE: /// http://www.euclideanspace.com/maths/algebra/matrix/orthogonal/rotation/ const auto [s, c] = sincos(angle); return { - c, s, 0, 0, - -s, c, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1}; + c, s, T{0}, T{0}, + -s, c, T{0}, T{0}, + T{0}, T{0}, T{1}, T{0}, + T{0}, T{0}, T{0}, T{1}}; } template < typename T > - [[nodiscard]] mat rotate_z(const mat& m, T angle) { + [[nodiscard]] constexpr mat rotate_z(const mat& m, T angle) { return m * rotate_z(angle); } @@ -396,10 +431,10 @@ namespace vmath_hpp /// https://en.wikipedia.org/wiki/Scaling_(geometry) return { - {x, 0, 0, 0}, - {0, y, 0, 0}, - {0, 0, z, 0}, - {0, 0, 0, 1}}; + { x, T{0}, T{0}, T{0}}, + {T{0}, y, T{0}, T{0}}, + {T{0}, T{0}, z, T{0}}, + {T{0}, T{0}, T{0}, T{1}}}; } template < typename T > @@ -420,7 +455,7 @@ namespace vmath_hpp // look_at template < typename T > - [[nodiscard]] mat look_at_lh(const vec& eye, const vec& at, const vec& up) { + [[nodiscard]] constexpr mat look_at_lh(const vec& eye, const vec& at, const vec& up) { /// REFERENCE: /// https://www.euclideanspace.com/maths/algebra/vectors/lookat/ @@ -433,14 +468,14 @@ namespace vmath_hpp const T dz = dot(az, eye); return { - ax.x, ay.x, az.x, 0, - ax.y, ay.y, az.y, 0, - ax.z, ay.z, az.z, 0, - -dx, -dy, -dz, 1}; + ax.x, ay.x, az.x, T{0}, + ax.y, ay.y, az.y, T{0}, + ax.z, ay.z, az.z, T{0}, + -dx, -dy, -dz, T{1}}; } template < typename T > - [[nodiscard]] mat look_at_rh(const vec& eye, const vec& at, const vec& up) { + [[nodiscard]] constexpr mat look_at_rh(const vec& eye, const vec& at, const vec& up) { /// REFERENCE: /// https://www.euclideanspace.com/maths/algebra/vectors/lookat/ @@ -453,10 +488,10 @@ namespace vmath_hpp const T dz = dot(az, eye); return { - ax.x, ay.x, az.x, 0, - ax.y, ay.y, az.y, 0, - ax.z, ay.z, az.z, 0, - -dx, -dy, -dz, 1}; + ax.x, ay.x, az.x, T{0}, + ax.y, ay.y, az.y, T{0}, + ax.z, ay.z, az.z, T{0}, + -dx, -dy, -dz, T{1}}; } } @@ -474,9 +509,9 @@ namespace vmath_hpp /// https://en.wikipedia.org/wiki/Translation_(geometry) return { - {1, 0, 0}, - {0, 1, 0}, - {x, y, 1}}; + {T{1}, T{0}, T{0}}, + {T{0}, T{1}, T{0}}, + { x, y, T{1}}}; } template < typename T > @@ -497,20 +532,20 @@ namespace vmath_hpp // rotate template < typename T > - [[nodiscard]] mat rotate(T angle) { + [[nodiscard]] constexpr mat rotate(T angle) { /// REFERENCE: /// http://www.euclideanspace.com/maths/algebra/matrix/orthogonal/rotation/ const auto [s, c] = sincos(angle); return { - c, s, 0, - -s, c, 0, - 0, 0, 1}; + c, s, T{0}, + -s, c, T{0}, + T{0}, T{0}, T{1}}; } template < typename T > - [[nodiscard]] mat rotate(const mat& m, T angle) { + [[nodiscard]] constexpr mat rotate(const mat& m, T angle) { return m * rotate(angle); } @@ -522,9 +557,9 @@ namespace vmath_hpp /// https://en.wikipedia.org/wiki/Scaling_(geometry) return { - {x, 0, 0}, - {0, y, 0}, - {0, 0, 1}}; + { x, T{0}, T{0}}, + {T{0}, y, T{0}}, + {T{0}, T{0}, T{1}}}; } template < typename T > @@ -550,9 +585,9 @@ namespace vmath_hpp /// https://en.wikipedia.org/wiki/Shear_matrix return { - {1, y, 0}, - {x, 1, 0}, - {0, 0, 1}}; + {T{1}, y, T{0}}, + { x, T{1}, T{0}}, + {T{0}, T{0}, T{1}}}; } template < typename T > @@ -576,9 +611,9 @@ namespace vmath_hpp /// https://en.wikipedia.org/wiki/Shear_matrix return { - {1, 0, 0}, - {x, 1, 0}, - {0, 0, 1}}; + {T{1}, T{0}, T{0}}, + { x, T{1}, T{0}}, + {T{0}, T{0}, T{1}}}; } template < typename T > @@ -592,9 +627,9 @@ namespace vmath_hpp /// https://en.wikipedia.org/wiki/Shear_matrix return { - {1, y, 0}, - {0, 1, 0}, - {0, 0, 1}}; + {T{1}, y, T{0}}, + {T{0}, T{1}, T{0}}, + {T{0}, T{0}, T{1}}}; } template < typename T > @@ -612,7 +647,7 @@ namespace vmath_hpp // orthographic template < typename T > - [[nodiscard]] mat orthographic_lh(T width, T height, T znear, T zfar) { + [[nodiscard]] constexpr mat orthographic_lh(T width, T height, T znear, T zfar) { /// REFERENCE: /// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixortholh @@ -620,20 +655,20 @@ namespace vmath_hpp const T rheight = rcp(height); const T frange = rcp(zfar - znear); - const T sx = T(2) * rwidth; - const T sy = T(2) * rheight; + const T sx = T{2} * rwidth; + const T sy = T{2} * rheight; const T sz = frange; const T tz = -frange * znear; return { - sx, 0, 0, 0, - 0, sy, 0, 0, - 0, 0, sz, 0, - 0, 0, tz, 1}; + sx, T{0}, T{0}, T{0}, + T{0}, sy, T{0}, T{0}, + T{0}, T{0}, sz, T{0}, + T{0}, T{0}, tz, T{1}}; } template < typename T > - [[nodiscard]] mat orthographic_rh(T width, T height, T znear, T zfar) { + [[nodiscard]] constexpr mat orthographic_rh(T width, T height, T znear, T zfar) { /// REFERENCE: /// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthorh @@ -641,20 +676,20 @@ namespace vmath_hpp const T rheight = rcp(height); const T frange = rcp(znear - zfar); - const T sx = T(2) * rwidth; - const T sy = T(2) * rheight; + const T sx = T{2} * rwidth; + const T sy = T{2} * rheight; const T sz = frange; const T tz = frange * znear; return { - sx, 0, 0, 0, - 0, sy, 0, 0, - 0, 0, sz, 0, - 0, 0, tz, 1}; + sx, T{0}, T{0}, T{0}, + T{0}, sy, T{0}, T{0}, + T{0}, T{0}, sz, T{0}, + T{0}, T{0}, tz, T{1}}; } template < typename T > - [[nodiscard]] mat orthographic_lh(T left, T right, T bottom, T top, T znear, T zfar) { + [[nodiscard]] constexpr mat orthographic_lh(T left, T right, T bottom, T top, T znear, T zfar) { /// REFERENCE: /// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterlh @@ -663,14 +698,14 @@ namespace vmath_hpp const T frange = rcp(zfar - znear); return { - T(2) * rwidth, 0, 0, 0, - 0, T(2) * rheight, 0, 0, - 0, 0, frange, 0, - -(left + right) * rwidth, -(top + bottom) * rheight, -frange * znear, 1}; + T{2} * rwidth, T{0}, T{0}, T{0}, + T{0}, T{2} * rheight, T{0}, T{0}, + T{0}, T{0}, frange, T{0}, + -(left + right) * rwidth, -(top + bottom) * rheight, -frange * znear, T{1}}; } template < typename T > - [[nodiscard]] mat orthographic_rh(T left, T right, T bottom, T top, T znear, T zfar) { + [[nodiscard]] constexpr mat orthographic_rh(T left, T right, T bottom, T top, T znear, T zfar) { /// REFERENCE: /// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterrh @@ -679,113 +714,113 @@ namespace vmath_hpp const T frange = rcp(znear - zfar); return { - T(2) * rwidth, 0, 0, 0, - 0, T(2) * rheight, 0, 0, - 0, 0, frange, 0, - -(left + right) * rwidth, -(top + bottom) * rheight, frange * znear, 1}; + T{2} * rwidth, T{0}, T{0}, T{0}, + T{0}, T{2} * rheight, T{0}, T{0}, + T{0}, T{0}, frange, T{0}, + -(left + right) * rwidth, -(top + bottom) * rheight, frange * znear, T{1}}; } // perspective template < typename T > - [[nodiscard]] mat perspective_lh(T width, T height, T znear, T zfar) { + [[nodiscard]] constexpr mat perspective_lh(T width, T height, T znear, T zfar) { /// REFERENCE: /// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivelh - const T sx = T(2) * znear * rcp(width); - const T sy = T(2) * znear * rcp(height); + const T sx = T{2} * znear * rcp(width); + const T sy = T{2} * znear * rcp(height); const T sz = zfar * rcp(zfar - znear); const T tz = (znear * zfar) * rcp(znear - zfar); return { - sx, 0, 0, 0, - 0, sy, 0, 0, - 0, 0, sz, 1, - 0, 0, tz, 0}; + T{sx}, T{0}, T{0}, T{0}, + T{0}, T{sy}, T{0}, T{0}, + T{0}, T{0}, T{sz}, T{1}, + T{0}, T{0}, T{tz}, T{0}}; } template < typename T > - [[nodiscard]] mat perspective_rh(T width, T height, T znear, T zfar) { + [[nodiscard]] constexpr mat perspective_rh(T width, T height, T znear, T zfar) { /// REFERENCE: /// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectiverh - const T sx = T(2) * znear * rcp(width); - const T sy = T(2) * znear * rcp(height); + const T sx = T{2} * znear * rcp(width); + const T sy = T{2} * znear * rcp(height); const T sz = zfar * rcp(znear - zfar); const T tz = (znear * zfar) * rcp(znear - zfar); return { - sx, 0, 0, 0, - 0, sy, 0, 0, - 0, 0, sz, -1, - 0, 0, tz, 0}; + sx, T{0}, T{0}, T{0}, + T{0}, sy, T{0}, T{0}, + T{0}, T{0}, sz, -T{1}, + T{0}, T{0}, tz, T{0}}; } template < typename T > - [[nodiscard]] mat perspective_lh(T left, T right, T bottom, T top, T znear, T zfar) { + [[nodiscard]] constexpr mat perspective_lh(T left, T right, T bottom, T top, T znear, T zfar) { /// REFERENCE: /// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectiveoffcenterlh - const T znear2 = T(2) * znear; + const T znear2 = T{2} * znear; const T rwidth = rcp(right - left); const T rheight = rcp(top - bottom); const T frange = zfar * rcp(zfar - znear); return { - znear2 * rwidth, 0, 0, 0, - 0, znear2 * rheight, 0, 0, - -(left + right) * rwidth, -(top + bottom) * rheight, frange, 1, - 0, 0, -frange * znear, 0}; + znear2 * rwidth, T{0}, T{0}, T{0}, + T{0}, znear2 * rheight, T{0}, T{0}, + -(left + right) * rwidth, -(top + bottom) * rheight, frange, T{1}, + T{0}, T{0}, -frange * znear, T{0}}; } template < typename T > - [[nodiscard]] mat perspective_rh(T left, T right, T bottom, T top, T znear, T zfar) { + [[nodiscard]] constexpr mat perspective_rh(T left, T right, T bottom, T top, T znear, T zfar) { /// REFERENCE: /// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectiveoffcenterrh - const T znear2 = T(2) * znear; + const T znear2 = T{2} * znear; const T rwidth = rcp(right - left); const T rheight = rcp(top - bottom); const T frange = zfar * rcp(znear - zfar); return { - znear2 * rwidth, 0, 0, 0, - 0, znear2 * rheight, 0, 0, - (left + right) * rwidth, (top + bottom) * rheight, frange, -1, - 0, 0, frange * znear, 0}; + znear2 * rwidth, T{0}, T{0}, T{0}, + T{0}, znear2 * rheight, T{0}, T{0}, + (left + right) * rwidth, (top + bottom) * rheight, frange, -T{1}, + T{0}, T{0}, frange * znear, T{0}}; } template < typename T > - [[nodiscard]] mat perspective_fov_lh(T fovy, T aspect, T znear, T zfar) { + [[nodiscard]] constexpr mat perspective_fov_lh(T fovy, T aspect, T znear, T zfar) { /// REFERENCE: /// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovlh - const T sy = rcp(tan(fovy * T(0.5))); + const T sy = rcp(tan(fovy * T{0.5f})); const T sx = sy * rcp(aspect); const T sz = zfar * rcp(zfar - znear); const T tz = (znear * zfar) * rcp(znear - zfar); return { - sx, 0, 0, 0, - 0, sy, 0, 0, - 0, 0, sz, 1, - 0, 0, tz, 0}; + sx, T{0}, T{0}, T{0}, + T{0}, sy, T{0}, T{0}, + T{0}, T{0}, sz, T{1}, + T{0}, T{0}, tz, T{0}}; } template < typename T > - [[nodiscard]] mat perspective_fov_rh(T fovy, T aspect, T znear, T zfar) { + [[nodiscard]] constexpr mat perspective_fov_rh(T fovy, T aspect, T znear, T zfar) { /// REFERENCE: /// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovrh - const T sy = rcp(tan(fovy * T(0.5))); + const T sy = rcp(tan(fovy * T{0.5f})); const T sx = sy * rcp(aspect); const T sz = zfar * rcp(znear - zfar); const T tz = (znear * zfar) * rcp(znear - zfar); return { - sx, 0, 0, 0, - 0, sy, 0, 0, - 0, 0, sz, -1, - 0, 0, tz, 0}; + sx, T{0}, T{0}, T{0}, + T{0}, sy, T{0}, T{0}, + T{0}, T{0}, sz, -T{1}, + T{0}, T{0}, tz, T{0}}; } } @@ -798,15 +833,15 @@ namespace vmath_hpp // angle template < typename T, std::size_t Size > - [[nodiscard]] T angle(const vec& x, const vec& y) { + [[nodiscard]] constexpr T angle(const vec& x, const vec& y) { const T rs = rsqrt(length2(x) * length2(y)); - return acos(clamp(dot(x, y) * rs, T(-1), T(1))); + return acos(clamp(dot(x, y) * rs, -T{1}, T{1})); } // rotate template < typename T > - [[nodiscard]] vec rotate(const vec& v, T angle) { + [[nodiscard]] constexpr vec rotate(const vec& v, T angle) { const auto [s, c] = sincos(angle); return { v.x * c - v.y * s, @@ -814,27 +849,27 @@ namespace vmath_hpp } template < typename T > - [[nodiscard]] vec rotate_x(const vec& v, T angle) { + [[nodiscard]] constexpr vec rotate_x(const vec& v, T angle) { return v * qrotate(angle, unit3_x); } template < typename T > - [[nodiscard]] vec rotate_y(const vec& v, T angle) { + [[nodiscard]] constexpr vec rotate_y(const vec& v, T angle) { return v * qrotate(angle, unit3_y); } template < typename T > - [[nodiscard]] vec rotate_z(const vec& v, T angle) { + [[nodiscard]] constexpr vec rotate_z(const vec& v, T angle) { return v * qrotate(angle, unit3_z); } template < typename T > - [[nodiscard]] vec rotate(const vec& v, const qua& q) { + [[nodiscard]] constexpr vec rotate(const vec& v, const qua& q) { return v * q; } template < typename T > - [[nodiscard]] vec rotate(const vec& v, T angle, const vec& axis) { + [[nodiscard]] constexpr vec rotate(const vec& v, T angle, const vec& axis) { return v * qrotate(angle, axis); } @@ -842,7 +877,7 @@ namespace vmath_hpp template < typename T, std::size_t Size > [[nodiscard]] constexpr vec project(const vec& v, const vec& normal) { - return dot(v, normal) * rcp(length2(normal)) * normal; + return dot(v, normal) * rlength2(normal) * normal; } // perpendicular @@ -862,115 +897,115 @@ namespace vmath_hpp // qrotate template < typename T > - [[nodiscard]] qua qrotate(const mat& m) { + [[nodiscard]] constexpr qua qrotate(const mat& m) { /// REFERENCE: /// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ - auto xyzw = T(0.5) * sqrt(max(T(0), vec{ - T(1) + m[0][0] - m[1][1] - m[2][2], - T(1) - m[0][0] + m[1][1] - m[2][2], - T(1) - m[0][0] - m[1][1] + m[2][2], - T(1) + m[0][0] + m[1][1] + m[2][2]})); + auto xyzw = T{0.5f} * sqrt(max(T{0}, vec{ + T{1} + m[0][0] - m[1][1] - m[2][2], + T{1} - m[0][0] + m[1][1] - m[2][2], + T{1} - m[0][0] - m[1][1] + m[2][2], + T{1} + m[0][0] + m[1][1] + m[2][2]})); return qua(copysign(xyzw, { m[1][2] - m[2][1], m[2][0] - m[0][2], m[0][1] - m[1][0], - T(1)})); + T{1}})); } template < typename T > - [[nodiscard]] qua qrotate(const qua& q, const mat& m) { + [[nodiscard]] constexpr qua qrotate(const qua& q, const mat& m) { return q * qrotate(m); } template < typename T > - [[nodiscard]] qua qrotate(const vec& from, const vec& to) { + [[nodiscard]] constexpr qua qrotate(const vec& from, const vec& to) { /// REFERENCE: /// http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final const T n = sqrt(length2(from) * length2(to)); const T s = dot(from, to) + n; - if ( s < T(0.000001) * n ) { - return abs(from.x) > abs(from.z) - ? normalize(qua{vec{-from.y, from.x, T(0)}, T(0)}) - : normalize(qua{vec{T(0), -from.z, from.y}, T(0)}); + if ( s < T{0.000001f} * n ) { + return abs(from.z) < abs(from.x) + ? normalize(qua{vec{-from.y, from.x, T{0}}, T{0}}) + : normalize(qua{vec{T{0}, -from.z, from.y}, T{0}}); } return normalize(qua{cross(from, to), s}); } template < typename T > - [[nodiscard]] qua qrotate(const qua& q, const vec& from, const vec& to) { + [[nodiscard]] constexpr qua qrotate(const qua& q, const vec& from, const vec& to) { return q * qrotate(from, to); } template < typename T > - [[nodiscard]] qua qrotate(T angle, const vec& axis) { + [[nodiscard]] constexpr qua qrotate(T angle, const vec& axis) { /// REFERENCE: /// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/ - const auto [s, c] = sincos(angle * T(0.5)); + const auto [s, c] = sincos(angle * T{0.5f}); const auto [x, y, z] = normalize(axis); - return {vec{x,y,z} * s, c}; + return {vec{x, y, z} * s, c}; } template < typename T > - [[nodiscard]] qua qrotate(const qua& q, T angle, const vec& axis) { + [[nodiscard]] constexpr qua qrotate(const qua& q, T angle, const vec& axis) { return q * qrotate(angle, axis); } template < typename T > - [[nodiscard]] qua qrotate_x(T angle) { + [[nodiscard]] constexpr qua qrotate_x(T angle) { /// REFERENCE: /// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/ - const auto [s, c] = sincos(angle * T(0.5)); + const auto [s, c] = sincos(angle * T{0.5f}); - return {s, T(0), T(0), c}; + return {vec{s, T{0}, T{0}}, c}; } template < typename T > - [[nodiscard]] qua qrotate_x(const qua& q, T angle) { + [[nodiscard]] constexpr qua qrotate_x(const qua& q, T angle) { return qrotate(q, angle, unit3_x); } template < typename T > - [[nodiscard]] qua qrotate_y(T angle) { + [[nodiscard]] constexpr qua qrotate_y(T angle) { /// REFERENCE: /// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/ - const auto [s, c] = sincos(angle * T(0.5)); + const auto [s, c] = sincos(angle * T{0.5f}); - return {T(0), s, T(0), c}; + return {vec{T{0}, s, T{0}}, c}; } template < typename T > - [[nodiscard]] qua qrotate_y(const qua& q, T angle) { + [[nodiscard]] constexpr qua qrotate_y(const qua& q, T angle) { return qrotate(q, angle, unit3_y); } template < typename T > - [[nodiscard]] qua qrotate_z(T angle) { + [[nodiscard]] constexpr qua qrotate_z(T angle) { /// REFERENCE: /// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/ - const auto [s, c] = sincos(angle * T(0.5)); + const auto [s, c] = sincos(angle * T{0.5f}); - return {T(0), T(0), s, c}; + return {vec{T{0}, T{0}, s}, c}; } template < typename T > - [[nodiscard]] qua qrotate_z(const qua& q, T angle) { + [[nodiscard]] constexpr qua qrotate_z(const qua& q, T angle) { return qrotate(q, angle, unit3_z); } // look_at template < typename T > - [[nodiscard]] qua qlook_at_lh(const vec& dir, const vec& up) { + [[nodiscard]] constexpr qua qlook_at_lh(const vec& dir, const vec& up) { /// REFERENCE: /// https://www.euclideanspace.com/maths/algebra/vectors/lookat/ @@ -985,7 +1020,7 @@ namespace vmath_hpp } template < typename T > - [[nodiscard]] qua qlook_at_rh(const vec& dir, const vec& up) { + [[nodiscard]] constexpr qua qlook_at_rh(const vec& dir, const vec& up) { /// REFERENCE: /// https://www.euclideanspace.com/maths/algebra/vectors/lookat/ diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index ad675d2..8da26fc 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -15,15 +15,13 @@ namespace vmath_hpp { template < typename T > - [[nodiscard]] std::enable_if_t, T> + [[nodiscard]] std::enable_if_t, T> constexpr abs(T x) noexcept { - return x >= T(0) ? x : -x; - } - - template < typename T > - [[nodiscard]] std::enable_if_t, T> - constexpr abs(T x) noexcept { - return x; + if constexpr ( std::is_signed_v ) { + return x < T{0} ? -x : x; + } else { + return x; + } } template < typename T > @@ -35,13 +33,13 @@ namespace vmath_hpp template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr sign(T x) noexcept { - return static_cast((T(0) < x) - (x < T(0))); + return static_cast((T{0} < x) - (x < T{0})); } template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr rcp(T x) noexcept { - return T(1) / x; + return T{1} / x; } template < typename T > @@ -113,13 +111,13 @@ namespace vmath_hpp template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr saturate(T x) noexcept { - return clamp(x, T(0), T(1)); + return clamp(x, T{0}, T{1}); } template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr lerp(T x, T y, T a) noexcept { - return x * (T(1) - a) + y * a; + return x * (T{1} - a) + y * a; } template < typename T > @@ -131,50 +129,14 @@ namespace vmath_hpp template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr step(T edge, T x) noexcept { - return x < edge ? T(0) : T(1); + return x < edge ? T{0} : T{1}; } template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr smoothstep(T edge0, T edge1, T x) noexcept { - const T t = clamp((x - edge0) * rcp(edge1 - edge0), T(0), T(1)); - return t * t * (T(3) - T(2) * t); - } - - template < typename T > - [[nodiscard]] std::enable_if_t, bool> - isnan(T x) noexcept { - return std::isnan(x); - } - - template < typename T > - [[nodiscard]] std::enable_if_t, bool> - isinf(T x) noexcept { - return std::isinf(x); - } - - template < typename T > - [[nodiscard]] std::enable_if_t, bool> - isfinite(T x) noexcept { - return std::isfinite(x); - } - - template < typename T > - [[nodiscard]] std::enable_if_t, T> - fma(T x, T y, T z) noexcept { - return std::fma(x, y, z); - } - - template < typename T > - [[nodiscard]] std::enable_if_t, T> - frexp(T x, int* exp) noexcept { - return std::frexp(x, exp); - } - - template < typename T > - [[nodiscard]] std::enable_if_t, T> - ldexp(T x, int exp) noexcept { - return std::ldexp(x, exp); + const T t = clamp((x - edge0) * rcp(edge1 - edge0), T{0}, T{1}); + return t * t * (T{3} - T{2} * t); } } @@ -355,12 +317,24 @@ namespace vmath_hpp return abs(x); } + template < typename T > + [[nodiscard]] std::enable_if_t, T> + constexpr rlength(T x) noexcept { + return rcp(abs(x)); + } + template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr length2(T x) noexcept { return dot(x, x); } + template < typename T > + [[nodiscard]] std::enable_if_t, T> + constexpr rlength2(T x) noexcept { + return rcp(dot(x, x)); + } + template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr distance(T x, T y) noexcept { @@ -375,28 +349,28 @@ namespace vmath_hpp template < typename T > [[nodiscard]] std::enable_if_t, T> - normalize(T x) noexcept { - return x * rsqrt(length2(x)); + constexpr normalize(T x) noexcept { + return x * rlength(x); } template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr faceforward(T n, T i, T nref) noexcept { - return dot(nref, i) < T(0) ? n : -n; + return dot(nref, i) < T{0} ? n : -n; } template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr reflect(T i, T n) noexcept { - return i - n * dot(n, i) * T(2); + return i - T{2} * dot(n, i) * n; } template < typename T > [[nodiscard]] std::enable_if_t, T> refract(T i, T n, T eta) noexcept { const T d = dot(n, i); - const T k = T(1) - eta * eta * (T(1) - d * d); - return T(k >= T(0)) * (eta * i - (eta * d + sqrt(k)) * n); + const T k = T{1} - sqr(eta) * (T{1} - sqr(d)); + return k < T{0} ? T{0} : (eta * i - (eta * d + sqrt(k)) * n); } } @@ -425,7 +399,7 @@ namespace vmath_hpp /// REFERENCE: /// http://www.realtimecollisiondetection.net/pubs/Tolerances const T epsilon = std::numeric_limits::epsilon(); - return abs(x - y) <= epsilon * max(max(T(1), abs(x)), abs(y)); + return abs(x - y) <= epsilon * max(max(T{1}, abs(x)), abs(y)); } else { return x == y; } @@ -437,7 +411,7 @@ namespace vmath_hpp if constexpr ( std::is_floating_point_v ) { /// REFERENCE: /// http://www.realtimecollisiondetection.net/pubs/Tolerances - return abs(x - y) <= epsilon * max(max(T(1), abs(x)), abs(y)); + return abs(x - y) <= epsilon * max(max(T{1}, abs(x)), abs(y)); } else { return abs(x - y) <= epsilon; } diff --git a/headers/vmath.hpp/vmath_mat.hpp b/headers/vmath.hpp/vmath_mat.hpp index c176340..42bbba8 100644 --- a/headers/vmath.hpp/vmath_mat.hpp +++ b/headers/vmath.hpp/vmath_mat.hpp @@ -20,21 +20,22 @@ namespace vmath_hpp::detail class mat_base { public: using row_type = vec; + row_type rows[2] = { - {1, 0}, - {0, 1}}; + row_type{T{1}, T{0}}, + row_type{T{0}, T{1}}}; public: constexpr mat_base() = default; constexpr explicit mat_base(T d) : rows{ - row_type{d, 0}, - row_type{0, d}} {} + row_type{d, T{0}}, + row_type{T{0}, d}} {} constexpr explicit mat_base(const row_type& d) : rows{ - row_type{d[0], 0}, - row_type{0, d[1]}} {} + row_type{d[0], T{0}}, + row_type{T{0}, d[1]}} {} constexpr mat_base( T m11, T m12, @@ -47,42 +48,31 @@ namespace vmath_hpp::detail const row_type& row0, const row_type& row1) : rows{row0, row1} {} - - constexpr explicit mat_base( - const mat_base& other) - : rows{ - row_type{other.rows[0]}, - row_type{other.rows[1]}} {} - - constexpr explicit mat_base( - const mat_base& other) - : rows{ - row_type{other.rows[0]}, - row_type{other.rows[1]}} {} }; template < typename T > class mat_base { public: using row_type = vec; + row_type rows[3] = { - {1, 0, 0}, - {0, 1, 0}, - {0, 0, 1}}; + row_type{T{1}, T{0}, T{0}}, + row_type{T{0}, T{1}, T{0}}, + row_type{T{0}, T{0}, T{1}}}; public: constexpr mat_base() = default; constexpr explicit mat_base(T d) : rows{ - row_type{d, 0, 0}, - row_type{0, d, 0}, - row_type{0, 0, d}} {} + row_type{d, T{0}, T{0}}, + row_type{T{0}, d, T{0}}, + row_type{T{0}, T{0}, d}} {} constexpr explicit mat_base(const row_type& d) : rows{ - row_type{d[0], 0, 0}, - row_type{0, d[1], 0}, - row_type{0, 0, d[2]}} {} + row_type{d[0], T{0}, T{0}}, + row_type{T{0}, d[1], T{0}}, + row_type{T{0}, T{0}, d[2]}} {} constexpr mat_base( T m11, T m12, T m13, @@ -103,50 +93,50 @@ namespace vmath_hpp::detail const mat_base& m, const vec_base& v) : rows{ - row_type{m.rows[0], 0}, - row_type{m.rows[1], 0}, - row_type{v, 1}} {} + row_type{m.rows[0], T{0}}, + row_type{m.rows[1], T{0}}, + row_type{v, T{1}}} {} constexpr explicit mat_base( const mat_base& other) : rows{ - row_type{other.rows[0], 0}, - row_type{other.rows[1], 0}, - row_type{0, 0, 1}} {} + row_type{other.rows[0], T{0}}, + row_type{other.rows[1], T{0}}, + row_type{T{0}, T{0}, T{1}}} {} - constexpr explicit mat_base( - const mat_base& other) - : rows{ - row_type{other.rows[0]}, - row_type{other.rows[1]}, - row_type{other.rows[2]}} {} + constexpr explicit operator mat() const { + return { + vec{rows[0]}, + vec{rows[1]}}; + } }; template < typename T > class mat_base { public: using row_type = vec; + row_type rows[4] = { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}}; + row_type{T{1}, T{0}, T{0}, T{0}}, + row_type{T{0}, T{1}, T{0}, T{0}}, + row_type{T{0}, T{0}, T{1}, T{0}}, + row_type{T{0}, T{0}, T{0}, T{1}}}; public: constexpr mat_base() = default; constexpr explicit mat_base(T d) : rows{ - row_type{d, 0, 0, 0}, - row_type{0, d, 0, 0}, - row_type{0, 0, d, 0}, - row_type{0, 0, 0, d}} {} + row_type{d, T{0}, T{0}, T{0}}, + row_type{T{0}, d, T{0}, T{0}}, + row_type{T{0}, T{0}, d, T{0}}, + row_type{T{0}, T{0}, T{0}, d}} {} constexpr explicit mat_base(const row_type& d) : rows{ - row_type{d[0], 0, 0, 0}, - row_type{0, d[1], 0, 0}, - row_type{0, 0, d[2], 0}, - row_type{0, 0, 0, d[3]}} {} + row_type{d[0], T{0}, T{0}, T{0}}, + row_type{T{0}, d[1], T{0}, T{0}}, + row_type{T{0}, T{0}, d[2], T{0}}, + row_type{T{0}, T{0}, T{0}, d[3]}} {} constexpr mat_base( T m11, T m12, T m13, T m14, @@ -170,26 +160,39 @@ namespace vmath_hpp::detail const mat_base& m, const vec_base& v) : rows{ - row_type{m.rows[0], 0}, - row_type{m.rows[1], 0}, - row_type{m.rows[2], 0}, - row_type{v, 1}} {} + row_type{m.rows[0], T{0}}, + row_type{m.rows[1], T{0}}, + row_type{m.rows[2], T{0}}, + row_type{v, T{1}}} {} constexpr explicit mat_base( const mat_base& other) : rows{ - row_type{other.rows[0], 0, 0}, - row_type{other.rows[1], 0, 0}, - row_type{0, 0, 1, 0}, - row_type{0, 0, 0, 1}} {} + row_type{other.rows[0], T{0}, T{0}}, + row_type{other.rows[1], T{0}, T{0}}, + row_type{T{0}, T{0}, T{1}, T{0}}, + row_type{T{0}, T{0}, T{0}, T{1}}} {} constexpr explicit mat_base( const mat_base& other) : rows{ - row_type{other.rows[0], 0}, - row_type{other.rows[1], 0}, - row_type{other.rows[2], 0}, - row_type{0, 0, 0, 1}} {} + row_type{other.rows[0], T{0}}, + row_type{other.rows[1], T{0}}, + row_type{other.rows[2], T{0}}, + row_type{T{0}, T{0}, T{0}, T{1}}} {} + + constexpr explicit operator mat() const { + return { + vec{rows[0]}, + vec{rows[1]}}; + } + + constexpr explicit operator mat() const { + return { + vec{rows[0]}, + vec{rows[1]}, + vec{rows[2]}}; + } }; } @@ -200,7 +203,8 @@ namespace vmath_hpp public: using self_type = mat; using base_type = detail::mat_base; - public: + using component_type = T; + using row_type = vec; using pointer = row_type*; @@ -214,7 +218,7 @@ namespace vmath_hpp using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - static constexpr std::size_t size = Size; + static inline constexpr std::size_t size = Size; public: using base_type::mat_base; using base_type::rows; @@ -253,14 +257,6 @@ namespace vmath_hpp return &rows[0]; } - [[nodiscard]] constexpr reference operator[](std::size_t index) noexcept { - return rows[index]; - } - - [[nodiscard]] constexpr const_reference operator[](std::size_t index) const noexcept { - return rows[index]; - } - [[nodiscard]] constexpr reference at(std::size_t index) { VMATH_HPP_THROW_IF(index >= size, std::out_of_range("mat::at")); return rows[index]; @@ -270,6 +266,14 @@ namespace vmath_hpp VMATH_HPP_THROW_IF(index >= size, std::out_of_range("mat::at")); return rows[index]; } + + [[nodiscard]] constexpr reference operator[](std::size_t index) noexcept { + return rows[index]; + } + + [[nodiscard]] constexpr const_reference operator[](std::size_t index) const noexcept { + return rows[index]; + } }; } diff --git a/headers/vmath.hpp/vmath_mat_fun.hpp b/headers/vmath.hpp/vmath_mat_fun.hpp index 3dc1eda..b44b485 100644 --- a/headers/vmath.hpp/vmath_mat_fun.hpp +++ b/headers/vmath.hpp/vmath_mat_fun.hpp @@ -18,88 +18,94 @@ namespace vmath_hpp::detail::impl { template < typename A, std::size_t Size, typename F, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join_impl( + mat + >::component_type, Size> + map_join_impl( F&& f, const mat& a, - std::index_sequence - ) -> mat>()))::component_type, Size> + std::index_sequence) { return { f(a[Is])... }; } template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join_impl( + mat, + vec + >::component_type, Size> + map_join_impl( F&& f, const mat& a, const mat& b, - std::index_sequence - ) -> mat>(), - std::declval>()))::component_type, Size> + std::index_sequence) { return { f(a[Is], b[Is])... }; } template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join_impl( + mat, + vec, + vec + >::component_type, Size> + map_join_impl( F&& f, const mat& a, const mat& b, const mat& c, - std::index_sequence - ) -> mat>(), - std::declval>(), - std::declval>()))::component_type, Size> + std::index_sequence) { return { f(a[Is], b[Is], c[Is])... }; } template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold_join_impl( + A fold_join_impl( F&& f, A init, const mat& b, - std::index_sequence - ) -> A { + std::index_sequence) + { return ((init = f(std::move(init), b[Is])), ...); } template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold_join_impl( + A fold_join_impl( F&& f, A init, const vec& b, const mat& c, - std::index_sequence - ) -> A { + std::index_sequence) + { return ((init = f(std::move(init), b[Is], c[Is])), ...); } template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold_join_impl( + A fold_join_impl( F&& f, A init, const mat& b, const mat& c, - std::index_sequence - ) -> A { + std::index_sequence) + { return ((init = f(std::move(init), b[Is], c[Is])), ...); } template < typename A, std::size_t Size, typename F, std::size_t I, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold1_join_impl( + vec fold1_join_impl( F&& f, const mat& a, - std::index_sequence - ) -> vec { + std::index_sequence) + { vec init = a[I]; return ((init = f(std::move(init), a[Is])), ...); } @@ -109,80 +115,44 @@ namespace vmath_hpp::detail { template < typename A, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join( - F&& f, - const mat& a - ) { - return impl::map_join_impl( - std::forward(f), a, std::make_index_sequence{}); + auto map_join(F&& f, const mat& a) { + return impl::map_join_impl(std::forward(f), a, std::make_index_sequence{}); } template < typename A, typename B, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join( - F&& f, - const mat& a, - const mat& b - ) { - return impl::map_join_impl( - std::forward(f), a, b, std::make_index_sequence{}); + auto map_join(F&& f, const mat& a, const mat& b) { + return impl::map_join_impl(std::forward(f), a, b, std::make_index_sequence{}); } template < typename A, typename B, typename C, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join( - F&& f, - const mat& a, - const mat& b, - const mat& c - ) { - return impl::map_join_impl( - std::forward(f), a, b, c, std::make_index_sequence{}); + auto map_join(F&& f, const mat& a, const mat& b, const mat& c) { + return impl::map_join_impl(std::forward(f), a, b, c, std::make_index_sequence{}); } template < typename A, typename B, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold_join( - F&& f, - A init, - const mat& b - ) { - return impl::fold_join_impl( - std::forward(f), std::move(init), b, std::make_index_sequence{}); + auto fold_join(F&& f, A init, const mat& b) { + return impl::fold_join_impl(std::forward(f), std::move(init), b, std::make_index_sequence{}); } template < typename A, typename B, typename C, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold_join( - F&& f, - A init, - const vec& b, - const mat& c - ) { - return impl::fold_join_impl( - std::forward(f), std::move(init), b, c, std::make_index_sequence{}); + auto fold_join(F&& f, A init, const vec& b, const mat& c) { + return impl::fold_join_impl(std::forward(f), std::move(init), b, c, std::make_index_sequence{}); } template < typename A, typename B, typename C, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold_join( - F&& f, - A init, - const mat& b, - const mat& c - ) { - return impl::fold_join_impl( - std::forward(f), std::move(init), b, c, std::make_index_sequence{}); + auto fold_join(F&& f, A init, const mat& b, const mat& c) { + return impl::fold_join_impl(std::forward(f), std::move(init), b, c, std::make_index_sequence{}); } template < typename A, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold1_join( - F&& f, - const mat& a - ) { - return impl::fold1_join_impl( - std::forward(f), a, std::make_index_sequence{}); + auto fold1_join(F&& f, const mat& a) { + return impl::fold1_join_impl(std::forward(f), a, std::make_index_sequence{}); } } @@ -195,45 +165,45 @@ namespace vmath_hpp // +operator template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator+(const mat& xs) { - return xs; + [[nodiscard]] constexpr auto operator+(const mat& xs) { + return map_join([](const vec& x){ return +x; }, xs); } // -operator template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator-(const mat& xs) { + [[nodiscard]] constexpr auto operator-(const mat& xs) { return map_join([](const vec& x){ return -x; }, xs); } // ~operator template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator~(const mat& xs) { + [[nodiscard]] constexpr auto operator~(const mat& xs) { return map_join([](const vec& x){ return ~x; }, xs); } // !operator template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator!(const mat& xs) { + [[nodiscard]] constexpr auto operator!(const mat& xs) { return map_join([](const vec& x){ return !x; }, xs); } // operator+ template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator+(const mat& xs, T y) { + [[nodiscard]] constexpr auto operator+(const mat& xs, T y) { return map_join([y](const vec& x){ return x + y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator+(T x, const mat& ys) { + [[nodiscard]] constexpr auto operator+(T x, const mat& ys) { return map_join([x](const vec& y){ return x + y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator+(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr auto operator+(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return x + y; }, xs, ys); } @@ -252,17 +222,17 @@ namespace vmath_hpp // operator- template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator-(const mat& xs, T y) { + [[nodiscard]] constexpr auto operator-(const mat& xs, T y) { return map_join([y](const vec& x){ return x - y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator-(T x, const mat& ys) { + [[nodiscard]] constexpr auto operator-(T x, const mat& ys) { return map_join([x](const vec& y){ return x - y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator-(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr auto operator-(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return x - y; }, xs, ys); } @@ -281,24 +251,24 @@ namespace vmath_hpp // operator* template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator*(const mat& xs, T y) { + [[nodiscard]] constexpr auto operator*(const mat& xs, T y) { return map_join([y](const vec& x){ return x * y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator*(T x, const mat& ys) { + [[nodiscard]] constexpr auto operator*(T x, const mat& ys) { return map_join([x](const vec& y){ return x * y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator*(const vec& xs, const mat& ys) { + [[nodiscard]] constexpr auto operator*(const vec& xs, const mat& ys) { return fold_join([](const vec& acc, T x, const vec& y){ return acc + x * y; }, vec{}, xs, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator*(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr auto operator*(const mat& xs, const mat& ys) { return map_join([&ys](const vec& x){ return x * ys; }, xs); @@ -324,12 +294,12 @@ namespace vmath_hpp // operator/ template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator/(const mat& xs, T y) { + [[nodiscard]] constexpr auto operator/(const mat& xs, T y) { return map_join([y](const vec& x){ return x / y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator/(T x, const mat& ys) { + [[nodiscard]] constexpr auto operator/(T x, const mat& ys) { return map_join([x](const vec& y){ return x / y; }, ys); } @@ -343,17 +313,17 @@ namespace vmath_hpp // operator& template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator&(const mat& xs, T y) { + [[nodiscard]] constexpr auto operator&(const mat& xs, T y) { return map_join([y](const vec& x){ return x & y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator&(T x, const mat& ys) { + [[nodiscard]] constexpr auto operator&(T x, const mat& ys) { return map_join([x](const vec& y){ return x & y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator&(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr auto operator&(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return x & y; }, xs, ys); } @@ -372,17 +342,17 @@ namespace vmath_hpp // operator| template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator|(const mat& xs, T y) { + [[nodiscard]] constexpr auto operator|(const mat& xs, T y) { return map_join([y](const vec& x){ return x | y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator|(T x, const mat& ys) { + [[nodiscard]] constexpr auto operator|(T x, const mat& ys) { return map_join([x](const vec& y){ return x | y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator|(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr auto operator|(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return x | y; }, xs, ys); } @@ -401,17 +371,17 @@ namespace vmath_hpp // operator^ template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator^(const mat& xs, T y) { + [[nodiscard]] constexpr auto operator^(const mat& xs, T y) { return map_join([y](const vec& x){ return x ^ y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator^(T x, const mat& ys) { + [[nodiscard]] constexpr auto operator^(T x, const mat& ys) { return map_join([x](const vec& y){ return x ^ y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator^(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr auto operator^(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return x ^ y; }, xs, ys); } @@ -430,34 +400,34 @@ namespace vmath_hpp // operator&& template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator&&(const mat& xs, T y) { + [[nodiscard]] constexpr auto operator&&(const mat& xs, T y) { return map_join([y](const vec& x){ return x && y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator&&(T x, const mat& ys) { + [[nodiscard]] constexpr auto operator&&(T x, const mat& ys) { return map_join([x](const vec& y){ return x && y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator&&(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr auto operator&&(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return x && y; }, xs, ys); } // operator|| template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator||(const mat& xs, T y) { + [[nodiscard]] constexpr auto operator||(const mat& xs, T y) { return map_join([y](const vec& x){ return x || y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator||(T x, const mat& ys) { + [[nodiscard]] constexpr auto operator||(T x, const mat& ys) { return map_join([x](const vec& y){ return x || y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat operator||(const mat& xs, const mat& ys) { + [[nodiscard]] constexpr auto operator||(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return x || y; }, xs, ys); } @@ -501,53 +471,80 @@ namespace vmath_hpp namespace vmath_hpp { - template < typename T, std::size_t Size > - [[nodiscard]] constexpr bool any(const mat& xs) { - return fold_join([](bool acc, const vec& x){ return acc || any(x); }, false, xs); + template < typename T, std::size_t Size + , typename U = decltype(any(std::declval>())) > + [[nodiscard]] constexpr U any(const mat& xs) { + return fold_join([](U acc, const vec& x){ return acc || any(x); }, U{false}, xs); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr bool all(const mat& xs) { - return fold_join([](bool acc, const vec& x){ return acc && all(x); }, true, xs); + template < typename T, std::size_t Size + , typename U = decltype(all(std::declval>())) > + [[nodiscard]] constexpr U all(const mat& xs) { + return fold_join([](U acc, const vec& x){ return acc && all(x); }, U{true}, xs); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat approx(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(approx( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat approx(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return approx(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat approx(const mat& xs, const mat& ys, T epsilon) { + template < typename T, std::size_t Size + , typename U = typename decltype(approx( + std::declval>(), + std::declval>(), + std::declval()))::component_type > + [[nodiscard]] constexpr mat approx(const mat& xs, const mat& ys, T epsilon) { return map_join([epsilon](const vec& x, const vec& y){ return approx(x, y, epsilon); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat less(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(less( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat less(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return less(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat less_equal(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(less_equal( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat less_equal(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return less_equal(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat greater(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(greater( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat greater(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return greater(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat greater_equal(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(greater_equal( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat greater_equal(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return greater_equal(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat equal_to(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(equal_to( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat equal_to(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return equal_to(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr mat not_equal_to(const mat& xs, const mat& ys) { + template < typename T, std::size_t Size + , typename U = typename decltype(not_equal_to( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr mat not_equal_to(const mat& xs, const mat& ys) { return map_join([](const vec& x, const vec& y){ return not_equal_to(x, y); }, xs, ys); } } diff --git a/headers/vmath.hpp/vmath_qua.hpp b/headers/vmath.hpp/vmath_qua.hpp index 7cced4b..fedac84 100644 --- a/headers/vmath.hpp/vmath_qua.hpp +++ b/headers/vmath.hpp/vmath_qua.hpp @@ -11,17 +11,63 @@ #include "vmath_vec.hpp" #include "vmath_vec_fun.hpp" +namespace vmath_hpp::detail +{ + template < typename T > + class qua_base { + public: + vec v = vec{T{0}}; + T s = T{1}; + public: + constexpr qua_base() = default; + + constexpr qua_base(T vx, T vy, T vz, T s) + : v{vx, vy, vz}, s{s} {} + + constexpr qua_base(const vec& v, T s) + : v{v}, s{s} {} + + constexpr explicit qua_base(const vec& vs) + : v{vs[0], vs[1], vs[2]}, s{vs[3]} {} + + constexpr explicit operator vec() const { + return {v, s}; + } + + [[nodiscard]] constexpr T& operator[](std::size_t index) noexcept { + switch ( index ) { + default: + case 0: return v.x; + case 1: return v.y; + case 2: return v.z; + case 3: return s; + } + } + + [[nodiscard]] constexpr const T& operator[](std::size_t index) const noexcept { + switch ( index ) { + default: + case 0: return v.x; + case 1: return v.y; + case 2: return v.z; + case 3: return s; + } + } + }; +} + namespace vmath_hpp { template < typename T > - class qua final { - public: - vec v{0}; - T s{1}; + class qua final : public detail::qua_base { public: using self_type = qua; + using base_type = detail::qua_base; using component_type = T; + using imag_type = vec; + using real_type = T; + using pointer = component_type*; using const_pointer = const component_type*; @@ -33,28 +79,15 @@ namespace vmath_hpp using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - static constexpr std::size_t size = 4; + static inline constexpr std::size_t size = 4; public: + using base_type::qua_base; + using base_type::operator[]; + constexpr qua() = default; constexpr qua(const qua&) = default; constexpr qua& operator=(const qua&) = default; - constexpr qua(T vx, T vy, T vz, T s) - : v{vx, vy, vz} - , s{s} {} - - constexpr qua(const vec& v, T s) - : v{v} - , s{s} {} - - constexpr explicit qua(const vec& vs) - : v{vs[0], vs[1], vs[2]} - , s{vs[3]} {} - - constexpr explicit operator vec() const { - return {(*this).v, (*this).s}; - } - void swap(qua& other) noexcept(std::is_nothrow_swappable_v) { for ( std::size_t i = 0; i < size; ++i ) { using std::swap; @@ -85,26 +118,6 @@ namespace vmath_hpp return &(*this)[0]; } - [[nodiscard]] constexpr reference operator[](std::size_t index) noexcept { - switch ( index ) { - default: - case 0: return v.x; - case 1: return v.y; - case 2: return v.z; - case 3: return s; - } - } - - [[nodiscard]] constexpr const_reference operator[](std::size_t index) const noexcept { - switch ( index ) { - default: - case 0: return v.x; - case 1: return v.y; - case 2: return v.z; - case 3: return s; - } - } - [[nodiscard]] constexpr reference at(std::size_t index) { VMATH_HPP_THROW_IF(index >= size, std::out_of_range("qua::at")); return (*this)[index]; diff --git a/headers/vmath.hpp/vmath_qua_fun.hpp b/headers/vmath.hpp/vmath_qua_fun.hpp index b9bde5f..efb03ea 100644 --- a/headers/vmath.hpp/vmath_qua_fun.hpp +++ b/headers/vmath.hpp/vmath_qua_fun.hpp @@ -14,6 +14,51 @@ #include "vmath_vec.hpp" #include "vmath_vec_fun.hpp" +namespace vmath_hpp::detail +{ + template < typename A, typename F > + [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE + auto map_join(F&& f, const qua& a) { + return qua(map_join(std::forward(f), vec{a})); + } + + template < typename A, typename B, typename F > + [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE + auto map_join(F&& f, const qua& a, const qua& b) { + return qua(map_join(std::forward(f), vec{a}, vec{b})); + } + + template < typename A, typename B, typename C, typename F > + [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE + auto map_join(F&& f, const qua& a, const qua& b, const qua& c) { + return qua(map_join(std::forward(f), vec{a}, vec{b}, vec{c})); + } + + template < typename A, typename B, typename C, typename D, typename F > + [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE + auto map_join(F&& f, const qua& a, const qua& b, const qua& c, const qua& d) { + return qua(map_join(std::forward(f), vec{a}, vec{b}, vec{c}, vec{d})); + } + + template < typename A, typename B, typename F > + [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE + auto fold_join(F&& f, A init, const qua& b) { + return fold_join(std::forward(f), std::move(init), vec{b}); + } + + template < typename A, typename B, typename C, typename F > + [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE + auto fold_join(F&& f, A init, const qua& b, const qua& c) { + return fold_join(std::forward(f), std::move(init), vec{b}, vec{c}); + } + + template < typename A, typename F > + [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE + auto fold1_join(F&& f, const qua& a) { + return fold1_join(std::forward(f), vec{a}); + } +} + // // Operators // @@ -23,21 +68,21 @@ namespace vmath_hpp // +operator template < typename T > - [[nodiscard]] constexpr qua operator+(const qua& xs) { - return xs; + [[nodiscard]] constexpr auto operator+(const qua& xs) { + return qua(+vec{xs}); } // -operator template < typename T > - [[nodiscard]] constexpr qua operator-(const qua& xs) { + [[nodiscard]] constexpr auto operator-(const qua& xs) { return qua(-vec{xs}); } // operator+ template < typename T > - [[nodiscard]] constexpr qua operator+(const qua& xs, const qua& ys) { + [[nodiscard]] constexpr auto operator+(const qua& xs, const qua& ys) { return qua(vec{xs} + vec{ys}); } @@ -51,7 +96,7 @@ namespace vmath_hpp // operator- template < typename T > - [[nodiscard]] constexpr qua operator-(const qua& xs, const qua& ys) { + [[nodiscard]] constexpr auto operator-(const qua& xs, const qua& ys) { return qua(vec{xs} - vec{ys}); } @@ -65,30 +110,30 @@ namespace vmath_hpp // operator* template < typename T > - [[nodiscard]] constexpr qua operator*(const qua& xs, T y) { + [[nodiscard]] constexpr auto operator*(const qua& xs, T y) { return qua(vec{xs} * y); } template < typename T > - [[nodiscard]] constexpr qua operator*(T x, const qua& ys) { + [[nodiscard]] constexpr auto operator*(T x, const qua& ys) { return qua(x * vec{ys}); } template < typename T > - [[nodiscard]] constexpr vec operator*(const vec& xs, const qua& ys) { + [[nodiscard]] constexpr auto operator*(const vec& xs, const qua& ys) { /// REFERENCE: /// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/ - const vec qv2 = cross(ys.v, xs) * T(2); + const vec qv2 = cross(ys.v, xs) * T{2}; return xs + qv2 * ys.s + cross(ys.v, qv2); } template < typename T > - [[nodiscard]] constexpr qua operator*(const qua& xs, const qua& ys) { + [[nodiscard]] constexpr auto operator*(const qua& xs, const qua& ys) { /// REFERENCE: /// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/arithmetic/ - return { + return qua{ cross(ys.v, xs.v) + ys.s * xs.v + xs.s * ys.v, ys.s * xs.s - dot(ys.v, xs.v)}; } @@ -113,12 +158,12 @@ namespace vmath_hpp // operator/ template < typename T > - [[nodiscard]] constexpr qua operator/(const qua& xs, T y) { + [[nodiscard]] constexpr auto operator/(const qua& xs, T y) { return qua(vec{xs} / y); } template < typename T > - [[nodiscard]] constexpr qua operator/(T x, const qua& ys) { + [[nodiscard]] constexpr auto operator/(T x, const qua& ys) { return qua(x / vec{ys}); } @@ -158,24 +203,24 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T > - [[nodiscard]] qua lerp(const qua& xs, const qua& ys, T a) { + [[nodiscard]] constexpr qua lerp(const qua& xs, const qua& ys, T a) { return qua(lerp(vec{xs}, vec{ys}, a)); } template < typename T > - [[nodiscard]] qua lerp(const qua& xs, const qua& ys, T xs_a, T ys_a) { - return qua(lerp(vec{xs}, vec{ys}, xs_a, ys_a)); + [[nodiscard]] constexpr qua lerp(const qua& xs, const qua& ys, T x_a, T y_a) { + return qua(lerp(vec{xs}, vec{ys}, x_a, y_a)); } template < typename T > - [[nodiscard]] qua nlerp(const qua& unit_xs, const qua& unit_ys, T a) { - const T xs_scale = T(1) - a; + [[nodiscard]] constexpr qua nlerp(const qua& unit_xs, const qua& unit_ys, T a) { + const T xs_scale = T{1} - a; const T ys_scale = a * sign(dot(unit_xs, unit_ys)); return normalize(lerp(unit_xs, unit_ys, xs_scale, ys_scale)); } template < typename T > - [[nodiscard]] qua slerp(const qua& unit_xs, const qua& unit_ys, T a) { + [[nodiscard]] constexpr qua slerp(const qua& unit_xs, const qua& unit_ys, T a) { /// REFERENCE: /// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ @@ -183,34 +228,19 @@ namespace vmath_hpp const T raw_cos_theta_sign = sign(raw_cos_theta); // half degree linear threshold: cos((pi / 180) * 0.25) - if ( const T cos_theta = raw_cos_theta * raw_cos_theta_sign; cos_theta < T(0.99999) ) { + if ( const T cos_theta = raw_cos_theta * raw_cos_theta_sign; cos_theta < T{0.99999f} ) { const T theta = acos(cos_theta); - const T rsin_theta = rsqrt(T(1) - sqr(cos_theta)); - const T xs_scale = sin((T(1) - a) * theta) * rsin_theta; + const T rsin_theta = rsqrt(T{1} - sqr(cos_theta)); + const T xs_scale = sin((T{1} - a) * theta) * rsin_theta; const T ys_scale = sin(a * theta) * raw_cos_theta_sign * rsin_theta; return lerp(unit_xs, unit_ys, xs_scale, ys_scale); } else { // use linear interpolation for small angles - const T xs_scale = T(1) - a; + const T xs_scale = T{1} - a; const T ys_scale = a * raw_cos_theta_sign; return normalize(lerp(unit_xs, unit_ys, xs_scale, ys_scale)); } } - - template < typename T > - [[nodiscard]] vec isnan(const qua& xs) { - return isnan(vec{xs}); - } - - template < typename T > - [[nodiscard]] vec isinf(const qua& xs) { - return isinf(vec{xs}); - } - - template < typename T > - [[nodiscard]] vec isfinite(const qua& xs) { - return isfinite(vec{xs}); - } } // @@ -225,23 +255,33 @@ namespace vmath_hpp } template < typename T > - [[nodiscard]] T length(const qua& xs) { + [[nodiscard]] constexpr T length(const qua& xs) { return length(vec{xs}); } + template < typename T > + [[nodiscard]] constexpr T rlength(const qua& xs) { + return rlength(vec{xs}); + } + template < typename T > [[nodiscard]] constexpr T length2(const qua& xs) { return length2(vec{xs}); } template < typename T > - [[nodiscard]] T distance(const qua& xs, const qua& ys) { - const qua zs = xs * conjugate(ys); - return T(2) * atan2(length(zs.v), abs(zs.s)); + [[nodiscard]] constexpr T rlength2(const qua& xs) { + return rlength2(vec{xs}); } template < typename T > - [[nodiscard]] qua normalize(const qua& xs) { + [[nodiscard]] constexpr T distance(const qua& xs, const qua& ys) { + const qua zs = xs * conjugate(ys); + return T{2} * atan2(length(zs.v), abs(zs.s)); + } + + template < typename T > + [[nodiscard]] constexpr qua normalize(const qua& xs) { return qua(normalize(vec{xs})); } } @@ -252,43 +292,80 @@ namespace vmath_hpp namespace vmath_hpp { - template < typename T > - [[nodiscard]] constexpr vec approx(const qua& xs, const qua& ys) { + template < typename T + , typename U = decltype(any(std::declval>())) > + [[nodiscard]] constexpr U any(const qua& xs) { + return any(vec{xs}); + } + + template < typename T + , typename U = decltype(all(std::declval>())) > + [[nodiscard]] constexpr U all(const qua& xs) { + return all(vec{xs}); + } + + template < typename T + , typename U = typename decltype(approx( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec approx(const qua& xs, const qua& ys) { return approx(vec{xs}, vec{ys}); } - template < typename T > - [[nodiscard]] constexpr vec approx(const qua& xs, const qua& ys, T epsilon) { + template < typename T + , typename U = typename decltype(approx( + std::declval>(), + std::declval>(), + std::declval()))::component_type > + [[nodiscard]] constexpr vec approx(const qua& xs, const qua& ys, T epsilon) { return approx(vec{xs}, vec{ys}, epsilon); } - template < typename T > - [[nodiscard]] constexpr vec less(const qua& xs, const qua& ys) { + template < typename T + , typename U = typename decltype(less( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec less(const qua& xs, const qua& ys) { return less(vec{xs}, vec{ys}); } - template < typename T > - [[nodiscard]] constexpr vec less_equal(const qua& xs, const qua& ys) { + template < typename T + , typename U = typename decltype(less_equal( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec less_equal(const qua& xs, const qua& ys) { return less_equal(vec{xs}, vec{ys}); } - template < typename T > - [[nodiscard]] constexpr vec greater(const qua& xs, const qua& ys) { + template < typename T + , typename U = typename decltype(greater( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec greater(const qua& xs, const qua& ys) { return greater(vec{xs}, vec{ys}); } - template < typename T > - [[nodiscard]] constexpr vec greater_equal(const qua& xs, const qua& ys) { + template < typename T + , typename U = typename decltype(greater_equal( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec greater_equal(const qua& xs, const qua& ys) { return greater_equal(vec{xs}, vec{ys}); } - template < typename T > - [[nodiscard]] constexpr vec equal_to(const qua& xs, const qua& ys) { + template < typename T + , typename U = typename decltype(equal_to( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec equal_to(const qua& xs, const qua& ys) { return equal_to(vec{xs}, vec{ys}); } - template < typename T > - [[nodiscard]] constexpr vec not_equal_to(const qua& xs, const qua& ys) { + template < typename T + , typename U = typename decltype(not_equal_to( + std::declval>(), + std::declval>()))::component_type > + [[nodiscard]] constexpr vec not_equal_to(const qua& xs, const qua& ys) { return not_equal_to(vec{xs}, vec{ys}); } } @@ -310,6 +387,6 @@ namespace vmath_hpp template < typename T > [[nodiscard]] constexpr qua inverse(const qua& q) { - return conjugate(q) * rcp(length2(q)); + return conjugate(q) * rlength2(q); } } diff --git a/headers/vmath.hpp/vmath_vec.hpp b/headers/vmath.hpp/vmath_vec.hpp index ccad622..2aaa027 100644 --- a/headers/vmath.hpp/vmath_vec.hpp +++ b/headers/vmath.hpp/vmath_vec.hpp @@ -16,7 +16,8 @@ namespace vmath_hpp::detail template < typename T > class vec_base { public: - T x{}, y{}; + T x = T{0}; + T y = T{0}; public: constexpr vec_base() = default; @@ -26,12 +27,6 @@ namespace vmath_hpp::detail constexpr vec_base(T x, T y) : x{x}, y{y} {} - constexpr explicit vec_base(const vec_base& xy) - : x{xy[0]}, y{xy[1]} {} - - constexpr explicit vec_base(const vec_base& xy) - : x{xy[0]}, y{xy[1]} {} - [[nodiscard]] constexpr T& operator[](std::size_t index) noexcept { switch ( index ) { default: @@ -52,7 +47,9 @@ namespace vmath_hpp::detail template < typename T > class vec_base { public: - T x{}, y{}, z{}; + T x = T{0}; + T y = T{0}; + T z = T{0}; public: constexpr vec_base() = default; @@ -68,8 +65,9 @@ namespace vmath_hpp::detail constexpr vec_base(T x, const vec_base& yz) : x{x}, y{yz[0]}, z{yz[1]} {} - constexpr explicit vec_base(const vec_base& xyz) - : x{xyz[0]}, y{xyz[1]}, z{xyz[2]} {} + constexpr explicit operator vec() const { + return {x, y}; + } [[nodiscard]] constexpr T& operator[](std::size_t index) noexcept { switch ( index ) { @@ -93,7 +91,10 @@ namespace vmath_hpp::detail template < typename T > class vec_base { public: - T x{}, y{}, z{}, w{}; + T x = T{0}; + T y = T{0}; + T z = T{0}; + T w = T{0}; public: constexpr vec_base() = default; @@ -121,6 +122,14 @@ namespace vmath_hpp::detail constexpr vec_base(T x, const vec_base& yzw) : x{x}, y{yzw[0]}, z{yzw[1]}, w{yzw[2]} {} + constexpr explicit operator vec() const { + return {x, y}; + } + + constexpr explicit operator vec() const { + return {x, y, z}; + } + [[nodiscard]] constexpr T& operator[](std::size_t index) noexcept { switch ( index ) { default: @@ -150,7 +159,6 @@ namespace vmath_hpp public: using self_type = vec; using base_type = detail::vec_base; - public: using component_type = T; using pointer = component_type*; @@ -164,7 +172,7 @@ namespace vmath_hpp using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - static constexpr std::size_t size = Size; + static inline constexpr std::size_t size = Size; public: using base_type::vec_base; using base_type::operator[]; diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index a91ce26..69c3c6e 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -15,94 +15,80 @@ namespace vmath_hpp::detail::impl { template < typename A, std::size_t Size, typename F, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join_impl( + vec, Size> map_join_impl( F&& f, const vec& a, - std::index_sequence - ) -> vec())), Size> + std::index_sequence) { return { f(a[Is])... }; } template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join_impl( + vec, Size> map_join_impl( F&& f, const vec& a, const vec& b, - std::index_sequence - ) -> vec(), - std::declval())), Size> + std::index_sequence) { return { f(a[Is], b[Is])... }; } template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join_impl( + vec, Size> map_join_impl( F&& f, const vec& a, const vec& b, const vec& c, - std::index_sequence - ) -> vec(), - std::declval(), - std::declval())), Size> + std::index_sequence) { return { f(a[Is], b[Is], c[Is])... }; } template < typename A, typename B, typename C, typename D, std::size_t Size, typename F, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join_impl( + vec, Size> map_join_impl( F&& f, const vec& a, const vec& b, const vec& c, const vec& d, - std::index_sequence - ) -> vec(), - std::declval(), - std::declval(), - std::declval())), Size> + std::index_sequence) { return { f(a[Is], b[Is], c[Is], d[Is])... }; } template < typename A, typename B, std::size_t Size, typename F, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold_join_impl( + A fold_join_impl( F&& f, A init, const vec& b, - std::index_sequence - ) -> A { + std::index_sequence) + { return ((init = f(std::move(init), b[Is])), ...); } template < typename A, typename B, typename C, std::size_t Size, typename F, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold_join_impl( + A fold_join_impl( F&& f, A init, const vec& b, const vec& c, - std::index_sequence - ) -> A { + std::index_sequence) + { return ((init = f(std::move(init), b[Is], c[Is])), ...); } template < typename A, std::size_t Size, typename F, std::size_t I, std::size_t... Is > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold1_join_impl( + A fold1_join_impl( F&& f, const vec& a, - std::index_sequence - ) -> A { + std::index_sequence) + { A init = a[I]; return ((init = f(std::move(init), a[Is])), ...); } @@ -112,81 +98,44 @@ namespace vmath_hpp::detail { template < typename A, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join( - F&& f, - const vec& a - ) { - return impl::map_join_impl( - std::forward(f), a, std::make_index_sequence{}); + auto map_join(F&& f, const vec& a) { + return impl::map_join_impl(std::forward(f), a, std::make_index_sequence{}); } template < typename A, typename B, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join( - F&& f, - const vec& a, - const vec& b - ) { - return impl::map_join_impl( - std::forward(f), a, b, std::make_index_sequence{}); + auto map_join(F&& f, const vec& a, const vec& b) { + return impl::map_join_impl(std::forward(f), a, b, std::make_index_sequence{}); } template < typename A, typename B, typename C, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join( - F&& f, - const vec& a, - const vec& b, - const vec& c - ) { - return impl::map_join_impl( - std::forward(f), a, b, c, std::make_index_sequence{}); + auto map_join(F&& f, const vec& a, const vec& b, const vec& c) { + return impl::map_join_impl(std::forward(f), a, b, c, std::make_index_sequence{}); } template < typename A, typename B, typename C, typename D, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto map_join( - F&& f, - const vec& a, - const vec& b, - const vec& c, - const vec& d - ) { - return impl::map_join_impl( - std::forward(f), a, b, c, d, std::make_index_sequence{}); + auto map_join(F&& f, const vec& a, const vec& b, const vec& c, const vec& d) { + return impl::map_join_impl(std::forward(f), a, b, c, d, std::make_index_sequence{}); } template < typename A, typename B, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold_join( - F&& f, - A init, - const vec& b - ) { - return impl::fold_join_impl( - std::forward(f), std::move(init), b, std::make_index_sequence{}); + auto fold_join(F&& f, A init, const vec& b) { + return impl::fold_join_impl(std::forward(f), std::move(init), b, std::make_index_sequence{}); } template < typename A, typename B, typename C, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold_join( - F&& f, - A init, - const vec& b, - const vec& c - ) { - return impl::fold_join_impl( - std::forward(f), std::move(init), b, c, std::make_index_sequence{}); + auto fold_join(F&& f, A init, const vec& b, const vec& c) { + return impl::fold_join_impl(std::forward(f), std::move(init), b, c, std::make_index_sequence{}); } template < typename A, std::size_t Size, typename F > [[nodiscard]] constexpr VMATH_HPP_FORCE_INLINE - auto fold1_join( - F&& f, - const vec& a - ) { - return impl::fold1_join_impl( - std::forward(f), a, std::make_index_sequence{}); + auto fold1_join(F&& f, const vec& a) { + return impl::fold1_join_impl(std::forward(f), a, std::make_index_sequence{}); } } @@ -199,45 +148,45 @@ namespace vmath_hpp // +operator template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator+(const vec& xs) { - return xs; + [[nodiscard]] constexpr auto operator+(const vec& xs) { + return map_join([](T x){ return +x; }, xs); } // -operator template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator-(const vec& xs) { + [[nodiscard]] constexpr auto operator-(const vec& xs) { return map_join([](T x){ return -x; }, xs); } // ~operator template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator~(const vec& xs) { + [[nodiscard]] constexpr auto operator~(const vec& xs) { return map_join([](T x){ return ~x; }, xs); } // !operator template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator!(const vec& xs) { + [[nodiscard]] constexpr auto operator!(const vec& xs) { return map_join([](T x){ return !x; }, xs); } // operator+ template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator+(const vec& xs, T y) { + [[nodiscard]] constexpr auto operator+(const vec& xs, T y) { return map_join([y](T x){ return x + y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator+(T x, const vec& ys) { + [[nodiscard]] constexpr auto operator+(T x, const vec& ys) { return map_join([x](T y){ return x + y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator+(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr auto operator+(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return x + y; }, xs, ys); } @@ -256,17 +205,17 @@ namespace vmath_hpp // operator- template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator-(const vec& xs, T y) { + [[nodiscard]] constexpr auto operator-(const vec& xs, T y) { return map_join([y](T x){ return x - y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator-(T x, const vec& ys) { + [[nodiscard]] constexpr auto operator-(T x, const vec& ys) { return map_join([x](T y){ return x - y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator-(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr auto operator-(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return x - y; }, xs, ys); } @@ -285,17 +234,17 @@ namespace vmath_hpp // operator* template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator*(const vec& xs, T y) { + [[nodiscard]] constexpr auto operator*(const vec& xs, T y) { return map_join([y](T x){ return x * y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator*(T x, const vec& ys) { + [[nodiscard]] constexpr auto operator*(T x, const vec& ys) { return map_join([x](T y){ return x * y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator*(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr auto operator*(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return x * y; }, xs, ys); } @@ -314,17 +263,17 @@ namespace vmath_hpp // operator/ template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator/(const vec& xs, T y) { + [[nodiscard]] constexpr auto operator/(const vec& xs, T y) { return map_join([y](T x){ return x / y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator/(T x, const vec& ys) { + [[nodiscard]] constexpr auto operator/(T x, const vec& ys) { return map_join([x](T y){ return x / y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator/(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr auto operator/(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return x / y; }, xs, ys); } @@ -343,17 +292,17 @@ namespace vmath_hpp // operator& template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator&(const vec& xs, T y) { + [[nodiscard]] constexpr auto operator&(const vec& xs, T y) { return map_join([y](T x){ return x & y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator&(T x, const vec& ys) { + [[nodiscard]] constexpr auto operator&(T x, const vec& ys) { return map_join([x](T y){ return x & y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator&(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr auto operator&(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return x & y; }, xs, ys); } @@ -372,17 +321,17 @@ namespace vmath_hpp // operator| template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator|(const vec& xs, T y) { + [[nodiscard]] constexpr auto operator|(const vec& xs, T y) { return map_join([y](T x){ return x | y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator|(T x, const vec& ys) { + [[nodiscard]] constexpr auto operator|(T x, const vec& ys) { return map_join([x](T y){ return x | y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator|(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr auto operator|(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return x | y; }, xs, ys); } @@ -401,17 +350,17 @@ namespace vmath_hpp // operator^ template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator^(const vec& xs, T y) { + [[nodiscard]] constexpr auto operator^(const vec& xs, T y) { return map_join([y](T x){ return x ^ y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator^(T x, const vec& ys) { + [[nodiscard]] constexpr auto operator^(T x, const vec& ys) { return map_join([x](T y){ return x ^ y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator^(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr auto operator^(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return x ^ y; }, xs, ys); } @@ -430,34 +379,34 @@ namespace vmath_hpp // operator&& template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator&&(const vec& xs, T y) { + [[nodiscard]] constexpr auto operator&&(const vec& xs, T y) { return map_join([y](T x){ return x && y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator&&(T x, const vec& ys) { + [[nodiscard]] constexpr auto operator&&(T x, const vec& ys) { return map_join([x](T y){ return x && y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator&&(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr auto operator&&(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return x && y; }, xs, ys); } // operator|| template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator||(const vec& xs, T y) { + [[nodiscard]] constexpr auto operator||(const vec& xs, T y) { return map_join([y](T x){ return x || y; }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator||(T x, const vec& ys) { + [[nodiscard]] constexpr auto operator||(T x, const vec& ys) { return map_join([x](T y){ return x || y; }, ys); } template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec operator||(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr auto operator||(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return x || y; }, xs, ys); } @@ -522,61 +471,61 @@ namespace vmath_hpp } template < typename T, std::size_t Size > - [[nodiscard]] vec floor(const vec& xs) { + [[nodiscard]] constexpr vec floor(const vec& xs) { return map_join([](T x) { return floor(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec trunc(const vec& xs) { + [[nodiscard]] constexpr vec trunc(const vec& xs) { return map_join([](T x) { return trunc(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec round(const vec& xs) { + [[nodiscard]] constexpr vec round(const vec& xs) { return map_join([](T x) { return round(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec ceil(const vec& xs) { + [[nodiscard]] constexpr vec ceil(const vec& xs) { return map_join([](T x) { return ceil(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec fract(const vec& xs) { + [[nodiscard]] constexpr vec fract(const vec& xs) { return map_join([](T x) { return fract(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec fmod(const vec& xs, T y) { + [[nodiscard]] constexpr vec fmod(const vec& xs, T y) { return map_join([y](T x) { return fmod(x, y); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec fmod(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec fmod(const vec& xs, const vec& ys) { return map_join([](T x, T y) { return fmod(x, y); }, xs, ys); } namespace impl { template < typename T, std::size_t Size, std::size_t... Is > - VMATH_HPP_FORCE_INLINE + constexpr VMATH_HPP_FORCE_INLINE vec modf_impl(const vec& xs, vec* is, std::index_sequence) { return { modf(xs[Is], &(*is)[Is])... }; } } template < typename T, std::size_t Size > - vec modf(const vec& xs, vec* is) { + constexpr vec modf(const vec& xs, vec* is) { return impl::modf_impl(xs, is, std::make_index_sequence{}); } template < typename T, std::size_t Size > - [[nodiscard]] vec copysign(const vec& xs, T s) { + [[nodiscard]] constexpr vec copysign(const vec& xs, T s) { return map_join([s](T x) { return copysign(x, s); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec copysign(const vec& xs, const vec& ss) { + [[nodiscard]] constexpr vec copysign(const vec& xs, const vec& ss) { return map_join([](T x, T s) { return copysign(x, s); }, xs, ss); } @@ -683,45 +632,6 @@ namespace vmath_hpp [[nodiscard]] constexpr vec smoothstep(const vec& edges0, const vec& edges1, const vec& xs) { return map_join([](T edge0, T edge1, T x) { return smoothstep(edge0, edge1, x); }, edges0, edges1, xs); } - - template < typename T, std::size_t Size > - [[nodiscard]] vec isnan(const vec& xs) { - return map_join([](T x) { return isnan(x); }, xs); - } - - template < typename T, std::size_t Size > - [[nodiscard]] vec isinf(const vec& xs) { - return map_join([](T x) { return isinf(x); }, xs); - } - - template < typename T, std::size_t Size > - [[nodiscard]] vec isfinite(const vec& xs) { - return map_join([](T x) { return isfinite(x); }, xs); - } - - template < typename T, std::size_t Size > - [[nodiscard]] vec fma(const vec& as, const vec& bs, const vec& cs) { - return map_join([](T a, T b, T c) { return fma(a, b, c); }, as, bs, cs); - } - - namespace impl - { - template < typename T, std::size_t Size, std::size_t... Is > - VMATH_HPP_FORCE_INLINE - vec frexp_impl(const vec& xs, vec* exps, std::index_sequence) { - return { frexp(xs[Is], &(*exps)[Is])... }; - } - } - - template < typename T, std::size_t Size > - vec frexp(const vec& xs, vec* exps) { - return impl::frexp_impl(xs, exps, std::make_index_sequence{}); - } - - template < typename T, std::size_t Size > - [[nodiscard]] vec ldexp(const vec& xs, const vec& exps) { - return map_join([](T x, int exp) { return ldexp(x, exp); }, xs, exps); - } } // @@ -741,77 +651,77 @@ namespace vmath_hpp } template < typename T, std::size_t Size > - [[nodiscard]] vec sin(const vec& xs) { + [[nodiscard]] constexpr vec sin(const vec& xs) { return map_join([](T x) { return sin(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec cos(const vec& xs) { + [[nodiscard]] constexpr vec cos(const vec& xs) { return map_join([](T x) { return cos(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec tan(const vec& xs) { + [[nodiscard]] constexpr vec tan(const vec& xs) { return map_join([](T x) { return tan(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec asin(const vec& xs) { + [[nodiscard]] constexpr vec asin(const vec& xs) { return map_join([](T x) { return asin(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec acos(const vec& xs) { + [[nodiscard]] constexpr vec acos(const vec& xs) { return map_join([](T x) { return acos(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec atan(const vec& xs) { + [[nodiscard]] constexpr vec atan(const vec& xs) { return map_join([](T x) { return atan(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec atan2(const vec& ys, const vec& xs) { + [[nodiscard]] constexpr vec atan2(const vec& ys, const vec& xs) { return map_join([](T y, T x) { return atan2(y, x); }, ys, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec sinh(const vec& xs) { + [[nodiscard]] constexpr vec sinh(const vec& xs) { return map_join([](T x) { return sinh(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec cosh(const vec& xs) { + [[nodiscard]] constexpr vec cosh(const vec& xs) { return map_join([](T x) { return cosh(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec tanh(const vec& xs) { + [[nodiscard]] constexpr vec tanh(const vec& xs) { return map_join([](T x) { return tanh(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec asinh(const vec& xs) { + [[nodiscard]] constexpr vec asinh(const vec& xs) { return map_join([](T x) { return asinh(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec acosh(const vec& xs) { + [[nodiscard]] constexpr vec acosh(const vec& xs) { return map_join([](T x) { return acosh(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec atanh(const vec& xs) { + [[nodiscard]] constexpr vec atanh(const vec& xs) { return map_join([](T x) { return atanh(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] std::pair, vec> sincos(const vec& xs) { + [[nodiscard]] constexpr std::pair, vec> sincos(const vec& xs) { return { sin(xs), cos(xs) }; } template < typename T, std::size_t Size > - void sincos(const vec& xs, vec* ss, vec* cs) { + constexpr void sincos(const vec& xs, vec* ss, vec* cs) { *ss = sin(xs); *cs = cos(xs); } @@ -824,37 +734,37 @@ namespace vmath_hpp namespace vmath_hpp { template < typename T, std::size_t Size > - [[nodiscard]] vec pow(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr vec pow(const vec& xs, const vec& ys) { return map_join([](T x, T y) { return pow(x, y); }, xs, ys); } template < typename T, std::size_t Size > - [[nodiscard]] vec exp(const vec& xs) { + [[nodiscard]] constexpr vec exp(const vec& xs) { return map_join([](T x) { return exp(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec log(const vec& xs) { + [[nodiscard]] constexpr vec log(const vec& xs) { return map_join([](T x) { return log(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec exp2(const vec& xs) { + [[nodiscard]] constexpr vec exp2(const vec& xs) { return map_join([](T x) { return exp2(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec log2(const vec& xs) { + [[nodiscard]] constexpr vec log2(const vec& xs) { return map_join([](T x) { return log2(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec sqrt(const vec& xs) { + [[nodiscard]] constexpr vec sqrt(const vec& xs) { return map_join([](T x) { return sqrt(x); }, xs); } template < typename T, std::size_t Size > - [[nodiscard]] vec rsqrt(const vec& xs) { + [[nodiscard]] constexpr vec rsqrt(const vec& xs) { return map_join([](T x) { return rsqrt(x); }, xs); } } @@ -869,21 +779,31 @@ namespace vmath_hpp [[nodiscard]] constexpr T dot(const vec& xs, const vec& ys) { return fold_join([](T acc, T x, T y){ return acc + (x * y); - }, T(0), xs, ys); + }, T{0}, xs, ys); } template < typename T, std::size_t Size > - [[nodiscard]] T length(const vec& xs) { + [[nodiscard]] constexpr T length(const vec& xs) { return sqrt(dot(xs, xs)); } + template < typename T, std::size_t Size > + [[nodiscard]] constexpr T rlength(const vec& xs) { + return rsqrt(dot(xs, xs)); + } + template < typename T, std::size_t Size > [[nodiscard]] constexpr T length2(const vec& xs) { return dot(xs, xs); } template < typename T, std::size_t Size > - [[nodiscard]] T distance(const vec& xs, const vec& ys) { + [[nodiscard]] constexpr T rlength2(const vec& xs) { + return rcp(dot(xs, xs)); + } + + template < typename T, std::size_t Size > + [[nodiscard]] constexpr T distance(const vec& xs, const vec& ys) { return length(ys - xs); } @@ -906,25 +826,25 @@ namespace vmath_hpp } template < typename T, std::size_t Size > - [[nodiscard]] vec normalize(const vec& xs) { - return xs * rsqrt(length2(xs)); + [[nodiscard]] constexpr vec normalize(const vec& xs) { + return xs * rlength(xs); } template < typename T, std::size_t Size > [[nodiscard]] constexpr vec faceforward(const vec& n, const vec& i, const vec& nref) { - return dot(nref, i) < T(0) ? n : -n; + return dot(nref, i) < T{0} ? n : -n; } template < typename T, std::size_t Size > [[nodiscard]] constexpr vec reflect(const vec& i, const vec& n) { - return i - n * dot(n, i) * T(2); + return i - T{2} * dot(n, i) * n; } template < typename T, std::size_t Size > - [[nodiscard]] vec refract(const vec& i, const vec& n, T eta) { + [[nodiscard]] constexpr vec refract(const vec& i, const vec& n, T eta) { const T d = dot(n, i); - const T k = T(1) - eta * eta * (T(1) - d * d); - return T(k >= T(0)) * (eta * i - (eta * d + sqrt(k)) * n); + const T k = T{1} - sqr(eta) * (T{1} - sqr(d)); + return k < T{0} ? vec{T{0}} : (eta * i - (eta * d + sqrt(k)) * n); } } @@ -934,53 +854,80 @@ namespace vmath_hpp namespace vmath_hpp { - template < typename T, std::size_t Size > - [[nodiscard]] constexpr bool any(const vec& xs) { - return fold_join([](bool acc, T x){ return acc || any(x); }, false, xs); + template < typename T, std::size_t Size + , typename U = decltype(any(std::declval())) > + [[nodiscard]] constexpr U any(const vec& xs) { + return fold_join([](U acc, T x){ return acc || any(x); }, U{false}, xs); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr bool all(const vec& xs) { - return fold_join([](bool acc, T x){ return acc && all(x); }, true, xs); + template < typename T, std::size_t Size + , typename U = decltype(all(std::declval())) > + [[nodiscard]] constexpr U all(const vec& xs) { + return fold_join([](U acc, T x){ return acc && all(x); }, U{true}, xs); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec approx(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(approx( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec approx(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return approx(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec approx(const vec& xs, const vec& ys, T epsilon) { + template < typename T, std::size_t Size + , typename U = decltype(approx( + std::declval(), + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec approx(const vec& xs, const vec& ys, T epsilon) { return map_join([epsilon](T x, T y){ return approx(x, y, epsilon); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec less(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(less( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec less(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return less(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec less_equal(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(less_equal( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec less_equal(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return less_equal(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec greater(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(greater( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec greater(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return greater(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec greater_equal(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(greater_equal( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec greater_equal(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return greater_equal(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec equal_to(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(equal_to( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec equal_to(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return equal_to(x, y); }, xs, ys); } - template < typename T, std::size_t Size > - [[nodiscard]] constexpr vec not_equal_to(const vec& xs, const vec& ys) { + template < typename T, std::size_t Size + , typename U = decltype(not_equal_to( + std::declval(), + std::declval())) > + [[nodiscard]] constexpr vec not_equal_to(const vec& xs, const vec& ys) { return map_join([](T x, T y){ return not_equal_to(x, y); }, xs, ys); } } diff --git a/untests/vmath_ext_tests.cpp b/untests/vmath_ext_tests.cpp index bfeb4ce..55b2f58 100644 --- a/untests/vmath_ext_tests.cpp +++ b/untests/vmath_ext_tests.cpp @@ -52,6 +52,8 @@ TEST_CASE("vmath/ext/units") { STATIC_CHECK(identity2x2 == int2x2()); STATIC_CHECK(identity3x3 == int3x3()); STATIC_CHECK(identity4x4 == int4x4()); + + STATIC_CHECK(qidentity == qfloat()); } TEST_CASE("vmath/ext/hash") { diff --git a/untests/vmath_fix_tests.cpp b/untests/vmath_fix_tests.cpp new file mode 100644 index 0000000..1af899d --- /dev/null +++ b/untests/vmath_fix_tests.cpp @@ -0,0 +1,956 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/vmath.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2020-2021, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include "vmath_tests.hpp" + +namespace +{ + template < typename T > + class fix { + public: + fix() = default; + + fix(fix&&) = default; + fix& operator=(fix&&) = default; + + fix(const fix&) = default; + fix& operator=(const fix&) = default; + + constexpr explicit fix(T underlying): underlying_(underlying) {} + constexpr T underlying() const noexcept { return underlying_; } + + constexpr friend fix abs(const fix& l) { using vmath_hpp::abs; return { fix{abs(l.underlying())} }; } + constexpr friend fix sqr(const fix& l) { using vmath_hpp::sqr; return { fix{sqr(l.underlying())} }; } + constexpr friend fix sign(const fix& l) { using vmath_hpp::sign; return { fix{sign(l.underlying())} }; } + + constexpr friend fix rcp(const fix& l) { using vmath_hpp::rcp; return { fix{rcp(l.underlying())} }; } + constexpr friend fix floor(const fix& l) { using vmath_hpp::floor; return { fix{floor(l.underlying())} }; } + constexpr friend fix trunc(const fix& l) { using vmath_hpp::trunc; return { fix{trunc(l.underlying())} }; } + constexpr friend fix round(const fix& l) { using vmath_hpp::round; return { fix{round(l.underlying())} }; } + constexpr friend fix ceil(const fix& l) { using vmath_hpp::ceil; return { fix{ceil(l.underlying())} }; } + constexpr friend fix fract(const fix& l) { using vmath_hpp::fract; return { fix{fract(l.underlying())} }; } + + constexpr friend fix fmod(const fix& l, const fix& r) { using vmath_hpp::fmod; return { fix{fmod(l.underlying(), r.underlying())} }; } + constexpr friend fix modf(const fix& l, fix* r) { using vmath_hpp::modf; return { fix{modf(l.underlying(), &r->underlying_)} }; } + constexpr friend fix copysign(const fix& l, const fix& r) { using vmath_hpp::copysign; return { fix{copysign(l.underlying(), r.underlying())} }; } + + constexpr friend fix min(const fix& l, const fix& r) { using vmath_hpp::min; return fix{min(l.underlying(), r.underlying())}; } + constexpr friend fix max(const fix& l, const fix& r) { using vmath_hpp::max; return fix{max(l.underlying(), r.underlying())}; } + constexpr friend fix clamp(const fix& l, const fix& min_l, const fix& max_l) { using vmath_hpp::clamp; return fix{clamp(l.underlying(), min_l.underlying(), max_l.underlying())}; } + constexpr friend fix saturate(const fix& l) { using vmath_hpp::saturate; return fix{saturate(l.underlying())}; } + constexpr friend fix lerp(const fix& l, const fix& r, const fix& a) { using vmath_hpp::lerp; return fix{lerp(l.underlying(), r.underlying(), a.underlying())}; } + constexpr friend fix lerp(const fix& l, const fix& r, const fix& a, const fix& b) { using vmath_hpp::lerp; return fix{lerp(l.underlying(), r.underlying(), a.underlying(), b.underlying())}; } + + constexpr friend fix step(const fix& e, const fix& l) { using vmath_hpp::step; return fix{step(e.underlying(), l.underlying())}; } + constexpr friend fix smoothstep(const fix& e0, const fix& e1, const fix& l) { using vmath_hpp::smoothstep; return fix{smoothstep(e0.underlying(), e1.underlying(), l.underlying())}; } + + // + + constexpr friend fix any(const fix& l) { using vmath_hpp::any; return fix{any(l.underlying())}; } + constexpr friend fix all(const fix& l) { using vmath_hpp::all; return fix{all(l.underlying())}; } + + constexpr friend fix approx(const fix& l, const fix& r) { using vmath_hpp::approx; return fix{approx(l.underlying(), r.underlying())}; } + constexpr friend fix approx(const fix& l, const fix& r, const fix& e) { using vmath_hpp::approx; return fix{approx(l.underlying(), r.underlying(), e.underlying())}; } + + constexpr friend fix less(const fix& l, const fix& r) { using vmath_hpp::less; return fix{less(l.underlying(), r.underlying())}; } + constexpr friend fix less_equal(const fix& l, const fix& r) { using vmath_hpp::less_equal; return fix{less_equal(l.underlying(), r.underlying())}; } + constexpr friend fix greater(const fix& l, const fix& r) { using vmath_hpp::greater; return fix{greater(l.underlying(), r.underlying())}; } + constexpr friend fix greater_equal(const fix& l, const fix& r) { using vmath_hpp::greater_equal; return fix{greater_equal(l.underlying(), r.underlying())}; } + constexpr friend fix equal_to(const fix& l, const fix& r) { using vmath_hpp::equal_to; return fix{equal_to(l.underlying(), r.underlying())}; } + constexpr friend fix not_equal_to(const fix& l, const fix& r) { using vmath_hpp::not_equal_to; return fix{not_equal_to(l.underlying(), r.underlying())}; } + + // + + constexpr friend fix radians(const fix& l) { using vmath_hpp::radians; return fix{radians(l.underlying())}; } + constexpr friend fix degrees(const fix& l) { using vmath_hpp::degrees; return fix{degrees(l.underlying())}; } + constexpr friend fix sin(const fix& l) { using vmath_hpp::sin; return fix{sin(l.underlying())}; } + constexpr friend fix cos(const fix& l) { using vmath_hpp::cos; return fix{cos(l.underlying())}; } + constexpr friend fix tan(const fix& l) { using vmath_hpp::tan; return fix{tan(l.underlying())}; } + constexpr friend fix asin(const fix& l) { using vmath_hpp::asin; return fix{asin(l.underlying())}; } + constexpr friend fix acos(const fix& l) { using vmath_hpp::acos; return fix{acos(l.underlying())}; } + constexpr friend fix atan(const fix& l) { using vmath_hpp::atan; return fix{atan(l.underlying())}; } + constexpr friend fix atan2(const fix& l, const fix& r) { using vmath_hpp::atan2; return fix{atan2(l.underlying(), r.underlying())}; } + constexpr friend fix sinh(const fix& l) { using vmath_hpp::sinh; return fix{sinh(l.underlying())}; } + constexpr friend fix cosh(const fix& l) { using vmath_hpp::cosh; return fix{cosh(l.underlying())}; } + constexpr friend fix tanh(const fix& l) { using vmath_hpp::tanh; return fix{tanh(l.underlying())}; } + constexpr friend fix asinh(const fix& l) { using vmath_hpp::asinh; return fix{asinh(l.underlying())}; } + constexpr friend fix acosh(const fix& l) { using vmath_hpp::acosh; return fix{acosh(l.underlying())}; } + constexpr friend fix atanh(const fix& l) { using vmath_hpp::atanh; return fix{atanh(l.underlying())}; } + constexpr friend std::pair sincos(const fix& l) { return { sin(l), cos(l) }; } + constexpr friend void sincos(const fix& l, fix* s, fix* c) { *s = sin(l); *c = cos(l); } + + // + + constexpr friend fix pow(const fix& l, const fix& r) { using vmath_hpp::pow; return fix{pow(l.underlying(), r.underlying())}; } + constexpr friend fix exp(const fix& l) { using vmath_hpp::exp; return fix{exp(l.underlying())}; } + constexpr friend fix log(const fix& l) { using vmath_hpp::log; return fix{log(l.underlying())}; } + constexpr friend fix exp2(const fix& l) { using vmath_hpp::exp2; return fix{exp2(l.underlying())}; } + constexpr friend fix log2(const fix& l) { using vmath_hpp::log2; return fix{log2(l.underlying())}; } + constexpr friend fix sqrt(const fix& l) { using vmath_hpp::sqrt; return fix{sqrt(l.underlying())}; } + constexpr friend fix rsqrt(const fix& l) { using vmath_hpp::rsqrt; return fix{rsqrt(l.underlying())}; } + + // + + constexpr friend fix operator+(const fix& l) { return { fix{+l.underlying()} }; } + constexpr friend fix operator-(const fix& l) { return { fix{-l.underlying()} }; } + constexpr friend fix operator~(const fix& l) { return { fix{~l.underlying()} }; } + constexpr friend fix operator!(const fix& l) { return { fix{!l.underlying()} }; } + + constexpr friend fix operator+(const fix& l, const fix& r) { return fix{l.underlying() + r.underlying()}; } + constexpr friend fix operator-(const fix& l, const fix& r) { return fix{l.underlying() - r.underlying()}; } + constexpr friend fix operator*(const fix& l, const fix& r) { return fix{l.underlying() * r.underlying()}; } + constexpr friend fix operator/(const fix& l, const fix& r) { return fix{l.underlying() / r.underlying()}; } + + constexpr friend fix operator&(const fix& l, const fix& r) { return fix{l.underlying() & r.underlying()}; } + constexpr friend fix operator|(const fix& l, const fix& r) { return fix{l.underlying() | r.underlying()}; } + constexpr friend fix operator^(const fix& l, const fix& r) { return fix{l.underlying() ^ r.underlying()}; } + + constexpr friend fix operator&&(const fix& l, const fix& r) { return fix{l.underlying() && r.underlying()}; } + constexpr friend fix operator||(const fix& l, const fix& r) { return fix{l.underlying() || r.underlying()}; } + + constexpr friend bool operator<(const fix& l, const fix& r) { return l.underlying() < r.underlying(); } + constexpr friend bool operator==(const fix& l, const fix& r) { return l.underlying() == r.underlying(); } + constexpr friend bool operator!=(const fix& l, const fix& r) { return l.underlying() != r.underlying(); } + private: + T underlying_{}; + }; + + using namespace vmath_hpp; + using namespace vmath_tests; + + using qfix = qua>; + + using fix2b = vec, 2>; + using fix3b = vec, 3>; + using fix4b = vec, 4>; + + using fix2i = vec, 2>; + using fix3i = vec, 3>; + using fix4i = vec, 4>; + + using fix2f = vec, 2>; + using fix3f = vec, 3>; + using fix4f = vec, 4>; + + using fix2x2b = mat, 2>; + using fix3x3b = mat, 3>; + using fix4x4b = mat, 4>; + + using fix2x2i = mat, 2>; + using fix3x3i = mat, 3>; + using fix4x4i = mat, 4>; + + using fix2x2f = mat, 2>; + using fix3x3f = mat, 3>; + using fix4x4f = mat, 4>; +} + +// +// Common Functions +// + +namespace vmath_hpp +{ + template fix2f abs(const fix2f&); + template fix2f sqr(const fix2f&); + template fix2f sign(const fix2f&); + + template fix2f rcp(const fix2f&); + template fix2f floor(const fix2f&); + template fix2f trunc(const fix2f&); + template fix2f round(const fix2f&); + template fix2f ceil(const fix2f&); + template fix2f fract(const fix2f&); + + template fix2f fmod(const fix2f&, fix); + template fix2f fmod(const fix2f&, const fix2f&); + + template fix2f modf(const fix2f&, fix2f*); + + template fix2f copysign(const fix2f&, fix); + template fix2f copysign(const fix2f&, const fix2f&); + + template fix min(const fix2f&); + template fix2f min(const fix2f&, fix); + template fix2f min(fix, const fix2f&); + template fix2f min(const fix2f&, const fix2f&); + + template fix max(const fix2f&); + template fix2f max(const fix2f&, fix); + template fix2f max(fix, const fix2f&); + template fix2f max(const fix2f&, const fix2f&); + + template fix2f clamp(const fix2f&, fix, fix); + template fix2f clamp(const fix2f&, const fix2f&, const fix2f&); + + template fix2f saturate(const fix2f&); + + template fix2f lerp(const fix2f&, const fix2f&, fix); + template fix2f lerp(const fix2f&, const fix2f&, fix, fix); + template fix2f lerp(const fix2f&, const fix2f&, const fix2f&); + template fix2f lerp(const fix2f&, const fix2f&, const fix2f&, const fix2f&); + + template fix2f step(fix, const fix2f&); + template fix2f step(const fix2f&, const fix2f&); + template fix2f smoothstep(fix, fix, const fix2f&); + template fix2f smoothstep(const fix2f&, const fix2f&, const fix2f&); +} + +namespace vmath_hpp +{ + template qfix lerp(const qfix&, const qfix&, fix); + template qfix lerp(const qfix&, const qfix&, fix, fix); + template qfix nlerp(const qfix&, const qfix&, fix); + template qfix slerp(const qfix&, const qfix&, fix); +} + +// +// Angle and Trigonometric Functions +// + +namespace vmath_hpp +{ + template fix2f radians(const fix2f&); + template fix2f degrees(const fix2f&); + template fix2f sin(const fix2f&); + template fix2f cos(const fix2f&); + template fix2f tan(const fix2f&); + template fix2f asin(const fix2f&); + template fix2f acos(const fix2f&); + template fix2f atan(const fix2f&); + template fix2f atan2(const fix2f&, const fix2f&); + template fix2f sinh(const fix2f&); + template fix2f cosh(const fix2f&); + template fix2f tanh(const fix2f&); + template fix2f asinh(const fix2f&); + template fix2f acosh(const fix2f&); + template fix2f atanh(const fix2f&); + template std::pair sincos(const fix2f&); + template void sincos(const fix2f&, fix2f*, fix2f*); +} + +// +// Exponential Functions +// + +namespace vmath_hpp +{ + template fix2f pow(const fix2f&, const fix2f&); + template fix2f exp(const fix2f&); + template fix2f log(const fix2f&); + template fix2f exp2(const fix2f&); + template fix2f log2(const fix2f&); + template fix2f sqrt(const fix2f&); + template fix2f rsqrt(const fix2f&); +} + +// +// Geometric Functions +// + +namespace vmath_hpp +{ + template fix dot(const fix2f&, const fix2f&); + template fix length(const fix2f&); + template fix rlength(const fix2f&); + template fix length2(const fix2f&); + template fix rlength2(const fix2f&); + template fix distance(const fix2f&, const fix2f&); + template fix distance2(const fix2f&, const fix2f&); + template fix cross(const fix2f&, const fix2f&); + template fix3f cross(const fix3f&, const fix3f&); + template fix2f normalize(const fix2f&); + template fix3f faceforward(const fix3f&, const fix3f&, const fix3f&); + template fix3f reflect(const fix3f&, const fix3f&); + template fix3f refract(const fix3f&, const fix3f&, fix); +} + +namespace vmath_hpp +{ + template fix dot(const qfix&, const qfix&); + template fix length(const qfix&); + template fix rlength(const qfix&); + template fix length2(const qfix&); + template fix rlength2(const qfix&); + template fix distance(const qfix&, const qfix&); + template qfix normalize(const qfix&); +} + +// +// Relational Functions +// + +namespace vmath_hpp +{ + template fix any(const fix2f&); + template fix all(const fix2f&); + template fix2b approx(const fix2f&, const fix2f&); + template fix2b approx(const fix2f&, const fix2f&, fix); + template fix2b less(const fix2f&, const fix2f&); + template fix2b less_equal(const fix2f&, const fix2f&); + template fix2b greater(const fix2f&, const fix2f&); + template fix2b greater_equal(const fix2f&, const fix2f&); + template fix2b equal_to(const fix2f&, const fix2f&); + template fix2b not_equal_to(const fix2f&, const fix2f&); +} + +namespace vmath_hpp +{ + template fix any(const fix2x2f&); + template fix all(const fix2x2f&); + template fix2x2b approx(const fix2x2f&, const fix2x2f&); + template fix2x2b approx(const fix2x2f&, const fix2x2f&, fix); + template fix2x2b less(const fix2x2f&, const fix2x2f&); + template fix2x2b less_equal(const fix2x2f&, const fix2x2f&); + template fix2x2b greater(const fix2x2f&, const fix2x2f&); + template fix2x2b greater_equal(const fix2x2f&, const fix2x2f&); + template fix2x2b equal_to(const fix2x2f&, const fix2x2f&); + template fix2x2b not_equal_to(const fix2x2f&, const fix2x2f&); +} + +namespace vmath_hpp +{ + template fix any(const qfix&); + template fix all(const qfix&); + template fix4b approx(const qfix&, const qfix&); + template fix4b approx(const qfix&, const qfix&, fix); + template fix4b less(const qfix&, const qfix&); + template fix4b less_equal(const qfix&, const qfix&); + template fix4b greater(const qfix&, const qfix&); + template fix4b greater_equal(const qfix&, const qfix&); + template fix4b equal_to(const qfix&, const qfix&); + template fix4b not_equal_to(const qfix&, const qfix&); +} + +// +// Matrix Functions +// + +namespace vmath_hpp +{ + template fix2x2f transpose(const fix2x2f&); + template fix3x3f transpose(const fix3x3f&); + template fix4x4f transpose(const fix4x4f&); + + template fix determinant(const fix2x2f&); + template fix determinant(const fix3x3f&); + template fix determinant(const fix4x4f&); + + template fix2x2f inverse(const fix2x2f&); + template fix3x3f inverse(const fix3x3f&); + template fix4x4f inverse(const fix4x4f&); +} + +// +// Quaternion Functions +// + +namespace vmath_hpp +{ + template qfix conjugate(const qfix&); + template qfix inverse(const qfix&); +} + +// +// Access +// + +namespace vmath_hpp +{ + template fix component(const fix2f&, std::size_t); + template fix2f component(fix2f, std::size_t, fix); + + template fix2f row(const fix2x2f&, std::size_t); + template fix2x2f row(fix2x2f, std::size_t, const fix2f&); + + template fix2f column(const fix2x2f&, std::size_t); + template fix2x2f column(const fix2x2f&, std::size_t, const fix2f&); + + template fix real(const qfix&); + template qfix real(qfix, fix); + + template fix3f imag(const qfix&); + template qfix imag(qfix, const fix3f&); +} + +// +// Matrix Transform 3D +// + +namespace vmath_hpp +{ + template fix4x4f translate(fix x, fix y, fix z); + template fix4x4f translate(const fix4x4f&, fix, fix, fix); + template fix4x4f translate(const fix3f&); + template fix4x4f translate(const fix4x4f&, const fix3f&); + + template fix4x4f rotate(const qfix&); + template fix4x4f rotate(const fix4x4f&, const qfix&); + template fix4x4f rotate(fix, const fix3f&); + template fix4x4f rotate(const fix4x4f&, fix, const fix3f&); + + template fix4x4f rotate_x(fix); + template fix4x4f rotate_x(const fix4x4f&, fix); + + template fix4x4f rotate_y(fix); + template fix4x4f rotate_y(const fix4x4f&, fix); + + template fix4x4f rotate_z(fix); + template fix4x4f rotate_z(const fix4x4f&, fix); + + template fix4x4f scale(fix, fix, fix); + template fix4x4f scale(const fix4x4f&, fix, fix, fix); + template fix4x4f scale(const fix3f&); + template fix4x4f scale(const fix4x4f&, const fix3f&); + + template fix4x4f look_at_lh(const fix3f&, const fix3f&, const fix3f&); + template fix4x4f look_at_rh(const fix3f&, const fix3f&, const fix3f&); +} + +// +// Matrix Transform 2D +// + +namespace vmath_hpp +{ + template fix3x3f translate(fix, fix); + template fix3x3f translate(const fix3x3f&, fix, fix); + template fix3x3f translate(const fix2f&); + template fix3x3f translate(const fix3x3f&, const fix2f&); + + template fix3x3f rotate(fix); + template fix3x3f rotate(const fix3x3f&, fix); + + template fix3x3f scale(fix, fix); + template fix3x3f scale(const fix3x3f&, fix, fix); + template fix3x3f scale(const fix2f&); + template fix3x3f scale(const fix3x3f&, const fix2f&); + + template fix3x3f shear(fix, fix); + template fix3x3f shear(const fix3x3f&, fix, fix); + template fix3x3f shear(const fix2f&); + template fix3x3f shear(const fix3x3f&, const fix2f&); + + template fix3x3f shear_x(fix); + template fix3x3f shear_x(const fix3x3f&, fix); + + template fix3x3f shear_y(fix); + template fix3x3f shear_y(const fix3x3f&, fix); +} + +// +// Matrix Projections +// + +namespace vmath_hpp +{ + template fix4x4f orthographic_lh(fix, fix, fix, fix); + template fix4x4f orthographic_rh(fix, fix, fix, fix); + + template fix4x4f orthographic_lh(fix, fix, fix, fix, fix, fix); + template fix4x4f orthographic_rh(fix, fix, fix, fix, fix, fix); + + template fix4x4f perspective_lh(fix, fix, fix, fix); + template fix4x4f perspective_rh(fix, fix, fix, fix); + + template fix4x4f perspective_lh(fix, fix, fix, fix, fix, fix); + template fix4x4f perspective_rh(fix, fix, fix, fix, fix, fix); + + template fix4x4f perspective_fov_lh(fix, fix, fix, fix); + template fix4x4f perspective_fov_rh(fix, fix, fix, fix); +} + +// +// Vector Transform +// + +namespace vmath_hpp +{ + template fix angle(const fix3f&, const fix3f&); + template fix2f rotate(const fix2f&, fix); + template fix3f rotate_x(const fix3f&, fix); + template fix3f rotate_y(const fix3f&, fix); + template fix3f rotate_z(const fix3f&, fix); + template fix3f rotate(const fix3f&, const qfix&); + template fix3f rotate(const fix3f&, fix, const fix3f&); + template fix3f project(const fix3f&, const fix3f&); + template fix3f perpendicular(const fix3f&, const fix3f&); +} + +// +// Quaternion Transform +// + +namespace vmath_hpp +{ + template qfix qrotate(const fix3x3f&); + template qfix qrotate(const qfix&, const fix3x3f&); + + template qfix qrotate(const fix3f&, const fix3f&); + template qfix qrotate(const qfix&, const fix3f&, const fix3f&); + + template qfix qrotate(fix, const fix3f&); + template qfix qrotate(const qfix&, fix, const fix3f&); + + template qfix qrotate_x(fix); + template qfix qrotate_x(const qfix&, fix); + + template qfix qrotate_y(fix); + template qfix qrotate_y(const qfix&, fix); + + template qfix qrotate_z(fix); + template qfix qrotate_z(const qfix&, fix); + + template qfix qlook_at_lh(const fix3f&, const fix3f&); + template qfix qlook_at_rh(const fix3f&, const fix3f&); +} + +// +// fix_vec +// + +TEST_CASE("vmath/fix_vec") { + SUBCASE("fix2 ctors") { + constexpr fix2i v0{}; + constexpr fix2i v1{fix(1)}; + constexpr fix2i v2{fix(1), fix(2)}; + constexpr fix2i v3{fix3i{fix(1), fix(2), fix(3)}}; + constexpr fix2i v4{fix4i{fix(1), fix(2), fix(3), fix(4)}}; + + STATIC_CHECK((v0[0] == fix(0))); + STATIC_CHECK((v1[0] == fix(1) && v1[1] == fix(1))); + STATIC_CHECK((v2[0] == fix(1) && v2[1] == fix(2))); + STATIC_CHECK((v3[0] == fix(1) && v3[1] == fix(2))); + STATIC_CHECK((v4[0] == fix(1) && v4[1] == fix(2))); + } + + SUBCASE("fix3 ctors") { + constexpr fix3i v0{}; + constexpr fix3i v1{fix(1)}; + constexpr fix3i v2{fix(1), fix(2), fix(3)}; + constexpr fix3i v3{fix2i{fix(1), fix(2)}, fix(3)}; + constexpr fix3i v4{fix(1), fix2i{fix(2), fix(3)}}; + constexpr fix3i v5{fix4i{fix(1), fix(2), fix(3), fix(4)}}; + + STATIC_CHECK((v0[0] == fix(0))); + STATIC_CHECK((v1[0] == fix(1) && v1[1] == fix(1) && v1[2] == fix(1))); + STATIC_CHECK((v2[0] == fix(1) && v2[1] == fix(2) && v2[2] == fix(3))); + STATIC_CHECK((v3[0] == fix(1) && v3[1] == fix(2) && v3[2] == fix(3))); + STATIC_CHECK((v4[0] == fix(1) && v4[1] == fix(2) && v4[2] == fix(3))); + STATIC_CHECK((v5[0] == fix(1) && v5[1] == fix(2) && v5[2] == fix(3))); + } + + SUBCASE("fix4 ctors") { + constexpr fix4i v0{}; + constexpr fix4i v1{fix(1)}; + constexpr fix4i v2{fix(1), fix(2), fix(3), fix(4)}; + constexpr fix4i v3{fix2i{fix(1), fix(2)}, fix(3), fix(4)}; + constexpr fix4i v4{fix(1), fix2i{fix(2), fix(3)}, fix(4)}; + constexpr fix4i v5{fix(1), fix(2), fix2i{fix(3), fix(4)}}; + constexpr fix4i v6{fix2i{fix(1), fix(2)}, fix2i{fix(3), fix(4)}}; + constexpr fix4i v7{fix3i{fix(1), fix(2), fix(3)}, fix(4)}; + constexpr fix4i v8{fix(1), fix3i{fix(2), fix(3), fix(4)}}; + + STATIC_CHECK((v0.at(0) == fix(0))); + STATIC_CHECK((v1.at(0) == fix(1) && v1.at(1) == fix(1) && v1.at(2) == fix(1) && v1.at(3) == fix(1))); + STATIC_CHECK((v2.at(0) == fix(1) && v2.at(1) == fix(2) && v2.at(2) == fix(3) && v2.at(3) == fix(4))); + STATIC_CHECK((v3.at(0) == fix(1) && v3.at(1) == fix(2) && v3.at(2) == fix(3) && v3.at(3) == fix(4))); + STATIC_CHECK((v4.at(0) == fix(1) && v4.at(1) == fix(2) && v4.at(2) == fix(3) && v4.at(3) == fix(4))); + STATIC_CHECK((v5.at(0) == fix(1) && v5.at(1) == fix(2) && v5.at(2) == fix(3) && v5.at(3) == fix(4))); + STATIC_CHECK((v6.at(0) == fix(1) && v6.at(1) == fix(2) && v6.at(2) == fix(3) && v6.at(3) == fix(4))); + STATIC_CHECK((v7.at(0) == fix(1) && v7.at(1) == fix(2) && v7.at(2) == fix(3) && v7.at(3) == fix(4))); + STATIC_CHECK((v8.at(0) == fix(1) && v8.at(1) == fix(2) && v8.at(2) == fix(3) && v8.at(3) == fix(4))); + } + + SUBCASE("swap") { + { + vec v0{fix(1), fix(2)}; + vec v1{fix(3), fix(4)}; + swap(v0, v1); + CHECK(v0 == fix2i(fix(3),fix(4))); + CHECK(v1 == fix2i(fix(1),fix(2))); + } + { + vec v0{fix{1},fix{2},fix{3}}; + vec v1{fix2i{fix(3),fix(4)}, fix{5}}; + swap(v0, v1); + CHECK(v0 == fix3i(fix(3),fix(4),fix(5))); + CHECK(v1 == fix3i(fix(1),fix(2),fix(3))); + } + { + vec v0{fix{1},fix{2},fix{3},fix{4}}; + vec v1{fix{3},fix3i{fix(4),fix(5),fix(6)}}; + swap(v0, v1); + CHECK(v0 == fix4i(fix(3),fix(4),fix(5),fix(6))); + CHECK(v1 == fix4i(fix(1),fix(2),fix(3),fix(4))); + } + } + + SUBCASE("operators") { + fix2b vb{}; + fix2i vi{}; + bool b{}; + + vi = {+fix2i{fix(1),fix(2)}}; + vi = {-fix2i{fix(1),fix(2)}}; + vi = {~fix2i{fix(1),fix(2)}}; + vb = {!fix2i{fix(1),fix(2)}}; + + vi = {fix2i{fix(1),fix(2)} + fix{3}}; + vi = {fix{3} + fix2i{fix(1),fix(2)}}; + vi = {fix2i{fix(1),fix(2)} + fix2i{fix(1),fix(2)}}; + + vi = {fix2i{fix(1),fix(2)} - fix{3}}; + vi = {fix{3} - fix2i{fix(1),fix(2)}}; + vi = {fix2i{fix(1),fix(2)} - fix2i{fix(1),fix(2)}}; + + vi = {fix2i{fix(1),fix(2)} * fix{3}}; + vi = {fix{3} * fix2i{fix(1),fix(2)}}; + vi = {fix2i{fix(1),fix(2)} * fix2i{fix(1),fix(2)}}; + + vi = {fix2i{fix(1),fix(2)} / fix{3}}; + vi = {fix{3} / fix2i{fix(1),fix(2)}}; + vi = {fix2i{fix(1),fix(2)} / fix2i{fix(1),fix(2)}}; + + vi = {fix2i{fix(1),fix(2)} & fix{3}}; + vi = {fix{3} & fix2i{fix(1),fix(2)}}; + vi = {fix2i{fix(1),fix(2)} & fix2i{fix(1),fix(2)}}; + + vi = {fix2i{fix(1),fix(2)} | fix{3}}; + vi = {fix{3} | fix2i{fix(1),fix(2)}}; + vi = {fix2i{fix(1),fix(2)} | fix2i{fix(1),fix(2)}}; + + vi = {fix2i{fix(1),fix(2)} ^ fix{3}}; + vi = {fix{3} ^ fix2i{fix(1),fix(2)}}; + vi = {fix2i{fix(1),fix(2)} ^ fix2i{fix(1),fix(2)}}; + + vb = {fix2i{fix(1),fix(2)} && fix{3}}; + vb = {fix{3} && fix2i{fix(1),fix(2)}}; + vb = {fix2i{fix(1),fix(2)} && fix2i{fix(1),fix(2)}}; + + vb = {fix2i{fix(1),fix(2)} || fix{3}}; + vb = {fix{3} || fix2i{fix(1),fix(2)}}; + vb = {fix2i{fix(1),fix(2)} || fix2i{fix(1),fix(2)}}; + + b = {fix2i{fix(1),fix(2)} == fix2i{fix(1),fix(2)}}; + b = {fix2i{fix(1),fix(2)} != fix2i{fix(1),fix(2)}}; + b = {fix2i{fix(1),fix(2)} < fix2i{fix(1),fix(2)}}; + + CHECK_FALSE(b); + + { + vi = {vi += fix{3}}; + vi = {vi += fix2i{fix(4),fix(5)}}; + vi = {vi -= fix{3}}; + vi = {vi -= fix2i{fix(4),fix(5)}}; + vi = {vi *= fix{3}}; + vi = {vi *= fix2i{fix(4),fix(5)}}; + vi = {vi /= fix{3}}; + vi = {vi /= fix2i{fix(4),fix(5)}}; + vi = {vi &= fix{3}}; + vi = {vi &= fix2i{fix(4),fix(5)}}; + vi = {vi |= fix{3}}; + vi = {vi |= fix2i{fix(4),fix(5)}}; + vi = {vi ^= fix{3}}; + vi = {vi ^= fix2i{fix(4),fix(5)}}; + } + } +} + +// +// fix_mat +// + +TEST_CASE("vmath/fix_mat") { + SUBCASE("fix2x2 ctors") { + constexpr fix2x2i v0{}; + constexpr fix2x2i v1{fix(2)}; + constexpr fix2x2i v2{fix2i{fix(1), fix(2)}}; + constexpr fix2x2i v3{fix(1), fix(2), fix(3), fix(4)}; + constexpr fix2x2i v4{{fix(1), fix(2)}, {fix(3), fix(4)}}; + constexpr fix2x2i v5{fix3x3i{fix(1)}}; + constexpr fix2x2i v6{fix4x4i{fix(1)}}; + + STATIC_CHECK((v0[0] == fix2i(fix(1),fix(0)) && v0[1] == fix2i(fix(0),fix(1)))); + STATIC_CHECK((v1[0] == fix2i(fix(2),fix(0)) && v1[1] == fix2i(fix(0),fix(2)))); + STATIC_CHECK((v2[0] == fix2i(fix(1),fix(0)) && v2[1] == fix2i(fix(0),fix(2)))); + STATIC_CHECK((v3[0] == fix2i(fix(1),fix(2)) && v3[1] == fix2i(fix(3),fix(4)))); + STATIC_CHECK((v4[0] == fix2i(fix(1),fix(2)) && v4[1] == fix2i(fix(3),fix(4)))); + STATIC_CHECK((v5[0] == fix2i(fix(1),fix(0)) && v5[1] == fix2i(fix(0),fix(1)))); + STATIC_CHECK((v6[0] == fix2i(fix(1),fix(0)) && v6[1] == fix2i(fix(0),fix(1)))); + } + + SUBCASE("fix3x3 ctors") { + constexpr fix3x3i v0{}; + constexpr fix3x3i v1{fix(2)}; + constexpr fix3x3i v2{fix3i{fix(1), fix(2), fix(3)}}; + constexpr fix3x3i v3{fix(1),fix(2),fix(3),fix(4),fix(5),fix(6),fix(7),fix(8),fix(9)}; + constexpr fix3x3i v4{{fix(1),fix(2),fix(3)},{fix(4),fix(5),fix(6)},{fix(7),fix(8),fix(9)}}; + constexpr fix3x3i v5{fix2x2i{fix(1)},fix2i{fix(0)}}; + constexpr fix3x3i v6{fix2x2i{fix(1)}}; + constexpr fix3x3i v7{fix4x4i{fix(1)}}; + + STATIC_CHECK((v0[0] == fix3i(fix(1),fix(0),fix(0)) && v0[1] == fix3i(fix(0),fix(1),fix(0)) && v0[2] == fix3i(fix(0),fix(0),fix(1)))); + STATIC_CHECK((v1[0] == fix3i(fix(2),fix(0),fix(0)) && v1[1] == fix3i(fix(0),fix(2),fix(0)) && v1[2] == fix3i(fix(0),fix(0),fix(2)))); + STATIC_CHECK((v2[0] == fix3i(fix(1),fix(0),fix(0)) && v2[1] == fix3i(fix(0),fix(2),fix(0)) && v2[2] == fix3i(fix(0),fix(0),fix(3)))); + STATIC_CHECK((v3[0] == fix3i(fix(1),fix(2),fix(3)) && v3[1] == fix3i(fix(4),fix(5),fix(6)) && v3[2] == fix3i(fix(7),fix(8),fix(9)))); + STATIC_CHECK((v4[0] == fix3i(fix(1),fix(2),fix(3)) && v4[1] == fix3i(fix(4),fix(5),fix(6)) && v4[2] == fix3i(fix(7),fix(8),fix(9)))); + STATIC_CHECK((v5[0] == fix3i(fix(1),fix(0),fix(0)) && v5[1] == fix3i(fix(0),fix(1),fix(0)) && v5[2] == fix3i(fix(0),fix(0),fix(1)))); + STATIC_CHECK((v6[0] == fix3i(fix(1),fix(0),fix(0)) && v6[1] == fix3i(fix(0),fix(1),fix(0)) && v6[2] == fix3i(fix(0),fix(0),fix(1)))); + STATIC_CHECK((v7[0] == fix3i(fix(1),fix(0),fix(0)) && v7[1] == fix3i(fix(0),fix(1),fix(0)) && v7[2] == fix3i(fix(0),fix(0),fix(1)))); + } + + SUBCASE("fix4x4 ctors") { + constexpr fix4x4i v0{}; + constexpr fix4x4i v1{fix(2)}; + constexpr fix4x4i v2{fix4i{fix(1),fix(2),fix(3),fix(4)}}; + constexpr fix4x4i v3{fix(1),fix(2),fix(3),fix(4),fix(5),fix(6),fix(7),fix(8),fix(9),fix(10),fix(11),fix(12),fix(13),fix(14),fix(15),fix(16)}; + constexpr fix4x4i v4{{fix(1),fix(2),fix(3),fix(4)},{fix(5),fix(6),fix(7),fix(8)},{fix(9),fix(10),fix(11),fix(12)},{fix(13),fix(14),fix(15),fix(16)}}; + constexpr fix4x4i v5{fix3x3i{fix(1)},fix3i{fix(0)}}; + constexpr fix4x4i v6{fix2x2i{fix(1)}}; + constexpr fix4x4i v7{fix3x3i{fix(1)}}; + + STATIC_CHECK((v0[0] == fix4i(fix(1),fix(0),fix(0),fix(0)) && v0[1] == fix4i(fix(0),fix(1),fix(0),fix(0)) && v0[2] == fix4i(fix(0),fix(0),fix(1),fix(0)) && v0[3] == fix4i(fix(0),fix(0),fix(0),fix(1)))); + STATIC_CHECK((v1[0] == fix4i(fix(2),fix(0),fix(0),fix(0)) && v1[1] == fix4i(fix(0),fix(2),fix(0),fix(0)) && v1[2] == fix4i(fix(0),fix(0),fix(2),fix(0)) && v1[3] == fix4i(fix(0),fix(0),fix(0),fix(2)))); + STATIC_CHECK((v2[0] == fix4i(fix(1),fix(0),fix(0),fix(0)) && v2[1] == fix4i(fix(0),fix(2),fix(0),fix(0)) && v2[2] == fix4i(fix(0),fix(0),fix(3),fix(0)) && v2[3] == fix4i(fix(0),fix(0),fix(0),fix(4)))); + STATIC_CHECK((v3[0] == fix4i(fix(1),fix(2),fix(3),fix(4)) && v3[1] == fix4i(fix(5),fix(6),fix(7),fix(8)) && v3[2] == fix4i(fix(9),fix(10),fix(11),fix(12)) && v3[3] == fix4i(fix(13),fix(14),fix(15),fix(16)))); + STATIC_CHECK((v4[0] == fix4i(fix(1),fix(2),fix(3),fix(4)) && v4[1] == fix4i(fix(5),fix(6),fix(7),fix(8)) && v4[2] == fix4i(fix(9),fix(10),fix(11),fix(12)) && v4[3] == fix4i(fix(13),fix(14),fix(15),fix(16)))); + STATIC_CHECK((v5[0] == fix4i(fix(1),fix(0),fix(0),fix(0)) && v5[1] == fix4i(fix(0),fix(1),fix(0),fix(0)) && v5[2] == fix4i(fix(0),fix(0),fix(1),fix(0)) && v5[3] == fix4i(fix(0),fix(0),fix(0),fix(1)))); + STATIC_CHECK((v6[0] == fix4i(fix(1),fix(0),fix(0),fix(0)) && v6[1] == fix4i(fix(0),fix(1),fix(0),fix(0)) && v6[2] == fix4i(fix(0),fix(0),fix(1),fix(0)) && v6[3] == fix4i(fix(0),fix(0),fix(0),fix(1)))); + STATIC_CHECK((v7[0] == fix4i(fix(1),fix(0),fix(0),fix(0)) && v7[1] == fix4i(fix(0),fix(1),fix(0),fix(0)) && v7[2] == fix4i(fix(0),fix(0),fix(1),fix(0)) && v7[3] == fix4i(fix(0),fix(0),fix(0),fix(1)))); + } + + SUBCASE("swap") { + { + fix2x2i v0{fix(1)}; + fix2x2i v1{fix(2)}; + swap(v0, v1); + CHECK(v0 == fix2x2i(fix(2))); + CHECK(v1 == fix2x2i(fix(1))); + } + { + fix3x3i v0{fix(1)}; + fix3x3i v1{fix(2)}; + swap(v0, v1); + CHECK(v0 == fix3x3i(fix(2))); + CHECK(v1 == fix3x3i(fix(1))); + } + { + fix4x4i v0{fix(1)}; + fix4x4i v1{fix(2)}; + swap(v0, v1); + CHECK(v0 == fix4x4i(fix(2))); + CHECK(v1 == fix4x4i(fix(1))); + } + } + + SUBCASE("operators") { + fix2x2b mb{}; + fix2x2i mi{}; + fix2i vi{}; + bool b{}; + + mi = {+fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + mi = {-fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + mi = {~fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + mb = {!fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} + fix{3}}; + mi = {fix{3} + fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} + fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} - fix{3}}; + mi = {fix{3} - fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} - fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} * fix{3}}; + mi = {fix{3} * fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + vi = {vi * mi}; + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} * fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} / fix{3}}; + mi = {fix{3} / fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + // mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} / fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} & fix{3}}; + mi = {fix{3} & fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} & fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} | fix{3}}; + mi = {fix{3} | fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} | fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} ^ fix{3}}; + mi = {fix{3} ^ fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + mi = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} ^ fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + + mb = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} && fix{3}}; + mb = {fix{3} && fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + mb = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} && fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + + mb = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} || fix{3}}; + mb = {fix{3} || fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + mb = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} || fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + + b = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} == fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + b = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} != fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + b = {fix2x2i{fix(1),fix(2),fix(3),fix(4)} < fix2x2i{fix(1),fix(2),fix(3),fix(4)}}; + + CHECK_FALSE(b); + + { + mi = {mi += fix{3}}; + mi = {mi += fix2x2i{fix(4),fix(5),fix(6),fix(7)}}; + mi = {mi -= fix{3}}; + mi = {mi -= fix2x2i{fix(4),fix(5),fix(6),fix(7)}}; + mi = {mi *= fix{3}}; + vi = {vi *= fix2x2i{fix(4),fix(5),fix(6),fix(7)}}; + mi = {mi *= fix2x2i{fix(4),fix(5),fix(6),fix(7)}}; + mi = {mi /= fix{3}}; + //mi = {mi /= fix2x2i{fix(4),fix(5),fix(6),fix(7)}}; + mi = {mi &= fix{3}}; + mi = {mi &= fix2x2i{fix(4),fix(5),fix(6),fix(7)}}; + mi = {mi |= fix{3}}; + mi = {mi |= fix2x2i{fix(4),fix(5),fix(6),fix(7)}}; + mi = {mi ^= fix{3}}; + mi = {mi ^= fix2x2i{fix(4),fix(5),fix(6),fix(7)}}; + } + } +} + +// +// fix_qua +// + +TEST_CASE("vmath/fix_qua") { + SUBCASE("ctors") { + constexpr qfix v0{}; + constexpr qfix v1{fix(1.f), fix(2.f), fix(3.f), fix(4.f)}; + constexpr qfix v2{fix3f{fix(1.f), fix(2.f), fix(3.f)}, fix(4.f)}; + constexpr qfix v3{fix4f{fix(1.f), fix(2.f), fix(3.f), fix(4.f)}}; + + STATIC_CHECK((v0.at(0) == fix(0.f))); + STATIC_CHECK((v1.at(0) == fix(1.f) && v1.at(1) == fix(2.f) && v1.at(2) == fix(3.f) && v1.at(3) == fix(4.f))); + STATIC_CHECK((v2.at(0) == fix(1.f) && v2.at(1) == fix(2.f) && v2.at(2) == fix(3.f) && v2.at(3) == fix(4.f))); + STATIC_CHECK((v3.at(0) == fix(1.f) && v3.at(1) == fix(2.f) && v3.at(2) == fix(3.f) && v3.at(3) == fix(4.f))); + } + + SUBCASE("swap") { + qfix v0{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}; + qfix v1{fix(4.f),fix(3.f),fix(2.f),fix(1.f)}; + swap(v0, v1); + CHECK(v0 == qfix(fix(4.f),fix(3.f),fix(2.f),fix(1.f))); + CHECK(v1 == qfix(fix(1.f),fix(2.f),fix(3.f),fix(4.f))); + } + + SUBCASE("operators") { + qfix qf; + fix3f vf; + bool b{}; + + qf = {+qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + qf = {-qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + + qf = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} + qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + qf = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} - qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + qf = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} * fix{1.f}}; + qf = {fix{1.f} * qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + vf = {fix3f{fix(1.f),fix(2.f),fix(3.f)} * qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + qf = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} * qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + qf = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} / fix{1.f}}; + qf = {fix{1.f} / qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + + qf = {qf += qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + qf = {qf -= qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + qf = {qf *= fix{1.f}}; + vf = {vf *= qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + qf = {qf *= qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + qf = {qf /= fix{1.f}}; + + b = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} == qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + b = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} != qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + b = {qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)} < qfix{fix(1.f),fix(2.f),fix(3.f),fix(4.f)}}; + + CHECK_FALSE(b); + } +} + +// +// Units +// + +TEST_CASE("vmath/fix_units") { + { + STATIC_CHECK(zero2> == fix2f{fix(0.f),fix(0.f)}); + STATIC_CHECK(zero3> == fix3f{fix(0.f),fix(0.f),fix(0.f)}); + STATIC_CHECK(zero4> == fix4f{fix(0.f),fix(0.f),fix(0.f),fix(0.f)}); + } + { + STATIC_CHECK(unit2> == fix2f{fix(1.f),fix(1.f)}); + STATIC_CHECK(unit3> == fix3f{fix(1.f),fix(1.f),fix(1.f)}); + STATIC_CHECK(unit4> == fix4f{fix(1.f),fix(1.f),fix(1.f),fix(1.f)}); + } + { + STATIC_CHECK(unit2_x> == fix2f{fix(1.f),fix(0.f)}); + STATIC_CHECK(unit2_y> == fix2f{fix(0.f),fix(1.f)}); + + STATIC_CHECK(unit3_x> == fix3f{fix(1.f),fix(0.f),fix(0.f)}); + STATIC_CHECK(unit3_y> == fix3f{fix(0.f),fix(1.f),fix(0.f)}); + STATIC_CHECK(unit3_z> == fix3f{fix(0.f),fix(0.f),fix(1.f)}); + + STATIC_CHECK(unit4_x> == fix4f{fix(1.f),fix(0.f),fix(0.f),fix(0.f)}); + STATIC_CHECK(unit4_y> == fix4f{fix(0.f),fix(1.f),fix(0.f),fix(0.f)}); + STATIC_CHECK(unit4_z> == fix4f{fix(0.f),fix(0.f),fix(1.f),fix(0.f)}); + STATIC_CHECK(unit4_w> == fix4f{fix(0.f),fix(0.f),fix(0.f),fix(1.f)}); + } + { + STATIC_CHECK(zero2x2> == fix2x2f{ + fix(0.f),fix(0.f), + fix(0.f),fix(0.f)}); + STATIC_CHECK(zero3x3> == fix3x3f{ + fix(0.f),fix(0.f),fix(0.f), + fix(0.f),fix(0.f),fix(0.f), + fix(0.f),fix(0.f),fix(0.f)}); + STATIC_CHECK(zero4x4> == fix4x4f{ + fix(0.f),fix(0.f),fix(0.f),fix(0.f), + fix(0.f),fix(0.f),fix(0.f),fix(0.f), + fix(0.f),fix(0.f),fix(0.f),fix(0.f), + fix(0.f),fix(0.f),fix(0.f),fix(0.f)}); + } + { + STATIC_CHECK(unit2x2> == fix2x2f{ + fix(1.f),fix(1.f), + fix(1.f),fix(1.f)}); + STATIC_CHECK(unit3x3> == fix3x3f{ + fix(1.f),fix(1.f),fix(1.f), + fix(1.f),fix(1.f),fix(1.f), + fix(1.f),fix(1.f),fix(1.f)}); + STATIC_CHECK(unit4x4> == fix4x4f{ + fix(1.f),fix(1.f),fix(1.f),fix(1.f), + fix(1.f),fix(1.f),fix(1.f),fix(1.f), + fix(1.f),fix(1.f),fix(1.f),fix(1.f), + fix(1.f),fix(1.f),fix(1.f),fix(1.f)}); + } + { + STATIC_CHECK(identity2x2> == fix2x2f{ + fix(1.f),fix(0.f), + fix(0.f),fix(1.f)}); + STATIC_CHECK(identity3x3> == fix3x3f{ + fix(1.f),fix(0.f),fix(0.f), + fix(0.f),fix(1.f),fix(0.f), + fix(0.f),fix(0.f),fix(1.f)}); + STATIC_CHECK(identity4x4> == fix4x4f{ + fix(1.f),fix(0.f),fix(0.f),fix(0.f), + fix(0.f),fix(1.f),fix(0.f),fix(0.f), + fix(0.f),fix(0.f),fix(1.f),fix(0.f), + fix(0.f),fix(0.f),fix(0.f),fix(1.f)}); + } + { + STATIC_CHECK(qidentity> == qfix{ + fix(0.f),fix(0.f),fix(0.f), + fix(1.f)}); + } +} diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index 7096730..9903781 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -105,29 +105,21 @@ TEST_CASE("vmath/fun") { STATIC_CHECK(step(0.5f, 0.4f) == uapprox(0.f)); STATIC_CHECK(step(0.5f, 0.6f) == uapprox(1.f)); STATIC_CHECK(smoothstep(0.f, 1.f, 0.1f) == uapprox(0.028f)); - - CHECK_FALSE(vmath_hpp::isnan(1.f)); - CHECK_FALSE(vmath_hpp::isinf(1.f)); - CHECK(vmath_hpp::isfinite(1.f)); - - CHECK(fma(2.f, 3.f, 4.f) == uapprox(10.f)); - - { - int out_exp{}; - CHECK(frexp(1.7f, &out_exp) == uapprox(0.85f)); - CHECK(out_exp == 1); - } - - CHECK(ldexp(0.85f, 1) == uapprox(1.7f)); } SUBCASE("Geometric Functions") { STATIC_CHECK(length(10.f) == uapprox(10.f)); STATIC_CHECK(length(-10.f) == uapprox(10.f)); + STATIC_CHECK(rlength(10.f) == uapprox(0.1f)); + STATIC_CHECK(rlength(-10.f) == uapprox(0.1f)); + STATIC_CHECK(length2(10.f) == uapprox(100.f)); STATIC_CHECK(length2(-10.f) == uapprox(100.f)); + STATIC_CHECK(rlength2(10.f) == uapprox(0.01f)); + STATIC_CHECK(rlength2(-10.f) == uapprox(0.01f)); + STATIC_CHECK(distance(5.f, 10.f) == uapprox(5.f)); STATIC_CHECK(distance(-5.f, -10.f) == uapprox(5.f)); @@ -135,7 +127,7 @@ TEST_CASE("vmath/fun") { STATIC_CHECK(distance2(-5.f, -10.f) == uapprox(25.f)); STATIC_CHECK(dot(2.f, 5.f) == uapprox(10.f)); - CHECK(normalize(0.5f) == uapprox(1.f)); + STATIC_CHECK(normalize(0.5f) == uapprox(1.f)); STATIC_CHECK(faceforward(1.f, 2.f, 3.f) == uapprox(-1.f)); STATIC_CHECK(reflect(1.f, 2.f) == uapprox(-7.f)); diff --git a/untests/vmath_qua_fun_tests.cpp b/untests/vmath_qua_fun_tests.cpp index f56a5e2..80bb33e 100644 --- a/untests/vmath_qua_fun_tests.cpp +++ b/untests/vmath_qua_fun_tests.cpp @@ -128,12 +128,6 @@ TEST_CASE("vmath/qua_fun") { qrotate_z(radians(290.f)), slerp(qrotate_z(radians(220.f)), qrotate_z(radians(0.f)), 0.5f)))); } - - { - CHECK_FALSE(any(isnan(qfloat(1,1,1,1)))); - CHECK_FALSE(any(isinf(qfloat(1,1,1,1)))); - CHECK(all(isfinite(qfloat(1,1,1,1)))); - } } SUBCASE("Geometric Functions") { @@ -142,9 +136,15 @@ TEST_CASE("vmath/qua_fun") { CHECK(length(qfloat(10.f,0.f,0.f,0.f)) == uapprox(10.f)); CHECK(length(qfloat(-10.f,0.f,0.f,0.f)) == uapprox(10.f)); + CHECK(rlength(qfloat(10.f,0.f,0.f,0.f)) == uapprox(0.1f)); + CHECK(rlength(qfloat(-10.f,0.f,0.f,0.f)) == uapprox(0.1f)); + STATIC_CHECK(length2(qfloat(10.f,0.f,0.f,0.f)) == uapprox(100.f)); STATIC_CHECK(length2(qfloat(-10.f,0.f,0.f,0.f)) == uapprox(100.f)); + STATIC_CHECK(rlength2(qfloat(10.f,0.f,0.f,0.f)) == uapprox(0.01f)); + STATIC_CHECK(rlength2(qfloat(-10.f,0.f,0.f,0.f)) == uapprox(0.01f)); + CHECK(distance(qrotate_z(radians(0.f)) * 2.f, qrotate_z(radians(0.f)) * 1.5f) == uapprox(radians(0.f))); CHECK(distance(qrotate_z(radians(0.f)) * 3.f, qrotate_z(radians(360.f)) * 2.5f) == uapprox(radians(0.f))); CHECK(distance(qrotate_z(radians(0.f)) * 4.f, qrotate_z(radians(180.f)) * 3.5f) == uapprox(radians(180.f))); @@ -156,6 +156,19 @@ TEST_CASE("vmath/qua_fun") { } SUBCASE("Relational Functions") { + STATIC_CHECK(any(qua(1,0,0,0))); + STATIC_CHECK(any(qua(0,1,0,0))); + STATIC_CHECK(any(qua(0,0,1,0))); + STATIC_CHECK(any(qua(0,0,0,1))); + STATIC_CHECK(any(qua(1,1,1,1))); + STATIC_CHECK_FALSE(any(qua(0,0,0,0))); + + STATIC_CHECK_FALSE(all(qua(1,0,0,0))); + STATIC_CHECK_FALSE(all(qua(0,1,0,0))); + STATIC_CHECK_FALSE(all(qua(0,0,1,0))); + STATIC_CHECK(all(qua(1,1,1,1))); + STATIC_CHECK_FALSE(all(qua(0,0,0,0))); + STATIC_CHECK(approx(qua(1,1,1,1), qua(0,1,2,3)) == bool4(false, true, false, false)); STATIC_CHECK(approx(qua(1,1,1,1), qua(0,1,2,3), 0) == bool4(false, true, false, false)); STATIC_CHECK(approx(qua(1,1,1,1), qua(0,1,2,3), 1) == bool4(true, true, true, false)); diff --git a/untests/vmath_tests.hpp b/untests/vmath_tests.hpp index d6be42e..558ecd0 100644 --- a/untests/vmath_tests.hpp +++ b/untests/vmath_tests.hpp @@ -13,7 +13,7 @@ namespace vmath_tests template < typename T > struct uapprox_base { - T epsilon = T(10) * std::numeric_limits::epsilon(); + T epsilon = T{10} * std::numeric_limits::epsilon(); }; template < typename T > @@ -57,7 +57,7 @@ namespace vmath_tests template < typename T > constexpr bool operator==(const vec& l, const uapprox2& r) { - return all(approx(l, r.value,r.epsilon)); + return all(approx(l, r.value, r.epsilon)); } template < typename T > diff --git a/untests/vmath_vec_fun_tests.cpp b/untests/vmath_vec_fun_tests.cpp index f5d54c3..262f1ec 100644 --- a/untests/vmath_vec_fun_tests.cpp +++ b/untests/vmath_vec_fun_tests.cpp @@ -16,27 +16,31 @@ TEST_CASE("vmath/vec_fun") { SUBCASE("Detail") { STATIC_CHECK(map_join([](const int& x){ return x * 2; - }, int2{1}) == int2{2}); + }, vec{1,2,3,4}) == vec{2,4,6,8}); STATIC_CHECK(map_join([](const int& x, const int& y){ return x + y; - }, int2{1}, int2{1}) == int2{2}); + }, vec{1,2,3,4}, vec{2,3,4,5}) == vec{3,5,7,9}); STATIC_CHECK(map_join([](const int& x, const int& y, const int& z){ return x + y + z; - }, int2{1}, int2{1}, int2{1}) == int2(3)); + }, vec{1,2,3,4}, vec{2,3,4,5}, vec{3,4,5,6}) == vec{6,9,12,15}); + + STATIC_CHECK(map_join([](const int& x, const int& y, const int& z, const int& w){ + return x + y + z + w; + }, vec{1,2,3,4}, vec{2,3,4,5}, vec{3,4,5,6}, vec{4,5,6,7}) == vec{10,14,18,22}); STATIC_CHECK(fold_join([](int acc, const int& x){ - return acc + x; - }, 0, int2{1}) == 2); + return acc - x; + }, 0, vec{1,2,3,4}) == -10); STATIC_CHECK(fold_join([](int acc, const int& x, const int& y){ - return acc + x + y; - }, 0, int2{1}, int2{1}) == 4); + return acc - x - y; + }, 0, vec{1,2,3,4}, vec{2,3,4,5}) == -24); STATIC_CHECK(fold1_join([](const int& acc, const int& x){ - return acc + x; - }, int2{1}) == 2); + return acc - x; + }, vec{1,2,3,4}) == -8); } SUBCASE("Operators") { @@ -245,29 +249,21 @@ TEST_CASE("vmath/vec_fun") { STATIC_CHECK(smoothstep(0.f, 1.f, float2(0.1f)) == uapprox2(0.028f)); STATIC_CHECK(smoothstep(float2(0.f), float2(1.f), float2(0.1f)) == uapprox2(0.028f)); - - CHECK_FALSE(isnan(float2(1.f)).x); - CHECK_FALSE(isinf(float2(1.f)).x); - CHECK(isfinite(float2(1.f)).x); - - CHECK_FALSE(fma(float2(2.f), float2(3.f), float2(4.f)).x == uapprox(12.f)); - - { - int2 out_exp{}; - CHECK(frexp(float2(1.7f), &out_exp).x == uapprox(0.85f)); - CHECK(out_exp == int2(1)); - } - - CHECK(ldexp(float2(0.85f), int2(1)).x == uapprox(1.7f)); } SUBCASE("Geometric Functions") { CHECK(length(float2(10.f,0.f)) == uapprox(10.f)); CHECK(length(float2(-10.f,0.f)) == uapprox(10.f)); + CHECK(rlength(float2(10.f,0.f)) == uapprox(0.1f)); + CHECK(rlength(float2(-10.f,0.f)) == uapprox(0.1f)); + STATIC_CHECK(length2(float2(10.f,0.f)) == uapprox(100.f)); STATIC_CHECK(length2(float2(-10.f,0.f)) == uapprox(100.f)); + STATIC_CHECK(rlength2(float2(10.f,0.f)) == uapprox(0.01f)); + STATIC_CHECK(rlength2(float2(-10.f,0.f)) == uapprox(0.01f)); + CHECK(distance(float2(5.f,0.f), float2(10.f,0.f)) == uapprox(5.f)); CHECK(distance(float2(-5.f,0.f), float2(-10.f,0.f)) == uapprox(5.f));