WIP coord: clean up operation templates

This commit is contained in:
Danny Robson 2015-10-19 17:06:19 +11:00
parent b824691541
commit 60f16cdc4a

View File

@ -35,22 +35,19 @@ namespace util {
// operation traits // operation traits
namespace coord { namespace coord {
template < template <
size_t S,
typename T,
typename U,
template <size_t,typename> class A, template <size_t,typename> class A,
template <size_t,typename> class B template <size_t,typename> class B
> >
struct traits { }; struct traits { };
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
template <size_t S, typename T, typename U> struct traits<S,T,U,colour,colour> { typedef colour<S,typename std::common_type<T,U>::type> result; }; template <> struct traits<colour,colour> { template <size_t S, typename T> using result = colour<S,T>; };
template <size_t S, typename T, typename U> struct traits<S,T,U,extent,extent> { typedef extent<S,typename std::common_type<T,U>::type> result; }; template <> struct traits<extent,extent> { template <size_t S, typename T> using result = extent<S,T>; };
template <size_t S, typename T, typename U> struct traits<S,T,U,extent,vector> { typedef extent<S,typename std::common_type<T,U>::type> result; }; template <> struct traits<extent,vector> { template <size_t S, typename T> using result = extent<S,T>; };
template <size_t S, typename T, typename U> struct traits<S,T,U,point,extent> { typedef point <S,typename std::common_type<T,U>::type> result; }; template <> struct traits<point,extent> { template <size_t S, typename T> using result = point <S,T>; };
template <size_t S, typename T, typename U> struct traits<S,T,U,point,vector> { typedef point <S,typename std::common_type<T,U>::type> result; }; template <> struct traits<point,vector> { template <size_t S, typename T> using result = point <S,T>; };
template <size_t S, typename T, typename U> struct traits<S,T,U,vector,point> { typedef point <S,typename std::common_type<T,U>::type> result; }; template <> struct traits<vector,point> { template <size_t S, typename T> using result = point <S,T>; };
template <size_t S, typename T, typename U> struct traits<S,T,U,vector,vector> { typedef vector<S,typename std::common_type<T,U>::type> result; }; template <> struct traits<vector,vector> { template <size_t S, typename T> using result = vector<S,T>; };
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -63,10 +60,12 @@ namespace util {
template <size_t,typename> class A, \ template <size_t,typename> class A, \
template <size_t,typename> class B \ template <size_t,typename> class B \
> \ > \
typename coord::traits<S,T,U,A,B>::result \ auto \
operator OP (A<S,T> a, B<S,U> b) \ operator OP (A<S,T> a, B<S,U> b) \
{ \ { \
typename coord::traits<S,T,U,A,B>::result out; \ typename coord::traits<A,B>::template result< \
S,typename std::common_type<T,U>::type \
> out; \
for (size_t i = 0; i < S; ++i) \ for (size_t i = 0; i < S; ++i) \
out[i] = a[i] OP b[i]; \ out[i] = a[i] OP b[i]; \
return out; \ return out; \
@ -75,11 +74,18 @@ namespace util {
template < \ template < \
size_t S, \ size_t S, \
typename T, \ typename T, \
typename U, \
template <size_t,typename> class A, \ template <size_t,typename> class A, \
template <size_t,typename> class B \ template <size_t,typename> class B \
> \ > \
typename coord::traits<S,T,T,A,B>::result& \ typename std::enable_if< \
operator PASTE(OP,=) (A<S,T>& a, B<S,T> b) \ std::is_same< \
typename std::common_type<T,U>::type, \
T \
>::value, \
A<S,T> \
>::type& \
operator PASTE(OP,=) (A<S,T>& a, B<S,U> b) \
{ \ { \
for (size_t i = 0; i < S; ++i) \ for (size_t i = 0; i < S; ++i) \
a[i] PASTE(OP,=) b[i]; \ a[i] PASTE(OP,=) b[i]; \
@ -95,37 +101,35 @@ namespace util {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// scalar operators // scalar operators
#define SCALAR_OP(OP) \ #define SCALAR_OP(OP) \
template < \ template < \
size_t S, \ size_t S, \
typename T, \ typename T, \
typename U, \ typename U, \
template <size_t,typename> class K \ template <size_t,typename> class K \
> \ > \
K<S,typename std::common_type<T,U>::type> \ auto \
operator OP (U u, K<S,T> k) \ operator OP (U u, K<S,T> k) \
{ \ { \
using out_t = typename std::common_type<T,U>::type; \ K<S,typename std::common_type<T,U>::type> out; \
K<S,out_t> out; \ for (size_t i = 0; i < S; ++i) \
for (size_t i = 0; i < S; ++i) \ out[i] = u OP k[i]; \
out[i] = u OP k[i]; \ return out; \
return out; \ } \
} \ \
\ template < \
template < \ size_t S, \
size_t S, \ typename T, \
typename T, \ typename U, \
typename U, \ template <size_t,typename> class K \
template <size_t,typename> class K \ > \
> \ auto \
K<S,typename std::common_type<T,U>::type> \ operator OP (K<S,T> k, U u) \
operator OP (K<S,T> k, U u) \ { \
{ \ K<S,typename std::common_type<T,U>::type> out; \
using out_t = typename std::common_type<T,U>::type; \ for (size_t i = 0; i < S; ++i) \
K<S,out_t> out; \ out[i] = k[i] OP u; \
for (size_t i = 0; i < S; ++i) \ return out; \
out[i] = k[i] OP u; \
return out; \
} }
SCALAR_OP(+) SCALAR_OP(+)
@ -188,6 +192,32 @@ namespace util {
} }
///////////////////////////////////////////////////////////////////////////
// unary operators
#define UNARY_OP(OP) \
template < \
size_t S, \
typename T, \
template <size_t,typename> class K \
> \
auto \
operator OP (K<S,T> k) \
{ \
K<S,decltype(OP std::declval<T> ())> out; \
\
for (size_t i = 0; i < S; ++i) \
out[i] = OP k[i]; \
\
return k; \
}
UNARY_OP(!)
UNARY_OP(~)
#undef UNARY_OP
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// logic operators // logic operators
@ -336,31 +366,58 @@ namespace util {
///------------------------------------------------------------------------ ///------------------------------------------------------------------------
/// return the minimum element of the coordinate type
template <size_t S, typename T, template<size_t,typename> class K> template <size_t S, typename T, template<size_t,typename> class K>
T T
min (K<S,T> k) min (K<S,T> k)
{ return *std::min_element (k.begin (), k.end ()); } { return *std::min_element (k.begin (), k.end ()); }
///------------------------------------------------------------------------
/// return the maximum element of the coordinate type
template <size_t S, typename T, template<size_t,typename> class K> template <size_t S, typename T, template<size_t,typename> class K>
T T
max (K<S,T> k) max (K<S,T> k)
{ return *std::max_element (k.begin (), k.end ()); } { return *std::max_element (k.begin (), k.end ()); }
template <size_t S, typename T, template<size_t,typename> class K> //-------------------------------------------------------------------------
bool #define SCALAR_OP(OP) \
operator>= (K<S,T> k, T t) template < \
{ return min (k) >= t; } size_t S, \
typename T, \
typename U, \
template <size_t,typename> class K \
> \
K<S,bool> \
operator OP (const K<S,T> k, const U u) \
{ \
K<S,bool> out; \
for (size_t i = 0; i < S; ++i) \
out[i] = k[i] OP u; \
return out; \
}
SCALAR_OP(<)
SCALAR_OP(>)
SCALAR_OP(<=)
SCALAR_OP(>=)
#undef SCALAR_OP
template <size_t S, typename T, template<size_t,typename> class K> //-------------------------------------------------------------------------
template <size_t S, template <size_t,typename> class K>
bool bool
operator<= (K<S,T> k, T t) any (const K<S,bool> k)
{ return max (k) <= t; } {
return std::any_of (k.begin (), k.end (), identity<bool>);
}
//-------------------------------------------------------------------------
template <size_t S, template <size_t,typename> class K>
bool
all (const K<S,bool> k)
{
return std::all_of (k.begin (), k.end (), identity<bool>);
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////