/* * Copyright 2013 The Android Open Source Project * * 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. */ #ifndef TVEC_IMPLEMENTATION #error "Don't include TVecHelpers.h directly. use ui/vec*.h instead" #else #undef TVEC_IMPLEMENTATION #endif #ifndef UI_TVEC_HELPERS_H #define UI_TVEC_HELPERS_H #include <stdint.h> #include <sys/types.h> #define PURE __attribute__((pure)) namespace android { // ------------------------------------------------------------------------------------- /* * No user serviceable parts here. * * Don't use this file directly, instead include ui/vec{2|3|4}.h */ /* * This class casts itself into anything and assign itself from anything! * Use with caution! */ template <typename TYPE> struct Impersonator { Impersonator& operator = (const TYPE& rhs) { reinterpret_cast<TYPE&>(*this) = rhs; return *this; } operator TYPE& () { return reinterpret_cast<TYPE&>(*this); } operator TYPE const& () const { return reinterpret_cast<TYPE const&>(*this); } }; /* * TVec{Add|Product}Operators implements basic arithmetic and basic compound assignments * operators on a vector of type BASE<T>. * * BASE only needs to implement operator[] and size(). * By simply inheriting from TVec{Add|Product}Operators<BASE, T> BASE will automatically * get all the functionality here. */ template <template<typename T> class BASE, typename T> class TVecAddOperators { public: /* compound assignment from a another vector of the same size but different * element type. */ template <typename OTHER> BASE<T>& operator += (const BASE<OTHER>& v) { BASE<T>& rhs = static_cast<BASE<T>&>(*this); for (size_t i=0 ; i<BASE<T>::size() ; i++) { rhs[i] += v[i]; } return rhs; } template <typename OTHER> BASE<T>& operator -= (const BASE<OTHER>& v) { BASE<T>& rhs = static_cast<BASE<T>&>(*this); for (size_t i=0 ; i<BASE<T>::size() ; i++) { rhs[i] -= v[i]; } return rhs; } /* compound assignment from a another vector of the same type. * These operators can be used for implicit conversion and handle operations * like "vector *= scalar" by letting the compiler implicitly convert a scalar * to a vector (assuming the BASE<T> allows it). */ BASE<T>& operator += (const BASE<T>& v) { BASE<T>& rhs = static_cast<BASE<T>&>(*this); for (size_t i=0 ; i<BASE<T>::size() ; i++) { rhs[i] += v[i]; } return rhs; } BASE<T>& operator -= (const BASE<T>& v) { BASE<T>& rhs = static_cast<BASE<T>&>(*this); for (size_t i=0 ; i<BASE<T>::size() ; i++) { rhs[i] -= v[i]; } return rhs; } /* * NOTE: the functions below ARE NOT member methods. They are friend functions * with they definition inlined with their declaration. This makes these * template functions available to the compiler when (and only when) this class * is instantiated, at which point they're only templated on the 2nd parameter * (the first one, BASE<T> being known). */ /* The operators below handle operation between vectors of the same side * but of a different element type. */ template<typename RT> friend inline BASE<T> PURE operator +(const BASE<T>& lv, const BASE<RT>& rv) { return BASE<T>(lv) += rv; } template<typename RT> friend inline BASE<T> PURE operator -(const BASE<T>& lv, const BASE<RT>& rv) { return BASE<T>(lv) -= rv; } /* The operators below (which are not templates once this class is instanced, * i.e.: BASE<T> is known) can be used for implicit conversion on both sides. * These handle operations like "vector * scalar" and "scalar * vector" by * letting the compiler implicitly convert a scalar to a vector (assuming * the BASE<T> allows it). */ friend inline BASE<T> PURE operator +(const BASE<T>& lv, const BASE<T>& rv) { return BASE<T>(lv) += rv; } friend inline BASE<T> PURE operator -(const BASE<T>& lv, const BASE<T>& rv) { return BASE<T>(lv) -= rv; } }; template <template<typename T> class BASE, typename T> class TVecProductOperators { public: /* compound assignment from a another vector of the same size but different * element type. */ template <typename OTHER> BASE<T>& operator *= (const BASE<OTHER>& v) { BASE<T>& rhs = static_cast<BASE<T>&>(*this); for (size_t i=0 ; i<BASE<T>::size() ; i++) { rhs[i] *= v[i]; } return rhs; } template <typename OTHER> BASE<T>& operator /= (const BASE<OTHER>& v) { BASE<T>& rhs = static_cast<BASE<T>&>(*this); for (size_t i=0 ; i<BASE<T>::size() ; i++) { rhs[i] /= v[i]; } return rhs; } /* compound assignment from a another vector of the same type. * These operators can be used for implicit conversion and handle operations * like "vector *= scalar" by letting the compiler implicitly convert a scalar * to a vector (assuming the BASE<T> allows it). */ BASE<T>& operator *= (const BASE<T>& v) { BASE<T>& rhs = static_cast<BASE<T>&>(*this); for (size_t i=0 ; i<BASE<T>::size() ; i++) { rhs[i] *= v[i]; } return rhs; } BASE<T>& operator /= (const BASE<T>& v) { BASE<T>& rhs = static_cast<BASE<T>&>(*this); for (size_t i=0 ; i<BASE<T>::size() ; i++) { rhs[i] /= v[i]; } return rhs; } /* * NOTE: the functions below ARE NOT member methods. They are friend functions * with they definition inlined with their declaration. This makes these * template functions available to the compiler when (and only when) this class * is instantiated, at which point they're only templated on the 2nd parameter * (the first one, BASE<T> being known). */ /* The operators below handle operation between vectors of the same side * but of a different element type. */ template<typename RT> friend inline BASE<T> PURE operator *(const BASE<T>& lv, const BASE<RT>& rv) { return BASE<T>(lv) *= rv; } template<typename RT> friend inline BASE<T> PURE operator /(const BASE<T>& lv, const BASE<RT>& rv) { return BASE<T>(lv) /= rv; } /* The operators below (which are not templates once this class is instanced, * i.e.: BASE<T> is known) can be used for implicit conversion on both sides. * These handle operations like "vector * scalar" and "scalar * vector" by * letting the compiler implicitly convert a scalar to a vector (assuming * the BASE<T> allows it). */ friend inline BASE<T> PURE operator *(const BASE<T>& lv, const BASE<T>& rv) { return BASE<T>(lv) *= rv; } friend inline BASE<T> PURE operator /(const BASE<T>& lv, const BASE<T>& rv) { return BASE<T>(lv) /= rv; } }; /* * TVecUnaryOperators implements unary operators on a vector of type BASE<T>. * * BASE only needs to implement operator[] and size(). * By simply inheriting from TVecUnaryOperators<BASE, T> BASE will automatically * get all the functionality here. * * These operators are implemented as friend functions of TVecUnaryOperators<BASE, T> */ template <template<typename T> class BASE, typename T> class TVecUnaryOperators { public: BASE<T>& operator ++ () { BASE<T>& rhs = static_cast<BASE<T>&>(*this); for (size_t i=0 ; i<BASE<T>::size() ; i++) { ++rhs[i]; } return rhs; } BASE<T>& operator -- () { BASE<T>& rhs = static_cast<BASE<T>&>(*this); for (size_t i=0 ; i<BASE<T>::size() ; i++) { --rhs[i]; } return rhs; } BASE<T> operator - () const { BASE<T> r(BASE<T>::NO_INIT); BASE<T> const& rv(static_cast<BASE<T> const&>(*this)); for (size_t i=0 ; i<BASE<T>::size() ; i++) { r[i] = -rv[i]; } return r; } }; /* * TVecComparisonOperators implements relational/comparison operators * on a vector of type BASE<T>. * * BASE only needs to implement operator[] and size(). * By simply inheriting from TVecComparisonOperators<BASE, T> BASE will automatically * get all the functionality here. */ template <template<typename T> class BASE, typename T> class TVecComparisonOperators { public: /* * NOTE: the functions below ARE NOT member methods. They are friend functions * with they definition inlined with their declaration. This makes these * template functions available to the compiler when (and only when) this class * is instantiated, at which point they're only templated on the 2nd parameter * (the first one, BASE<T> being known). */ template<typename RT> friend inline bool PURE operator ==(const BASE<T>& lv, const BASE<RT>& rv) { for (size_t i = 0; i < BASE<T>::size(); i++) if (lv[i] != rv[i]) return false; return true; } template<typename RT> friend inline bool PURE operator !=(const BASE<T>& lv, const BASE<RT>& rv) { return !operator ==(lv, rv); } template<typename RT> friend inline bool PURE operator >(const BASE<T>& lv, const BASE<RT>& rv) { for (size_t i = 0; i < BASE<T>::size(); i++) if (lv[i] <= rv[i]) return false; return true; } template<typename RT> friend inline bool PURE operator <=(const BASE<T>& lv, const BASE<RT>& rv) { return !(lv > rv); } template<typename RT> friend inline bool PURE operator <(const BASE<T>& lv, const BASE<RT>& rv) { for (size_t i = 0; i < BASE<T>::size(); i++) if (lv[i] >= rv[i]) return false; return true; } template<typename RT> friend inline bool PURE operator >=(const BASE<T>& lv, const BASE<RT>& rv) { return !(lv < rv); } }; /* * TVecFunctions implements functions on a vector of type BASE<T>. * * BASE only needs to implement operator[] and size(). * By simply inheriting from TVecFunctions<BASE, T> BASE will automatically * get all the functionality here. */ template <template<typename T> class BASE, typename T> class TVecFunctions { public: /* * NOTE: the functions below ARE NOT member methods. They are friend functions * with they definition inlined with their declaration. This makes these * template functions available to the compiler when (and only when) this class * is instantiated, at which point they're only templated on the 2nd parameter * (the first one, BASE<T> being known). */ template<typename RT> friend inline T PURE dot(const BASE<T>& lv, const BASE<RT>& rv) { T r(0); for (size_t i = 0; i < BASE<T>::size(); i++) r += lv[i]*rv[i]; return r; } friend inline T PURE length(const BASE<T>& lv) { return sqrt( dot(lv, lv) ); } template<typename RT> friend inline T PURE distance(const BASE<T>& lv, const BASE<RT>& rv) { return length(rv - lv); } friend inline BASE<T> PURE normalize(const BASE<T>& lv) { return lv * (1 / length(lv)); } }; #undef PURE // ------------------------------------------------------------------------------------- }; // namespace android #endif /* UI_TVEC_HELPERS_H */