/************************************************************************/ /* */ /* Copyright 1998-2002 by Ullrich Koethe */ /* Cognitive Systems Group, University of Hamburg, Germany */ /* */ /* This file is part of the VIGRA computer vision library. */ /* The VIGRA Website is */ /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* Please direct questions, bug reports, and contributions to */ /* koethe@informatik.uni-hamburg.de or */ /* vigra@kogs1.informatik.uni-hamburg.de */ /* */ /* Permission is hereby granted, free of charge, to any person */ /* obtaining a copy of this software and associated documentation */ /* files (the "Software"), to deal in the Software without */ /* restriction, including without limitation the rights to use, */ /* copy, modify, merge, publish, distribute, sublicense, and/or */ /* sell copies of the Software, and to permit persons to whom the */ /* Software is furnished to do so, subject to the following */ /* conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the */ /* Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* OTHER DEALINGS IN THE SOFTWARE. */ /* */ /************************************************************************/ #ifndef VIGRA_TINYVECTOR_HXX #define VIGRA_TINYVECTOR_HXX #include // abs(double) #include // abs(int) #include // ostream #include "vigra/config.hxx" #include "vigra/error.hxx" #include "vigra/numerictraits.hxx" #include "vigra/mathutil.hxx" namespace vigra { using VIGRA_CSTD::abs; using VIGRA_CSTD::ceil; using VIGRA_CSTD::floor; template class TinyVectorBase; template inline typename TinyVectorBase::SquaredNormType squaredNorm(TinyVectorBase const & t); namespace detail { #define VIGRA_EXEC_LOOP(NAME, OPER) \ template \ static void NAME(T1 * left, T2 const * right) \ { \ for(int i=0; i \ static void NAME(T1 * left, T2 right) \ { \ for(int i=0; i struct ExecLoop { template static void assignCast(T1 * left, T2 const * right) { for(int i=0; i::cast(right[i]); } VIGRA_EXEC_LOOP(assign, =) VIGRA_EXEC_LOOP(add, +=) VIGRA_EXEC_LOOP(sub, -=) VIGRA_EXEC_LOOP(mul, *=) VIGRA_EXEC_LOOP(neg, = -) VIGRA_EXEC_LOOP(abs, = vigra::abs) VIGRA_EXEC_LOOP(floor, = vigra::floor) VIGRA_EXEC_LOOP(ceil, = vigra::ceil) VIGRA_EXEC_LOOP(fromPromote, = NumericTraits::fromPromote) VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits::fromRealPromote) VIGRA_EXEC_LOOP_SCALAR(assignScalar, =) VIGRA_EXEC_LOOP_SCALAR(mulScalar, *=) VIGRA_EXEC_LOOP_SCALAR(divScalar, /=) template static bool notEqual(T1 const * left, T2 const * right) { for(int i=0; i static typename NumericTraits::Promote dot(T const * d) { typename NumericTraits::Promote res(*d * *d); for(int i=1; i static typename PromoteTraits::Promote dot(T1 const * left, T2 const * right) { typename PromoteTraits::Promote res(*left * *right); for(int i=1; i static typename NormTraits::SquaredNormType squaredNorm(T const * d) { typename NormTraits::SquaredNormType res = vigra::squaredNorm(*d); for(int i=1; i struct UnrollDot { template static typename NumericTraits::Promote dot(T const * d) { return *d * *d + UnrollDot::dot(d+1); } template static typename PromoteTraits::Promote dot(T1 const * left, T2 const * right) { return *left * *right + UnrollDot::dot(left+1, right+1); } }; template <> struct UnrollDot<1> { template static typename NumericTraits::Promote dot(T const * d) { return *d * *d ; } template static typename PromoteTraits::Promote dot(T1 const * left, T2 const * right) { return *left * *right; } }; template struct UnrollSquaredNorm { template static typename NormTraits::SquaredNormType squaredNorm(T const * d) { return vigra::squaredNorm(*d) + UnrollSquaredNorm::squaredNorm(d+1); } }; template <> struct UnrollSquaredNorm<1> { template static typename NormTraits::SquaredNormType squaredNorm(T const * d) { return vigra::squaredNorm(*d); } }; #undef VIGRA_EXEC_LOOP #undef VIGRA_EXEC_LOOP_SCALAR #define VIGRA_UNROLL_LOOP(NAME, OPER) \ template \ static void NAME(T1 * left, T2 const * right) \ { \ (*left) OPER (*right); \ UnrollLoop::NAME(left+1, right+1); \ } #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \ template \ static void NAME(T1 * left, T2 right) \ { \ (*left) OPER (right); \ UnrollLoop::NAME(left+1, right); \ } template struct UnrollLoop { template static void assignCast(T1 * left, T2 const * right) { *left = detail::RequiresExplicitCast::cast(*right); UnrollLoop::assignCast(left+1, right+1); } VIGRA_UNROLL_LOOP(assign, =) VIGRA_UNROLL_LOOP(add, +=) VIGRA_UNROLL_LOOP(sub, -=) VIGRA_UNROLL_LOOP(mul, *=) VIGRA_UNROLL_LOOP(neg, = -) VIGRA_UNROLL_LOOP(abs, = vigra::abs) VIGRA_UNROLL_LOOP(floor, = vigra::floor) VIGRA_UNROLL_LOOP(ceil, = vigra::ceil) VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits::fromPromote) VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits::fromRealPromote) VIGRA_UNROLL_LOOP_SCALAR(assignScalar, =) VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *=) VIGRA_UNROLL_LOOP_SCALAR(divScalar, /=) template static bool notEqual(T1 const * left, T2 const * right) { return (*left != *right) || UnrollLoop::notEqual(left+1, right+1); } template static typename NumericTraits::Promote dot(T const * d) { return UnrollDot::dot(d); } template static typename PromoteTraits::Promote dot(T1 const * left, T2 const * right) { return UnrollDot::dot(left, right); } template static typename NormTraits::SquaredNormType squaredNorm(T const * d) { return UnrollSquaredNorm::squaredNorm(d); } }; #undef VIGRA_UNROLL_LOOP #undef VIGRA_UNROLL_LOOP_SCALAR template <> struct UnrollLoop<0> { template static void assignCast(T1, T2) {} template static void assign(T1, T2) {} template static void assignScalar(T1, T2) {} template static void add(T1, T2) {} template static void sub(T1, T2) {} template static void mul(T1, T2) {} template static void mulScalar(T1, T2) {} template static void div(T1, T2) {} template static void divScalar(T1, T2) {} template static void fromPromote(T1, T2) {} template static void fromRealPromote(T1, T2) {} template static void neg(T1, T2) {} template static void abs(T1, T2) {} template static void floor(T1, T2) {} template static void ceil(T1, T2) {} template static bool notEqual(T1, T2) { return false; } }; template struct TinyVectorIf { template struct res { typedef T type; }; }; template <> struct TinyVectorIf { template struct res { typedef F type; }; }; template struct LoopType { typedef typename TinyVectorIf:: template res, ExecLoop >::type type; }; struct DontInit {}; inline DontInit dontInit() {return DontInit(); } } // namespace detail template class TinyVector; template class TinyVectorView; /********************************************************/ /* */ /* TinyVectorBase */ /* */ /********************************************************/ /** \brief Base class for fixed size vectors. This class contains functionality shared by \ref TinyVector and \ref TinyVectorView, and enables these classes to be freely mixed within expressions. It is typically not used directly. \#include "vigra/tinyvector.hxx"
Namespace: vigra **/ template class TinyVectorBase { TinyVectorBase(TinyVectorBase const &); // do not use TinyVectorBase & operator=(TinyVectorBase const & other); // do not use protected: typedef typename detail::LoopType::type Loop; TinyVectorBase() {} public: /** STL-compatible definition of valuetype */ typedef VALUETYPE value_type; /** reference (return of operator[]). */ typedef VALUETYPE & reference; /** const reference (return of operator[] const). */ typedef VALUETYPE const & const_reference; /** pointer (return of operator->). */ typedef VALUETYPE * pointer; /** const pointer (return of operator-> const). */ typedef VALUETYPE const * const_pointer; /** STL-compatible definition of iterator */ typedef value_type * iterator; /** STL-compatible definition of const iterator */ typedef value_type const * const_iterator; /** STL-compatible definition of size_type */ typedef unsigned int size_type; /** STL-compatible definition of difference_type */ typedef int difference_type; /** the scalar type for the outer product */ typedef double scalar_multiplier; /** the vector's squared norm type */ typedef typename NormTraits::SquaredNormType SquaredNormType; /** the vector's norm type */ typedef typename SquareRootTraits::SquareRootResult NormType; /** the vector's size */ enum { static_size = SIZE }; /** Initialize from another sequence (must have length SIZE!) */ template void init(Iterator i, Iterator end) { vigra_precondition(end-i == SIZE, "TinyVector::init(): Sequence has wrong size."); Loop::assignCast(data_, i); } /** Component-wise add-assignment */ template DERIVED & operator+=(TinyVectorBase const & r) { Loop::add(data_, r.begin()); return static_cast(*this); } /** Component-wise subtract-assignment */ template DERIVED & operator-=(TinyVectorBase const & r) { Loop::sub(data_, r.begin()); return static_cast(*this); } /** Component-wise multiply-assignment */ template DERIVED & operator*=(TinyVectorBase const & r) { Loop::mul(data_, r.begin()); return static_cast(*this); } /** Component-wise scalar multiply-assignment */ DERIVED & operator*=(double r) { Loop::mulScalar(data_, r); return static_cast(*this); } /** Component-wise scalar divide-assignment */ DERIVED & operator/=(double r) { Loop::divScalar(data_, r); return static_cast(*this); } /** Calculate magnitude. */ NormType magnitude() const { return sqrt(static_cast::SquareRootArgument>(squaredMagnitude())); } /** Calculate squared magnitude. */ SquaredNormType squaredMagnitude() const { return Loop::squaredNorm(data_); } /** Access component by index. */ reference operator[](difference_type i) { return data_[i]; } /** Get component by index. */ const_reference operator[](difference_type i) const { return data_[i]; } /** Get random access iterator to begin of vector. */ iterator begin() { return data_; } /** Get random access iterator past-the-end of vector. */ iterator end() { return data_ + SIZE; } /** Get const random access iterator to begin of vector. */ const_iterator begin() const { return data_; } /** Get const random access iterator past-the-end of vector. */ const_iterator end() const { return data_ + SIZE; } /** Size of TinyVector vector always equals the template parameter SIZE. */ size_type size() const { return SIZE; } pointer data() { return data_; } const_pointer data() const { return data_; } protected: DATA data_; }; /** \brief Class for fixed size vectors. This class contains an array of size SIZE of the specified VALUETYPE. The interface conforms to STL vector, except that there are no functions that change the size of a TinyVector. \ref TinyVectorOperators "Arithmetic operations" on TinyVectors are defined as component-wise applications of these operations. Addition and subtraction of two TinyVectors (+=, -=, +, -, unary -), multiplication and division of an TinyVector with a double, and NumericTraits/PromoteTraits are defined, so that TinyVector fulfills the requirements of \ref LinearAlgebra. VIGRA algorithms typically use \ref vigra::VectorAccessor to access TinyVectors as a whole, or specific components of them. See also:
- \ref vigra::TinyVectorBase
- \ref vigra::TinyVectorView
- \ref TinyVectorTraits
- \ref TinyVectorOperators
\#include "vigra/tinyvector.hxx"
Namespace: vigra **/ template class TinyVector : public TinyVectorBase > { typedef TinyVectorBase > BaseType; typedef typename BaseType::Loop Loop; public: typedef typename BaseType::value_type value_type; typedef typename BaseType::reference reference; typedef typename BaseType::const_reference const_reference; typedef typename BaseType::pointer pointer; typedef typename BaseType::const_pointer const_pointer; typedef typename BaseType::iterator iterator; typedef typename BaseType::const_iterator const_iterator; typedef typename BaseType::size_type size_type; typedef typename BaseType::difference_type difference_type; typedef typename BaseType::scalar_multiplier scalar_multiplier; typedef typename BaseType::SquaredNormType SquaredNormType; typedef typename BaseType::NormType NormType; /** Construction with constant value */ explicit TinyVector(value_type const & initial) : BaseType() { Loop::assignScalar(BaseType::begin(), initial); } /** Construction with explicit values. Call only if SIZE == 2 */ TinyVector(value_type const & i1, value_type const & i2) : BaseType() { BaseType::data_[0] = i1; BaseType::data_[1] = i2; } /** Construction with explicit values. Call only if SIZE == 3 */ TinyVector(value_type const & i1, value_type const & i2, value_type const & i3) : BaseType() { BaseType::data_[0] = i1; BaseType::data_[1] = i2; BaseType::data_[2] = i3; } /** Construction with explicit values. Call only if SIZE == 4 */ TinyVector(value_type const & i1, value_type const & i2, value_type const & i3, value_type const & i4) : BaseType() { BaseType::data_[0] = i1; BaseType::data_[1] = i2; BaseType::data_[2] = i3; BaseType::data_[3] = i4; } /** Default constructor (initializes all components with zero) */ TinyVector() : BaseType() { Loop::assignScalar(BaseType::data_, NumericTraits::zero()); } /** Copy constructor. */ TinyVector(TinyVector const & r) : BaseType() { Loop::assign(BaseType::data_, r.data_); } /** Constructor from C array. */ explicit TinyVector(const_pointer data) : BaseType() { Loop::assign(BaseType::data_, data); } /** Copy assignment. */ TinyVector & operator=(TinyVector const & r) { Loop::assign(BaseType::data_, r.data_); return *this; } /** Copy with type conversion. */ template TinyVector(TinyVectorBase const & r) : BaseType() { Loop::assignCast(BaseType::data_, r.begin()); } /** Copy assignment with type conversion. */ template TinyVector & operator=(TinyVectorBase const & r) { Loop::assignCast(BaseType::data_, r.begin()); return *this; } explicit TinyVector(detail::DontInit) : BaseType() {} }; /** \brief Wrapper for fixed size vectors. This class wraps an array of size SIZE of the specified VALUETYPE. Thus, the array can be accessed with an interface similar to that of std::vector (except that there are no functions that change the size of a TinyVectorView). The TinyVectorView does not assume ownership of the given memory. \ref TinyVectorOperators "Arithmetic operations" on TinyVectorViews are defined as component-wise applications of these operations. Addition and subtraction of two TinyVectorViews (+=, -=, +, -, unary -), multiplication and division of an TinyVectorViews with a double, and NumericTraits/PromoteTraits are defined, so that TinyVectorView fulfills the requirements of \ref LinearAlgebra. VIGRA algorithms typically use \ref vigra::VectorAccessor to access TinyVectorViews as a whole, or specific components of them. See also:
  • \ref vigra::TinyVectorBase
  • \ref vigra::TinyVector
  • \ref TinyVectorTraits
  • \ref TinyVectorOperators
\#include "vigra/tinyvector.hxx"
Namespace: vigra **/ template class TinyVectorView : public TinyVectorBase > { typedef TinyVectorBase > BaseType; typedef typename BaseType::Loop Loop; public: typedef typename BaseType::value_type value_type; typedef typename BaseType::reference reference; typedef typename BaseType::const_reference const_reference; typedef typename BaseType::pointer pointer; typedef typename BaseType::const_pointer const_pointer; typedef typename BaseType::iterator iterator; typedef typename BaseType::const_iterator const_iterator; typedef typename BaseType::size_type size_type; typedef typename BaseType::difference_type difference_type; typedef typename BaseType::scalar_multiplier scalar_multiplier; typedef typename BaseType::SquaredNormType SquaredNormType; typedef typename BaseType::NormType NormType; /** Default constructor (pointer to wrapped data is NULL). */ TinyVectorView() : BaseType() { BaseType::data_ = 0; } /** Construct view for given data array */ TinyVectorView(const_pointer data) : BaseType() { BaseType::data_ = const_cast(data); } /** Copy constructor (shallow copy). */ TinyVectorView(TinyVectorView const & other) : BaseType() { BaseType::data_ = const_cast(other.data_); } /** Construct view from other TinyVector. */ template TinyVectorView(TinyVectorBase const & other) : BaseType() { BaseType::data_ = const_cast(other.data()); } /** Copy the data (not the pointer) of the rhs. */ TinyVectorView & operator=(TinyVectorView const & r) { Loop::assign(BaseType::data_, r.begin()); return *this; } /** Copy the data of the rhs with cast. */ template TinyVectorView & operator=(TinyVectorBase const & r) { Loop::assignCast(BaseType::data_, r.begin()); return *this; } }; /********************************************************/ /* */ /* TinyVector Comparison */ /* */ /********************************************************/ /** \addtogroup TinyVectorOperators Functions for TinyVector \brief \#include "vigra/tinyvector.hxx These functions fulfill the requirements of a Linear Space (vector space). Return types are determined according to \ref TinyVectorTraits. Namespace: vigra

*/ //@{ /// component-wise equal template inline bool operator==(TinyVectorBase const & l, TinyVectorBase const & r) { return !(l != r); } /// component-wise not equal template inline bool operator!=(TinyVectorBase const & l, TinyVectorBase const & r) { typedef typename detail::LoopType::type ltype; return ltype::notEqual(l.begin(), r.begin()); } /********************************************************/ /* */ /* TinyVector Output */ /* */ /********************************************************/ /// stream output template std::ostream & operator<<(std::ostream & out, TinyVectorBase const & l) { out << "("; int i; for(i=0; i struct NumericTraits > { typedef TinyVector::Promote, SIZE> Promote; typedef TinyVector::RealPromote, SIZE> RealPromote; typedef typename NumericTraits::isIntegral isIntegral; typedef VigraFalseType isScalar; typedef typename NumericTraits::isSigned isSigned; // etc. }; template struct NormTraits > { typedef TinyVector Type; typedef typename Type::SquaredNormType SquaredNormType; typedef typename Type::NormType NormType; }; template struct PromoteTraits, TinyVector > { typedef TinyVector::Promote, SIZE> Promote; }; \endcode \#include "vigra/tinyvector.hxx"
Namespace: vigra On compilers that don't support pertial template specialization (e.g. MS VisualC++), the traits classes are explicitly specialized for TinyVector with VALUETYPE = unsigned char | int | float | double and SIZE = 2 | 3 | 4. */ #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION) template struct NumericTraits > { typedef TinyVector Type; typedef TinyVector::Promote, SIZE> Promote; typedef TinyVector::RealPromote, SIZE> RealPromote; typedef TinyVector::ComplexPromote, SIZE> ComplexPromote; typedef T ValueType; typedef typename NumericTraits::isIntegral isIntegral; typedef VigraFalseType isScalar; typedef typename NumericTraits::isSigned isSigned; typedef VigraFalseType isOrdered; typedef VigraFalseType isComplex; static TinyVector zero() { return TinyVector(NumericTraits::zero()); } static TinyVector one() { return TinyVector(NumericTraits::one()); } static TinyVector nonZero() { return TinyVector(NumericTraits::nonZero()); } template static Promote toPromote(TinyVectorBase const & v) { return Promote(v); } template static RealPromote toRealPromote(TinyVectorBase const & v) { return RealPromote(v); } template static TinyVector fromPromote(TinyVectorBase::Promote, SIZE, D1, D2> const & v) { TinyVector res(detail::dontInit()); typedef typename detail::LoopType::type ltype; ltype::fromPromote(res.begin(), v.begin()); return res; } template static TinyVector fromRealPromote(TinyVectorBase::RealPromote, SIZE, D1, D2> const & v) { TinyVector res(detail::dontInit()); typedef typename detail::LoopType::type ltype; ltype::fromRealPromote(res.begin(), v.begin()); return res; } }; template struct NumericTraits > : public NumericTraits > { typedef TinyVector Type; typedef TinyVector::Promote, SIZE> Promote; typedef TinyVector::RealPromote, SIZE> RealPromote; typedef TinyVector::ComplexPromote, SIZE> ComplexPromote; typedef T ValueType; typedef typename NumericTraits::isIntegral isIntegral; typedef VigraFalseType isScalar; typedef typename NumericTraits::isSigned isSigned; typedef VigraFalseType isOrdered; typedef VigraFalseType isComplex; }; template struct NormTraits > { typedef TinyVector Type; typedef typename Type::SquaredNormType SquaredNormType; typedef typename Type::NormType NormType; }; template struct NormTraits > { typedef TinyVector Type; typedef typename Type::SquaredNormType SquaredNormType; typedef typename Type::NormType NormType; }; template struct PromoteTraits, TinyVector > { typedef TinyVector::Promote, SIZE> Promote; }; template struct PromoteTraits, TinyVectorView > { typedef TinyVector::Promote, SIZE> Promote; }; template struct PromoteTraits, TinyVector > { typedef TinyVector::Promote, SIZE> Promote; }; template struct PromoteTraits, TinyVectorView > { typedef TinyVector::Promote, SIZE> Promote; }; template struct PromoteTraits, double > { typedef TinyVector::RealPromote, SIZE> Promote; }; template struct PromoteTraits > { typedef TinyVector::RealPromote, SIZE> Promote; }; template struct PromoteTraits, double > { typedef TinyVector::RealPromote, SIZE> Promote; }; template struct PromoteTraits > { typedef TinyVector::RealPromote, SIZE> Promote; }; #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION #define TINYVECTOR_NUMTRAITS(T, SIZE) \ template<>\ struct NumericTraits >\ {\ typedef TinyVector Type;\ typedef TinyVector::Promote, SIZE> Promote;\ typedef TinyVector::RealPromote, SIZE> RealPromote;\ typedef TinyVector::ComplexPromote, SIZE> ComplexPromote;\ typedef T ValueType; \ typedef NumericTraits::isIntegral isIntegral;\ typedef VigraFalseType isScalar;\ typedef NumericTraits::isSigned isSigned; \ typedef VigraFalseType isOrdered;\ typedef VigraFalseType isComplex;\ \ static TinyVector zero() { \ return TinyVector(NumericTraits::zero()); \ }\ static TinyVector one() { \ return TinyVector(NumericTraits::one()); \ }\ static TinyVector nonZero() { \ return TinyVector(NumericTraits::nonZero()); \ }\ \ static Promote toPromote(TinyVector const & v) { \ return Promote(v); \ }\ static RealPromote toRealPromote(TinyVector const & v) { \ return RealPromote(v); \ }\ static TinyVector fromPromote(Promote const & v) { \ TinyVector res;\ TinyVector::iterator d = res.begin(), dend = res.end();\ Promote::const_iterator s = v.begin();\ for(; d != dend; ++d, ++s)\ *d = NumericTraits::fromPromote(*s);\ return res;\ }\ static TinyVector fromRealPromote(RealPromote const & v) {\ TinyVector res;\ TinyVector::iterator d = res.begin(), dend = res.end();\ RealPromote::const_iterator s = v.begin();\ for(; d != dend; ++d, ++s)\ *d = NumericTraits::fromRealPromote(*s);\ return res;\ }\ }; \ template<>\ struct NormTraits >\ {\ typedef TinyVector Type;\ typedef Type::SquaredNormType SquaredNormType; \ typedef Type::NormType NormType; \ }; #define TINYVECTOR_PROMTRAITS1(type1, SIZE) \ template<> \ struct PromoteTraits, TinyVector > \ { \ typedef TinyVector::Promote, SIZE> Promote; \ static Promote toPromote(TinyVector const & v) { \ return static_cast(v); } \ }; #define TINYVECTOR_PROMTRAITS2(type1, type2, SIZE) \ template<> \ struct PromoteTraits, TinyVector > \ { \ typedef TinyVector::Promote, SIZE> Promote; \ static Promote toPromote(TinyVector const & v) { \ return static_cast(v); } \ static Promote toPromote(TinyVector const & v) { \ return static_cast(v); } \ }; #define TINYVECTOR_TRAITS(SIZE) \ TINYVECTOR_NUMTRAITS(unsigned char, SIZE)\ TINYVECTOR_NUMTRAITS(int, SIZE)\ TINYVECTOR_NUMTRAITS(float, SIZE)\ TINYVECTOR_NUMTRAITS(double, SIZE)\ TINYVECTOR_PROMTRAITS1(unsigned char, SIZE)\ TINYVECTOR_PROMTRAITS1(int, SIZE)\ TINYVECTOR_PROMTRAITS1(float, SIZE)\ TINYVECTOR_PROMTRAITS1(double, SIZE)\ TINYVECTOR_PROMTRAITS2(float, unsigned char, SIZE)\ TINYVECTOR_PROMTRAITS2(unsigned char, float, SIZE)\ TINYVECTOR_PROMTRAITS2(int, unsigned char, SIZE)\ TINYVECTOR_PROMTRAITS2(unsigned char, int, SIZE)\ TINYVECTOR_PROMTRAITS2(int, float, SIZE)\ TINYVECTOR_PROMTRAITS2(float, int, SIZE)\ TINYVECTOR_PROMTRAITS2(double, unsigned char, SIZE)\ TINYVECTOR_PROMTRAITS2(unsigned char, double, SIZE)\ TINYVECTOR_PROMTRAITS2(int, double, SIZE)\ TINYVECTOR_PROMTRAITS2(double, int, SIZE)\ TINYVECTOR_PROMTRAITS2(double, float, SIZE)\ TINYVECTOR_PROMTRAITS2(float, double, SIZE) TINYVECTOR_TRAITS(2) TINYVECTOR_TRAITS(3) TINYVECTOR_TRAITS(4) #undef TINYVECTOR_NUMTRAITS #undef TINYVECTOR_PROMTRAITS1 #undef TINYVECTOR_PROMTRAITS2 #undef TINYVECTOR_TRAITS #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION /********************************************************/ /* */ /* TinyVector-Arithmetic */ /* */ /********************************************************/ /** \addtogroup TinyVectorOperators */ //@{ /// component-wise addition template inline typename PromoteTraits, TinyVector >::Promote operator+(TinyVectorBase const & l, TinyVectorBase const & r) { return typename PromoteTraits, TinyVector >::Promote(l) += r; } /// component-wise subtraction template inline typename PromoteTraits, TinyVector >::Promote operator-(TinyVectorBase const & l, TinyVectorBase const & r) { return typename PromoteTraits, TinyVector >::Promote(l) -= r; } /// component-wise multiplication template inline typename PromoteTraits, TinyVector >::Promote operator*(TinyVectorBase const & l, TinyVectorBase const & r) { return typename PromoteTraits, TinyVector >::Promote(l) *= r; } /// component-wise left scalar multiplication template inline typename NumericTraits >::RealPromote operator*(double v, TinyVectorBase const & r) { return typename NumericTraits >::RealPromote(r) *= v; } /// component-wise right scalar multiplication template inline typename NumericTraits >::RealPromote operator*(TinyVectorBase const & l, double v) { return typename NumericTraits >::RealPromote(l) *= v; } /// component-wise scalar division template inline typename NumericTraits >::RealPromote operator/(TinyVectorBase const & l, double v) { return typename NumericTraits >::RealPromote(l) /= v; } /** Unary negation (construct TinyVector with negative values) */ template inline TinyVector operator-(TinyVectorBase const & v) { TinyVector res(detail::dontInit()); typedef typename detail::LoopType::type ltype; ltype::neg(res.begin(), v.begin()); return res; } /// component-wise absolute value template inline TinyVector abs(TinyVectorBase const & v) { TinyVector res(detail::dontInit()); typedef typename detail::LoopType::type ltype; ltype::abs(res.begin(), v.begin()); return res; } /** Apply ceil() function to each vector component. */ template inline TinyVector ceil(TinyVectorBase const & v) { TinyVector res(detail::dontInit()); typedef typename detail::LoopType::type ltype; ltype::ceil(res.begin(), v.begin()); return res; } /** Apply floor() function to each vector component. */ template inline TinyVector floor(TinyVectorBase const & v) { TinyVector res(detail::dontInit()); typedef typename detail::LoopType::type ltype; ltype::floor(res.begin(), v.begin()); return res; } /// cross product template inline TinyVector::Promote, 3> cross(TinyVectorBase const & r1, TinyVectorBase const & r2) { typedef TinyVector::Promote, 3> Res; return Res(r1[1]*r2[2] - r1[2]*r2[1], r1[2]*r2[0] - r1[0]*r2[2], r1[0]*r2[1] - r1[1]*r2[0]); } /// dot product template inline typename PromoteTraits::Promote dot(TinyVectorBase const & l, TinyVectorBase const & r) { typedef typename detail::LoopType::type ltype; return ltype::dot(l.begin(), r.begin()); } /// squared norm template inline typename TinyVectorBase::SquaredNormType squaredNorm(TinyVectorBase const & t) { return t.squaredMagnitude(); } /// squared norm template inline typename TinyVector::SquaredNormType squaredNorm(TinyVector const & t) { return t.squaredMagnitude(); } //@} } // namespace vigra #endif // VIGRA_TINYVECTOR_HXX