From 32c53d71066004490ef9d4df3d6636ff36005d74 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Wed, 26 Oct 2022 16:24:08 +0800 Subject: [PATCH] Add structured binding support to math::matrix. Replace math::vector floating point static asserts with floating point concepts --- src/game/system/terrain.cpp | 95 ++++----- src/math/matrix.hpp | 396 ++++++++++++++++++++++++------------ src/math/vector.hpp | 173 ++++++++-------- 3 files changed, 392 insertions(+), 272 deletions(-) diff --git a/src/game/system/terrain.cpp b/src/game/system/terrain.cpp index 93deceb..46003d3 100644 --- a/src/game/system/terrain.cpp +++ b/src/game/system/terrain.cpp @@ -84,54 +84,32 @@ void terrain::update(double t, double dt) const scene::camera& cam = *camera.object; - - - - - // for (int i = 0; i < 8; ++i) - // std::cout << "corner " << i << ": " << cam.get_view_frustum().get_corners()[i] << std::endl; - - geom::primitive::ray rays[8]; - rays[0] = cam.pick({-1, -1}); - rays[1] = cam.pick({-1, 1}); - rays[2] = cam.pick({ 1, 1}); - rays[3] = cam.pick({ 1, -1}); - - float3 ntl = rays[0].origin; - float3 nbl = rays[1].origin; - float3 nbr = rays[2].origin; - float3 ntr = rays[3].origin; + // Determine camera node location + const auto [x, y, z] = cam.get_translation(); - float3 ftl = rays[0].origin + rays[0].direction * (cam.get_clip_far() - cam.get_clip_near()); - float3 fbl = rays[1].origin + rays[1].direction * (cam.get_clip_far() - cam.get_clip_near()); - float3 fbr = rays[2].origin + rays[2].direction * (cam.get_clip_far() - cam.get_clip_near()); - float3 ftr = rays[3].origin + rays[3].direction * (cam.get_clip_far() - cam.get_clip_near()); + quadtree_node_type node_x = static_cast((x / patch_side_length) + quadtree.resolution / 4); + quadtree_node_type node_y = static_cast((z / patch_side_length) + quadtree.resolution / 4); + quadtree_node_type node_location = geom::morton::encode(node_x, node_y); + quadtree.insert(quadtree.node(quadtree.max_depth, node_location)); - // for (int i = 0; i < 8; ++i) - // std::cout << "ray or " << i << ": " << rays[i].origin << std::endl; + balance_quadtree(); - geom::convex_hull hull(6); - hull.planes[0] = geom::plane(ftl, fbl, nbl); - hull.planes[1] = geom::plane(ntr, nbr, fbr); - hull.planes[2] = geom::plane(fbl, fbr, nbr); - hull.planes[3] = geom::plane(ftl, ntl, ntr); - hull.planes[4] = geom::plane(ntl, nbl, nbr); - hull.planes[5] = geom::plane(ftr, fbr, fbl); - - geom::sphere sphere; - sphere.center = cam.get_translation(); - //sphere.radius = patch_side_length; - sphere.radius = 1.0f; - - // Determine camera position node - auto translation = cam.get_translation(); - - //visit_quadtree(cam.get_view_frustum().get_bounds(), quadtree_type::root); - visit_quadtree(sphere, quadtree_type::root); + for (const quadtree_node_type& node: quadtree) + { + if (!quadtree.is_leaf(node)) + continue; + + if (patches.find(node) == patches.end()) + { + patch* node_patch = generate_patch(node); + patches[node] = node_patch; + scene_collection->add_object(node_patch->model_instance); + } + } } ); - balance_quadtree(); + //std::cout << "qsize: " << quadtree.size() << std::endl; std::size_t qvis = 0; @@ -337,23 +315,30 @@ void terrain::balance_quadtree() quadtree_node_type x, y; geom::morton::decode(location, x, y); - --depth; - if (x < quadtree.resolution - 1) - { - if (y < quadtree.resolution - 1) - nodes.insert(quadtree.node(depth, geom::morton::encode(x + 1, y + 1))); - if (y > 0) - nodes.insert(quadtree.node(depth, geom::morton::encode(x + 1, y - 1))); - } + // TODO!!!! + + // DONT USE quadtree.resolution, use a depth-specific resolution - if (x > 0) + if (!quadtree.is_leaf(node)) { - if (y < quadtree.resolution - 1) - nodes.insert(quadtree.node(depth, geom::morton::encode(x - 1, y + 1))); - if (y > 0) - nodes.insert(quadtree.node(depth, geom::morton::encode(x - 1, y - 1))); + if (x < (quadtree.resolution / 4) - 1) + { + if (y < (quadtree.resolution / 4) - 1) + nodes.insert(quadtree.node(depth, geom::morton::encode(x + 1, y + 1))); + if (y > 0) + nodes.insert(quadtree.node(depth, geom::morton::encode(x + 1, y - 1))); + } + + if (x > 0) + { + if (y < (quadtree.resolution / 4) - 1) + nodes.insert(quadtree.node(depth, geom::morton::encode(x - 1, y + 1))); + if (y > 0) + nodes.insert(quadtree.node(depth, geom::morton::encode(x - 1, y - 1))); + } } + } for (const auto& node: nodes) diff --git a/src/math/matrix.hpp b/src/math/matrix.hpp index 22d8328..8cbcf76 100644 --- a/src/math/matrix.hpp +++ b/src/math/matrix.hpp @@ -33,7 +33,7 @@ namespace math { /** * *n* by *m* column-major matrix. * - * @tparam T Matrix element data type. + * @tparam T Element type. * @tparam N Number of columns. * @tparam M Number of rows. * @@ -63,6 +63,58 @@ struct matrix /// Array of matrix column vectors. column_vector_type columns[column_count]; + /// @name Conversion + /// @{ + + /// @private + template + constexpr inline matrix type_cast(std::index_sequence) const noexcept + { + return {vector(columns[I])...}; + } + + /** + * Type-casts the elements of this matrix using `static_cast`. + * + * @tparam U Target element type. + * + * @return Matrix containing the type-casted elements. + */ + template + constexpr inline explicit operator matrix() const noexcept + { + return type_cast(std::make_index_sequence{}); + } + + /// @private + template + constexpr inline matrix size_cast(std::index_sequence) const noexcept + { + if constexpr (O == M) + return {((I < N) ? columns[I] : matrix::identity()[I]) ...}; + else + return {((I < N) ? vector(columns[I]) : matrix::identity()[I]) ...}; + } + + /** + * Size-casts this matrix to a matrix with different dimensions. Casting to greater dimensions causes new elements to be set to identity matrix elements. + * + * @tparam P Target number of columns. + * @tparam O Target number of rows. + * + * @return *p* by *o* matrix. + */ + template + constexpr inline explicit operator matrix() const noexcept + { + return size_cast(std::make_index_sequence

{}); + } + + /// @} + + /// @name Column access + /// @{ + /** * Returns a reference to the column vector at a given index. * @@ -90,25 +142,9 @@ struct matrix /// @} /** - * Returns a reference to the element at a given column-major index. - * - * @param i Column-major index of a matrix element. - * - * @return Reference to the element at column-major index @p i. + * Returns a reference to the first column vector. */ /// @{ - constexpr inline T& element(std::size_t i) noexcept - { - return columns[i / row_count][i % row_count]; - } - constexpr inline const T& element(std::size_t i) const noexcept - { - return columns[i / row_count][i % row_count]; - } - /// @} - - /// Returns a reference to the first column vector. - /// @{ constexpr inline column_vector_type& front() noexcept { return columns[0]; @@ -119,7 +155,9 @@ struct matrix } /// @} - /// Returns a reference to the last column vector. + /** + * Returns a reference to the last column vector. + */ /// @{ constexpr inline column_vector_type& back() noexcept { @@ -131,6 +169,29 @@ struct matrix } /// @} + /// @} + + /// @name Element access + /// @{ + + /** + * Returns a reference to the element at a given column-major index. + * + * @param i Column-major index of a matrix element. + * + * @return Reference to the element at column-major index @p i. + */ + /// @{ + constexpr inline T& element(std::size_t i) noexcept + { + return columns[i / row_count][i % row_count]; + } + constexpr inline const T& element(std::size_t i) const noexcept + { + return columns[i / row_count][i % row_count]; + } + /// @} + /** * Returns a pointer to the first element. * @@ -147,7 +208,14 @@ struct matrix }; /// @} - /// Returns an iterator to the first column vector. + /// @} + + /// @name Iterators + /// @{ + + /** + * Returns an iterator to the first column vector. + */ /// @{ constexpr inline column_vector_type* begin() noexcept { @@ -163,7 +231,9 @@ struct matrix } /// @} - /// Returns an iterator to the column vector following the last column vector. + /** + * Returns an iterator to the column vector following the last column vector. + */ /// @{ constexpr inline column_vector_type* end() noexcept { @@ -179,7 +249,9 @@ struct matrix } /// @} - /// Returns a reverse iterator to the first column vector of the reversed matrix. + /** + * Returns a reverse iterator to the first column vector of the reversed matrix. + */ /// @{ constexpr inline std::reverse_iterator rbegin() noexcept { @@ -195,7 +267,9 @@ struct matrix } /// @} - /// Returns a reverse iterator to the column vector following the last column vector of the reversed matrix. + /** + * Returns a reverse iterator to the column vector following the last column vector of the reversed matrix. + */ /// @{ constexpr inline std::reverse_iterator rend() noexcept { @@ -211,57 +285,27 @@ struct matrix } /// @} - /// Returns the number of elements in the matrix. - constexpr inline std::size_t size() const noexcept - { - return element_count; - }; + /// @} - /// @private - template - constexpr inline matrix type_cast(std::index_sequence) const noexcept - { - return {vector(columns[I])...}; - } + /// @name Capacity + /// @{ /** - * Type-casts the elements of this matrix using `static_cast`. - * - * @tparam U Target element type. - * - * @return Matrix containing the type-casted elements. + * Returns the number of elements in the matrix. */ - template - constexpr inline explicit operator matrix() const noexcept + constexpr inline std::size_t size() const noexcept { - return type_cast(std::make_index_sequence{}); - } + return element_count; + }; - /// @private - template - constexpr inline matrix size_cast(std::index_sequence) const noexcept - { - if constexpr (O == M) - return {((I < N) ? columns[I] : matrix::identity()[I]) ...}; - else - return {((I < N) ? vector(columns[I]) : matrix::identity()[I]) ...}; - } + /// @} + + /// @name Constants + /// @{ /** - * Size-casts this matrix to a matrix with different dimensions. Casting to greater dimensions causes new elements to be set to identity matrix elements. - * - * @tparam P Target number of columns. - * @tparam O Target number of rows. - * - * @return *p* by *o* matrix. + * Returns a zero matrix, where every element is equal to zero. */ - template - constexpr inline explicit operator matrix() const noexcept - { - return size_cast(std::make_index_sequence

{}); - } - - /// Returns a zero matrix, where every element is equal to zero. static constexpr matrix zero() noexcept { return {}; @@ -277,7 +321,9 @@ struct matrix return {(I ? column_vector_type::one() : column_vector_type::one()) ...}; } - /// Returns a matrix of ones, where every element is equal to one. + /** + * Returns a matrix of ones, where every element is equal to one. + */ static constexpr matrix one() noexcept { return one(std::make_index_sequence{}); @@ -297,11 +343,15 @@ struct matrix return {identity_column(I, std::make_index_sequence{}) ...}; } - /// Returns an identity matrix, with ones on the main diagonal and zeros elsewhere. + /** + * Returns an identity matrix, with ones on the main diagonal and zeros elsewhere. + */ static constexpr matrix identity() noexcept { return identity(std::make_index_sequence{}); } + + /// @} }; /// 2x2 matrix. @@ -362,18 +412,6 @@ constexpr matrix add(const matrix& a, T b) noexcept; template constexpr T determinant(const matrix& m) noexcept; -/** - * Calculates the inverse of a square matrix. - * - * @param m Square matrix. - * - * @return Inverse of matrix @p m. - * - * @warning Currently only implemented for 2x2, 3x3, and 4x4 matrices. - */ -template -constexpr matrix inverse(const matrix& m) noexcept; - /** * Performs a component-wise multiplication of two matrices. * @@ -418,6 +456,41 @@ constexpr matrix div(const matrix& a, T b) noexcept; template constexpr matrix div(T a, const matrix& b) noexcept; +/** + * Extracts the Ith column from a matrix. + * + * @tparam I Index of a column. + * @tparam T Element type. + * @tparam N Number of columns. + * @tparam M Number of rows. + * + * @param m Matrix from which to extract a column. + * + * @return Reference to the Ith column of @p m. + */ +/// @{ +template +constexpr typename matrix::column_vector_type& get(math::matrix& m) noexcept; +template +constexpr typename matrix::column_vector_type&& get(math::matrix&& m) noexcept; +template +constexpr const typename matrix::column_vector_type& get(const math::matrix& m) noexcept; +template +constexpr const typename matrix::column_vector_type&& get(const math::matrix&& m) noexcept; +/// @} + +/** + * Calculates the inverse of a square matrix. + * + * @param m Square matrix. + * + * @return Inverse of matrix @p m. + * + * @warning Currently only implemented for 2x2, 3x3, and 4x4 matrices. + */ +template +constexpr matrix inverse(const matrix& m) noexcept; + /** * Creates a viewing transformation matrix. * @@ -659,6 +732,86 @@ constexpr T determinant(const matrix& m) noexcept m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3]; } +/// @private +template +constexpr inline matrix componentwise_mul(const matrix& a, const matrix& b, std::index_sequence) noexcept +{ + return {(a[I] * b[I]) ...}; +} + +template +constexpr matrix componentwise_mul(const matrix& a, const matrix& b) noexcept +{ + return componentwise_mul(a, b, std::make_index_sequence{}); +} + +/// @private +template +constexpr inline matrix div(const matrix& a, const matrix& b, std::index_sequence) noexcept +{ + return {(a[I] / b[I]) ...}; +} + +template +constexpr matrix div(const matrix& a, const matrix& b) noexcept +{ + return div(a, b, std::make_index_sequence{}); +} + +/// @private +template +constexpr inline matrix div(const matrix& a, T b, std::index_sequence) noexcept +{ + return {(a[I] / b) ...}; +} + +template +constexpr matrix div(const matrix& a, T b) noexcept +{ + return div(a, b, std::make_index_sequence{}); +} + +/// @private +template +constexpr inline matrix div(T a, const matrix& b, std::index_sequence) noexcept +{ + return {(a / b[I]) ...}; +} + +template +constexpr matrix div(T a, const matrix& b) noexcept +{ + return div(a, b, std::make_index_sequence{}); +} + +template +constexpr inline typename matrix::column_vector_type& get(math::matrix& m) noexcept +{ + static_assert(I < N); + return m.columns[I]; +} + +template +constexpr inline typename matrix::column_vector_type&& get(math::matrix&& m) noexcept +{ + static_assert(I < N); + return std::move(m.columns[I]); +} + +template +constexpr inline const typename matrix::column_vector_type& get(const math::matrix& m) noexcept +{ + static_assert(I < N); + return m.columns[I]; +} + +template +constexpr inline const typename matrix::column_vector_type&& get(const math::matrix&& m) noexcept +{ + static_assert(I < N); + return std::move(m.columns[I]); +} + template constexpr matrix inverse(const matrix& m) noexcept { @@ -723,58 +876,6 @@ constexpr matrix inverse(const matrix& m) noexcept }; } -/// @private -template -constexpr inline matrix componentwise_mul(const matrix& a, const matrix& b, std::index_sequence) noexcept -{ - return {(a[I] * b[I]) ...}; -} - -template -constexpr matrix componentwise_mul(const matrix& a, const matrix& b) noexcept -{ - return componentwise_mul(a, b, std::make_index_sequence{}); -} - -/// @private -template -constexpr inline matrix div(const matrix& a, const matrix& b, std::index_sequence) noexcept -{ - return {(a[I] / b[I]) ...}; -} - -template -constexpr matrix div(const matrix& a, const matrix& b) noexcept -{ - return div(a, b, std::make_index_sequence{}); -} - -/// @private -template -constexpr inline matrix div(const matrix& a, T b, std::index_sequence) noexcept -{ - return {(a[I] / b) ...}; -} - -template -constexpr matrix div(const matrix& a, T b) noexcept -{ - return div(a, b, std::make_index_sequence{}); -} - -/// @private -template -constexpr inline matrix div(T a, const matrix& b, std::index_sequence) noexcept -{ - return {(a / b[I]) ...}; -} - -template -constexpr matrix div(T a, const matrix& b) noexcept -{ - return div(a, b, std::make_index_sequence{}); -} - template constexpr matrix look_at(const vector& position, const vector& target, vector up) { @@ -1238,4 +1339,37 @@ std::istream& operator>>(std::istream& is, matrix& m) using namespace math::operators; +// Structured binding support +namespace std +{ + /** + * Provides access to the number of columns in a math::matrix as a compile-time constant expression. + * + * @tparam T Element type. + * @tparam N Number of columns. + * @tparam M Number of rows. + */ + template + struct tuple_size> + { + /// Number of columns in the matrix. + static constexpr std::size_t value = math::matrix::column_count; + }; + + /** + * Provides compile-time indexed access to the type of the columns in a math::matrix using a tuple-like interface. + * + * @tparam I Index of a column. + * @tparam T Element type. + * @tparam N Number of columns. + * @tparam M Number of rows. + */ + template + struct tuple_element> + { + /// Type of columns in the matrix. + using type = math::matrix::column_vector_type; + }; +} + #endif // ANTKEEPER_MATH_MATRIX_HPP diff --git a/src/math/vector.hpp b/src/math/vector.hpp index e4bde71..d5e930b 100644 --- a/src/math/vector.hpp +++ b/src/math/vector.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,51 @@ struct vector /// Array of vector elements. element_type elements[N]; + /// @name Conversion + /// @{ + + /// @private + template + constexpr inline vector type_cast(std::index_sequence) const noexcept + { + return {static_cast(elements[I])...}; + } + + /** + * Type-casts the elements of this vector using `static_cast`. + * + * @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 zero. + * + * @tparam M Target number of elements. + * + * @return *m*-dimensional vector. + */ + template + constexpr inline explicit operator vector() const noexcept + { + return size_cast(std::make_index_sequence{}); + } + + /// @} + /// @name Element access /// @{ @@ -250,47 +296,12 @@ struct vector /// @} - /// @private - template - constexpr inline vector type_cast(std::index_sequence) const noexcept - { - return {static_cast(elements[I])...}; - } - - /** - * Type-casts the elements of this vector using `static_cast`. - * - * @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} ...}; - } + /// @name Constants + /// @{ /** - * 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 zero. - * - * @tparam M Target number of elements. - * - * @return *m*-dimensional vector. + * Returns a zero vector, where every element is equal to zero. */ - template - constexpr inline explicit operator vector() const noexcept - { - return size_cast(std::make_index_sequence{}); - } - - /// Returns a zero vector, where every element is equal to zero. static constexpr vector zero() noexcept { return {}; @@ -306,11 +317,15 @@ struct vector return {(I ? T{1} : T{1})...}; } - /// Returns a vector of ones, where every element is equal to one. + /** + * Returns a vector of ones, where every element is equal to one. + */ static constexpr vector one() noexcept { return one(std::make_index_sequence{}); } + + /// @} }; /// Vector with two elements. @@ -883,14 +898,13 @@ constexpr inline bool any(const vector& x) noexcept } /// @private -template +template constexpr inline vector ceil(const vector& x, std::index_sequence) { - static_assert(std::is_floating_point::value); return {std::ceil(x[I])...}; } -template +template constexpr inline vector ceil(const vector& x) { return ceil(x, std::make_index_sequence{}); @@ -922,10 +936,9 @@ constexpr inline vector clamp(const vector& x, T min, T max) return clamp(x, min, max, std::make_index_sequence{}); } -template +template vector clamp_length(const vector& x, T max_length) { - static_assert(std::is_floating_point::value); T length2 = sqr_length(x); return (length2 > max_length * max_length) ? (x * (max_length / std::sqrt(length2))) : x; } @@ -1013,56 +1026,52 @@ constexpr inline vector equal(const vector& x, const vector } /// @private -template +template constexpr inline vector floor(const vector& x, std::index_sequence) { - static_assert(std::is_floating_point::value); return {std::floor(x[I])...}; } -template +template constexpr inline vector floor(const vector& x) { return floor(x, std::make_index_sequence{}); } /// @private -template +template constexpr inline vector fma(const vector& x, const vector& y, const vector& z, std::index_sequence) { - static_assert(std::is_floating_point::value); return {std::fma(x[I], y[I], z[I])...}; } -template +template constexpr inline vector fma(const vector& x, const vector& y, const vector& z) { return fma(x, y, z, std::make_index_sequence{}); } /// @private -template +template constexpr inline vector fma(const vector& x, T y, T z, std::index_sequence) { - static_assert(std::is_floating_point::value); return {std::fma(x[I], y, z)...}; } -template +template constexpr inline vector fma(const vector& x, T y, T z) { return fma(x, y, z, std::make_index_sequence{}); } /// @private -template +template constexpr inline vector fract(const vector& x, std::index_sequence) { - static_assert(std::is_floating_point::value); return {x[I] - std::floor(x[I])...}; } -template +template constexpr inline vector fract(const vector& x) { return fract(x, std::make_index_sequence{}); @@ -1122,16 +1131,15 @@ constexpr inline vector greater_than_equal(const vector& x, const return greater_than_equal(x, y, std::make_index_sequence{}); } -template +template inline T inv_length(const vector& x) { return T{1} / length(x); } -template +template inline T length(const vector& x) { - static_assert(std::is_floating_point::value); return std::sqrt(sqr_length(x)); } @@ -1200,28 +1208,26 @@ constexpr inline T min(const vector& x) } /// @private -template +template constexpr inline vector mod(const vector& x, const vector& y, std::index_sequence) { - static_assert(std::is_floating_point::value); return {std::fmod(x[I], y[I])...}; } -template +template constexpr inline vector mod(const vector& x, const vector& y) { return mod(x, y, std::make_index_sequence{}); } /// @private -template +template constexpr inline vector mod(const vector& x, T y, std::index_sequence) { - static_assert(std::is_floating_point::value); return {std::fmod(x[I], y)...}; } -template +template constexpr inline vector mod(const vector& x, T y) { return mod(x, y, std::make_index_sequence{}); @@ -1266,7 +1272,7 @@ constexpr inline vector negate(const vector& x) noexcept return negate(x, std::make_index_sequence{}); } -template +template inline vector normalize(const vector& x) { return mul(x, inv_length(x)); @@ -1299,56 +1305,52 @@ constexpr inline vector not_equal(const vector& x, const vector +template inline vector pow(const vector& x, const vector& y, std::index_sequence) { - static_assert(std::is_floating_point::value); return {std::pow(x[I], y[I])...}; } -template +template inline vector pow(const vector& x, const vector& y) { return pow(x, y, std::make_index_sequence{}); } /// @private -template +template inline vector pow(const vector& x, T y, std::index_sequence) { - static_assert(std::is_floating_point::value); return {std::pow(x[I], y)...}; } -template +template inline vector pow(const vector& x, T y) { return pow(x, y, std::make_index_sequence{}); } /// @private -template +template constexpr inline vector round(const vector& x, std::index_sequence) { - static_assert(std::is_floating_point::value); return {std::round(x[I])...}; } -template +template constexpr inline vector round(const vector& x) { return round(x, std::make_index_sequence{}); } /// @private -template +template constexpr inline vector sign(const vector& x, std::index_sequence) { - static_assert(std::is_floating_point::value); return {std::copysign(T{1}, x[I])...}; } -template +template constexpr inline vector sign(const vector& x) { return sign(x, std::make_index_sequence{}); @@ -1367,14 +1369,13 @@ constexpr inline T sqr_length(const vector& x) noexcept } /// @private -template +template inline vector sqrt(const vector& x, std::index_sequence) { - static_assert(std::is_floating_point::value); return {std::sqrt(x[I])...}; } -template +template inline vector sqrt(const vector& x, const vector& y) { return sqrt(x, std::make_index_sequence{}); @@ -1439,14 +1440,13 @@ constexpr inline vector swizzle(const vector& x) no } /// @private -template +template constexpr inline vector trunc(const vector& x, std::index_sequence) { - static_assert(std::is_floating_point::value); return {std::trunc(x[I])...}; } -template +template constexpr inline vector trunc(const vector& x) { return trunc(x, std::make_index_sequence{}); @@ -1687,12 +1687,13 @@ namespace std struct tuple_size> { /// Number of elements in the vector. - static constexpr std::size_t value = N; + static constexpr std::size_t value = math::vector::element_count; }; /** * Provides compile-time indexed access to the type of the elements in a math::vector using a tuple-like interface. * + * @tparam I Index of an element. * @tparam T Element type. * @tparam N Number of elements. */ @@ -1700,7 +1701,7 @@ namespace std struct tuple_element> { /// Type of elements in the vector. - using type = T; + using type = math::vector::element_type; }; }