/* * Copyright (C) 2021 Christopher J. Howard * * This file is part of Antkeeper source code. * * Antkeeper source code is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Antkeeper source code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Antkeeper source code. If not, see . */ #ifndef ANTKEEPER_MATH_VECTOR_HPP #define ANTKEEPER_MATH_VECTOR_HPP #include #include #include #include #include #include #include #include namespace math { /** * *n*-dimensional Euclidean vector. * * @tparam T Element type. * @tparam N Number of elements. */ template struct vector { /// Vector element data type. typedef T element_type; /// Number of elements. static constexpr std::size_t element_count = N; /// Array of vector elements. element_type elements[N]; /** * Returns a reference to the element at a given index. * * @param i Index of an element. * * @return Reference to the element at index @p i. */ /// @{ constexpr inline element_type& operator[](std::size_t i) noexcept { return elements[i]; } constexpr inline const element_type& operator[](std::size_t i) const noexcept { return elements[i]; } /// @} /// Returns a reference to the first element. /// @{ constexpr inline element_type& front() noexcept { return elements[0]; } constexpr inline const element_type& front() const noexcept { return elements[0]; } /// @} /// Returns a reference to the last element. /// @{ constexpr inline element_type& back() noexcept { return elements[N - 1]; } constexpr inline const element_type& back() const noexcept { return elements[N - 1]; } /// @} /// Returns a reference to the first element. /// @{ constexpr inline element_type& x() noexcept { static_assert(N > 0, "Vector does not contain an x element."); return elements[0]; } constexpr inline const element_type& x() const noexcept { static_assert(N > 0, "Vector does not contain an x element."); return elements[0]; } /// @} /// Returns a reference to the second element. /// @{ constexpr inline element_type& y() noexcept { static_assert(N > 1, "Vector does not contain a y element."); return elements[1]; } constexpr inline const element_type& y() const noexcept { static_assert(N > 1, "Vector does not contain a y element."); return elements[1]; } /// @} /// Returns a reference to the third element. /// @{ constexpr inline element_type& z() noexcept { static_assert(N > 2, "Vector does not contain a z element."); return elements[2]; } constexpr inline const element_type& z() const noexcept { static_assert(N > 2, "Vector does not contain a z element."); return elements[2]; } /// @} /// Returns a pointer to the element array. /// @{ constexpr inline element_type* data() noexcept { return elements; }; constexpr inline const element_type* data() const noexcept { return elements; }; /// @} /// Returns an iterator to the first element. /// @{ constexpr inline element_type* begin() noexcept { return elements; } constexpr inline const element_type* begin() const noexcept { return elements; } constexpr inline const element_type* cbegin() const noexcept { return elements; } /// @} /// Returns an iterator to the element following the last element. /// @{ constexpr inline element_type* end() noexcept { return elements + N; } constexpr inline const element_type* end() const noexcept { return elements + N; } constexpr inline const element_type* cend() const noexcept { return elements + N; } /// @} /// Returns a reverse iterator to the first element of the reversed vector. /// @{ constexpr inline std::reverse_iterator rbegin() noexcept { return std::reverse_iterator(elements + N); } constexpr inline std::reverse_iterator rbegin() const noexcept { return std::reverse_iterator(elements + N); } constexpr inline std::reverse_iterator crbegin() const noexcept { return std::reverse_iterator(elements + N); } /// @} /// Returns a reverse iterator to the element following the last element of the reversed vector. /// @{ constexpr inline std::reverse_iterator rend() noexcept { return std::reverse_iterator(elements); } constexpr inline std::reverse_iterator rend() const noexcept { return std::reverse_iterator(elements); } constexpr inline std::reverse_iterator crend() const noexcept { return std::reverse_iterator(elements); } /// @} /// Returns the number of elements in the vector. constexpr inline std::size_t size() const noexcept { return N; }; /// @private template constexpr inline vector type_cast(std::index_sequence) const noexcept { return {static_cast(elements[I])...}; } /** * Type-casts the elements of this vector. * * @tparam U Target element type. * * @return Vector containing the type-casted elements. */ template constexpr inline explicit operator vector() const noexcept { return type_cast(std::make_index_sequence{}); } /// @private template constexpr inline vector size_cast(std::index_sequence) const noexcept { return {(I < N) ? elements[I] : T{0} ...}; } /** * Size-casts this vector to a vector with a different number of elements. Casting to a greater number of elements causes new elements to be set to `0`. * * @tparam M Target number of elements. * * @return Vector containing the type-casted elements. */ template constexpr inline explicit operator vector() const noexcept { return size_cast(std::make_index_sequence{}); } }; // Ensure vector is a POD type static_assert(std::is_standard_layout>::value, "Vector is not a standard-layout type."); static_assert(std::is_trivial>::value, "Vector is not a trivial type."); static_assert(sizeof(vector) == sizeof(float) * 3, "Vector size is greater than the size of its elements."); /// Vector with two elements. template using vector2 = vector; /// Vector with three elements. template using vector3 = vector; /// Vector with four elements. template using vector4 = vector; /** * Returns the absolute values of each element. * * @param x Input vector * @return Absolute values of input vector elements. */ template constexpr vector abs(const vector& x); /** * Adds two values. * * @param x First value. * @param y Second value. * @return Sum of the two values. */ /// @{ template constexpr vector add(const vector& x, const vector& y); template constexpr vector add(const vector& x, T y); /// @} /** * Checks if all elements of a boolean vector are `true`. * * @param x Vector to be tested for truth. * @return `true` if all elements are `true`, `false` otherwise. */ template constexpr bool all(const vector& x); /** * Checks if any elements of a boolean vector are `true`. * * @param x Vector to be tested for truth. * @return `true` if any elements are `true`, `false` otherwise. */ template constexpr bool any(const vector& x); /** * Reinterprets data as an *n*-dimensional vector of type `T`. * * @param data Data to reinterpret. */ template constexpr vector& as_vector(T& data); /** * Performs a element-wise ceil operation. * * @param x Input vector * @return Component-wise ceil of input vector. */ template constexpr vector ceil(const vector& x); /** * Clamps the values of a vector's elements. * * @param x Vector to clamp. * @param min_val Minimum value. * @param max_val Maximum value. * @return Clamped vector. */ /// @{ template constexpr vector clamp(const vector& x, const vector& min_val, const vector& max_val); template constexpr vector clamp(const vector& x, T min_val, T max_val); /// @} /** * Clamps the length of a vector. * * @param x Vector to clamp. * @param max_length Maximum length. * @return Length-clamped vector. */ template vector clamp_length(const vector& x, T max_length); /** * Calculate the cross product of two vectors. * * @param x First vector. * @param y Second vector. * @return Cross product of the two vectors. */ template constexpr vector cross(const vector& x, const vector& y); /** * Calculates the distance between two points. * * @param p0 First of two points. * @param p1 Second of two points. * @return Distance between the two points. */ template T distance(const vector& p0, const vector& p1); /** * Calculates the squared distance between two points. The squared distance can be calculated faster than the distance because a call to `std::sqrt` is saved. * * @param p0 First of two points. * @param p1 Second of two points. * @return Squared distance between the two points. */ template constexpr T distance_squared(const vector& p0, const vector& p1); /** * Divides a vector by a value. * * @param x First value. * @param y Second value. * @return Result of the division. */ /// @{ template constexpr vector div(const vector& x, const vector& y); template constexpr vector div(const vector& x, T y); /// @} /** * Calculates the dot product of two vectors. * * @param x First vector. * @param y Second vector. * @return Dot product of the two vectors. */ template constexpr T dot(const vector& x, const vector& y); /** * Compares two vectors for equality * * @param x First vector. * @param y Second vector. * @return Boolean vector containing the result of the element comparisons. */ template constexpr vector equal(const vector& x, const vector& y); /** * Performs a element-wise floor operation. * * @param x Input vector * @return Component-wise floor of input vector. */ template constexpr vector floor(const vector& x); /** * Performs a multiply-add operation. * * @param x Input vector * @param y Value to multiply. * @param z Value to add. * * @return Vector containing the multiply-add results. */ /// @{ template constexpr vector fma(const vector& x, const vector& y, const vector& z); template constexpr vector fma(const vector& x, T y, T z); /// @} /** * Returns a vector containing the fractional part of each element. * * @param x Input vector * @return Fractional parts of input vector. */ template constexpr vector fract(const vector& x); /** * Performs a element-wise greater-than comparison of two vectors. * * @param x First vector. * @param y Second vector. * @return Boolean vector containing the result of the element comparisons. */ template constexpr vector greater_than(const vector& x, const vector& y); /** * Performs a element-wise greater-than or equal-to comparison of two vectors. * * @param x First vector. * @param y Second vector. * @return Boolean vector containing the result of the element comparisons. */ template constexpr vector greater_than_equal(const vector& x, const vector& y); /** * Calculates the length of a vector. * * @param x Vector of which to calculate the length. * @return Length of the vector. */ template T length(const vector& x); /** * Calculates the squared length of a vector. The squared length can be calculated faster than the length because a call to `std::sqrt` is saved. * * @param x Vector of which to calculate the squared length. * @return Squared length of the vector. */ template constexpr T length_squared(const vector& x); /** * Performs a element-wise less-than comparison of two vectors. * * @param x First vector. * @param y Second vector. * @return Boolean vector containing the result of the element comparisons. */ template constexpr vector less_than(const vector& x, const vector& y); /** * Performs a element-wise less-than or equal-to comparison of two vectors. * * @param x First vector. * @param y Second vector. * @return Boolean vector containing the result of the element comparisons. */ template constexpr vector less_than_equal(const vector& x, const vector& y); /** * Returns the value of the greatest element in a vector. * * @param x Input vector. * * @return Value of the greatest element in the input vector. */ template constexpr T max(const vector& x); /** * Returns the value of the smallest element in a vector. * * @param x Input vector. * * @return Value of the smallest element in the input vector. */ template constexpr T min(const vector& x); /** * Calculates the element-wise remainder of the division operation `x / y`. * * @param x First vector. * @param y Second vector. * @return Remainders of `x / y`. */ /// @{ template constexpr vector mod(const vector& x, const vector& y); template constexpr vector mod(const vector& x, T y); /// @} /** * Multiplies two values. * * @param x First value. * @param y Second value. * @return Product of the two values. */ /// @{ template constexpr vector mul(const vector& x, const vector& y); template constexpr vector mul(const vector& x, T y); /// @} /** * Negates a vector. * * @param x Vector to negate. * @return Negated vector. */ template constexpr vector negate(const vector& x); /** * Calculates the unit vector in the same direction as the original vector. * * @param x Vector to normalize. * @return Normalized vector. */ template vector normalize(const vector& x); /** * Logically inverts a boolean vector. * * @param x Vector to be inverted. * @return Logically inverted vector. */ template constexpr vector not(const vector& x); /** * Compares two vectors for inequality * * @param x First vector. * @param y Second vector. * @return Boolean vector containing the result of the element comparisons. */ template constexpr vector not_equal(const vector& x, const vector& y); /** * Resizes a vector. Any new elements will be set to `0`. * * @tparam M Target number of elements. * * @param x Vector to resize. * * @return Resized vector. */ template constexpr vector resize(const vector& x); /** * Performs a element-wise round operation. * * @param x Input vector * @return Component-wise round of input vector. */ template constexpr vector round(const vector& x); /** * Returns a vector containing the signs of each element. * * @param x Input vector * @return Signs of input vector elements. */ template constexpr vector sign(const vector& x); /** * Subtracts a value by another value. * * @param x First value. * @param y Second value. * @return Difference between the two values. */ /// @{ template constexpr vector sub(const vector& x, const vector& y); template constexpr vector sub(const vector& x, T y); /// @} /** * Calculates the sum of all elements in a vector. * * @param x Vector to sum. * @return Sum of the vector's elements. */ template constexpr T sum(const vector& x); /** * Makes an *m*-dimensional vector by rearranging and/or duplicating elements of an *n*-dimensional vector. * * @tparam Indices List of indices of elements in @p x. * @tparam T Vector element type. * @tparam N Number of dimensions in @p x. * * @param x Vector to swizzle. * * @return Vector containing elements from @p x in the order specified by @p Indices. The size of the returned vector is equivalent to the number of indices in @p Indices. */ template constexpr vector swizzle(const vector& x); /** * Performs a element-wise trunc operation. * * @param x Input vector * @return Component-wise trunc of input vector. */ template constexpr vector trunc(const vector& x); /** * Types casts each vector element and returns a vector of the casted type. * * @tparam U Target vector element type. * @tparam T Source vector element type. * @tparam N Number of dimensions. * @param x Vector to type cast. * * @return Type-casted vector. */ template constexpr vector type_cast(const vector& x); /// @private template constexpr inline vector abs(const vector& x, std::index_sequence) { return {std::abs(x[I])...}; } template constexpr inline vector abs(const vector& x) { return abs(x, std::make_index_sequence{}); } /// @private template constexpr inline vector add(const vector& x, const vector& y, std::index_sequence) { return {(x[I] + y[I])...}; } template constexpr inline vector add(const vector& x, const vector& y) { return add(x, y, std::make_index_sequence{}); } /// @private template constexpr inline vector add(const vector& x, T y, std::index_sequence) { return {(x[I] + y)...}; } template constexpr inline vector add(const vector& x, T y) { return add(x, y, std::make_index_sequence{}); } /// @private template constexpr inline bool all(const vector& x, std::index_sequence) { return (x[I] && ...); } template constexpr inline bool all(const vector& x) { return all(x, std::make_index_sequence{}); } /// @private template constexpr inline bool any(const vector& x, std::index_sequence) { return (x[I] || ...); } template constexpr inline bool any(const vector& x) { return any(x, std::make_index_sequence{}); } template constexpr inline vector& as_vector(T& data) { static_assert(std::is_pod>::value); return reinterpret_cast&>(data); } /// @private template constexpr inline vector ceil(const vector& x, std::index_sequence) { return {std::ceil(x[I])...}; } template constexpr inline vector ceil(const vector& x) { static_assert(std::is_floating_point::value); return ceil(x, std::make_index_sequence{}); } /// @private template constexpr inline vector clamp(const vector& x, const vector& min_val, const vector& max_val, std::index_sequence) { return {std::min(max_val[I], std::max(min_val[I], x[I]))...}; } template constexpr inline vector clamp(const vector& x, const vector& min_val, const vector& max_val) { return clamp(x, min_val, max_val, std::make_index_sequence{}); } /// @private template constexpr inline vector clamp(const vector& x, T min_val, T max_val, std::index_sequence) { return {std::min(max_val, std::max(min_val, x[I]))...}; } template constexpr inline vector clamp(const vector& x, T min_val, T max_val) { return clamp(x, min_val, max_val, std::make_index_sequence{}); } template vector clamp_length(const vector& x, T max_length) { static_assert(std::is_floating_point::value); T length2 = length_squared(x); return (length2 > max_length * max_length) ? (x * max_length / std::sqrt(length2)) : x; } template constexpr inline vector cross(const vector& x, const vector& y) { return { x[1] * y[2] - y[1] * x[2], x[2] * y[0] - y[2] * x[0], x[0] * y[1] - y[0] * x[1] }; } template inline T distance(const vector& p0, const vector& p1) { static_assert(std::is_floating_point::value); return length(sub(p0, p1)); } template constexpr inline T distance_squared(const vector& p0, const vector& p1) { static_assert(std::is_floating_point::value); return length_squared(sub(p0, p1)); } /// @private template constexpr inline vector div(const vector& x, const vector& y, std::index_sequence) { return {(x[I] / y[I])...}; } template constexpr inline vector div(const vector& x, const vector& y) { return div(x, y, std::make_index_sequence{}); } /// @private template constexpr inline vector div(const vector& x, T y, std::index_sequence) { return {(x[I] / y)...}; } template constexpr inline vector div(const vector& x, T y) { return div(x, y, std::make_index_sequence{}); } /// @private template constexpr inline T dot(const vector& x, const vector& y, std::index_sequence) { return ((x[I] * y[I]) + ...); } template constexpr inline T dot(const vector& x, const vector& y) { return dot(x, y, std::make_index_sequence{}); } /// @private template constexpr inline vector equal(const vector& x, const vector& y, std::index_sequence) { return {(x[I] == y[I])...}; } template constexpr inline vector equal(const vector& x, const vector& y) { return equal(x, y, std::make_index_sequence{}); } /// @private template constexpr inline vector floor(const vector& x, std::index_sequence) { return {std::floor(x[I])...}; } template constexpr inline vector floor(const vector& x) { static_assert(std::is_floating_point::value); return floor(x, std::make_index_sequence{}); } /// @private template constexpr inline vector fma(const vector& x, const vector& y, const vector& z, std::index_sequence) { return {std::fma(x[I], y[I], z[I])...}; } template constexpr inline vector fma(const vector& x, const vector& y, const vector& z) { static_assert(std::is_floating_point::value); return fma(x, y, z, std::make_index_sequence{}); } /// @private template constexpr inline vector fma(const vector& x, T y, T z, std::index_sequence) { return {std::fma(x[I], y, z)...}; } template constexpr inline vector fma(const vector& x, T y, T z) { static_assert(std::is_floating_point::value); return fma(x, y, z, std::make_index_sequence{}); } /// @private template constexpr inline vector fract(const vector& x, std::index_sequence) { return {x[I] - std::floor(x[I])...}; } template constexpr inline vector fract(const vector& x) { static_assert(std::is_floating_point::value); return fract(x, std::make_index_sequence{}); } /// @private template constexpr inline vector greater_than(const vector& x, const vector& y, std::index_sequence) { return {(x[I] > y[I])...}; } template constexpr inline vector greater_than(const vector& x, const vector& y) { return greater_than(x, y, std::make_index_sequence{}); } /// @private template constexpr inline vector greater_than_equal(const vector& x, const vector& y, std::index_sequence) { return {(x[I] >= y[I])...}; } template constexpr inline vector greater_than_equal(const vector& x, const vector& y) { return greater_than_equal(x, y, std::make_index_sequence{}); } template inline T length(const vector& x) { static_assert(std::is_floating_point::value); return std::sqrt(dot(x, x)); } template constexpr inline T length_squared(const vector& x) { return dot(x, x); } /// @private template constexpr inline vector less_than(const vector& x, const vector& y, std::index_sequence) { return {(x[I] < y[I])...}; } template constexpr inline vector less_than(const vector& x, const vector& y) { return less_than(x, y, std::make_index_sequence{}); } /// @private template constexpr inline vector less_than_equal(const vector& x, const vector& y, std::index_sequence) { return {(x[I] <= y[I])...}; } template constexpr inline vector less_than_equal(const vector& x, const vector& y) { return less_than_equal(x, y, std::make_index_sequence{}); } template constexpr inline T max(const vector& x) { return *std::max_element(x.elements, x.elements + N); } template constexpr inline T min(const vector& x) { return *std::min_element(x.elements, x.elements + N); } /// @private template constexpr inline vector mod(const vector& x, const vector& y, std::index_sequence) { return {std::fmod(x[I], y[I])...}; } template constexpr inline vector mod(const vector& x, const vector& y) { static_assert(std::is_floating_point::value); return mod(x, y, std::make_index_sequence{}); } /// @private template constexpr inline vector mod(const vector& x, T y, std::index_sequence) { return {std::fmod(x[I], y)...}; } template constexpr inline vector mod(const vector& x, T y) { static_assert(std::is_floating_point::value); return mod(x, y, std::make_index_sequence{}); } /// @private template constexpr inline vector mul(const vector& x, const vector& y, std::index_sequence) { return {(x[I] * y[I])...}; } template constexpr inline vector mul(const vector& x, const vector& y) { return mul(x, y, std::make_index_sequence{}); } /// @private template constexpr inline vector mul(const vector& x, T y, std::index_sequence) { return {(x[I] * y)...}; } template constexpr inline vector mul(const vector& x, T y) { return mul(x, y, std::make_index_sequence{}); } /// @private template constexpr inline vector negate(const vector& x, std::index_sequence) { return {(-x[I])...}; } template constexpr inline vector negate(const vector& x) { return negate(x, std::make_index_sequence{}); } template inline vector normalize(const vector& x) { static_assert(std::is_floating_point::value); return mul(x, T(1) / length(x)); } /// @private template constexpr inline vector not(const vector& x, std::index_sequence) { return {!x[I]...}; } template constexpr inline vector not(const vector& x) { return not(x, std::make_index_sequence{}); } /// @private template constexpr inline vector not_equal(const vector& x, const vector& y, std::index_sequence) { return {(x[I] != y[I])...}; } template constexpr inline vector not_equal(const vector& x, const vector& y) { return not_equal(x, y, std::make_index_sequence{}); } /// @private template constexpr inline vector resize(const vector& x, std::index_sequence) { return {(I < N) ? x[I] : T{0} ...}; } template constexpr inline vector resize(const vector& x) { return resize(x, std::make_index_sequence{}); } /// @private template constexpr inline vector round(const vector& x, std::index_sequence) { return {std::round(x[I])...}; } template constexpr inline vector round(const vector& x) { static_assert(std::is_floating_point::value); return round(x, std::make_index_sequence{}); } /// @private template constexpr inline vector sign(const vector& x, std::index_sequence) { return {std::copysign(T{1}, x[I])...}; } template constexpr inline vector sign(const vector& x) { static_assert(std::is_floating_point::value); return sign(x, std::make_index_sequence{}); } /// @private template constexpr inline vector sub(const vector& x, const vector& y, std::index_sequence) { return {(x[I] - y[I])...}; } template constexpr inline vector sub(const vector& x, const vector& y) { return sub(x, y, std::make_index_sequence{}); } /// @private template constexpr inline vector sub(const vector& x, T y, std::index_sequence) { return {(x[I] - y)...}; } template constexpr inline vector sub(const vector& x, T y) { return sub(x, y, std::make_index_sequence{}); } /// @private template constexpr inline T sum(const vector& x, std::index_sequence) { return (x[I] + ...); } template constexpr inline T sum(const vector& x) { return sum(x, std::make_index_sequence{}); } template constexpr inline vector swizzle(const vector& x) { return {x[Indices]...}; } /// @private template constexpr inline vector trunc(const vector& x, std::index_sequence) { return {std::trunc(x[I])...}; } template constexpr inline vector trunc(const vector& x) { static_assert(std::is_floating_point::value); return trunc(x, std::make_index_sequence{}); } /// @private template constexpr inline vector type_cast(const vector& x, std::index_sequence) { return {static_cast(x[I])...}; } template constexpr inline vector type_cast(const vector& x) { return type_cast(x, std::make_index_sequence{}); } } // namespace math /// @copydoc math::add(const math::vector&, const math::vector&) template constexpr math::vector operator+(const math::vector& x, const math::vector& y); /// @copydoc math::add(const math::vector&, T) /// @{ template constexpr math::vector operator+(const math::vector& x, T y); template constexpr math::vector operator+(T x, const math::vector& y); /// @} /// @copydoc math::div(const math::vector&, const math::vector&) template constexpr math::vector operator/(const math::vector& x, const math::vector& y); /// @copydoc math::div(const math::vector&, T y) template constexpr math::vector operator/(const math::vector& x, T y); /// @copydoc math::mul(const math::vector&, const math::vector&) template constexpr math::vector operator*(const math::vector& x, const math::vector& y); /// @copydoc math::mul(const math::vector&, T) /// @{ template constexpr math::vector operator*(const math::vector& x, T y); template constexpr math::vector operator*(T x, const math::vector& y); /// @} /// @copydoc math::negate(const math::vector&) template constexpr math::vector operator-(const math::vector& x); /// @copydoc math::sub(const math::vector&, const math::vector&) template constexpr math::vector operator-(const math::vector& x, const math::vector& y); /// @copydoc math::sub(const math::vector&, T) template constexpr math::vector operator-(const math::vector& x, T y); /** * Adds two values and stores the result in the first value. * * @param x First value. * @param y Second value. * @return Reference to the first value. */ /// @{ template constexpr math::vector& operator+=(math::vector& x, const math::vector& y); template constexpr math::vector& operator+=(math::vector& x, T y); /// @} /** * Subtracts the first value by the second value and stores the result in the first value. * * @param x First value. * @param y Second value. * @return Reference to the first value. */ /// @{ template constexpr math::vector& operator-=(math::vector& x, const math::vector& y); template constexpr math::vector& operator-=(math::vector& x, T y); /// @} /** * Multiplies two values and stores the result in the first value. * * @param x First value. * @param y Second value. * @return Reference to the first value. */ /// @{ template constexpr math::vector& operator*=(math::vector& x, const math::vector& y); template constexpr math::vector& operator*=(math::vector& x, T y); /// @} /** * Divides the first value by the second value and stores the result in the first value. * * @param x First value. * @param y Second value. * @return Reference to the first value. */ /// @{ template constexpr math::vector& operator/=(math::vector& x, const math::vector& y); template constexpr math::vector& operator/=(math::vector& x, T y); /// @} /** * Writes the elements of a vector to an output stream, with each element delimeted by a space. * * @param os Output stream. * @param x Vector. * * @return Output stream. */ template std::ostream& operator<<(std::ostream& os, const math::vector& x); /** * Reads the elements of a vector from an input stream, with each element delimeted by a space. * * @param is Input stream. * @param x Vector. * * @return Input stream. */ template std::istream& operator>>(std::istream& is, math::vector& v); template constexpr inline math::vector operator+(const math::vector& x, const math::vector& y) { return add(x, y); } template constexpr inline math::vector operator+(const math::vector& x, T y) { return add(x, y); } template constexpr inline math::vector operator+(T x, const math::vector& y) { return add(y, x); } template constexpr inline math::vector operator-(const math::vector& x) { return negate(x); } template constexpr inline math::vector operator-(const math::vector& x, const math::vector& y) { return sub(x, y); } template constexpr inline math::vector operator-(const math::vector& x, T y) { return sub(x, y); } template constexpr inline math::vector operator*(const math::vector& x, const math::vector& y) { return mul(x, y); } template constexpr inline math::vector operator*(const math::vector& x, T y) { return mul(x, y); } template constexpr inline math::vector operator*(T x, const math::vector& y) { return mul(y, x); } template constexpr inline math::vector operator/(const math::vector& x, const math::vector& y) { return div(x, y); } template constexpr inline math::vector operator/(const math::vector& x, T y) { return div(x, y); } template constexpr inline math::vector& operator+=(math::vector& x, const math::vector& y) { return (x = x + y); } template constexpr inline math::vector& operator+=(math::vector& x, T y) { return (x = x + y); } template constexpr inline math::vector& operator-=(math::vector& x, const math::vector& y) { return (x = x - y); } template constexpr inline math::vector& operator-=(math::vector& x, T y) { return (x = x - y); } template constexpr inline math::vector& operator*=(math::vector& x, const math::vector& y) { return (x = x * y); } template constexpr inline math::vector& operator*=(math::vector& x, T y) { return (x = x * y); } template constexpr inline math::vector& operator/=(math::vector& x, const math::vector& y) { return (x = x / y); } template constexpr inline math::vector& operator/=(math::vector& x, T y) { return (x = x / y); } template std::ostream& operator<<(std::ostream& os, const math::vector& x) { for (std::size_t i = 0; i < N; ++i) { if (i) os << ' '; os << x[i]; } return os; } template std::istream& operator>>(std::istream& is, math::vector& x) { for (std::size_t i = 0; i < N; ++i) is >> x[i]; return is; } #endif // ANTKEEPER_MATH_VECTOR_HPP