[ 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.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)