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

| vigra/tinyvector.hxx |
--- | --- | ---

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