From e461654de8d7a9a39400a0e9c025ba4ec88c3127 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Fri, 6 Mar 2015 01:46:01 +1100 Subject: [PATCH] coord: split coord header into components --- Makefile.am | 7 +- colour.hpp | 4 +- coord.hpp | 359 +----------------------------------------------- coord/base.hpp | 63 +++++++++ coord/init.hpp | 79 +++++++++++ coord/names.hpp | 32 +++++ coord/ops.hpp | 211 ++++++++++++++++++++++++++++ coord/store.hpp | 145 +++++++++++++++++++ extent.hpp | 4 +- point.hpp | 4 +- region.hpp | 1 - vector.hpp | 4 +- 12 files changed, 546 insertions(+), 367 deletions(-) create mode 100644 coord/base.hpp create mode 100644 coord/init.hpp create mode 100644 coord/names.hpp create mode 100644 coord/ops.hpp create mode 100644 coord/store.hpp diff --git a/Makefile.am b/Makefile.am index 73107231..e5dcf262 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,7 +16,12 @@ UTIL_FILES = \ bitwise.hpp \ colour.cpp \ colour.hpp \ - detail/coord.hpp \ + coord.hpp \ + coord/base.hpp \ + coord/init.hpp \ + coord/names.hpp \ + coord/ops.hpp \ + coord/store.hpp \ debug.cpp \ debug.hpp \ endian.cpp \ diff --git a/colour.hpp b/colour.hpp index 32061391..e2174b50 100644 --- a/colour.hpp +++ b/colour.hpp @@ -29,8 +29,8 @@ namespace util { /// An RGBA colour POD type. template - struct colour : public coord<4,T,detail::rgba> { - using coord<4,T,detail::rgba>::coord; + struct colour : public coord::base<4,T,coord::rgba> { + using coord::base<4,T,coord::rgba>::base; static const colour WHITE; static const colour BLACK; diff --git a/coord.hpp b/coord.hpp index c22994d5..20fd4566 100644 --- a/coord.hpp +++ b/coord.hpp @@ -20,362 +20,7 @@ #ifndef __UTIL_COORD_HPP #define __UTIL_COORD_HPP -#include "platform.hpp" -#include "preprocessor.hpp" - -#include -#include -#include - -#include - -namespace util { - namespace detail { - /////////////////////////////////////////////////////////////////////// - // tags for accessor names - struct rgba { }; - struct xyzw { }; - struct stpq { }; - struct whd { }; - - - /////////////////////////////////////////////////////////////////////// - // Disable GCC warnings about validity of anonyous structures in - // unions. Push comes to shove I'll manually redsign everything to - // keep this syntax anyway. -#pragma GCC diagnostic push -#if defined(COMPILER_GCC) - #pragma GCC diagnostic ignored "-pedantic" -#endif -#if defined(COMPILER_CLANG) - #pragma GCC diagnostic ignored "-Wgnu" -#endif - - template - struct coord_base { - T data[S]; - }; - - - template - struct coord_base<3,T,rgba> { - union { - T data[3]; - struct { T r,g,b; }; - }; - }; - - template - struct coord_base<4,T,rgba> { - union { - T data[4]; - struct { T r,g,b,a; }; - }; - }; - - - template - struct coord_base<2,T,xyzw> { - union { - T data[2]; - struct { T x,y; }; - }; - }; - - - template - struct coord_base<3,T,xyzw> { - union { - T data[3]; - struct { T x,y,z; }; - }; - }; - - - template - struct coord_base<4,T,xyzw> { - union { - T data[4]; - struct { T x,y,z,w; }; - }; - }; - - - template - struct coord_base<2,T,xyzw,stpq> { - union { - T data[2]; - struct { T x,y; }; - struct { T s,t; }; - }; - }; - - - template - struct coord_base<3,T,xyzw,stpq> { - union { - T data[3]; - struct { T x,y,z; }; - struct { T s,t,p; }; - }; - }; - - - template - struct coord_base<4,T,xyzw,stpq> { - union { - T data[4]; - struct { T x,y,z,w; }; - struct { T s,t,p,q; }; - }; - }; - - - template - struct coord_base<2,T,whd> { - union { - T data[2]; - struct { T w,h; }; - }; - }; - - - template - struct coord_base<3,T,whd> { - union { - T data[3]; - struct { T w,h,d; }; - }; - }; - -#pragma GCC diagnostic pop - - /////////////////////////////////////////////////////////////////////// - // 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_init; - - ////--------------------------------------------------------------------- - template - struct coord_init<1,T,tags...> : public coord_base<1,T,tags...> - { - using coord_base<1,T,tags...>::coord_base; - coord_init () = default; - coord_init (T v0): - coord_base<1,T,tags...> ({v0}) - { ; } - }; - - - ////--------------------------------------------------------------------- - template - struct coord_init<2,T,tags...> : public coord_base<2,T,tags...> - { - using coord_base<2,T,tags...>::coord_base; - coord_init () = default; - coord_init (T v0, T v1): - coord_base<2,T,tags...> ({ v0, v1 }) - { ; } - }; - - - ////--------------------------------------------------------------------- - template - struct coord_init<3,T,tags...> : public coord_base<3,T,tags...> - { - using coord_base<3,T,tags...>::coord_base; - coord_init () = default; - coord_init (T v0, T v1, T v2): - coord_base<3,T,tags...> ({v0, v1, v2}) - { ; } - }; - - - ////--------------------------------------------------------------------- - template - struct coord_init<4,T,tags...> : public coord_base<4,T,tags...> - { - using coord_base<4,T,tags...>::coord_base; - coord_init () = default; - coord_init (T v0, T v1, T v2, T v3): - coord_base<4,T,tags...> ({ v0, v1, v2, v3 }) - { ; } - }; - } - - - ///////////////////////////////////////////////////////////////////////// - template - struct coord : public detail::coord_init { - static_assert (S > 0, "coord dimensions must be strictly positive"); - - typedef T value_type; - static constexpr size_t dimension = S; - static constexpr size_t elements = S; - - size_t size (void) const { return S; } - - // constructors - using detail::coord_init::coord_init; - coord () = default; - - explicit coord (T v) - { std::fill (std::begin (this->data), std::end (this->data), v); } - - coord (const coord &rhs) = default; - coord& operator= (const coord &rhs) = default; - - // element accessors - T& operator[] (size_t i) { return this->data[i]; } - T operator[] (size_t i) const { return this->data[i]; } - - const T* begin (void) const { return std::begin (this->data); } - const T* end (void) const { return std::end (this->data); } - - T* begin (void) { return std::begin (this->data); } - T* end (void) { return std::end (this->data); } - }; - - - /////////////////////////////////////////////////////////////////////// - // operation traits - template class point; - template class extent; - template class vector; - - template < - size_t S, - typename T, - template class A, - template class B - > - struct coord_traits { }; - - - template struct coord_traits { typedef extent result; }; - template struct coord_traits { typedef extent result; }; - template struct coord_traits { typedef point result; }; - template struct coord_traits { typedef point result; }; - template struct coord_traits { typedef vector result; }; - - - /////////////////////////////////////////////////////////////////////////// - // vector operators -#define ELEMENT_OP(OP) \ - template < \ - size_t S, \ - typename T, \ - template class A, \ - template class B \ - > \ - typename coord_traits::result \ - operator OP (A a, B b) \ - { \ - typename coord_traits::result out; \ - for (size_t i = 0; i < S; ++i) \ - out[i] = a[i] OP b[i]; \ - return out; \ - } \ - \ - template < \ - size_t S, \ - typename T, \ - template class A, \ - template class B \ - > \ - typename coord_traits::result& \ - operator PASTE(OP,=) (A& a, B b) \ - { \ - for (size_t i = 0; i < S; ++i) \ - a[i] PASTE(OP,=) b[i]; \ - return a; \ - } - - ELEMENT_OP(+) - ELEMENT_OP(-) - ELEMENT_OP(*) - ELEMENT_OP(/) -#undef ELEMENT_OP - - /////////////////////////////////////////////////////////////////////////// - // scalar operators -#define SCALAR_OP(OP) \ - template class K> \ - K \ - operator OP (T t, K k) \ - { \ - K out; \ - for (size_t i = 0; i < S; ++i) \ - out[i] = t OP k[i]; \ - return out; \ - } \ - \ - template class K> \ - K \ - operator OP (K k, T t) \ - { \ - K out; \ - for (size_t i = 0; i < S; ++i) \ - out[i] = t OP k[i]; \ - return out; \ - } - - SCALAR_OP(+) - SCALAR_OP(-) - SCALAR_OP(*) - SCALAR_OP(/) - -#undef SCALAR_OP - - -#define SCALAR_OP(OP) \ - template class K> \ - K& \ - operator OP (K &k, T t) \ - { \ - for (size_t i = 0; i < S; ++i) \ - k[i] OP t; \ - return k; \ - } - - SCALAR_OP(+=) - SCALAR_OP(-=) - SCALAR_OP(*=) - SCALAR_OP(/=) -#undef SCALAR_OP - - - /////////////////////////////////////////////////////////////////////////// - // logic operators - template class K> - bool operator== (K a, K b) - { return std::equal (std::begin (a), std::end (a), std::begin (b)); } - - template class K> - bool operator!= (K a, K b) - { return !(a == b); } - - - /////////////////////////////////////////////////////////////////////////// - // special operators - template vector operator- (point a, point b) - { - vector out; - for (size_t i = 0; i < S; ++i) - out[i] = a[i] - b[i]; - return out; - } - - template class A, template class B> - T dot (A a, B b) - { - T sum { 0 }; - for (size_t i = 0; i < S; ++i) - sum += a[i] * b[i]; - return sum; - } -} +#include "coord/base.hpp" +#include "coord/ops.hpp" #endif diff --git a/coord/base.hpp b/coord/base.hpp new file mode 100644 index 00000000..6e4ca876 --- /dev/null +++ b/coord/base.hpp @@ -0,0 +1,63 @@ +/* + * This file is part of libgim. + * + * libgim 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. + * + * 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-2015 Danny Robson + */ + +#ifndef __UTIL_COORD_BASE_HPP +#define __UTIL_COORD_BASE_HPP + +#include "init.hpp" + +#include +#include + +namespace util { namespace coord { + ///////////////////////////////////////////////////////////////////////// + template + struct base : public init { + static_assert (S > 0, "coord dimensions must be strictly positive"); + + typedef T value_type; + static constexpr size_t dimension = S; + static constexpr size_t elements = S; + + size_t size (void) const { return S; } + + // constructors + using init::init; + base () = default; + + explicit base (T v) + { std::fill (std::begin (this->data), std::end (this->data), v); } + + base (const base &rhs) = default; + base& operator= (const base &rhs) = default; + + // element accessors + T& operator[] (size_t i) { return this->data[i]; } + T operator[] (size_t i) const { return this->data[i]; } + + const T* begin (void) const { return std::begin (this->data); } + const T* end (void) const { return std::end (this->data); } + + T* begin (void) { return std::begin (this->data); } + T* end (void) { return std::end (this->data); } + }; +} } + + +#endif diff --git a/coord/init.hpp b/coord/init.hpp new file mode 100644 index 00000000..98b609ed --- /dev/null +++ b/coord/init.hpp @@ -0,0 +1,79 @@ +/* + * This file is part of libgim. + * + * libgim 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. + * + * 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 2015 Danny Robson + */ + +#ifndef __UTIL_COORD_INIT_HPP +#define __UTIL_COORD_INIT_HPP + +#include "store.hpp" + +#include + +namespace util { namespace coord { + template + struct init; + + //------------------------------------------------------------------------- + template + struct init<1,T,tags...> : public store<1,T,tags...> + { + using store<1,T,tags...>::store; + init () = default; + init (T v0): + store<1,T,tags...> ({v0}) + { ; } + }; + + + //------------------------------------------------------------------------- + template + struct init<2,T,tags...> : public store<2,T,tags...> + { + using store<2,T,tags...>::store; + init () = default; + init (T v0, T v1): + store<2,T,tags...> ({ v0, v1 }) + { ; } + }; + + + //------------------------------------------------------------------------- + template + struct init<3,T,tags...> : public store<3,T,tags...> + { + using store<3,T,tags...>::store; + init () = default; + init (T v0, T v1, T v2): + store<3,T,tags...> ({v0, v1, v2}) + { ; } + }; + + + //------------------------------------------------------------------------- + template + struct init<4,T,tags...> : public store<4,T,tags...> + { + using store<4,T,tags...>::store; + init () = default; + init (T v0, T v1, T v2, T v3): + store<4,T,tags...> ({ v0, v1, v2, v3 }) + { ; } + }; +} } + +#endif diff --git a/coord/names.hpp b/coord/names.hpp new file mode 100644 index 00000000..f0a7d8d2 --- /dev/null +++ b/coord/names.hpp @@ -0,0 +1,32 @@ +/* + * This file is part of libgim. + * + * libgim 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. + * + * 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 2015 Danny Robson + */ + +#ifndef __UTIL_COORD_NAMES_HPP +#define __UTIL_COORD_NAMES_HPP + +namespace util { namespace coord { + /////////////////////////////////////////////////////////////////////// + // tags for accessor names + struct rgba { }; + struct xyzw { }; + struct stpq { }; + struct whd { }; +} } + +#endif diff --git a/coord/ops.hpp b/coord/ops.hpp new file mode 100644 index 00000000..0057291e --- /dev/null +++ b/coord/ops.hpp @@ -0,0 +1,211 @@ +/* + * This file is part of libgim. + * + * libgim 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. + * + * 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-2015 Danny Robson + */ + +#ifndef __UTIL_COORDS_OPS +#define __UTIL_COORDS_OPS + +#include "preprocessor.hpp" + +#include + +namespace util { + // forward declerations for traits + template class point; + template class extent; + template class vector; + + /////////////////////////////////////////////////////////////////////// + // operation traits + namespace coord { + template < + size_t S, + typename T, + template class A, + template class B + > + struct traits { }; + + + //------------------------------------------------------------------------- + template struct traits { typedef extent result; }; + template struct traits { typedef extent result; }; + template struct traits { typedef point result; }; + template struct traits { typedef point result; }; + template struct traits { typedef vector result; }; + } + + /////////////////////////////////////////////////////////////////////////// + // vector operators +#define ELEMENT_OP(OP) \ + template < \ + size_t S, \ + typename T, \ + template class A, \ + template class B \ + > \ + typename coord::traits::result \ + operator OP (A a, B b) \ + { \ + typename coord::traits::result out; \ + for (size_t i = 0; i < S; ++i) \ + out[i] = a[i] OP b[i]; \ + return out; \ + } \ + \ + template < \ + size_t S, \ + typename T, \ + template class A, \ + template class B \ + > \ + typename coord::traits::result& \ + operator PASTE(OP,=) (A& a, B b) \ + { \ + for (size_t i = 0; i < S; ++i) \ + a[i] PASTE(OP,=) b[i]; \ + return a; \ + } + + ELEMENT_OP(+) + ELEMENT_OP(-) + ELEMENT_OP(*) + ELEMENT_OP(/) +#undef ELEMENT_OP + + /////////////////////////////////////////////////////////////////////////// + // scalar operators +#define SCALAR_OP(OP) \ + template < \ + size_t S, \ + typename T, \ + template class K \ + > \ + K \ + operator OP (T t, K k) \ + { \ + K out; \ + for (size_t i = 0; i < S; ++i) \ + out[i] = t OP k[i]; \ + return out; \ + } \ + \ + template < \ + size_t S, \ + typename T, \ + template class K \ + > \ + K \ + operator OP (K k, T t) \ + { \ + K out; \ + for (size_t i = 0; i < S; ++i) \ + out[i] = t OP k[i]; \ + return out; \ + } + + SCALAR_OP(+) + SCALAR_OP(-) + SCALAR_OP(*) + SCALAR_OP(/) + +#undef SCALAR_OP + + +#define SCALAR_OP(OP) \ + template < \ + size_t S, \ + typename T, \ + template class K \ + > \ + K& \ + operator OP (K &k, T t) \ + { \ + for (size_t i = 0; i < S; ++i) \ + k[i] OP t; \ + return k; \ + } + + SCALAR_OP(+=) + SCALAR_OP(-=) + SCALAR_OP(*=) + SCALAR_OP(/=) +#undef SCALAR_OP + + + /////////////////////////////////////////////////////////////////////////// + // logic operators + template < + size_t S, + typename T, + template class K + > + bool + operator== (K a, K b) + { + return std::equal (std::begin (a), + std::end (a), + std::begin (b)); + } + + //------------------------------------------------------------------------- + template < + size_t S, + typename T, + template class K + > + bool + operator!= (K a, K b) + { + return !(a == b); + } + + + /////////////////////////////////////////////////////////////////////////// + // special operators + template < + size_t S, + typename T + > + vector + operator- (point a, point b) + { + vector out; + for (size_t i = 0; i < S; ++i) + out[i] = a[i] - b[i]; + return out; + } + + + //------------------------------------------------------------------------- + template < + size_t S, + typename T, + template class A, + template class B + > + T dot (A a, B b) + { + T sum { 0 }; + for (size_t i = 0; i < S; ++i) + sum += a[i] * b[i]; + return sum; + } +} + +#endif diff --git a/coord/store.hpp b/coord/store.hpp new file mode 100644 index 00000000..1b435e36 --- /dev/null +++ b/coord/store.hpp @@ -0,0 +1,145 @@ +/* + * This file is part of libgim. + * + * libgim 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. + * + * 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 2015 Danny Robson + */ + +#ifndef __UTIL_COORD_STORE_HPP +#define __UTIL_COORD_STORE_HPP + +#include "names.hpp" + +#include "../platform.hpp" + +#include + +namespace util { namespace coord { + /////////////////////////////////////////////////////////////////////// + // Disable GCC warnings about validity of anonyous structures in + // unions. Push comes to shove I'll manually redsign everything to + // keep this syntax anyway. +#pragma GCC diagnostic push +#if defined(COMPILER_GCC) +#pragma GCC diagnostic ignored "-pedantic" +#endif +#if defined(COMPILER_CLANG) +#pragma GCC diagnostic ignored "-Wgnu" +#endif + + /////////////////////////////////////////////////////////////////////////// + template + struct store { + T data[S]; + }; + + + /////////////////////////////////////////////////////////////////////////// + template + struct store<3,T,rgba> { + union { + T data[3]; + struct { T r,g,b; }; + }; + }; + + template + struct store<4,T,rgba> { + union { + T data[4]; + struct { T r,g,b,a; }; + }; + }; + + + /////////////////////////////////////////////////////////////////////////// + template + struct store<2,T,xyzw> { + union { + T data[2]; + struct { T x,y; }; + }; + }; + + + template + struct store<3,T,xyzw> { + union { + T data[3]; + struct { T x,y,z; }; + }; + }; + + + template + struct store<4,T,xyzw> { + union { + T data[4]; + struct { T x,y,z,w; }; + }; + }; + + + /////////////////////////////////////////////////////////////////////////// + template + struct store<2,T,xyzw,stpq> { + union { + T data[2]; + struct { T x,y; }; + struct { T s,t; }; + }; + }; + + + template + struct store<3,T,xyzw,stpq> { + union { + T data[3]; + struct { T x,y,z; }; + struct { T s,t,p; }; + }; + }; + + + template + struct store<4,T,xyzw,stpq> { + union { + T data[4]; + struct { T x,y,z,w; }; + struct { T s,t,p,q; }; + }; + }; + + + /////////////////////////////////////////////////////////////////////////// + template + struct store<2,T,whd> { + union { + T data[2]; + struct { T w,h; }; + }; + }; + + + template + struct store<3,T,whd> { + union { + T data[3]; + struct { T w,h,d; }; + }; + }; +} } + +#endif diff --git a/extent.hpp b/extent.hpp index 3ee9d631..0c84c251 100644 --- a/extent.hpp +++ b/extent.hpp @@ -30,9 +30,9 @@ namespace util { * A pure two-dimensional size, without positioning */ template - struct extent : public coord + struct extent : public coord::base { - using coord::coord; + using coord::base::base; extent () = default; extent (vector); diff --git a/point.hpp b/point.hpp index d4285a1c..7c3b68b1 100644 --- a/point.hpp +++ b/point.hpp @@ -32,9 +32,9 @@ namespace util { /// An n-dimensional position in space. template - struct point : public coord + struct point : public coord::base { - using coord::coord; + using coord::base::base; // point operators template typename std::common_type::type distance (const point &) const; diff --git a/region.hpp b/region.hpp index e70c3712..1b8fb362 100644 --- a/region.hpp +++ b/region.hpp @@ -137,5 +137,4 @@ namespace util { std::ostream& operator<< (std::ostream&, const util::region&); } - #endif diff --git a/vector.hpp b/vector.hpp index 70838e9c..8379e925 100644 --- a/vector.hpp +++ b/vector.hpp @@ -29,8 +29,8 @@ namespace util { template - struct vector : public coord { - using coord::coord; + struct vector : public coord::base { + using coord::base::base; bool is_zero (void) const;