[ VIGRA Homepage | Class Index | Function Index | File Index | Main Page ]

details vigra/tinyvector.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
00005 /*                                                                      */
00006 /*    This file is part of the VIGRA computer vision library.           */
00007 /*    ( Version 1.2.0, Aug 07 2003 )                                    */
00008 /*    You may use, modify, and distribute this software according       */
00009 /*    to the terms stated in the LICENSE file included in               */
00010 /*    the VIGRA distribution.                                           */
00011 /*                                                                      */
00012 /*    The VIGRA Website is                                              */
00013 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00014 /*    Please direct questions, bug reports, and contributions to        */
00015 /*        koethe@informatik.uni-hamburg.de                              */
00016 /*                                                                      */
00017 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
00018 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
00019 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
00020 /*                                                                      */
00021 /************************************************************************/
00022 
00023 
00024 #ifndef VIGRA_TINYVECTOR_HXX
00025 #define VIGRA_TINYVECTOR_HXX
00026 
00027 #include <cmath>    // abs(double)
00028 #include <cstdlib>  // abs(int)
00029 #include <iosfwd>   // ostream
00030 #include "vigra/config.hxx"
00031 #include "vigra/numerictraits.hxx"
00032 
00033 namespace vigra {
00034 
00035 using VIGRA_CSTD::abs;
00036 using VIGRA_CSTD::ceil;
00037 using VIGRA_CSTD::floor;
00038 
00039 namespace detail {
00040 
00041 #define VIGRA_EXEC_LOOP(NAME, OPER) \
00042     template <class T1, class T2>  \
00043     static void NAME(T1 * left, T2 const * right)  \
00044     {  \
00045         for(int i=0; i<LEVEL; ++i)  \
00046             (left[i]) OPER (right[i]);  \
00047     }
00048 
00049 #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \
00050     template <class T1, class T2>  \
00051     static void NAME(T1 * left, T2 right)  \
00052     {  \
00053         for(int i=0; i<LEVEL; ++i)  \
00054             (left[i]) OPER (right);  \
00055     }
00056 
00057 template <int LEVEL>
00058 struct ExecLoop
00059 {
00060     template <class T1, class T2>
00061     static void assignCast(T1 * left, T2 const * right)
00062     {
00063         for(int i=0; i<LEVEL; ++i)
00064             left[i] = detail::RequiresExplicitCast<T1>::cast(right[i]);
00065     }
00066 
00067     VIGRA_EXEC_LOOP(assign, =)
00068     VIGRA_EXEC_LOOP(add, +=)
00069     VIGRA_EXEC_LOOP(sub, -=)
00070     VIGRA_EXEC_LOOP(mul, *=)
00071     VIGRA_EXEC_LOOP(neg, = -)
00072     VIGRA_EXEC_LOOP(abs, = vigra::abs)
00073     VIGRA_EXEC_LOOP(floor, = vigra::floor)
00074     VIGRA_EXEC_LOOP(ceil, = vigra::ceil)
00075     VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
00076     VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
00077     VIGRA_EXEC_LOOP_SCALAR(assignScalar, =)
00078     VIGRA_EXEC_LOOP_SCALAR(mulScalar, *=)
00079     VIGRA_EXEC_LOOP_SCALAR(divScalar, /=)
00080 
00081     template <class T1, class T2>
00082     static bool notEqual(T1 const * left, T2 const * right)
00083     {
00084         for(int i=0; i<LEVEL; ++i)
00085             if(left[i] != right[i])
00086                 return true;
00087         return false;
00088     }
00089 
00090     template <class T>
00091     static typename NumericTraits<T>::Promote
00092     dot(T const * d)
00093     {
00094         typename NumericTraits<T>::Promote  res(*d * *d);
00095         for(int i=1; i<LEVEL; ++i)
00096             res += d[i] * d[i];
00097         return res;
00098     }
00099 
00100     template <class T1, class T2>
00101     static typename PromoteTraits<T1, T2>::Promote
00102     dot(T1 const * left, T2 const * right)
00103     {
00104         typename PromoteTraits<T1, T2>::Promote res(*left * *right);
00105         for(int i=1; i<LEVEL; ++i)
00106             res += left[i] * right[i];
00107         return res;
00108     }
00109 };
00110 
00111 template <int LEVEL>
00112 struct UnrollDot
00113 {
00114     template <class T>
00115     static typename NumericTraits<T>::Promote
00116     dot(T const * d)
00117     {
00118         return *d * *d + UnrollDot<LEVEL-1>::dot(d+1);
00119     }
00120 
00121     template <class T1, class T2>
00122     static typename PromoteTraits<T1, T2>::Promote
00123     dot(T1 const * left, T2 const * right)
00124     {
00125         return *left * *right + UnrollDot<LEVEL-1>::dot(left+1, right+1);
00126     }
00127 };
00128 
00129 template <>
00130 struct UnrollDot<1>
00131 {
00132     template <class T>
00133     static typename NumericTraits<T>::Promote
00134     dot(T const * d)
00135     {
00136         return *d * *d ;
00137     }
00138 
00139     template <class T1, class T2>
00140     static typename PromoteTraits<T1, T2>::Promote
00141     dot(T1 const * left, T2 const * right)
00142     {
00143         return *left * *right;
00144     }
00145 };
00146 
00147 #undef VIGRA_EXEC_LOOP
00148 #undef VIGRA_EXEC_LOOP_SCALAR
00149 
00150 #define VIGRA_UNROLL_LOOP(NAME, OPER) \
00151     template <class T1, class T2>  \
00152     static void NAME(T1 * left, T2 const * right)  \
00153     {  \
00154         (*left) OPER (*right);  \
00155         UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \
00156     }
00157 
00158 #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \
00159     template <class T1, class T2>  \
00160     static void NAME(T1 * left, T2 right)  \
00161     {  \
00162         (*left) OPER (right);  \
00163         UnrollLoop<LEVEL-1>::NAME(left+1, right); \
00164     }
00165 
00166 
00167 template <int LEVEL>
00168 struct UnrollLoop
00169 {
00170     template <class T1, class T2>
00171     static void assignCast(T1 * left, T2 const * right)
00172     {
00173         *left = detail::RequiresExplicitCast<T1>::cast(*right);
00174         UnrollLoop<LEVEL-1>::assignCast(left+1, right+1);
00175     }
00176 
00177     VIGRA_UNROLL_LOOP(assign, =)
00178     VIGRA_UNROLL_LOOP(add, +=)
00179     VIGRA_UNROLL_LOOP(sub, -=)
00180     VIGRA_UNROLL_LOOP(mul, *=)
00181     VIGRA_UNROLL_LOOP(neg, = -)
00182     VIGRA_UNROLL_LOOP(abs, = vigra::abs)
00183     VIGRA_UNROLL_LOOP(floor, = vigra::floor)
00184     VIGRA_UNROLL_LOOP(ceil, = vigra::ceil)
00185     VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
00186     VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
00187     VIGRA_UNROLL_LOOP_SCALAR(assignScalar, =)
00188     VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *=)
00189     VIGRA_UNROLL_LOOP_SCALAR(divScalar, /=)
00190 
00191     template <class T1, class T2>
00192     static bool notEqual(T1 const * left, T2 const * right)
00193     {
00194         return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1);
00195     }
00196 
00197     template <class T>
00198     static typename NumericTraits<T>::Promote
00199     dot(T const * d)
00200     {
00201         return UnrollDot<LEVEL>::dot(d);
00202     }
00203 
00204     template <class T1, class T2>
00205     static typename PromoteTraits<T1, T2>::Promote
00206     dot(T1 const * left, T2 const * right)
00207     {
00208         return UnrollDot<LEVEL>::dot(left, right);
00209     }
00210 };
00211 
00212 #undef VIGRA_UNROLL_LOOP
00213 #undef VIGRA_UNROLL_LOOP_SCALAR
00214 
00215 template <>
00216 struct UnrollLoop<0>
00217 {
00218     template <class T1, class T2>
00219     static void assignCast(T1, T2) {}
00220     template <class T1, class T2>
00221     static void assign(T1, T2) {}
00222     template <class T1, class T2>
00223     static void assignScalar(T1, T2) {}
00224     template <class T1, class T2>
00225     static void add(T1, T2) {}
00226     template <class T1, class T2>
00227     static void sub(T1, T2) {}
00228     template <class T1, class T2>
00229     static void mul(T1, T2) {}
00230     template <class T1, class T2>
00231     static void mulScalar(T1, T2) {}
00232     template <class T1, class T2>
00233     static void div(T1, T2) {}
00234     template <class T1, class T2>
00235     static void divScalar(T1, T2) {}
00236     template <class T1, class T2>
00237     static void fromPromote(T1, T2) {}
00238     template <class T1, class T2>
00239     static void fromRealPromote(T1, T2) {}
00240     template <class T1, class T2>
00241     static void neg(T1, T2) {}
00242     template <class T1, class T2>
00243     static void abs(T1, T2) {}
00244     template <class T1, class T2>
00245     static void floor(T1, T2) {}
00246     template <class T1, class T2>
00247     static void ceil(T1, T2) {}
00248     template <class T1, class T2>
00249     static bool notEqual(T1, T2) { return false; }
00250 };
00251 
00252 template <bool PREDICATE>
00253 struct If
00254 {
00255     template <class T, class F>
00256     struct res
00257     {
00258         typedef T type;
00259     };
00260 };
00261 
00262 template <>
00263 struct If<false>
00264 {
00265     template <class T, class F>
00266     struct res
00267     {
00268         typedef F type;
00269     };
00270 };
00271 
00272 template <int SIZE>
00273 struct LoopType
00274 {
00275     typedef typename If<SIZE < 5>::
00276             template res<UnrollLoop<SIZE>, ExecLoop<SIZE> >::type type;
00277 };
00278 
00279 struct DontInit {};
00280 
00281 inline DontInit dontInit() {return DontInit(); }
00282 
00283 } // namespace detail
00284 
00285 template <class T, int SIZE>
00286 class TinyVector;
00287 
00288 template <class T, int SIZE>
00289 class TinyVectorView;
00290 
00291 /********************************************************/
00292 /*                                                      */
00293 /*                    TinyVectorBase                    */
00294 /*                                                      */
00295 /********************************************************/
00296 
00297 /** \brief Base class for fixed size vectors.
00298 
00299     This class contains functionality shared by 
00300     \ref TinyVector and \ref TinyVectorBase, and enables these classes
00301     to be freely mixed within expressions. It is typically not used directly.
00302 
00303     <b>\#include</b> "<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>"<br>
00304     Namespace: vigra
00305 **/
00306 template <class VALUETYPE, int SIZE, class DATA, class DERIVED>
00307 class TinyVectorBase
00308 {
00309     TinyVectorBase(TinyVectorBase const &); // do not use
00310 
00311     TinyVectorBase & operator=(TinyVectorBase const & other); // do not use
00312 
00313   protected:
00314   
00315     typedef typename detail::LoopType<SIZE>::type Loop;
00316 
00317     TinyVectorBase()
00318     {}
00319 
00320   public:
00321         /** STL-compatible definition of valuetype
00322         */
00323     typedef VALUETYPE value_type;
00324 
00325         /** reference (return of operator[]).
00326         */
00327     typedef VALUETYPE & reference;
00328 
00329         /** const reference (return of operator[] const).
00330         */
00331     typedef VALUETYPE const & const_reference;
00332 
00333         /** pointer (return of operator->).
00334         */
00335     typedef VALUETYPE * pointer;
00336 
00337         /** const pointer (return of operator-> const).
00338         */
00339     typedef VALUETYPE const * const_pointer;
00340 
00341         /** STL-compatible definition of iterator
00342         */
00343     typedef value_type * iterator;
00344 
00345         /** STL-compatible definition of const iterator
00346         */
00347     typedef value_type const * const_iterator;
00348 
00349         /** STL-compatible definition of size_type
00350         */
00351     typedef unsigned int size_type;
00352 
00353         /** STL-compatible definition of difference_type
00354         */
00355     typedef int difference_type;
00356 
00357         /** the scalar type for the outer product
00358         */
00359     typedef double scalar_multiplier;
00360 
00361         /** Initialize from another sequence (must have length SIZE!)
00362         */
00363     template <class Iterator>
00364     void init(Iterator i, Iterator end)
00365     {
00366         vigra_precondition(end-i == SIZE,
00367             "TinyVector::init(): Sequence has wrong size.");
00368         Loop::assignCast(data_, i);
00369     }
00370 
00371         /** Component-wise add-assignment
00372         */
00373     template <class T1, class D1, class D2>
00374     DERIVED & operator+=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
00375     {
00376         Loop::add(data_, r.begin());
00377         return static_cast<DERIVED &>(*this);
00378     }
00379 
00380         /** Component-wise subtract-assignment
00381         */
00382     template <class T1, class D1, class D2>
00383     DERIVED & operator-=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
00384     {
00385         Loop::sub(data_, r.begin());
00386         return static_cast<DERIVED &>(*this);
00387     }
00388 
00389         /** Component-wise multiply-assignment
00390         */
00391     template <class T1, class D1, class D2>
00392     DERIVED & operator*=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
00393     {
00394         Loop::mul(data_, r.begin());
00395         return static_cast<DERIVED &>(*this);
00396     }
00397 
00398         /** Component-wise scalar multiply-assignment
00399         */
00400     DERIVED & operator*=(double r)
00401     {
00402         Loop::mulScalar(data_, r);
00403         return static_cast<DERIVED &>(*this);
00404     }
00405 
00406         /** Component-wise scalar divide-assignment
00407         */
00408     DERIVED & operator/=(double r)
00409     {
00410         Loop::divScalar(data_, r);
00411         return static_cast<DERIVED &>(*this);
00412     }
00413 
00414         /** Calculate magnitude.
00415         */
00416     typename NumericTraits<VALUETYPE>::RealPromote
00417     magnitude() const
00418     {
00419          return VIGRA_CSTD::sqrt(
00420                (typename NumericTraits<VALUETYPE>::RealPromote)squaredMagnitude());
00421     }
00422 
00423         /** Calculate squared magnitude.
00424         */
00425     typename NumericTraits<VALUETYPE>::Promote
00426     squaredMagnitude() const
00427     {
00428         return Loop::dot(data_);
00429     }
00430 
00431         /** Access component by index.
00432         */
00433     reference operator[](difference_type i) { return data_[i]; }
00434 
00435         /** Get component by index.
00436         */
00437     const_reference operator[](difference_type i) const { return data_[i]; }
00438 
00439         /** Get random access iterator to begin of vector.
00440         */
00441     iterator begin() { return data_; }
00442         /** Get random access iterator past-the-end of vector.
00443         */
00444     iterator end() { return data_ + SIZE; }
00445 
00446         /** Get const random access iterator to begin of vector.
00447         */
00448     const_iterator begin() const { return data_; }
00449 
00450         /** Get const random access iterator past-the-end of vector.
00451         */
00452     const_iterator end() const { return data_ + SIZE; }
00453 
00454         /** Size of TinyVector vector always equals the template parameter SIZE.
00455         */
00456     size_type size() const { return SIZE; }
00457 
00458   protected:
00459     DATA data_;
00460 };
00461 
00462 /** \brief Class for fixed size vectors.
00463 
00464     This class contains an array of size SIZE of the specified VALUETYPE.
00465     The interface conforms to STL vector, except that there are no functions
00466     that change the size of a TinyVector.
00467 
00468     \ref TinyVectorOperators "Arithmetic operations"
00469     on TinyVectors are defined as component-wise applications of these
00470     operations. Addition and subtraction of two TinyVectors
00471     (+=, -=, +, -, unary -), multiplication and division of an
00472     TinyVector with a double, and NumericTraits/PromoteTraits are defined,
00473     so that TinyVector fulfills the requirements of \ref LinearAlgebra.
00474 
00475     VIGRA algorithms typically use \ref vigra::VectorAccessor to access
00476     TinyVectors as a whole, or specific components of them.
00477 
00478     <b>\#include</b> "<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>"<br>
00479     Namespace: vigra
00480 **/
00481 template <class T, int SIZE>
00482 class TinyVector
00483 : public TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> >
00484 {
00485     typedef TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> > BaseType;
00486     typedef typename BaseType::Loop Loop;
00487 
00488   public:
00489 
00490     typedef typename BaseType::value_type value_type;
00491     typedef typename BaseType::reference reference;
00492     typedef typename BaseType::const_reference const_reference;
00493     typedef typename BaseType::pointer pointer;
00494     typedef typename BaseType::const_pointer const_pointer;
00495     typedef typename BaseType::iterator iterator;
00496     typedef typename BaseType::const_iterator const_iterator;
00497     typedef typename BaseType::size_type size_type;
00498     typedef typename BaseType::difference_type difference_type;
00499     typedef typename BaseType::scalar_multiplier scalar_multiplier;
00500 
00501         /** Construction with constant value
00502         */
00503     explicit TinyVector(value_type const & initial)
00504     : BaseType()
00505     {
00506         Loop::assignScalar(begin(), initial);
00507     }
00508 
00509         /** Construction with explicit values.
00510             Call only if SIZE == 2
00511         */
00512     TinyVector(value_type const & i1, value_type const & i2)
00513     : BaseType()
00514     {
00515         data_[0] = i1;
00516         data_[1] = i2;
00517     }
00518 
00519         /** Construction with explicit values.
00520             Call only if SIZE == 3
00521         */
00522     TinyVector(value_type const & i1, value_type const & i2, value_type const & i3)
00523     : BaseType()
00524     {
00525         data_[0] = i1;
00526         data_[1] = i2;
00527         data_[2] = i3;
00528     }
00529 
00530         /** Construction with explicit values.
00531             Call only if SIZE == 4
00532         */
00533     TinyVector(value_type const & i1, value_type const & i2,
00534                value_type const & i3, value_type const & i4)
00535     : BaseType()
00536     {
00537         data_[0] = i1;
00538         data_[1] = i2;
00539         data_[2] = i3;
00540         data_[3] = i4;
00541     }
00542 
00543        /** Default constructor (initializes all components with zero)
00544         */
00545     TinyVector()
00546     : BaseType()
00547     {
00548         Loop::assignScalar(data_, NumericTraits<value_type>::zero());
00549     }
00550 
00551         /** Copy constructor.
00552         */
00553     TinyVector(TinyVector const & r)
00554     : BaseType()
00555     {
00556         Loop::assign(data_, r.data_);
00557     }
00558 
00559         /** Copy assignment.
00560         */
00561     TinyVector & operator=(TinyVector const & r)
00562     {
00563         Loop::assign(data_, r.data_);
00564         return *this;
00565     }
00566 
00567         /** Copy with type conversion.
00568         */
00569     template <class U, class DATA, class DERIVED>
00570     TinyVector(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r)
00571     : BaseType()
00572     {
00573         Loop::assignCast(data_, r.begin());
00574     }
00575 
00576         /** Copy assignment with type conversion.
00577         */
00578     template <class U, class DATA, class DERIVED>
00579     TinyVector & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r)
00580     {
00581         Loop::assignCast(data_, r.begin());
00582         return *this;
00583     }
00584 
00585     explicit TinyVector(detail::DontInit)
00586     : BaseType()
00587     {}
00588 };
00589 
00590 /** \brief Wrapper for fixed size vectors.
00591 
00592     This class wraps an array of size SIZE of the specified VALUETYPE.
00593     Thus, the array can be accessed with an interface similar to
00594     that of std::vector (except that there are no functions
00595     that change the size of a TinyVectorView). The TinyVectorView
00596     does <em>not</em> assume ownership of the given memory.
00597 
00598     \ref TinyVectorOperators "Arithmetic operations"
00599     on TinyVectorViews are defined as component-wise applications of these
00600     operations. Addition and subtraction of two TinyVectorViews
00601     (+=, -=, +, -, unary -), multiplication and division of an
00602     TinyVectorViews with a double, and NumericTraits/PromoteTraits are defined,
00603     so that TinyVectorView fulfills the requirements of \ref LinearAlgebra.
00604 
00605     VIGRA algorithms typically use \ref vigra::VectorAccessor to access
00606     TinyVectorViews as a whole, or specific components of them.
00607 
00608     <b>\#include</b> "<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>"<br>
00609     Namespace: vigra
00610 **/
00611 template <class T, int SIZE>
00612 class TinyVectorView
00613 : public TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> >
00614 {
00615     typedef TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> > BaseType;
00616     typedef typename BaseType::Loop Loop;
00617 
00618   public:
00619 
00620     typedef typename BaseType::value_type value_type;
00621     typedef typename BaseType::reference reference;
00622     typedef typename BaseType::const_reference const_reference;
00623     typedef typename BaseType::pointer pointer;
00624     typedef typename BaseType::const_pointer const_pointer;
00625     typedef typename BaseType::iterator iterator;
00626     typedef typename BaseType::const_iterator const_iterator;
00627     typedef typename BaseType::size_type size_type;
00628     typedef typename BaseType::difference_type difference_type;
00629     typedef typename BaseType::scalar_multiplier scalar_multiplier;
00630 
00631         /** Default constructor 
00632             (pointer to wrapped data is NULL).
00633         */
00634     TinyVectorView()
00635     : BaseType()
00636     {
00637         data_ = 0;
00638     }
00639 
00640         /** Construct view for given data array
00641         */
00642     TinyVectorView(const_pointer data)
00643     : BaseType()
00644     {
00645         data_ = const_cast<pointer>(data);
00646     }
00647 
00648         /** Copy constructor (shallow copy).
00649         */
00650     TinyVectorView(TinyVectorView const & other)
00651     : BaseType()
00652     {
00653         data_ = const_cast<pointer>(other.data_);
00654     }
00655 
00656         /** Construct view from other TinyVector.
00657         */
00658     template <class DATA, class DERIVED>
00659     TinyVectorView(TinyVectorBase<T, SIZE, DATA, DERIVED> const & other)
00660     : BaseType()
00661     {
00662         data_ = const_cast<pointer>(other.data_);
00663     }
00664 
00665         /** Copy the data (not the pointer) of the rhs.
00666         */
00667    TinyVectorView & operator=(TinyVectorView const & r)
00668     {
00669         Loop::assign(data_, r.begin());
00670         return *this;
00671     }
00672 
00673         /** Copy the data of the rhs with cast.
00674         */
00675     template <class U, class DATA, class DERIVED>
00676     TinyVectorView & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r)
00677     {
00678         Loop::assignCast(data_, r.begin());
00679         return *this;
00680     }
00681 };
00682 
00683 
00684 } // namespace vigra
00685 
00686 /********************************************************/
00687 /*                                                      */
00688 /*                     TinyVector Output                */
00689 /*                                                      */
00690 /********************************************************/
00691 
00692 /** \addtogroup TinyVectorOperators
00693  */
00694 //@{
00695     /// stream output
00696 template <class V1, int SIZE, class DATA, class DERIVED>
00697 std::ostream &
00698 operator<<(std::ostream & out, vigra::TinyVectorBase<V1, SIZE, DATA, DERIVED> const & l)
00699 {
00700     out << "(";
00701     int i;
00702     for(i=0; i<SIZE-1; ++i)
00703         out << l[i] << ", ";
00704     out << l[i] << ")";
00705     return out;
00706 }
00707 
00708 /********************************************************/
00709 /*                                                      */
00710 /*                     TinyVector Comparison            */
00711 /*                                                      */
00712 /********************************************************/
00713 
00714 namespace vigra {
00715 
00716 /** \addtogroup TinyVectorOperators Functions for TinyVector
00717 
00718     \brief <b>\#include</b> "<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>
00719 
00720     These functions fulfill the requirements of a Linear Space (vector space).
00721     Return types are determined according to \ref TinyVectorTraits.
00722 
00723     Namespace: vigra
00724     <p>
00725 
00726  */
00727 //@{
00728     /// component-wise equal
00729 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
00730 inline bool
00731 operator==(TinyVectorBase<V1, SIZE, D1, D2> const & l,
00732            TinyVectorBase<V2, SIZE, D3, D4> const & r)
00733 {
00734     return !(l != r);
00735 }
00736 
00737     /// component-wise not equal
00738 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
00739 inline bool
00740 operator!=(TinyVectorBase<V1, SIZE, D1, D2> const & l,
00741            TinyVectorBase<V2, SIZE, D3, D4> const & r)
00742 {
00743     return detail::LoopType<SIZE>::type::notEqual(l.begin(), r.begin());
00744 }
00745 
00746 //@}
00747 
00748 /********************************************************/
00749 /*                                                      */
00750 /*                      TinyVector-Traits               */
00751 /*                                                      */
00752 /********************************************************/
00753 
00754 /** \page TinyVectorTraits Numeric and Promote Traits of TinyVector
00755     The numeric and promote traits for TinyVectors follow
00756     the general specifications for \ref NumericPromotionTraits.
00757     They are implemented in terms of the traits of the basic types by
00758     partial template specialization:
00759 
00760     \code
00761 
00762     template <class T, int SIZE>
00763     struct NumericTraits<TinyVector<T, SIZE> >
00764     {
00765         typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
00766         typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
00767 
00768         typedef typename NumericTraits<T>::isIntegral isIntegral;
00769         typedef VigraFalseType isScalar;
00770 
00771         // etc.
00772     };
00773 
00774     template <class T1, class T2, SIZE>
00775     struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> >
00776     {
00777         typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
00778     };
00779     \endcode
00780 
00781     <b>\#include</b> "<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>"<br>
00782     Namespace: vigra
00783 
00784     On compilers that don't support pertial template specialization (e.g.
00785     MS VisualC++), the traits classes are explicitly specialized for
00786     <TT>TinyVector<VALUETYPE, SIZE></TT> with
00787     <TT>VALUETYPE = unsigned char | int | float | double</TT> and <TT>SIZE = 2 | 3 | 4</TT>.
00788 
00789 */
00790 
00791 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION)
00792 
00793 template <class T, int SIZE>
00794 struct NumericTraits<TinyVector<T, SIZE> >
00795 {
00796     typedef TinyVector<T, SIZE> Type;
00797     typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
00798     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
00799 
00800     typedef typename NumericTraits<T>::isIntegral isIntegral;
00801     typedef VigraFalseType isScalar;
00802     typedef VigraFalseType isOrdered;
00803 
00804     static TinyVector<T, SIZE> zero() {
00805         return TinyVector<T, SIZE>(NumericTraits<T>::zero());
00806     }
00807     static TinyVector<T, SIZE> one() {
00808         return TinyVector<T, SIZE>(NumericTraits<T>::one());
00809     }
00810     static TinyVector<T, SIZE> nonZero() {
00811         return TinyVector<T, SIZE>(NumericTraits<T>::nonZero());
00812     }
00813 
00814     template <class D1, class D2>
00815     static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
00816     {
00817         return Promote(v);
00818     }
00819 
00820     template <class D1, class D2>
00821     static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
00822     {
00823         return RealPromote(v);
00824     }
00825 
00826     template <class D1, class D2>
00827     static TinyVector<T, SIZE>
00828     fromPromote(TinyVectorBase<typename NumericTraits<T>::Promote, SIZE, D1, D2> const & v)
00829     {
00830         TinyVector<T, SIZE> res(detail::dontInit());
00831         detail::LoopType<SIZE>::type::fromPromote(res.begin(), v.begin());
00832         return res;
00833     }
00834 
00835     template <class D1, class D2>
00836     static TinyVector<T, SIZE>
00837     fromRealPromote(TinyVectorBase<typename NumericTraits<T>::RealPromote, SIZE, D1, D2> const & v)
00838     {
00839         TinyVector<T, SIZE> res(detail::dontInit());
00840         detail::LoopType<SIZE>::type::fromRealPromote(res.begin(), v.begin());
00841         return res;
00842     }
00843 };
00844 
00845 template <class T, int SIZE>
00846 struct NumericTraits<TinyVectorView<T, SIZE> >
00847 : public NumericTraits<TinyVector<T, SIZE> >
00848 {
00849     typedef TinyVector<T, SIZE> Type;
00850     typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
00851     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
00852 
00853     typedef typename NumericTraits<T>::isIntegral isIntegral;
00854     typedef VigraFalseType isScalar;
00855     typedef VigraFalseType isOrdered;
00856 };
00857 
00858 template <class T1, class T2, int SIZE>
00859 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> >
00860 {
00861     typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
00862 };
00863 
00864 template <class T1, class T2, int SIZE>
00865 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVectorView<T2, SIZE> >
00866 {
00867     typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
00868 };
00869 
00870 template <class T1, class T2, int SIZE>
00871 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVector<T2, SIZE> >
00872 {
00873     typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
00874 };
00875 
00876 template <class T1, class T2, int SIZE>
00877 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVectorView<T2, SIZE> >
00878 {
00879     typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
00880 };
00881 
00882 template <class T, int SIZE>
00883 struct PromoteTraits<TinyVector<T, SIZE>, double >
00884 {
00885     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
00886 };
00887 
00888 template <class T, int SIZE>
00889 struct PromoteTraits<double, TinyVector<T, SIZE> >
00890 {
00891     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
00892 };
00893 
00894 template <class T, int SIZE>
00895 struct PromoteTraits<TinyVectorView<T, SIZE>, double >
00896 {
00897     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
00898 };
00899 
00900 template <class T, int SIZE>
00901 struct PromoteTraits<double, TinyVectorView<T, SIZE> >
00902 {
00903     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
00904 };
00905 
00906 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
00907 
00908 
00909 #define TINYVECTOR_NUMTRAITS(T, SIZE) \
00910 template<>\
00911 struct NumericTraits<TinyVector<T, SIZE> >\
00912 {\
00913     typedef TinyVector<T, SIZE> Type;\
00914     typedef TinyVector<NumericTraits<T>::Promote, SIZE> Promote;\
00915     typedef TinyVector<NumericTraits<T>::RealPromote, SIZE> RealPromote;\
00916     typedef NumericTraits<T>::isIntegral isIntegral;\
00917     typedef VigraFalseType isScalar;\
00918     typedef VigraFalseType isOrdered;\
00919     \
00920     static TinyVector<T, SIZE> zero() { \
00921         return TinyVector<T, SIZE>(NumericTraits<T>::zero()); \
00922     }\
00923     static TinyVector<T, SIZE> one() { \
00924         return TinyVector<T, SIZE>(NumericTraits<T>::one()); \
00925     }\
00926     static TinyVector<T, SIZE> nonZero() { \
00927         return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); \
00928     }\
00929     \
00930     static Promote toPromote(TinyVector<T, SIZE> const & v) { \
00931         return Promote(v); \
00932     }\
00933     static RealPromote toRealPromote(TinyVector<T, SIZE> const & v) { \
00934         return RealPromote(v); \
00935     }\
00936     static TinyVector<T, SIZE> fromPromote(Promote const & v) { \
00937         TinyVector<T, SIZE> res;\
00938         TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\
00939         Promote::const_iterator s = v.begin();\
00940         for(; d != dend; ++d, ++s)\
00941             *d = NumericTraits<T>::fromPromote(*s);\
00942         return res;\
00943     }\
00944     static TinyVector<T, SIZE> fromRealPromote(RealPromote const & v) {\
00945         TinyVector<T, SIZE> res;\
00946         TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\
00947         RealPromote::const_iterator s = v.begin();\
00948         for(; d != dend; ++d, ++s)\
00949             *d = NumericTraits<T>::fromRealPromote(*s);\
00950         return res;\
00951     }\
00952 };
00953 
00954 #define TINYVECTOR_PROMTRAITS1(type1, SIZE) \
00955 template<> \
00956 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type1, SIZE> > \
00957 { \
00958     typedef TinyVector<PromoteTraits<type1, type1>::Promote, SIZE> Promote; \
00959     static Promote toPromote(TinyVector<type1, SIZE> const & v) { \
00960         return static_cast<Promote>(v); } \
00961 };
00962 
00963 #define TINYVECTOR_PROMTRAITS2(type1, type2, SIZE) \
00964 template<> \
00965 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type2, SIZE> > \
00966 { \
00967     typedef TinyVector<PromoteTraits<type1, type2>::Promote, SIZE> Promote; \
00968     static Promote toPromote(TinyVector<type1, SIZE> const & v) { \
00969         return static_cast<Promote>(v); } \
00970     static Promote toPromote(TinyVector<type2, SIZE> const & v) { \
00971        return static_cast<Promote>(v); } \
00972 };
00973 
00974 #define TINYVECTOR_TRAITS(SIZE) \
00975 TINYVECTOR_NUMTRAITS(unsigned char, SIZE)\
00976 TINYVECTOR_NUMTRAITS(int, SIZE)\
00977 TINYVECTOR_NUMTRAITS(float, SIZE)\
00978 TINYVECTOR_NUMTRAITS(double, SIZE)\
00979 TINYVECTOR_PROMTRAITS1(unsigned char, SIZE)\
00980 TINYVECTOR_PROMTRAITS1(int, SIZE)\
00981 TINYVECTOR_PROMTRAITS1(float, SIZE)\
00982 TINYVECTOR_PROMTRAITS1(double, SIZE)\
00983 TINYVECTOR_PROMTRAITS2(float, unsigned char, SIZE)\
00984 TINYVECTOR_PROMTRAITS2(unsigned char, float, SIZE)\
00985 TINYVECTOR_PROMTRAITS2(int, unsigned char, SIZE)\
00986 TINYVECTOR_PROMTRAITS2(unsigned char, int, SIZE)\
00987 TINYVECTOR_PROMTRAITS2(int, float, SIZE)\
00988 TINYVECTOR_PROMTRAITS2(float, int, SIZE)\
00989 TINYVECTOR_PROMTRAITS2(double, unsigned char, SIZE)\
00990 TINYVECTOR_PROMTRAITS2(unsigned char, double, SIZE)\
00991 TINYVECTOR_PROMTRAITS2(int, double, SIZE)\
00992 TINYVECTOR_PROMTRAITS2(double, int, SIZE)\
00993 TINYVECTOR_PROMTRAITS2(double, float, SIZE)\
00994 TINYVECTOR_PROMTRAITS2(float, double, SIZE)
00995 
00996 TINYVECTOR_TRAITS(2)
00997 TINYVECTOR_TRAITS(3)
00998 TINYVECTOR_TRAITS(4)
00999 
01000 #undef TINYVECTOR_NUMTRAITS
01001 #undef TINYVECTOR_PROMTRAITS1
01002 #undef TINYVECTOR_PROMTRAITS2
01003 #undef TINYVECTOR_TRAITS
01004 
01005 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01006 
01007 
01008 /********************************************************/
01009 /*                                                      */
01010 /*                      TinyVector-Arithmetic           */
01011 /*                                                      */
01012 /********************************************************/
01013 
01014 /** \addtogroup TinyVectorOperators
01015  */
01016 //@{
01017 
01018     /// component-wise addition
01019 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01020 inline
01021 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
01022 operator+(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01023           TinyVectorBase<V2, SIZE, D3, D4> const & r)
01024 {
01025     typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote res(l);
01026     res += r;
01027     return res;
01028 }
01029 
01030     /// component-wise subtraction
01031 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01032 inline
01033 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
01034 operator-(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01035           TinyVectorBase<V2, SIZE, D3, D4> const & r)
01036 {
01037     typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote res(l);
01038     res -= r;
01039     return res;
01040 }
01041 
01042     /// component-wise multiplication
01043 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01044 inline
01045 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
01046 operator*(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01047           TinyVectorBase<V2, SIZE, D3, D4> const & r)
01048 {
01049     typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote res(l);
01050     res *= r;
01051     return res;
01052 }
01053 
01054     /// component-wise left scalar multiplication
01055 template <class V, int SIZE, class D1, class D2>
01056 inline
01057 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
01058 operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r)
01059 {
01060     return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *= v;
01061 }
01062 
01063     /// component-wise right scalar multiplication
01064 template <class V, int SIZE, class D1, class D2>
01065 inline
01066 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
01067 operator*(TinyVectorBase<V, SIZE, D1, D2> const & l, double v)
01068 {
01069     return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) *= v;
01070 }
01071 
01072     /// component-wise scalar division
01073 template <class V, int SIZE, class D1, class D2>
01074 inline
01075 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
01076 operator/(TinyVectorBase<V, SIZE, D1, D2> const & l, double v)
01077 {
01078     return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) /= v;
01079 }
01080 
01081 
01082     /** Unary negation (construct TinyVector with negative values)
01083     */
01084 template <class V, int SIZE, class D1, class D2>
01085 inline
01086 TinyVector<V, SIZE>
01087 operator-(TinyVectorBase<V, SIZE, D1, D2> const & v)
01088 {
01089     TinyVector<V, SIZE> res(detail::dontInit());
01090     detail::LoopType<SIZE>::type::neg(res.begin(), v.begin());
01091     return res;
01092 }
01093 
01094     /// component-wise absolute value
01095 template <class V, int SIZE, class D1, class D2>
01096 inline
01097 TinyVector<V, SIZE>
01098 abs(TinyVectorBase<V, SIZE, D1, D2> const & v)
01099 {
01100     TinyVector<V, SIZE> res(detail::dontInit());
01101     detail::LoopType<SIZE>::type::abs(res.begin(), v.begin());
01102     return res;
01103 }
01104 
01105     /** Apply ceil() function to each vector component.
01106     */
01107 template <class V, int SIZE, class D1, class D2>
01108 inline
01109 TinyVector<V, SIZE>
01110 ceil(TinyVectorBase<V, SIZE, D1, D2> const & v)
01111 {
01112     TinyVector<V, SIZE> res(detail::dontInit());
01113     detail::LoopType<SIZE>::type::ceil(res.begin(), v.begin());
01114     return res;
01115 }
01116 
01117     /** Apply floor() function to each vector component.
01118     */
01119 template <class V, int SIZE, class D1, class D2>
01120 inline
01121 TinyVector<V, SIZE>
01122 floor(TinyVectorBase<V, SIZE, D1, D2> const & v)
01123 {
01124     TinyVector<V, SIZE> res(detail::dontInit());
01125     detail::LoopType<SIZE>::type::floor(res.begin(), v.begin());
01126     return res;
01127 }
01128 
01129     /// dot product
01130 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01131 inline
01132 typename PromoteTraits<V1, V2>::Promote
01133 dot(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01134     TinyVectorBase<V2, SIZE, D3, D4> const & r)
01135 {
01136     return detail::LoopType<SIZE>::type::dot(l.begin(), r.begin());
01137 }
01138 
01139 //@}
01140 
01141 
01142 } // namespace vigra
01143 
01144 #endif // VIGRA_TINYVECTOR_HXX

© Ullrich Köthe (koethe@informatik.uni-hamburg.de)
Cognitive Systems Group, University of Hamburg, Germany

html generated using doxygen and Python
VIGRA 1.2.0 (7 Aug 2003)