diff --git a/detail/coord.hpp b/detail/coord.hpp index d842a3f7..f3157b37 100644 --- a/detail/coord.hpp +++ b/detail/coord.hpp @@ -5,16 +5,16 @@ * 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. - * + * * libgim 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 libgim. If not, see . * - * Copyright 2012 Danny Robson + * Copyright 2012-2015 Danny Robson */ #ifndef __UTIL_COORD_HPP @@ -39,173 +39,120 @@ namespace util { #if defined(COMPILER_CLANG) #pragma GCC diagnostic ignored "-Wgnu" #endif + + //--------------------------------------------------------------------- + // coord types are not really intended to have arbitrary dimension, so + // don't add specialisations (or a general case) without a decent + // reason. template - struct coord { - typedef T value_type; - - coord () { ; } - - explicit coord (T v) - { std::fill (std::begin (data), std::end (data), v); } - - template - coord (U ..._u): data{_u...} - { ; } - - coord (const coord &rhs) = default; - coord& operator= (const coord &rhs) = default; - - T data[S]; - - static constexpr size_t dimension = S; - - T& operator[] (size_t i) { return data[i]; } - T operator[] (size_t i) const { return data[i]; } - }; + struct coord_data; + //--------------------------------------------------------------------- template - struct coord<1,T> { - typedef T value_type; - - coord () { ; } - - explicit coord (T v) - { std::fill (std::begin (data), std::end (data), v); } - - template - coord (U ..._u): data{_u...} + struct coord_data<1, T> + { + coord_data () = default; + coord_data (T v0): + data { v0 } { ; } - coord (const coord<1,T> &rhs) = default; - coord& operator= (const coord<1,T> &rhs) = default; - union { T data[1]; T x; }; - - static constexpr size_t dimension = 1; - - T& operator[] (size_t i) { return data[i]; } - T operator[] (size_t i) const { return data[i]; } }; + + //--------------------------------------------------------------------- template - struct coord<2,T> { - typedef T value_type; - - coord () { ; } - - explicit coord (T v) - { std::fill (std::begin (data), std::end (data), v); } - - template - coord (U ..._u): data{_u...} + struct coord_data<2,T> + { + coord_data () = default; + coord_data (T v0, T v1): + data { v0, v1 } { ; } - coord (const coord<2,T> &rhs) = default; - coord& operator= (const coord<2,T> &rhs) = default; - union { T data[2]; - struct { - T x; - T y; - }; - struct { - T s; - T t; - }; + + struct { T x, y; }; + struct { T s, t; }; }; - - static constexpr size_t dimension = 2; - - T& operator[] (size_t i) { return data[i]; } - T operator[] (size_t i) const { return data[i]; } }; + + //--------------------------------------------------------------------- template - struct coord<3,T> { - typedef T value_type; + struct coord_data<3,T> + { + coord_data () = default; + coord_data (T v0, T v1, T v2): + data { v0, v1, v2 } + { ; } union { T data[3]; - struct { - T x; - T y; - T z; - }; - struct { - T r; - T g; - T b; - }; + + struct { T x, y, z; }; + struct { T s, t, p; }; + struct { T r, g, b; }; }; - - static constexpr size_t dimension = 3; - - coord () { ; } - - explicit coord (T v) - { std::fill (std::begin (data), std::end (data), v); } - - template - coord (U... u): data{u...} - { ; } - - coord (const coord<3,T> &rhs) = default; - coord& operator= (const coord<3,T> &rhs) = default; - - T& operator[] (size_t i) { return data[i]; } - T operator[] (size_t i) const { return data[i]; } }; - template - T dot (const coord &a, const coord &b) - { - T sum { 0 }; - for (size_t i = 0; i < S; ++i) - sum += a.data[i] * b.data[i]; - return sum; - } + //--------------------------------------------------------------------- template - struct coord<4,T> { - typedef T value_type; + struct coord_data<4,T> + { + coord_data () = default; + coord_data (T v0, T v1, T v2, T v3): + data { v0, v1, v2, v3 } + { ; } union { T data[4]; - struct { - T x; - T y; - T z; - T w; - }; - struct { - T r; - T g; - T b; - T a; - }; + + struct { T x, y, z, w; }; + struct { T s, t, p, q; }; + struct { T r, g, b, a; }; }; + }; - static constexpr size_t dimension = 4; - coord () { ; } + //--------------------------------------------------------------------- + template + struct coord : public coord_data { + static_assert (S > 0, "coord dimensions must be strictly positive"); + + typedef T value_type; + static constexpr size_t dimension = S; + + using coord_data::coord_data; + coord () = default; explicit coord (T v) - { std::fill (std::begin (data), std::end (data), v); } + { std::fill (std::begin (this->data), std::end (this->data), v); } - template - coord (U... u): data{u...} - { ; } + coord (const coord &rhs) = default; + coord& operator= (const coord &rhs) = default; - coord (const coord<4,T> &rhs) = default; - coord& operator= (const coord<4,T> &rhs) = default; - - T& operator[] (size_t i) { return data[i]; } - T operator[] (size_t i) const { return data[i]; } + T& operator[] (size_t i) { return this->data[i]; } + T operator[] (size_t i) const { return this->data[i]; } }; + + + //--------------------------------------------------------------------- + // XXX: Unsure whether this should really be defined for arbitrary + // types in a semantic sense, but practicality suggestes this is the + // best option; point/vector dot product is too useful. + template + T dot (const coord &a, const coord &b) + { + return std::inner_product (std::begin (a.data), + std::end (a.data), + std::begin (b.data), + T {0}); + } #pragma GCC diagnostic pop } } diff --git a/point.hpp b/point.hpp index ba3dab8a..a3137a09 100644 --- a/point.hpp +++ b/point.hpp @@ -32,8 +32,6 @@ namespace util { /// An n-dimensional position in space. template struct point : public detail::coord { - static_assert (S > 0, "point dimensions must be strictly positive."); - using detail::coord::coord; // point operators diff --git a/vector.hpp b/vector.hpp index 9f6f72db..8bf86c32 100644 --- a/vector.hpp +++ b/vector.hpp @@ -30,8 +30,6 @@ namespace util { template struct vector : public detail::coord { - static_assert (S > 0, "vector dimensions must be strictly positive"); - using detail::coord::coord; // arithmetic operators