/* * 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 "../maths.hpp" #include namespace util { // forward declerations for traits template struct point; template struct extent; template struct 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] = k[i] OP t; \ 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 //------------------------------------------------------------------------- // negation template class K> K operator- (K k) { k *= -1; return ; } /////////////////////////////////////////////////////////////////////////// // logic operators /// elementwise equality operator 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)); } ///------------------------------------------------------------------------ /// elementwise inquality operator template < size_t S, typename T, template class K > bool operator!= (K a, K b) { return !(a == b); } /////////////////////////////////////////////////////////////////////////// // special operators /// point-point subtraction giving a vector difference 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 > vector operator- (T t, point p) { return point {t} - p; } //------------------------------------------------------------------------- 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; } /////////////////////////////////////////////////////////////////////////// // logical element operators /// return a coord type containing the max element at each offset template < size_t S, typename T, template class K > K min (K a, K b) { K out; for (size_t i = 0; i < S; ++i) out[i] = min (a[i], b[i]); return out; } ///------------------------------------------------------------------------ // /return a coord type containing the max element at each offset template < size_t S, typename T, template class K > K max (K a, K b) { K out; for (size_t i = 0; i < S; ++i) out[i] = max (a[i], b[i]); return out; } ///------------------------------------------------------------------------ /// return the minimum element of the coordinate type template class K> T min (K k) { return *std::min_element (k.begin (), k.end ()); } ///------------------------------------------------------------------------ /// return the maximum element of the coordinate type template class K> T max (K k) { return *std::max_element (k.begin (), k.end ()); } } #endif