From 8b3a1480a18f3bfe679e781c169d19d7aa7cb8af Mon Sep 17 00:00:00 2001 From: namark <namark@disroot.org> Date: Sun, 25 Oct 2020 03:04:22 +0400 Subject: [PATCH] Various small improvements for vector: removed default values of template parameters (barely used, still breaking change) a basic plan for specialization of vector using intrinsics, get goes through operator[] instead of going directly to raw, operator[] forwards, tuple interface Tests: unary operators for bool matrix (cause those are kind of an edge casey), structured binding works and respects order --- source/simple/geom/vector.hpp | 118 ++++++++++++++++++++++++++++------ unit_tests/point.cpp | 23 +++++++ 2 files changed, 122 insertions(+), 19 deletions(-) diff --git a/source/simple/geom/vector.hpp b/source/simple/geom/vector.hpp index a90ac97..ddebf4a 100644 --- a/source/simple/geom/vector.hpp +++ b/source/simple/geom/vector.hpp @@ -17,13 +17,37 @@ namespace simple::geom { - template <typename Coordinate = float, size_t Dimensions = 2, + template <typename Type, size_t Size> + struct vector_array + { + using type = support::array<Type, Size>; + }; + + template <typename Type, size_t Size> + using vector_array_t = typename vector_array<Type, Size>::type; + + // TODO; in an optional header + // template <size_t Size> + // struct vector_array<unsigned int, Size> + // { + // using value_type = unsigned int; + // typedef value_type type __attribute__ ((vector_size (Size * sizeof(value_type)))); + // }; + // + // template <size_t Size> + // struct vector_array<int, Size> + // { + // using value_type = int; + // typedef value_type type __attribute__ ((vector_size (Size * sizeof(value_type)))); + // }; + + template <typename Coordinate, size_t Dimensions, typename Order = std::make_index_sequence<Dimensions>, std::enable_if_t<Order::size() == Dimensions>* = nullptr> class vector { public: - using array = support::array<Coordinate, Dimensions>; + using array = vector_array_t<Coordinate, Dimensions>; using coordinate_type = Coordinate; using order = Order; using value_type = Coordinate; @@ -410,7 +434,7 @@ namespace simple::geom { static_assert(dimension < Dimensions); constexpr size_t index = support::car<Order, dimension>; - return raw[index]; + return (*this)[index]; } template <size_t dimension> @@ -419,18 +443,50 @@ namespace simple::geom { static_assert(dimension < Dimensions); constexpr size_t index = support::car<Order, dimension>; - return raw[index]; + return (*this)[index]; + } + + template <size_t dimension> + [[nodiscard]] + constexpr coordinate_type && get() && + { + static_assert(dimension < Dimensions); + constexpr size_t index = support::car<Order, dimension>; + return std::move(*this)[index]; } + template <size_t dimension> [[nodiscard]] - constexpr const coordinate_type & operator[](size_t dimension) const& + constexpr const coordinate_type && get() const&& + { + static_assert(dimension < Dimensions); + constexpr size_t index = support::car<Order, dimension>; + return (*this)[index]; + } + + [[nodiscard]] constexpr const coordinate_type & + operator[](size_t dimension) const& { assert(dimension < Dimensions); return raw[dimension]; } - [[nodiscard]] - constexpr coordinate_type & operator[](size_t dimension) & + [[nodiscard]] constexpr coordinate_type & + operator[](size_t dimension) & + { + assert(dimension < Dimensions); + return raw[dimension]; + } + + [[nodiscard]] constexpr coordinate_type && + operator[](size_t dimension) && + { + assert(dimension < Dimensions); + return std::move(raw[dimension]); + } + + [[nodiscard]] constexpr const coordinate_type && + operator[](size_t dimension) const&& { assert(dimension < Dimensions); return raw[dimension]; @@ -472,19 +528,19 @@ namespace simple::geom return raw[index[0]]; } - [[nodiscard]] constexpr auto begin() noexcept { return std::begin(raw); } - [[nodiscard]] constexpr auto end() noexcept { return std::end(raw); } - [[nodiscard]] constexpr auto begin() const noexcept { return std::cbegin(raw); } - [[nodiscard]] constexpr auto end() const noexcept { return std::cend(raw); } - [[nodiscard]] constexpr auto cbegin() const noexcept { return std::cbegin(raw); } - [[nodiscard]] constexpr auto cend() const noexcept { return std::cend(raw); } + [[nodiscard]] constexpr auto begin() noexcept { using std::begin; return begin(raw); } + [[nodiscard]] constexpr auto end() noexcept { using std::end; return end(raw); } + [[nodiscard]] constexpr auto begin() const noexcept { using std::cbegin; return cbegin(raw); } + [[nodiscard]] constexpr auto end() const noexcept { using std::cend; return cend(raw); } + [[nodiscard]] constexpr auto cbegin() const noexcept { using std::cbegin; return cbegin(raw); } + [[nodiscard]] constexpr auto cend() const noexcept { using std::cend; return cend(raw); } - [[nodiscard]] constexpr auto rbegin() noexcept { return std::rbegin(raw); } - [[nodiscard]] constexpr auto rend() noexcept { return std::rend(raw); } - [[nodiscard]] constexpr auto rbegin() const noexcept { return std::crbegin(raw); } - [[nodiscard]] constexpr auto rend() const noexcept { return std::crend(raw); } - [[nodiscard]] constexpr auto crbegin() const noexcept { return std::crbegin(raw); } - [[nodiscard]] constexpr auto crend() const noexcept { return std::crend(raw); } + [[nodiscard]] constexpr auto rbegin() noexcept { using std::rbegin; return rbegin(raw); } + [[nodiscard]] constexpr auto rend() noexcept { using std::rend; return rend(raw); } + [[nodiscard]] constexpr auto rbegin() const noexcept { using std::crbegin; return crbegin(raw); } + [[nodiscard]] constexpr auto rend() const noexcept { using std::crend; return crend(raw); } + [[nodiscard]] constexpr auto crbegin() const noexcept { using std::crbegin; return crbegin(raw); } + [[nodiscard]] constexpr auto crend() const noexcept { using std::crend; return crend(raw); } constexpr vector& min(const vector& other) { @@ -890,6 +946,20 @@ namespace simple::geom template <typename C, size_t D, typename O, void* SFINAE> vector(vector<C,D,O,SFINAE>) -> vector<vector<C,D,O,SFINAE>,1>; + template <typename> + struct is_vector_instance : public std::false_type {}; + + template <typename C, size_t D, typename O> + struct is_vector_instance<vector<C,D,O>> : public std::true_type {}; + + template <typename V> + constexpr auto is_vector_instance_v = is_vector_instance<V>::value; + + template <size_t I, typename V, + std::enable_if_t<is_vector_instance_v<std::decay_t<V>>>* = nullptr> + constexpr decltype(auto) get(V&& v) + { return std::forward<V>(v).template get<I>(); } + } // namespace simple::geom namespace simple @@ -945,6 +1015,16 @@ class std::numeric_limits<simple::geom::vector<T,C,O>> } }; +template <typename C, size_t D, typename O> +struct std::tuple_size<simple::geom::vector<C,D,O>> : + std::integral_constant<size_t, D> {}; + +template <size_t I, typename C, size_t D, typename O> +struct std::tuple_element<I, simple::geom::vector<C,D,O>> +{ + using type = C; +}; + #include "bool_algebra.hpp" // oof TODO: comparison ops are here now, though some would say not having them is a blessing, that would be a breaking change... #endif /* end of include guard */ diff --git a/unit_tests/point.cpp b/unit_tests/point.cpp index 165b3c1..2d3633e 100644 --- a/unit_tests/point.cpp +++ b/unit_tests/point.cpp @@ -403,6 +403,23 @@ void DiscreteArithmetic() assert( (!vector(true, false, true, false)) == vector(false, true, false, true) ); assert( (!vector(true, true, false, false)) == vector(false, false, true, true) ); assert( (!vector(true, true, true, true)) == vector(false, false, false, false) ); + + // ~ for vector<vector<bool>> + assert( (~vector(vector(true, false), vector(true, false))) == + vector(vector(false, true), vector(false, true)) ); + assert( (~vector(vector(true, true), vector(false, false))) == + vector(vector(false, false), vector(true, true)) ); + assert( (~vector(vector(true, true), vector(true, true))) == + vector(vector(false, false), vector(false, false)) ); + + // ! for vector<vector<bool>> + assert( (!vector(vector(true, false), vector(true, false))) == + vector(vector(false, true), vector(false, true)) ); + assert( (!vector(vector(true, true), vector(false, false))) == + vector(vector(false, false), vector(true, true)) ); + assert( (!vector(vector(true, true), vector(true, true))) == + vector(vector(false, false), vector(false, false)) ); + } void ComparisonOperators() @@ -456,6 +473,12 @@ void CoordinateOrder() assert( p_wzyx[2] == 3 ); assert( p_wzyx[3] == 4 ); assert( int4(p_wzyx) == int4(4,3,2,1) ); + + auto [x,y,z,w] = p_wzyx; + assert( x == p_wzyx.x() ); + assert( y == p_wzyx.y() ); + assert( z == p_wzyx.z() ); + assert( w == p_wzyx.w() ); } void DefyPromotion() -- GitLab