/* * 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_FUNCTIONS_HPP #define ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP #include "math/vector-type.hpp" #include #include #include #include namespace math { /** * Adds two vectors. * * @param x First vector. * @param y Second vector. * @return Sum of the two vectors. */ template vector add(const vector& x, const vector& 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 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 bool any(const vector& x); /** * Reinterprets data as an `N`-dimensional vector of type `T`. * * @tparam N Number of vector dimensions. * @tparam T Scalar type. * @param data Data to reinterpret. */ template vector& as_vector(T& data); /** * Clamps the values of a vector's elements. * * @param x Vector to clamp. * @param min_value Minimum element value. * @param max_value Maximum element value. * @return Clamped vector. */ template vector clamp(const vector& x, T min_value, T max_value); /** * 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 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 vector 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 vector distance_squared(const vector& p0, const vector& p1); /** * Divides a vector by another vector. * * @param x First vector. * @param y Second vector. * @return Result of the division. */ template vector div(const vector& x, const vector& y); /** * Divides a vector by a scalar. * * @param v Vector. * @param s Scalar. * @return Result of the division. */ template vector div(const vector& v, T s); /** * Calculates the dot product of two vectors. * * @param x First vector. * @param y Second vector. * @return Dot product of the two vectors. */ template 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 vector equal(const vector& x, const vector& y); /** * Performs a component-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 vector greater_than(const vector& x, const vector& y); /** * Performs a component-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 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 T length_squared(const vector& x); /** * Performs a component-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 vector less_than(const vector& x, const vector& y); /** * Performs a component-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 vector less_than_equal(const vector& x, const vector& y); /** * Multiplies two vectors. * * @param x First vector. * @param y Second vector. * @return Product of the two vectors. */ template vector mul(const vector& x, const vector& y); /** * Multiplies a vector by a scalar. * * @param v Vector. * @param s Scalar. * @return Product of the vector and scalar. */ template vector mul(const vector& v, T s); /** * Negates a vector. * * @param x Vector to negate. * @return Negated vector. */ template 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 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 vector not_equal(const vector& x, const vector& y); /** * Resizes a vector. Any new elements will be set to `0`. * * @param v Vector to resize. * @return Resized vector. */ template vector resize(const vector& v); /** * Subtracts a vector from another vector. * * @param x First vector. * @param y Second vector. * @return Difference between the two vectors. */ template vector sub(const vector& x, const vector& y); /** * Makes an m-dimensional vector by rearranging and/or duplicating elements of an n-dimensional vector. * * @tparam Indices List of indices of elements in the vector `v`. * @tparam T Vector component type. * @tparam N Number of dimensions in vector `v`. * @return Vector containing elements from vector `v` in the order specified by `Indices`. The size of the returned vector is equivalent to the number of indices in `Indices`. */ template vector swizzle(const vector& v); /** * Types casts each vector component and returns a vector of the casted type. * * @tparam T2 Target vector component type. * @tparam T1 Source vector component type. * @tparam N Number of dimensions. * @param v Vector to type cast. * @return Type-casted vector. */ template vector type_cast(const vector& v); /// @private template inline vector add(const vector& x, const vector& y, std::index_sequence) { return {(x[I] + y[I])...}; } template inline vector add(const vector& x, const vector& y) { return add(x, y, std::make_index_sequence{}); } /// @private template inline bool all(const vector& x, std::index_sequence) { return (x[I] && ...); } template inline bool all(const vector& x) { return all(x, std::make_index_sequence{}); } /// @private template inline bool any(const vector& x, std::index_sequence) { return (x[I] || ...); } template inline bool any(const vector& x) { return any(x, std::make_index_sequence{}); } template inline vector& as_vector(T& data) { static_assert(std::is_pod>::value); return reinterpret_cast&>(data); } /// @private template inline vector clamp(const vector& x, T min_value, T max_value, std::index_sequence) { return {std::min(max_value, std::max(min_value, x[I]))...}; } template inline vector clamp(const vector& x, T min_value, T max_value) { return clamp(x, min_value, max_value, std::make_index_sequence{}); } template vector clamp_length(const vector& x, T max_length) { T length2 = length_squared(x); return (length2 > max_length * max_length) ? (x * max_length / std::sqrt(length2)) : x; } template 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 vector distance(const vector& p0, const vector& p1) { static_assert(std::is_floating_point::value); return length(sub(p0, p1)); } template inline vector distance_squared(const vector& p0, const vector& p1) { static_assert(std::is_floating_point::value); return length_squared(sub(p0, p1)); } /// @private template inline vector div(const vector& x, const vector& y, std::index_sequence) { return {(x[I] / y[I])...}; } template inline vector div(const vector& x, const vector& y) { return div(x, y, std::make_index_sequence{}); } /// @private template inline vector div(const vector& v, T s, std::index_sequence) { return {(v[I] / s)...}; } template inline vector div(const vector& v, T s) { return div(v, s, std::make_index_sequence{}); } /// @private template inline T dot(const vector& x, const vector& y, std::index_sequence) { return ((x[I] * y[I]) + ...); } template inline T dot(const vector& x, const vector& y) { return dot(x, y, std::make_index_sequence{}); } /// @private template inline vector equal(const vector& x, const vector& y, std::index_sequence) { return {(x[I] == y[I])...}; } template inline vector equal(const vector& x, const vector& y) { return equal(x, y, std::make_index_sequence{}); } /// @private template inline vector greater_than(const vector& x, const vector& y, std::index_sequence) { return {(x[I] > y[I])...}; } template inline vector greater_than(const vector& x, const vector& y) { return greater_than(x, y, std::make_index_sequence{}); } /// @private template inline vector greater_than_equal(const vector& x, const vector& y, std::index_sequence) { return {(x[I] >= y[I])...}; } template 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 inline T length_squared(const vector& x) { static_assert(std::is_floating_point::value); return dot(x, x); } /// @private template inline vector less_than(const vector& x, const vector& y, std::index_sequence) { return {(x[I] < y[I])...}; } template inline vector less_than(const vector& x, const vector& y) { return less_than(x, y, std::make_index_sequence{}); } /// @private template inline vector less_than_equal(const vector& x, const vector& y, std::index_sequence) { return {(x[I] <= y[I])...}; } template inline vector less_than_equal(const vector& x, const vector& y) { return less_than_equal(x, y, std::make_index_sequence{}); } /// @private template inline vector mul(const vector& x, const vector& y, std::index_sequence) { return {(x[I] * y[I])...}; } template inline vector mul(const vector& x, const vector& y) { return mul(x, y, std::make_index_sequence{}); } /// @private template inline vector mul(const vector& v, T s, std::index_sequence) { return {(v[I] * s)...}; } template inline vector mul(const vector& v, T s) { return mul(v, s, std::make_index_sequence{}); } /// @private template inline vector negate(const vector& x, std::index_sequence) { return {(-x[I])...}; } template 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 inline vector not(const vector& x, std::index_sequence) { return {!x[I]...}; } template inline vector not(const vector& x) { return not(x, std::make_index_sequence{}); } /// @private template inline vector not_equal(const vector& x, const vector& y, std::index_sequence) { return {(x[I] != y[I])...}; } template inline vector not_equal(const vector& x, const vector& y) { return not_equal(x, y, std::make_index_sequence{}); } template vector resize(const vector& v) { vector resized; for (std::size_t i = 0; i < N1; ++i) { resized[i] = (i < N0) ? v[i] : T(0); } return resized; } /// @private template inline vector sub(const vector& x, const vector& y, std::index_sequence) { return {(x[I] - y[I])...}; } template inline vector sub(const vector& x, const vector& y) { return sub(x, y, std::make_index_sequence{}); } template inline vector swizzle(const vector& v) { return { v[Indices]... }; } /// @private template inline vector type_cast(const vector& v, std::index_sequence) { return {static_cast(v[I])...}; } template inline vector type_cast(const vector& v) { return type_cast(v, std::make_index_sequence{}); } } // namespace math #endif // ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP