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

vigra/tinyvector.hxx
00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
00004 /*                                                                      */
00005 /*    This file is part of the VIGRA computer vision library.           */
00006 /*    The VIGRA Website is                                              */
00007 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
00008 /*    Please direct questions, bug reports, and contributions to        */
00009 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00010 /*        vigra@informatik.uni-hamburg.de                               */
00011 /*                                                                      */
00012 /*    Permission is hereby granted, free of charge, to any person       */
00013 /*    obtaining a copy of this software and associated documentation    */
00014 /*    files (the "Software"), to deal in the Software without           */
00015 /*    restriction, including without limitation the rights to use,      */
00016 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00017 /*    sell copies of the Software, and to permit persons to whom the    */
00018 /*    Software is furnished to do so, subject to the following          */
00019 /*    conditions:                                                       */
00020 /*                                                                      */
00021 /*    The above copyright notice and this permission notice shall be    */
00022 /*    included in all copies or substantial portions of the             */
00023 /*    Software.                                                         */
00024 /*                                                                      */
00025 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00026 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00027 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00028 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00029 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00030 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00031 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00032 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
00033 /*                                                                      */
00034 /************************************************************************/
00035 
00036 
00037 #ifndef VIGRA_TINYVECTOR_HXX
00038 #define VIGRA_TINYVECTOR_HXX
00039 
00040 #include <cmath>    // abs(double)
00041 #include <cstdlib>  // abs(int)
00042 #include <iosfwd>   // ostream
00043 #include "config.hxx"
00044 #include "error.hxx"
00045 #include "metaprogramming.hxx"
00046 #include "numerictraits.hxx"
00047 #include "memory.hxx"
00048 #include "mathutil.hxx"
00049 #include "diff2d.hxx"
00050 
00051 #ifdef VIGRA_CHECK_BOUNDS
00052 #define VIGRA_ASSERT_INSIDE(diff) \
00053   vigra_precondition(diff >= 0, "Index out of bounds");\
00054   vigra_precondition(diff < SIZE, "Index out of bounds");
00055 #else
00056 #define VIGRA_ASSERT_INSIDE(diff)
00057 #endif
00058 
00059 namespace vigra {
00060 
00061 using VIGRA_CSTD::abs;
00062 using VIGRA_CSTD::ceil;
00063 using VIGRA_CSTD::floor;
00064 
00065 
00066 template <class V1, int SIZE, class D1, class D2>
00067 class TinyVectorBase;
00068 
00069 template <class V1, int SIZE, class D1, class D2>
00070 inline
00071 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType
00072 squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t);
00073 
00074 
00075 namespace detail {
00076 
00077 #define VIGRA_EXEC_LOOP(NAME, OPER) \
00078     template <class T1, class T2>  \
00079     static void NAME(T1 * left, T2 const * right)  \
00080     {  \
00081         for(int i=0; i<LEVEL; ++i)  \
00082             (left[i]) OPER (right[i]);  \
00083     }
00084 
00085 #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \
00086     template <class T1, class T2>  \
00087     static void NAME(T1 * left, T2 right)  \
00088     {  \
00089         for(int i=0; i<LEVEL; ++i)  \
00090             (left[i]) = detail::RequiresExplicitCast<T1>::cast((left[i]) OPER (right));  \
00091     }
00092 
00093 template <int LEVEL>
00094 struct ExecLoop
00095 {
00096     template <class T1, class T2>
00097     static void assignCast(T1 * left, T2 const * right)
00098     {
00099         for(int i=0; i<LEVEL; ++i)
00100             left[i] = detail::RequiresExplicitCast<T1>::cast(right[i]);
00101     }
00102 
00103     template <class T1, class T2>
00104     static void reverseAssign(T1 * left, T2 const * right)
00105     {
00106         for(int i=0; i<LEVEL; ++i)
00107             left[i] = right[-i];
00108     }
00109 
00110     template <class T1, class T2>
00111     static void assignScalar(T1 * left, T2 right)
00112     {
00113         for(int i=0; i<LEVEL; ++i)
00114             left[i] = detail::RequiresExplicitCast<T1>::cast(right);
00115     }
00116 
00117     VIGRA_EXEC_LOOP(assign, =)
00118     VIGRA_EXEC_LOOP(add, +=)
00119     VIGRA_EXEC_LOOP(sub, -=)
00120     VIGRA_EXEC_LOOP(mul, *=)
00121     VIGRA_EXEC_LOOP(div, /=)
00122     VIGRA_EXEC_LOOP(neg, = -)
00123     VIGRA_EXEC_LOOP(abs, = vigra::abs)
00124     VIGRA_EXEC_LOOP(floor, = vigra::floor)
00125     VIGRA_EXEC_LOOP(ceil, = vigra::ceil)
00126     VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
00127     VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
00128     VIGRA_EXEC_LOOP_SCALAR(mulScalar, *)
00129     VIGRA_EXEC_LOOP_SCALAR(divScalar, /)
00130 
00131     template <class T1, class T2>
00132     static bool notEqual(T1 const * left, T2 const * right)
00133     {
00134         for(int i=0; i<LEVEL; ++i)
00135             if(left[i] != right[i])
00136                 return true;
00137         return false;
00138     }
00139 
00140     template <class T>
00141     static typename NumericTraits<T>::Promote
00142     dot(T const * d)
00143     {
00144         typename NumericTraits<T>::Promote  res(*d * *d);
00145         for(int i=1; i<LEVEL; ++i)
00146             res += d[i] * d[i];
00147         return res;
00148     }
00149 
00150     template <class T1, class T2>
00151     static typename PromoteTraits<T1, T2>::Promote
00152     dot(T1 const * left, T2 const * right)
00153     {
00154         typename PromoteTraits<T1, T2>::Promote res(*left * *right);
00155         for(int i=1; i<LEVEL; ++i)
00156             res += left[i] * right[i];
00157         return res;
00158     }
00159 
00160     template <class T>
00161     static typename NormTraits<T>::SquaredNormType
00162     squaredNorm(T const * d)
00163     {
00164         typename NormTraits<T>::SquaredNormType  res = vigra::squaredNorm(*d);
00165         for(int i=1; i<LEVEL; ++i)
00166             res += vigra::squaredNorm(d[i]);
00167         return res;
00168     }
00169 };
00170 
00171 template <int LEVEL>
00172 struct UnrollDot
00173 {
00174     template <class T>
00175     static typename NumericTraits<T>::Promote
00176     dot(T const * d)
00177     {
00178         return *d * *d + UnrollDot<LEVEL-1>::dot(d+1);
00179     }
00180 
00181     template <class T1, class T2>
00182     static typename PromoteTraits<T1, T2>::Promote
00183     dot(T1 const * left, T2 const * right)
00184     {
00185         return *left * *right + UnrollDot<LEVEL-1>::dot(left+1, right+1);
00186     }
00187 };
00188 
00189 template <>
00190 struct UnrollDot<1>
00191 {
00192     template <class T>
00193     static typename NumericTraits<T>::Promote
00194     dot(T const * d)
00195     {
00196         return *d * *d ;
00197     }
00198 
00199     template <class T1, class T2>
00200     static typename PromoteTraits<T1, T2>::Promote
00201     dot(T1 const * left, T2 const * right)
00202     {
00203         return *left * *right;
00204     }
00205 };
00206 
00207 template <int LEVEL>
00208 struct UnrollSquaredNorm
00209 {
00210     template <class T>
00211     static typename NormTraits<T>::SquaredNormType
00212     squaredNorm(T const * d)
00213     {
00214         return vigra::squaredNorm(*d) + UnrollSquaredNorm<LEVEL-1>::squaredNorm(d+1);
00215     }
00216 };
00217 
00218 template <>
00219 struct UnrollSquaredNorm<1>
00220 {
00221     template <class T>
00222     static typename NormTraits<T>::SquaredNormType
00223     squaredNorm(T const * d)
00224     {
00225         return vigra::squaredNorm(*d);
00226     }
00227 };
00228 
00229 #undef VIGRA_EXEC_LOOP
00230 #undef VIGRA_EXEC_LOOP_SCALAR
00231 
00232 #define VIGRA_UNROLL_LOOP(NAME, OPER) \
00233     template <class T1, class T2>  \
00234     static void NAME(T1 * left, T2 const * right)  \
00235     {  \
00236         (*left) OPER (*right);  \
00237         UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \
00238     }
00239 
00240 #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \
00241     template <class T1, class T2>  \
00242     static void NAME(T1 * left, T2 right)  \
00243     {  \
00244         (*left) = detail::RequiresExplicitCast<T1>::cast((*left) OPER (right));  \
00245         UnrollLoop<LEVEL-1>::NAME(left+1, right); \
00246     }
00247 
00248 
00249 template <int LEVEL>
00250 struct UnrollLoop
00251 {
00252     template <class T1, class T2>
00253     static void reverseAssign(T1 * left, T2 const * right)
00254     {
00255         *left = *right;
00256         UnrollLoop<LEVEL-1>::reverseAssign(left+1, right-1);
00257     }
00258 
00259     template <class T1, class T2>
00260     static void assignCast(T1 * left, T2 const * right)
00261     {
00262         *left = detail::RequiresExplicitCast<T1>::cast(*right);
00263         UnrollLoop<LEVEL-1>::assignCast(left+1, right+1);
00264     }
00265 
00266     template <class T1, class T2>
00267     static void assignScalar(T1 * left, T2 right)
00268     {
00269         *left = detail::RequiresExplicitCast<T1>::cast(right);
00270         UnrollLoop<LEVEL-1>::assignScalar(left+1, right);
00271     }
00272 
00273     VIGRA_UNROLL_LOOP(assign, =)
00274     VIGRA_UNROLL_LOOP(add, +=)
00275     VIGRA_UNROLL_LOOP(sub, -=)
00276     VIGRA_UNROLL_LOOP(mul, *=)
00277     VIGRA_UNROLL_LOOP(div, /=)
00278     VIGRA_UNROLL_LOOP(neg, = -)
00279     VIGRA_UNROLL_LOOP(abs, = vigra::abs)
00280     VIGRA_UNROLL_LOOP(floor, = vigra::floor)
00281     VIGRA_UNROLL_LOOP(ceil, = vigra::ceil)
00282     VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
00283     VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
00284     VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *)
00285     VIGRA_UNROLL_LOOP_SCALAR(divScalar, /)
00286 
00287     template <class T1, class T2>
00288     static bool notEqual(T1 const * left, T2 const * right)
00289     {
00290         return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1);
00291     }
00292 
00293     template <class T>
00294     static typename NumericTraits<T>::Promote
00295     dot(T const * d)
00296     {
00297         return UnrollDot<LEVEL>::dot(d);
00298     }
00299 
00300     template <class T1, class T2>
00301     static typename PromoteTraits<T1, T2>::Promote
00302     dot(T1 const * left, T2 const * right)
00303     {
00304         return UnrollDot<LEVEL>::dot(left, right);
00305     }
00306 
00307     template <class T>
00308     static typename NormTraits<T>::SquaredNormType
00309     squaredNorm(T const * d)
00310     {
00311         return UnrollSquaredNorm<LEVEL>::squaredNorm(d);
00312     }
00313 };
00314 
00315 #undef VIGRA_UNROLL_LOOP
00316 #undef VIGRA_UNROLL_LOOP_SCALAR
00317 
00318 template <>
00319 struct UnrollLoop<0>
00320 {
00321     template <class T1, class T2>
00322     static void reverseAssign(T1, T2) {}
00323     template <class T1, class T2>
00324     static void assignCast(T1, T2) {}
00325     template <class T1, class T2>
00326     static void assign(T1, T2) {}
00327     template <class T1, class T2>
00328     static void assignScalar(T1, T2) {}
00329     template <class T1, class T2>
00330     static void add(T1, T2) {}
00331     template <class T1, class T2>
00332     static void sub(T1, T2) {}
00333     template <class T1, class T2>
00334     static void mul(T1, T2) {}
00335     template <class T1, class T2>
00336     static void mulScalar(T1, T2) {}
00337     template <class T1, class T2>
00338     static void div(T1, T2) {}
00339     template <class T1, class T2>
00340     static void divScalar(T1, T2) {}
00341     template <class T1, class T2>
00342     static void fromPromote(T1, T2) {}
00343     template <class T1, class T2>
00344     static void fromRealPromote(T1, T2) {}
00345     template <class T1, class T2>
00346     static void neg(T1, T2) {}
00347     template <class T1, class T2>
00348     static void abs(T1, T2) {}
00349     template <class T1, class T2>
00350     static void floor(T1, T2) {}
00351     template <class T1, class T2>
00352     static void ceil(T1, T2) {}
00353     template <class T1, class T2>
00354     static bool notEqual(T1, T2) { return false; }
00355 };
00356 
00357 template <int SIZE>
00358 struct LoopType
00359 {
00360     typedef typename IfBool<(SIZE < 5), UnrollLoop<SIZE>, ExecLoop<SIZE> >::type type;
00361 
00362 };
00363 
00364 struct DontInit {};
00365 
00366 inline DontInit dontInit() {return DontInit(); }
00367 
00368 } // namespace detail
00369 
00370 template <class T, int SIZE>
00371 class TinyVector;
00372 
00373 template <class T, int SIZE>
00374 class TinyVectorView;
00375 
00376 /********************************************************/
00377 /*                                                      */
00378 /*                    TinyVectorBase                    */
00379 /*                                                      */
00380 /********************************************************/
00381 
00382 /** \brief Base class for fixed size vectors.
00383 
00384     This class contains functionality shared by
00385     \ref TinyVector and \ref TinyVectorView, and enables these classes
00386     to be freely mixed within expressions. It is typically not used directly.
00387 
00388     <b>\#include</b> <<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>><br>
00389     Namespace: vigra
00390 **/
00391 template <class VALUETYPE, int SIZE, class DATA, class DERIVED>
00392 class TinyVectorBase
00393 {
00394     TinyVectorBase(TinyVectorBase const &); // do not use
00395 
00396     TinyVectorBase & operator=(TinyVectorBase const & other); // do not use
00397 
00398   protected:
00399 
00400     typedef typename detail::LoopType<SIZE>::type Loop;
00401 
00402     TinyVectorBase()
00403     {}
00404 
00405   public:
00406         /** STL-compatible definition of valuetype
00407         */
00408     typedef VALUETYPE value_type;
00409 
00410         /** reference (return of operator[]).
00411         */
00412     typedef VALUETYPE & reference;
00413 
00414         /** const reference (return of operator[] const).
00415         */
00416     typedef VALUETYPE const & const_reference;
00417 
00418         /** pointer (return of operator->).
00419         */
00420     typedef VALUETYPE * pointer;
00421 
00422         /** const pointer (return of operator-> const).
00423         */
00424     typedef VALUETYPE const * const_pointer;
00425 
00426         /** STL-compatible definition of iterator
00427         */
00428     typedef value_type * iterator;
00429 
00430         /** STL-compatible definition of const iterator
00431         */
00432     typedef value_type const * const_iterator;
00433 
00434         /** STL-compatible definition of size_type
00435         */
00436     typedef unsigned int size_type;
00437 
00438         /** STL-compatible definition of difference_type
00439         */
00440     typedef int difference_type;
00441 
00442         /** the scalar type for the outer product
00443         */
00444     typedef double scalar_multiplier;
00445 
00446         /** the vector's squared norm type
00447         */
00448     typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType;
00449 
00450         /** the vector's norm type
00451         */
00452     typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType;
00453 
00454         /** the vector's size
00455         */
00456     enum { static_size = SIZE };
00457 
00458         /** Initialize from another sequence (must have length SIZE!)
00459         */
00460     template <class Iterator>
00461     void init(Iterator i, Iterator end)
00462     {
00463         vigra_precondition(end-i == SIZE,
00464             "TinyVector::init(): Sequence has wrong size.");
00465         Loop::assignCast(data_, i);
00466     }
00467 
00468         /** Initialize with constant value
00469         */
00470     void init(value_type initial)
00471     {
00472         Loop::assignScalar(data_, initial);
00473     }
00474 
00475         /** Component-wise add-assignment
00476         */
00477     template <class T1, class D1, class D2>
00478     DERIVED & operator+=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
00479     {
00480         Loop::add(data_, r.begin());
00481         return static_cast<DERIVED &>(*this);
00482     }
00483 
00484         /** Component-wise subtract-assignment
00485         */
00486     template <class T1, class D1, class D2>
00487     DERIVED & operator-=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
00488     {
00489         Loop::sub(data_, r.begin());
00490         return static_cast<DERIVED &>(*this);
00491     }
00492 
00493         /** Component-wise multiply-assignment
00494         */
00495     template <class T1, class D1, class D2>
00496     DERIVED & operator*=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
00497     {
00498         Loop::mul(data_, r.begin());
00499         return static_cast<DERIVED &>(*this);
00500     }
00501 
00502         /** Component-wise divide-assignment
00503         */
00504     template <class T1, class D1, class D2>
00505     DERIVED & operator/=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
00506     {
00507         Loop::div(data_, r.begin());
00508         return static_cast<DERIVED &>(*this);
00509     }
00510 
00511         /** Component-wise scalar multiply-assignment
00512         */
00513     DERIVED & operator*=(double r)
00514     {
00515         Loop::mulScalar(data_, r);
00516         return static_cast<DERIVED &>(*this);
00517     }
00518 
00519         /** Component-wise scalar divide-assignment
00520         */
00521     DERIVED & operator/=(double r)
00522     {
00523         Loop::divScalar(data_, r);
00524         return static_cast<DERIVED &>(*this);
00525     }
00526 
00527         /** Calculate magnitude.
00528         */
00529     NormType magnitude() const
00530     {
00531          return sqrt(static_cast<typename
00532               SquareRootTraits<SquaredNormType>::SquareRootArgument>(squaredMagnitude()));
00533     }
00534 
00535         /** Calculate squared magnitude.
00536         */
00537     SquaredNormType squaredMagnitude() const
00538     {
00539         return Loop::squaredNorm(data_);
00540     }
00541 
00542         /** Access component by index.
00543         */
00544     reference operator[](difference_type i)
00545     {
00546         VIGRA_ASSERT_INSIDE(i);
00547         return data_[i];
00548     }
00549 
00550         /** Get component by index.
00551         */
00552     const_reference operator[](difference_type i) const
00553     {
00554         VIGRA_ASSERT_INSIDE(i);
00555         return data_[i];
00556     }
00557 
00558         /** Get random access iterator to begin of vector.
00559         */
00560     iterator begin() { return data_; }
00561         /** Get random access iterator past-the-end of vector.
00562         */
00563     iterator end() { return data_ + SIZE; }
00564 
00565         /** Get const random access iterator to begin of vector.
00566         */
00567     const_iterator begin() const { return data_; }
00568 
00569         /** Get const random access iterator past-the-end of vector.
00570         */
00571     const_iterator end() const { return data_ + SIZE; }
00572 
00573         /** Size of TinyVector vector always equals the template parameter SIZE.
00574         */
00575     size_type size() const { return SIZE; }
00576 
00577     pointer data() { return data_; }
00578 
00579     const_pointer data() const { return data_; }
00580 
00581   protected:
00582   
00583     DATA data_;
00584 };
00585 
00586 /** \brief Class for fixed size vectors.
00587 
00588     This class contains an array of size SIZE of the specified VALUETYPE.
00589     The interface conforms to STL vector, except that there are no functions
00590     that change the size of a TinyVector.
00591 
00592     \ref TinyVectorOperators "Arithmetic operations"
00593     on TinyVectors are defined as component-wise applications of these
00594     operations. Addition and subtraction of two TinyVectors
00595     (+=, -=, +, -, unary -), multiplication and division of an
00596     TinyVector with a double, and NumericTraits/PromoteTraits are defined,
00597     so that TinyVector fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra".
00598 
00599     VIGRA algorithms typically use \ref vigra::VectorAccessor to access
00600     TinyVectors as a whole, or specific components of them.
00601 
00602     See also:<br>
00603     <UL style="list-style-image:url(documents/bullet.gif)">
00604         <LI> \ref vigra::TinyVectorBase
00605         <LI> \ref vigra::TinyVectorView
00606         <LI> \ref TinyVectorTraits
00607         <LI> \ref TinyVectorOperators
00608     </UL>
00609 
00610     <b>\#include</b> <<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>><br>
00611     Namespace: vigra
00612 **/
00613 template <class T, int SIZE>
00614 class TinyVector
00615 : public TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> >
00616 {
00617     typedef TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> > BaseType;
00618     typedef typename BaseType::Loop Loop;
00619 
00620   public:
00621 
00622     typedef typename BaseType::value_type value_type;
00623     typedef typename BaseType::reference reference;
00624     typedef typename BaseType::const_reference const_reference;
00625     typedef typename BaseType::pointer pointer;
00626     typedef typename BaseType::const_pointer const_pointer;
00627     typedef typename BaseType::iterator iterator;
00628     typedef typename BaseType::const_iterator const_iterator;
00629     typedef typename BaseType::size_type size_type;
00630     typedef typename BaseType::difference_type difference_type;
00631     typedef typename BaseType::scalar_multiplier scalar_multiplier;
00632     typedef typename BaseType::SquaredNormType SquaredNormType;
00633     typedef typename BaseType::NormType NormType;
00634     
00635     enum ReverseCopyTag { ReverseCopy };
00636 
00637         /** Construction with constant value
00638         */
00639     explicit TinyVector(value_type const & initial)
00640     : BaseType()
00641     {
00642         Loop::assignScalar(BaseType::begin(), initial);
00643     }
00644 
00645         /** Construction with Diff2D (only implemented for 2D TinyVector)
00646         */
00647     explicit TinyVector(Diff2D const & initial)
00648     : BaseType()
00649     {
00650         BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial.x);
00651         BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial.y);
00652     }
00653 
00654         /** Construction with explicit values.
00655             Call only if SIZE == 2
00656         */
00657     TinyVector(value_type const & i1, value_type const & i2)
00658     : BaseType()
00659     {
00660         BaseType::data_[0] = i1;
00661         BaseType::data_[1] = i2;
00662     }
00663 
00664         /** Construction with explicit values.
00665             Call only if SIZE == 3
00666         */
00667     TinyVector(value_type const & i1, value_type const & i2, value_type const & i3)
00668     : BaseType()
00669     {
00670         BaseType::data_[0] = i1;
00671         BaseType::data_[1] = i2;
00672         BaseType::data_[2] = i3;
00673     }
00674 
00675         /** Construction with explicit values.
00676             Call only if SIZE == 4
00677         */
00678     TinyVector(value_type const & i1, value_type const & i2,
00679                value_type const & i3, value_type const & i4)
00680     : BaseType()
00681     {
00682         BaseType::data_[0] = i1;
00683         BaseType::data_[1] = i2;
00684         BaseType::data_[2] = i3;
00685         BaseType::data_[3] = i4;
00686     }
00687 
00688         /** Construction with explicit values.
00689             Call only if SIZE == 5
00690         */
00691     TinyVector(value_type const & i1, value_type const & i2,
00692                value_type const & i3, value_type const & i4,
00693                value_type const & i5)
00694     : BaseType()
00695     {
00696         BaseType::data_[0] = i1;
00697         BaseType::data_[1] = i2;
00698         BaseType::data_[2] = i3;
00699         BaseType::data_[3] = i4;
00700         BaseType::data_[4] = i5;
00701     }
00702        /** Default constructor (initializes all components with zero)
00703         */
00704     TinyVector()
00705     : BaseType()
00706     {
00707         Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero());
00708     }
00709 
00710         /** Copy constructor.
00711         */
00712     TinyVector(TinyVector const & r)
00713     : BaseType()
00714     {
00715         Loop::assign(BaseType::data_, r.data_);
00716     }
00717 
00718         /** Constructor from C array.
00719         */
00720     explicit TinyVector(const_pointer data)
00721     : BaseType()
00722     {
00723         Loop::assign(BaseType::data_, data);
00724     }
00725 
00726         /** Constructor by reverse copy from C array.
00727             
00728             Usage:
00729             \code
00730             TinyVector<int, 3> v(1,2,3);
00731             TinyVector<int, 3> reverse(v.begin(), TinyVector<int, 3>::ReverseCopy);
00732             \endcode
00733         */
00734     explicit TinyVector(const_pointer data, ReverseCopyTag)
00735     : BaseType()
00736     {
00737         Loop::reverseAssign(BaseType::data_, data+SIZE-1);
00738     }
00739 
00740         /** Copy assignment.
00741         */
00742     TinyVector & operator=(TinyVector const & r)
00743     {
00744         Loop::assign(BaseType::data_, r.data_);
00745         return *this;
00746     }
00747 
00748         /** Assignment from Diff2D.
00749         */
00750     TinyVector & operator=(Diff2D const & r)
00751     {
00752         BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(r.x);
00753         BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(r.y);
00754         return *this;
00755     }
00756 
00757         /** Copy with type conversion.
00758         */
00759     template <class U>
00760     TinyVector(TinyVector<U, SIZE> const & r)
00761     : BaseType()
00762     {
00763         Loop::assignCast(BaseType::data_, r.begin());
00764     }
00765 
00766         /** Copy with type conversion.
00767         */
00768     template <class U, class DATA, class DERIVED>
00769     TinyVector(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r)
00770     : BaseType()
00771     {
00772         Loop::assignCast(BaseType::data_, r.begin());
00773     }
00774 
00775         /** Copy assignment with type conversion.
00776         */
00777     template <class U, class DATA, class DERIVED>
00778     TinyVector & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r)
00779     {
00780         Loop::assignCast(BaseType::data_, r.begin());
00781         return *this;
00782     }
00783 
00784     explicit TinyVector(SkipInitializationTag)
00785     : BaseType()
00786     {}
00787 
00788     explicit TinyVector(detail::DontInit)
00789     : BaseType()
00790     {}
00791 };
00792 
00793 /** \brief Wrapper for fixed size vectors.
00794 
00795     This class wraps an array of size SIZE of the specified VALUETYPE.
00796     Thus, the array can be accessed with an interface similar to
00797     that of std::vector (except that there are no functions
00798     that change the size of a TinyVectorView). The TinyVectorView
00799     does <em>not</em> assume ownership of the given memory.
00800 
00801     \ref TinyVectorOperators "Arithmetic operations"
00802     on TinyVectorViews are defined as component-wise applications of these
00803     operations. Addition and subtraction of two TinyVectorViews
00804     (+=, -=, +, -, unary -), multiplication and division of an
00805     TinyVectorViews with a double, and NumericTraits/PromoteTraits are defined,
00806     so that TinyVectorView fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra".
00807 
00808     VIGRA algorithms typically use \ref vigra::VectorAccessor to access
00809     TinyVectorViews as a whole, or specific components of them.
00810 
00811     <b>See also:</b>
00812     <ul>
00813         <li> \ref vigra::TinyVectorBase
00814         <li> \ref vigra::TinyVector
00815         <li> \ref TinyVectorTraits
00816         <li> \ref TinyVectorOperators
00817     </ul>
00818 
00819     <b>\#include</b> <<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>><br>
00820     Namespace: vigra
00821 **/
00822 template <class T, int SIZE>
00823 class TinyVectorView
00824 : public TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> >
00825 {
00826     typedef TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> > BaseType;
00827     typedef typename BaseType::Loop Loop;
00828 
00829   public:
00830 
00831     typedef typename BaseType::value_type value_type;
00832     typedef typename BaseType::reference reference;
00833     typedef typename BaseType::const_reference const_reference;
00834     typedef typename BaseType::pointer pointer;
00835     typedef typename BaseType::const_pointer const_pointer;
00836     typedef typename BaseType::iterator iterator;
00837     typedef typename BaseType::const_iterator const_iterator;
00838     typedef typename BaseType::size_type size_type;
00839     typedef typename BaseType::difference_type difference_type;
00840     typedef typename BaseType::scalar_multiplier scalar_multiplier;
00841     typedef typename BaseType::SquaredNormType SquaredNormType;
00842     typedef typename BaseType::NormType NormType;
00843 
00844         /** Default constructor
00845             (pointer to wrapped data is NULL).
00846         */
00847     TinyVectorView()
00848     : BaseType()
00849     {
00850         BaseType::data_ = 0;
00851     }
00852 
00853         /** Construct view for given data array
00854         */
00855     TinyVectorView(const_pointer data)
00856     : BaseType()
00857     {
00858         BaseType::data_ = const_cast<pointer>(data);
00859     }
00860 
00861         /** Copy constructor (shallow copy).
00862         */
00863     TinyVectorView(TinyVectorView const & other)
00864     : BaseType()
00865     {
00866         BaseType::data_ = const_cast<pointer>(other.data_);
00867     }
00868 
00869         /** Construct view from other TinyVector.
00870         */
00871     template <class DATA, class DERIVED>
00872     TinyVectorView(TinyVectorBase<T, SIZE, DATA, DERIVED> const & other)
00873     : BaseType()
00874     {
00875         BaseType::data_ = const_cast<pointer>(other.data());
00876     }
00877 
00878         /** Copy the data (not the pointer) of the rhs.
00879         */
00880    TinyVectorView & operator=(TinyVectorView const & r)
00881     {
00882         Loop::assign(BaseType::data_, r.begin());
00883         return *this;
00884     }
00885 
00886         /** Copy the data of the rhs with cast.
00887         */
00888     template <class U, class DATA, class DERIVED>
00889     TinyVectorView & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r)
00890     {
00891         Loop::assignCast(BaseType::data_, r.begin());
00892         return *this;
00893     }
00894 };
00895 
00896 /********************************************************/
00897 /*                                                      */
00898 /*                     TinyVector Comparison            */
00899 /*                                                      */
00900 /********************************************************/
00901 
00902 /** \addtogroup TinyVectorOperators Functions for TinyVector
00903 
00904     \brief Implement basic arithmetic and equality for TinyVector.
00905 
00906     These functions fulfill the requirements of a Linear Space (vector space).
00907     Return types are determined according to \ref TinyVectorTraits.
00908 
00909     <b>\#include</b> <<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>><br>
00910     Namespace: vigra
00911 */
00912 //@{
00913     /// component-wise equal
00914 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
00915 inline bool
00916 operator==(TinyVectorBase<V1, SIZE, D1, D2> const & l,
00917            TinyVectorBase<V2, SIZE, D3, D4> const & r)
00918 {
00919     return !(l != r);
00920 }
00921 
00922     /// component-wise not equal
00923 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
00924 inline bool
00925 operator!=(TinyVectorBase<V1, SIZE, D1, D2> const & l,
00926            TinyVectorBase<V2, SIZE, D3, D4> const & r)
00927 {
00928     typedef typename detail::LoopType<SIZE>::type ltype;
00929     return ltype::notEqual(l.begin(), r.begin());
00930 }
00931 
00932 /********************************************************/
00933 /*                                                      */
00934 /*                     TinyVector Output                */
00935 /*                                                      */
00936 /********************************************************/
00937 
00938     /// stream output
00939 template <class V1, int SIZE, class DATA, class DERIVED>
00940 std::ostream &
00941 operator<<(std::ostream & out, TinyVectorBase<V1, SIZE, DATA, DERIVED> const & l)
00942 {
00943     out << "(";
00944     int i;
00945     for(i=0; i<SIZE-1; ++i)
00946         out << l[i] << ", ";
00947     out << l[i] << ")";
00948     return out;
00949 }
00950 //@}
00951 
00952 /********************************************************/
00953 /*                                                      */
00954 /*                      TinyVector-Traits               */
00955 /*                                                      */
00956 /********************************************************/
00957 
00958 /** \page TinyVectorTraits Numeric and Promote Traits of TinyVector
00959     The numeric and promote traits for TinyVectors follow
00960     the general specifications for \ref NumericPromotionTraits.
00961     They are implemented in terms of the traits of the basic types by
00962     partial template specialization:
00963 
00964     \code
00965 
00966     template <class T, int SIZE>
00967     struct NumericTraits<TinyVector<T, SIZE> >
00968     {
00969         typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
00970         typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
00971 
00972         typedef typename NumericTraits<T>::isIntegral isIntegral;
00973         typedef VigraFalseType isScalar;
00974         typedef typename NumericTraits<T>::isSigned isSigned;
00975 
00976         // etc.
00977     };
00978 
00979     template <class T, int SIZE>
00980     struct NormTraits<TinyVector<T, SIZE> >
00981     {
00982         typedef TinyVector<T, SIZE> Type;
00983         typedef typename Type::SquaredNormType    SquaredNormType;
00984         typedef typename Type::NormType           NormType;
00985     };
00986 
00987     template <class T1, class T2, SIZE>
00988     struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> >
00989     {
00990         typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
00991     };
00992     \endcode
00993 
00994     <b>\#include</b> <<a href="tinyvector_8hxx-source.html">vigra/tinyvector.hxx</a>><br>
00995     Namespace: vigra
00996 
00997     On compilers that don't support pertial template specialization (e.g.
00998     MS VisualC++), the traits classes are explicitly specialized for
00999     <TT>TinyVector<VALUETYPE, SIZE></TT> with
01000     <TT>VALUETYPE = unsigned char | int | float | double</TT> and <TT>SIZE = 2 | 3 | 4</TT>.
01001 
01002 */
01003 
01004 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION)
01005 
01006 template <class T, int SIZE>
01007 struct NumericTraits<TinyVector<T, SIZE> >
01008 {
01009     typedef TinyVector<T, SIZE> Type;
01010     typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
01011     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
01012     typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;
01013     typedef T ValueType;
01014 
01015     typedef typename NumericTraits<T>::isIntegral isIntegral;
01016     typedef VigraFalseType isScalar;
01017     typedef typename NumericTraits<T>::isSigned isSigned;
01018     typedef VigraFalseType isOrdered;
01019     typedef VigraFalseType isComplex;
01020 
01021     static TinyVector<T, SIZE> zero() {
01022         return TinyVector<T, SIZE>(NumericTraits<T>::zero());
01023     }
01024     static TinyVector<T, SIZE> one() {
01025         return TinyVector<T, SIZE>(NumericTraits<T>::one());
01026     }
01027     static TinyVector<T, SIZE> nonZero() {
01028         return TinyVector<T, SIZE>(NumericTraits<T>::nonZero());
01029     }
01030 
01031     template <class D1, class D2>
01032     static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
01033     {
01034         return Promote(v);
01035     }
01036 
01037     template <class D1, class D2>
01038     static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
01039     {
01040         return RealPromote(v);
01041     }
01042 
01043     template <class D1, class D2>
01044     static TinyVector<T, SIZE>
01045     fromPromote(TinyVectorBase<typename NumericTraits<T>::Promote, SIZE, D1, D2> const & v)
01046     {
01047         TinyVector<T, SIZE> res(detail::dontInit());
01048         typedef typename detail::LoopType<SIZE>::type ltype;
01049         ltype::fromPromote(res.begin(), v.begin());
01050         return res;
01051     }
01052 
01053     template <class D1, class D2>
01054     static TinyVector<T, SIZE>
01055     fromRealPromote(TinyVectorBase<typename NumericTraits<T>::RealPromote, SIZE, D1, D2> const & v)
01056     {
01057         TinyVector<T, SIZE> res(detail::dontInit());
01058         typedef typename detail::LoopType<SIZE>::type ltype;
01059         ltype::fromRealPromote(res.begin(), v.begin());
01060         return res;
01061     }
01062 };
01063 
01064 template <class T, int SIZE>
01065 struct NumericTraits<TinyVectorView<T, SIZE> >
01066 : public NumericTraits<TinyVector<T, SIZE> >
01067 {
01068     typedef TinyVector<T, SIZE> Type;
01069     typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
01070     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
01071     typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;
01072     typedef T ValueType;
01073 
01074     typedef typename NumericTraits<T>::isIntegral isIntegral;
01075     typedef VigraFalseType isScalar;
01076     typedef typename NumericTraits<T>::isSigned isSigned;
01077     typedef VigraFalseType isOrdered;
01078     typedef VigraFalseType isComplex;
01079 };
01080 
01081 template <class T, int SIZE>
01082 struct NormTraits<TinyVector<T, SIZE> >
01083 {
01084     typedef TinyVector<T, SIZE> Type;
01085     typedef typename Type::SquaredNormType    SquaredNormType;
01086     typedef typename Type::NormType           NormType;
01087 };
01088 
01089 template <class T, int SIZE>
01090 struct NormTraits<TinyVectorView<T, SIZE> >
01091 {
01092     typedef TinyVector<T, SIZE> Type;
01093     typedef typename Type::SquaredNormType    SquaredNormType;
01094     typedef typename Type::NormType           NormType;
01095 };
01096 
01097 template <class T1, class T2, int SIZE>
01098 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> >
01099 {
01100     typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
01101 };
01102 
01103 template <class T1, class T2, int SIZE>
01104 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVectorView<T2, SIZE> >
01105 {
01106     typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
01107 };
01108 
01109 template <class T1, class T2, int SIZE>
01110 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVector<T2, SIZE> >
01111 {
01112     typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
01113 };
01114 
01115 template <class T1, class T2, int SIZE>
01116 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVectorView<T2, SIZE> >
01117 {
01118     typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
01119 };
01120 
01121 template <class T, int SIZE>
01122 struct PromoteTraits<TinyVector<T, SIZE>, double >
01123 {
01124     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
01125 };
01126 
01127 template <class T, int SIZE>
01128 struct PromoteTraits<double, TinyVector<T, SIZE> >
01129 {
01130     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
01131 };
01132 
01133 template <class T, int SIZE>
01134 struct PromoteTraits<TinyVectorView<T, SIZE>, double >
01135 {
01136     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
01137 };
01138 
01139 template <class T, int SIZE>
01140 struct PromoteTraits<double, TinyVectorView<T, SIZE> >
01141 {
01142     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
01143 };
01144 
01145 template<class T, int SIZE>
01146 struct CanSkipInitialization<TinyVectorView<T, SIZE> >
01147 {
01148     typedef typename CanSkipInitialization<T>::type type;
01149     static const bool value = type::asBool;
01150 };
01151 
01152 template<class T, int SIZE>
01153 struct CanSkipInitialization<TinyVector<T, SIZE> >
01154 {
01155     typedef typename CanSkipInitialization<T>::type type;
01156     static const bool value = type::asBool;
01157 };
01158 
01159 
01160 
01161 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01162 
01163 
01164 #define TINYVECTOR_NUMTRAITS(T, SIZE) \
01165 template<>\
01166 struct NumericTraits<TinyVector<T, SIZE> >\
01167 {\
01168     typedef TinyVector<T, SIZE> Type;\
01169     typedef TinyVector<NumericTraits<T>::Promote, SIZE> Promote;\
01170     typedef TinyVector<NumericTraits<T>::RealPromote, SIZE> RealPromote;\
01171     typedef TinyVector<NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;\
01172     typedef T ValueType; \
01173     typedef NumericTraits<T>::isIntegral isIntegral;\
01174     typedef VigraFalseType isScalar;\
01175     typedef NumericTraits<T>::isSigned isSigned; \
01176     typedef VigraFalseType isOrdered;\
01177     typedef VigraFalseType isComplex;\
01178     \
01179     static TinyVector<T, SIZE> zero() { \
01180         return TinyVector<T, SIZE>(NumericTraits<T>::zero()); \
01181     }\
01182     static TinyVector<T, SIZE> one() { \
01183         return TinyVector<T, SIZE>(NumericTraits<T>::one()); \
01184     }\
01185     static TinyVector<T, SIZE> nonZero() { \
01186         return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); \
01187     }\
01188     \
01189     static Promote toPromote(TinyVector<T, SIZE> const & v) { \
01190         return Promote(v); \
01191     }\
01192     static RealPromote toRealPromote(TinyVector<T, SIZE> const & v) { \
01193         return RealPromote(v); \
01194     }\
01195     static TinyVector<T, SIZE> fromPromote(Promote const & v) { \
01196         TinyVector<T, SIZE> res;\
01197         TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\
01198         Promote::const_iterator s = v.begin();\
01199         for(; d != dend; ++d, ++s)\
01200             *d = NumericTraits<T>::fromPromote(*s);\
01201         return res;\
01202     }\
01203     static TinyVector<T, SIZE> fromRealPromote(RealPromote const & v) {\
01204         TinyVector<T, SIZE> res;\
01205         TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\
01206         RealPromote::const_iterator s = v.begin();\
01207         for(; d != dend; ++d, ++s)\
01208             *d = NumericTraits<T>::fromRealPromote(*s);\
01209         return res;\
01210     }\
01211 }; \
01212 template<>\
01213 struct NormTraits<TinyVector<T, SIZE> >\
01214 {\
01215     typedef TinyVector<T, SIZE> Type;\
01216     typedef Type::SquaredNormType           SquaredNormType; \
01217     typedef Type::NormType NormType; \
01218 };
01219 
01220 #define TINYVECTOR_PROMTRAITS1(type1, SIZE) \
01221 template<> \
01222 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type1, SIZE> > \
01223 { \
01224     typedef TinyVector<PromoteTraits<type1, type1>::Promote, SIZE> Promote; \
01225     static Promote toPromote(TinyVector<type1, SIZE> const & v) { \
01226         return static_cast<Promote>(v); } \
01227 };
01228 
01229 #define TINYVECTOR_PROMTRAITS2(type1, type2, SIZE) \
01230 template<> \
01231 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type2, SIZE> > \
01232 { \
01233     typedef TinyVector<PromoteTraits<type1, type2>::Promote, SIZE> Promote; \
01234     static Promote toPromote(TinyVector<type1, SIZE> const & v) { \
01235         return static_cast<Promote>(v); } \
01236     static Promote toPromote(TinyVector<type2, SIZE> const & v) { \
01237        return static_cast<Promote>(v); } \
01238 };
01239 
01240 #define TINYVECTOR_TRAITS(SIZE) \
01241 TINYVECTOR_NUMTRAITS(unsigned char, SIZE)\
01242 TINYVECTOR_NUMTRAITS(int, SIZE)\
01243 TINYVECTOR_NUMTRAITS(float, SIZE)\
01244 TINYVECTOR_NUMTRAITS(double, SIZE)\
01245 TINYVECTOR_PROMTRAITS1(unsigned char, SIZE)\
01246 TINYVECTOR_PROMTRAITS1(int, SIZE)\
01247 TINYVECTOR_PROMTRAITS1(float, SIZE)\
01248 TINYVECTOR_PROMTRAITS1(double, SIZE)\
01249 TINYVECTOR_PROMTRAITS2(float, unsigned char, SIZE)\
01250 TINYVECTOR_PROMTRAITS2(unsigned char, float, SIZE)\
01251 TINYVECTOR_PROMTRAITS2(int, unsigned char, SIZE)\
01252 TINYVECTOR_PROMTRAITS2(unsigned char, int, SIZE)\
01253 TINYVECTOR_PROMTRAITS2(int, float, SIZE)\
01254 TINYVECTOR_PROMTRAITS2(float, int, SIZE)\
01255 TINYVECTOR_PROMTRAITS2(double, unsigned char, SIZE)\
01256 TINYVECTOR_PROMTRAITS2(unsigned char, double, SIZE)\
01257 TINYVECTOR_PROMTRAITS2(int, double, SIZE)\
01258 TINYVECTOR_PROMTRAITS2(double, int, SIZE)\
01259 TINYVECTOR_PROMTRAITS2(double, float, SIZE)\
01260 TINYVECTOR_PROMTRAITS2(float, double, SIZE)
01261 
01262 TINYVECTOR_TRAITS(2)
01263 TINYVECTOR_TRAITS(3)
01264 TINYVECTOR_TRAITS(4)
01265 
01266 #undef TINYVECTOR_NUMTRAITS
01267 #undef TINYVECTOR_PROMTRAITS1
01268 #undef TINYVECTOR_PROMTRAITS2
01269 #undef TINYVECTOR_TRAITS
01270 
01271 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01272 
01273 
01274 /********************************************************/
01275 /*                                                      */
01276 /*                      TinyVector-Arithmetic           */
01277 /*                                                      */
01278 /********************************************************/
01279 
01280 /** \addtogroup TinyVectorOperators
01281  */
01282 //@{
01283 
01284     /// component-wise addition
01285 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01286 inline
01287 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
01288 operator+(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01289           TinyVectorBase<V2, SIZE, D3, D4> const & r)
01290 {
01291     return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) += r;
01292 }
01293 
01294     /// component-wise subtraction
01295 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01296 inline
01297 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
01298 operator-(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01299           TinyVectorBase<V2, SIZE, D3, D4> const & r)
01300 {
01301     return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) -= r;
01302 }
01303 
01304     /// component-wise multiplication
01305 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01306 inline
01307 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
01308 operator*(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01309           TinyVectorBase<V2, SIZE, D3, D4> const & r)
01310 {
01311     return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) *= r;
01312 }
01313 
01314     /// component-wise division
01315 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01316 inline
01317 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
01318 operator/(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01319           TinyVectorBase<V2, SIZE, D3, D4> const & r)
01320 {
01321     return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) /= r;
01322 }
01323 
01324     /// component-wise left scalar multiplication
01325 template <class V, int SIZE, class D1, class D2>
01326 inline
01327 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
01328 operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r)
01329 {
01330     return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *= v;
01331 }
01332 
01333     /// component-wise right scalar multiplication
01334 template <class V, int SIZE, class D1, class D2>
01335 inline
01336 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
01337 operator*(TinyVectorBase<V, SIZE, D1, D2> const & l, double v)
01338 {
01339     return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) *= v;
01340 }
01341 
01342     /// component-wise scalar division
01343 template <class V, int SIZE, class D1, class D2>
01344 inline
01345 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
01346 operator/(TinyVectorBase<V, SIZE, D1, D2> const & l, double v)
01347 {
01348     return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) /= v;
01349 }
01350 
01351 
01352     /** Unary negation (construct TinyVector with negative values)
01353     */
01354 template <class V, int SIZE, class D1, class D2>
01355 inline
01356 TinyVector<V, SIZE>
01357 operator-(TinyVectorBase<V, SIZE, D1, D2> const & v)
01358 {
01359     TinyVector<V, SIZE> res(detail::dontInit());
01360     typedef typename detail::LoopType<SIZE>::type ltype;
01361     ltype::neg(res.begin(), v.begin());
01362     return res;
01363 }
01364 
01365     /// component-wise absolute value
01366 template <class V, int SIZE, class D1, class D2>
01367 inline
01368 TinyVector<V, SIZE>
01369 abs(TinyVectorBase<V, SIZE, D1, D2> const & v)
01370 {
01371     TinyVector<V, SIZE> res(detail::dontInit());
01372     typedef typename detail::LoopType<SIZE>::type ltype;
01373     ltype::abs(res.begin(), v.begin());
01374     return res;
01375 }
01376 
01377     /** Apply ceil() function to each vector component.
01378     */
01379 template <class V, int SIZE, class D1, class D2>
01380 inline
01381 TinyVector<V, SIZE>
01382 ceil(TinyVectorBase<V, SIZE, D1, D2> const & v)
01383 {
01384     TinyVector<V, SIZE> res(detail::dontInit());
01385     typedef typename detail::LoopType<SIZE>::type ltype;
01386     ltype::ceil(res.begin(), v.begin());
01387     return res;
01388 }
01389 
01390     /** Apply floor() function to each vector component.
01391     */
01392 template <class V, int SIZE, class D1, class D2>
01393 inline
01394 TinyVector<V, SIZE>
01395 floor(TinyVectorBase<V, SIZE, D1, D2> const & v)
01396 {
01397     TinyVector<V, SIZE> res(detail::dontInit());
01398     typedef typename detail::LoopType<SIZE>::type ltype;
01399     ltype::floor(res.begin(), v.begin());
01400     return res;
01401 }
01402 
01403     /// cross product
01404 template <class V1, class D1, class D2, class V2, class D3, class D4>
01405 inline
01406 TinyVector<typename PromoteTraits<V1, V2>::Promote, 3>
01407 cross(TinyVectorBase<V1, 3, D1, D2> const & r1,
01408       TinyVectorBase<V2, 3, D3, D4> const & r2)
01409 {
01410     typedef TinyVector<typename PromoteTraits<V1, V2>::Promote, 3>
01411             Res;
01412     return  Res(r1[1]*r2[2] - r1[2]*r2[1],
01413                 r1[2]*r2[0] - r1[0]*r2[2],
01414                 r1[0]*r2[1] - r1[1]*r2[0]);
01415 }
01416 
01417     /// dot product
01418 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01419 inline
01420 typename PromoteTraits<V1, V2>::Promote
01421 dot(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01422     TinyVectorBase<V2, SIZE, D3, D4> const & r)
01423 {
01424     typedef typename detail::LoopType<SIZE>::type ltype;
01425     return ltype::dot(l.begin(), r.begin());
01426 }
01427 
01428 
01429     /// squared norm
01430 template <class V1, int SIZE, class D1, class D2>
01431 inline
01432 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType
01433 squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t)
01434 {
01435     return t.squaredMagnitude();
01436 }
01437 
01438     /// squared norm
01439 template <class V, int SIZE>
01440 inline
01441 typename TinyVector<V, SIZE>::SquaredNormType
01442 squaredNorm(TinyVector<V, SIZE> const & t)
01443 {
01444     return t.squaredMagnitude();
01445 }
01446 //@}
01447 
01448 
01449 } // namespace vigra
01450 #undef VIGRA_ASSERT_INSIDE
01451 #endif // VIGRA_TINYVECTOR_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.7.0 (Thu Aug 25 2011)