/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright 2012-2015 Danny Robson */ #ifndef __UTIL_COORDS_OPS #define __UTIL_COORDS_OPS #include "../preprocessor.hpp" #include "../maths.hpp" #include "../types/bits.hpp" #include namespace util { // forward declerations for traits template struct point; template struct extent; template struct vector; template struct colour; /////////////////////////////////////////////////////////////////////// // operation traits namespace coord { template < size_t S, typename T, typename U, template class A, template class B > struct traits { }; //------------------------------------------------------------------------- template struct traits { typedef colour::type> result; }; template struct traits { typedef extent::type> result; }; template struct traits { typedef extent::type> result; }; template struct traits { typedef point ::type> result; }; template struct traits { typedef point ::type> result; }; template struct traits { typedef point ::type> result; }; template struct traits { typedef vector::type> result; }; } /////////////////////////////////////////////////////////////////////////// // vector operators #define ELEMENT_OP(OP) \ template < \ size_t S, \ typename T, \ typename U, \ 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(/) ELEMENT_OP(%) #undef ELEMENT_OP /////////////////////////////////////////////////////////////////////////// // scalar operators #define SCALAR_OP(OP) \ template < \ size_t S, \ typename T, \ typename U, \ template class K \ > \ typename std::enable_if::value, K>::type \ operator OP (U u, K k) \ { \ K out; \ for (size_t i = 0; i < S; ++i) \ out[i] = u OP k[i]; \ return out; \ } \ \ template < \ size_t S, \ typename T, \ typename U, \ template class K \ > \ typename std::enable_if::value, K>::type \ operator OP (K k, U u) \ { \ K 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(/) 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(/=) SCALAR_OP(%=) #undef SCALAR_OP //------------------------------------------------------------------------- // negation template class K> K operator- (K k) { return k * T{-1}; } /////////////////////////////////////////////////////////////////////////// // logic operators /// elementwise equality operator template < size_t S, typename T, template class K > bool operator== (K a, K b) { bool (*predicate)(const T&, const T&) = almost_equal; return std::equal (std::begin (a), std::end (a), std::begin (b), predicate); } ///------------------------------------------------------------------------ /// 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, typename U > vector::type> operator- (point a, point b) { vector::type> out; for (size_t i = 0; i < S; ++i) out[i] = a[i] - b[i]; return out; } //------------------------------------------------------------------------- template < size_t S, typename T, typename U > vector::type> operator- (U u, point p) { return point {u} - 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; } //------------------------------------------------------------------------- template < size_t S, typename T, template class K > K abs (K k) { for (auto &v: k) v = std::abs (v); return k; } /////////////////////////////////////////////////////////////////////////// // 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 ()); } template class K> bool operator>= (K k, T t) { return min (k) >= t; } template class K> bool operator<= (K k, T t) { return max (k) <= t; } } #endif