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

vigra/tinyvector.hxx VIGRA

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 <algorithm>
00044 #include "config.hxx"
00045 #include "error.hxx"
00046 #include "metaprogramming.hxx"
00047 #include "numerictraits.hxx"
00048 #include "memory.hxx"
00049 #include "mathutil.hxx"
00050 #include "diff2d.hxx"
00051 
00052 #ifdef VIGRA_CHECK_BOUNDS
00053 #define VIGRA_ASSERT_INSIDE(diff) \
00054   vigra_precondition(diff >= 0, "Index out of bounds");\
00055   vigra_precondition(diff < SIZE, "Index out of bounds");
00056 #else
00057 #define VIGRA_ASSERT_INSIDE(diff)
00058 #endif
00059 
00060 namespace vigra {
00061 
00062 // mask cl.exe shortcomings [begin]
00063 #if defined(_MSC_VER)
00064 #pragma warning( push )
00065 #pragma warning( disable : 4503 )
00066 #endif
00067 
00068 using VIGRA_CSTD::abs;
00069 using VIGRA_CSTD::ceil;
00070 using VIGRA_CSTD::floor;
00071 using VIGRA_CSTD::sqrt;
00072 
00073 
00074 template <class V1, int SIZE, class D1, class D2>
00075 class TinyVectorBase;
00076 
00077 template <class V1, int SIZE, class D1, class D2>
00078 inline
00079 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType
00080 squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t);
00081 
00082 
00083 namespace detail {
00084 
00085 #define VIGRA_EXEC_LOOP(NAME, OPER) \
00086     template <class T1, class T2>  \
00087     static void NAME(T1 * left, T2 const * right)  \
00088     {  \
00089         for(int i=0; i<LEVEL; ++i)  \
00090             (left[i]) OPER (right[i]);  \
00091     }
00092 
00093 #define VIGRA_EXEC_LOOP_MINMAX(NAME, OPER) \
00094     template <class T1, class T2>  \
00095     static void NAME(T1 * left, T2 const * right)  \
00096     {  \
00097         for(int i=0; i<LEVEL; ++i)  \
00098             if(left[i] OPER right[i]) \
00099                 left[i] = right[i];  \
00100     }
00101 
00102 #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \
00103     template <class T1, class T2>  \
00104     static void NAME(T1 * left, T2 right)  \
00105     {  \
00106         for(int i=0; i<LEVEL; ++i)  \
00107             (left[i]) = detail::RequiresExplicitCast<T1>::cast((left[i]) OPER (right));  \
00108     }
00109 
00110 template <int LEVEL>
00111 struct ExecLoop
00112 {
00113     template <class T1, class T2>
00114     static void assignCast(T1 * left, T2 const * right)
00115     {
00116         for(int i=0; i<LEVEL; ++i)
00117             left[i] = detail::RequiresExplicitCast<T1>::cast(right[i]);
00118     }
00119 
00120     template <class T1, class T2>
00121     static void reverseAssign(T1 * left, T2 const * right)
00122     {
00123         for(int i=0; i<LEVEL; ++i)
00124             left[i] = right[-i];
00125     }
00126 
00127     template <class T1, class T2>
00128     static void assignScalar(T1 * left, T2 right)
00129     {
00130         for(int i=0; i<LEVEL; ++i)
00131             left[i] = detail::RequiresExplicitCast<T1>::cast(right);
00132     }
00133 
00134     template <class T1, class T2>
00135     static void power(T1 * left, T2 right)
00136     {
00137         for(int i=0; i<LEVEL; ++i)
00138             left[i] = detail::RequiresExplicitCast<T1>::cast(pow(left, right));
00139     }
00140 
00141     VIGRA_EXEC_LOOP(assign, =)
00142     VIGRA_EXEC_LOOP(add, +=)
00143     VIGRA_EXEC_LOOP(sub, -=)
00144     VIGRA_EXEC_LOOP(mul, *=)
00145     VIGRA_EXEC_LOOP(div, /=)
00146     VIGRA_EXEC_LOOP(neg, = -)
00147     VIGRA_EXEC_LOOP(abs, = vigra::abs)
00148     VIGRA_EXEC_LOOP(floor, = vigra::floor)
00149     VIGRA_EXEC_LOOP(ceil, = vigra::ceil)
00150     VIGRA_EXEC_LOOP(sqrt, = vigra::sqrt)
00151     VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
00152     VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
00153     VIGRA_EXEC_LOOP_SCALAR(mulScalar, *)
00154     VIGRA_EXEC_LOOP_SCALAR(divScalar, /)
00155     
00156     VIGRA_EXEC_LOOP_MINMAX(min, >)
00157     VIGRA_EXEC_LOOP_MINMAX(max, <)
00158 
00159     template <class T>
00160     static T const & minimum(T const * p)
00161     {
00162         return *std::min_element(p, p+LEVEL);
00163     }
00164 
00165     template <class T>
00166     static T const & maximum(T const * p)
00167     {
00168         return *std::max_element(p, p+LEVEL);
00169     }
00170 
00171     template <class T1, class T2>
00172     static bool notEqual(T1 const * left, T2 const * right)
00173     {
00174         for(int i=0; i<LEVEL; ++i)
00175             if(left[i] != right[i])
00176                 return true;
00177         return false;
00178     }
00179 
00180     template <class T1, class T2>
00181     static bool less(T1 const * left, T2 const * right)
00182     {
00183         for(int i=0; i<LEVEL; ++i)
00184         {
00185             if(left[i] < right[i])
00186                 return true;
00187             if(right[i] < left[i])
00188                 return false;
00189         }
00190         return false;
00191     }
00192     template <class T>
00193     static typename NumericTraits<T>::Promote
00194     dot(T const * d)
00195     {
00196         typename NumericTraits<T>::Promote  res(*d * *d);
00197         for(int i=1; i<LEVEL; ++i)
00198             res += d[i] * d[i];
00199         return res;
00200     }
00201 
00202     template <class T1, class T2>
00203     static typename PromoteTraits<T1, T2>::Promote
00204     dot(T1 const * left, T2 const * right)
00205     {
00206         typename PromoteTraits<T1, T2>::Promote res(*left * *right);
00207         for(int i=1; i<LEVEL; ++i)
00208             res += left[i] * right[i];
00209         return res;
00210     }
00211 
00212     template <class T>
00213     static typename NormTraits<T>::SquaredNormType
00214     squaredNorm(T const * d)
00215     {
00216         typename NormTraits<T>::SquaredNormType  res = vigra::squaredNorm(*d);
00217         for(int i=1; i<LEVEL; ++i)
00218             res += vigra::squaredNorm(d[i]);
00219         return res;
00220     }
00221 };
00222 
00223 template <int LEVEL>
00224 struct UnrollScalarResult
00225 {
00226     template <class T>
00227     static typename NumericTraits<T>::Promote
00228     dot(T const * d)
00229     {
00230         return *d * *d + UnrollScalarResult<LEVEL-1>::dot(d+1);
00231     }
00232 
00233     template <class T1, class T2>
00234     static typename PromoteTraits<T1, T2>::Promote
00235     dot(T1 const * left, T2 const * right)
00236     {
00237         return *left * *right + UnrollScalarResult<LEVEL-1>::dot(left+1, right+1);
00238     }
00239     
00240     template <class T>
00241     static typename NormTraits<T>::SquaredNormType
00242     squaredNorm(T const * d)
00243     {
00244         return vigra::squaredNorm(*d) + UnrollScalarResult<LEVEL-1>::squaredNorm(d+1);
00245     }
00246 
00247     static std::ptrdiff_t
00248     squaredNorm(std::ptrdiff_t const * d)
00249     {
00250         return (*d)*(*d) + UnrollScalarResult<LEVEL-1>::squaredNorm(d+1);
00251     }
00252     
00253     template <class T>
00254     static T const & minimum(T const * p)
00255     {
00256         T const & m = UnrollScalarResult<LEVEL - 1>::minimum(p+1);
00257         return *p < m
00258                     ? *p
00259                     : m;
00260     }
00261 
00262     template <class T>
00263     static T const & maximum(T const * p)
00264     {
00265         T const & m = UnrollScalarResult<LEVEL - 1>::maximum(p+1);
00266         return *p > m
00267                     ? *p
00268                     : m;
00269     }
00270 };
00271 
00272 template <>
00273 struct UnrollScalarResult<1>
00274 {
00275     template <class T>
00276     static typename NumericTraits<T>::Promote
00277     dot(T const * d)
00278     {
00279         return *d * *d ;
00280     }
00281 
00282     template <class T1, class T2>
00283     static typename PromoteTraits<T1, T2>::Promote
00284     dot(T1 const * left, T2 const * right)
00285     {
00286         return *left * *right;
00287     }
00288 
00289     template <class T>
00290     static typename NormTraits<T>::SquaredNormType
00291     squaredNorm(T const * d)
00292     {
00293         return vigra::squaredNorm(*d);
00294     }
00295 
00296     static std::ptrdiff_t
00297     squaredNorm(std::ptrdiff_t const * d)
00298     {
00299         return (*d)*(*d);
00300     }
00301 
00302     template <class T>
00303     static T const & minimum(T const * p)
00304     {
00305         return *p;
00306     }
00307 
00308     template <class T>
00309     static T const & maximum(T const * p)
00310     {
00311         return *p;
00312     }
00313 };
00314 
00315 #undef VIGRA_EXEC_LOOP
00316 #undef VIGRA_EXEC_LOOP_MINMAX
00317 #undef VIGRA_EXEC_LOOP_SCALAR
00318 
00319 #define VIGRA_UNROLL_LOOP(NAME, OPER) \
00320     template <class T1, class T2>  \
00321     static void NAME(T1 * left, T2 const * right)  \
00322     {  \
00323         (*left) OPER (*right);  \
00324         UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \
00325     }
00326 
00327 #define VIGRA_UNROLL_LOOP_MINMAX(NAME, OPER) \
00328     template <class T1, class T2>  \
00329     static void NAME(T1 * left, T2 const * right)  \
00330     {  \
00331         if(*left OPER *right) \
00332             *left = *right;  \
00333         UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \
00334     }
00335 
00336 #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \
00337     template <class T1, class T2>  \
00338     static void NAME(T1 * left, T2 right)  \
00339     {  \
00340         (*left) = detail::RequiresExplicitCast<T1>::cast((*left) OPER (right));  \
00341         UnrollLoop<LEVEL-1>::NAME(left+1, right); \
00342     }
00343 
00344 
00345 template <int LEVEL>
00346 struct UnrollLoop
00347 {
00348     template <class T1, class T2>
00349     static void reverseAssign(T1 * left, T2 const * right)
00350     {
00351         *left = *right;
00352         UnrollLoop<LEVEL-1>::reverseAssign(left+1, right-1);
00353     }
00354 
00355     template <class T1, class T2>
00356     static void assignCast(T1 * left, T2 const * right)
00357     {
00358         *left = detail::RequiresExplicitCast<T1>::cast(*right);
00359         UnrollLoop<LEVEL-1>::assignCast(left+1, right+1);
00360     }
00361 
00362     template <class T1, class T2>
00363     static void assignScalar(T1 * left, T2 right)
00364     {
00365         *left = detail::RequiresExplicitCast<T1>::cast(right);
00366         UnrollLoop<LEVEL-1>::assignScalar(left+1, right);
00367     }
00368 
00369     template <class T1, class T2>
00370     static void power(T1 * left, T2 right)
00371     {
00372         *left = detail::RequiresExplicitCast<T1>::cast(pow(*left, right));
00373         UnrollLoop<LEVEL-1>::power(left+1, right);
00374     }
00375 
00376     VIGRA_UNROLL_LOOP(assign, =)
00377     VIGRA_UNROLL_LOOP(add, +=)
00378     VIGRA_UNROLL_LOOP(sub, -=)
00379     VIGRA_UNROLL_LOOP(mul, *=)
00380     VIGRA_UNROLL_LOOP(div, /=)
00381     VIGRA_UNROLL_LOOP(neg, = -)
00382     VIGRA_UNROLL_LOOP(abs, = vigra::abs)
00383     VIGRA_UNROLL_LOOP(floor, = vigra::floor)
00384     VIGRA_UNROLL_LOOP(ceil, = vigra::ceil)
00385     VIGRA_UNROLL_LOOP(sqrt, = vigra::sqrt)
00386     VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
00387     VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
00388     VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *)
00389     VIGRA_UNROLL_LOOP_SCALAR(divScalar, /)
00390     
00391     VIGRA_UNROLL_LOOP_MINMAX(min, >)
00392     VIGRA_UNROLL_LOOP_MINMAX(max, <)
00393 
00394     template <class T>
00395     static T const & minimum(T const * p)
00396     {
00397         return UnrollScalarResult<LEVEL>::minimum(p);
00398     }
00399 
00400     template <class T>
00401     static T const & maximum(T const * p)
00402     {
00403         return UnrollScalarResult<LEVEL>::maximum(p);
00404     }
00405 
00406     template <class T1, class T2>
00407     static bool notEqual(T1 const * left, T2 const * right)
00408     {
00409         return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1);
00410     }
00411 
00412     template <class T1, class T2>
00413     static bool less(T1 const * left, T2 const * right)
00414     {
00415         if(*left < *right)
00416             return true;
00417         if(*right < *left)
00418             return false;
00419         return UnrollLoop<LEVEL - 1>::less(left+1, right+1);
00420     }
00421 
00422     template <class T>
00423     static typename NumericTraits<T>::Promote
00424     dot(T const * d)
00425     {
00426         return UnrollScalarResult<LEVEL>::dot(d);
00427     }
00428 
00429     template <class T1, class T2>
00430     static typename PromoteTraits<T1, T2>::Promote
00431     dot(T1 const * left, T2 const * right)
00432     {
00433         return UnrollScalarResult<LEVEL>::dot(left, right);
00434     }
00435 
00436     template <class T>
00437     static typename NormTraits<T>::SquaredNormType
00438     squaredNorm(T const * d)
00439     {
00440         return UnrollScalarResult<LEVEL>::squaredNorm(d);
00441     }
00442 };
00443 
00444 #undef VIGRA_UNROLL_LOOP
00445 #undef VIGRA_UNROLL_LOOP_MINMAX
00446 #undef VIGRA_UNROLL_LOOP_SCALAR
00447 
00448 template <>
00449 struct UnrollLoop<0>
00450 {
00451     template <class T1, class T2>
00452     static void reverseAssign(T1, T2) {}
00453     template <class T1, class T2>
00454     static void assignCast(T1, T2) {}
00455     template <class T1, class T2>
00456     static void assign(T1, T2) {}
00457     template <class T1, class T2>
00458     static void assignScalar(T1, T2) {}
00459     template <class T1, class T2>
00460     static void power(T1, T2) {}
00461     template <class T1, class T2>
00462     static void add(T1, T2) {}
00463     template <class T1, class T2>
00464     static void sub(T1, T2) {}
00465     template <class T1, class T2>
00466     static void mul(T1, T2) {}
00467     template <class T1, class T2>
00468     static void mulScalar(T1, T2) {}
00469     template <class T1, class T2>
00470     static void div(T1, T2) {}
00471     template <class T1, class T2>
00472     static void divScalar(T1, T2) {}
00473     template <class T1, class T2>
00474     static void fromPromote(T1, T2) {}
00475     template <class T1, class T2>
00476     static void fromRealPromote(T1, T2) {}
00477     template <class T1, class T2>
00478     static void neg(T1, T2) {}
00479     template <class T1, class T2>
00480     static void abs(T1, T2) {}
00481     template <class T1, class T2>
00482     static void floor(T1, T2) {}
00483     template <class T1, class T2>
00484     static void ceil(T1, T2) {}
00485     template <class T1, class T2>
00486     static void sqrt(T1, T2) {}
00487     template <class T1, class T2>
00488     static bool notEqual(T1, T2) { return false; }
00489     template <class T1, class T2>
00490     static bool less(T1, T2) { return false; }
00491     template <class T1, class T2>
00492     static void min(T1, T2) {}
00493     template <class T1, class T2>
00494     static void max(T1, T2) {}
00495     template <class T>
00496     static T minimum(T const * p)
00497     {
00498         return NumericTraits<T>::max();
00499     }
00500     template <class T>
00501     static T maximum(T const * p)
00502     {
00503         return NumericTraits<T>::min();
00504     }
00505 };
00506 
00507 template <int SIZE>
00508 struct LoopType
00509 {
00510     typedef typename IfBool<(SIZE <= 5), UnrollLoop<SIZE>, ExecLoop<SIZE> >::type type;
00511 
00512 };
00513 
00514 struct DontInit {};
00515 
00516 inline DontInit dontInit() {return DontInit(); }
00517 
00518 } // namespace detail
00519 
00520 template <class T, int SIZE>
00521 class TinyVector;
00522 
00523 template <class T, int SIZE>
00524 class TinyVectorView;
00525 
00526 /********************************************************/
00527 /*                                                      */
00528 /*                    TinyVectorBase                    */
00529 /*                                                      */
00530 /********************************************************/
00531 
00532 /** \brief Base class for fixed size vectors.
00533 
00534     This class contains functionality shared by
00535     \ref TinyVector and \ref TinyVectorView, and enables these classes
00536     to be freely mixed within expressions. It is typically not used directly.
00537 
00538     <b>\#include</b> <vigra/tinyvector.hxx><br>
00539     Namespace: vigra
00540 **/
00541 template <class VALUETYPE, int SIZE, class DATA, class DERIVED>
00542 class TinyVectorBase
00543 {
00544     TinyVectorBase(TinyVectorBase const &); // do not use
00545 
00546     TinyVectorBase & operator=(TinyVectorBase const & other); // do not use
00547 
00548   protected:
00549 
00550     typedef typename detail::LoopType<SIZE>::type Loop;
00551 
00552     TinyVectorBase()
00553     {}
00554 
00555   public:
00556         /** STL-compatible definition of valuetype
00557         */
00558     typedef VALUETYPE value_type;
00559 
00560         /** reference (return of operator[]).
00561         */
00562     typedef VALUETYPE & reference;
00563 
00564         /** const reference (return of operator[] const).
00565         */
00566     typedef VALUETYPE const & const_reference;
00567 
00568         /** pointer (return of operator->).
00569         */
00570     typedef VALUETYPE * pointer;
00571 
00572         /** const pointer (return of operator-> const).
00573         */
00574     typedef VALUETYPE const * const_pointer;
00575 
00576         /** STL-compatible definition of iterator
00577         */
00578     typedef value_type * iterator;
00579 
00580         /** STL-compatible definition of const iterator
00581         */
00582     typedef value_type const * const_iterator;
00583 
00584         /** STL-compatible definition of size_type
00585         */
00586     typedef unsigned int size_type;
00587 
00588         /** STL-compatible definition of difference_type
00589         */
00590     typedef std::ptrdiff_t difference_type;
00591 
00592         /** the scalar type for the outer product
00593         */
00594     typedef double scalar_multiplier;
00595 
00596         /** the vector's squared norm type
00597         */
00598     typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType;
00599 
00600         /** the vector's norm type
00601         */
00602     typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType;
00603 
00604         /** the vector's size
00605         */
00606     enum { static_size = SIZE };
00607 
00608         /** Initialize from another sequence (must have length SIZE!)
00609         */
00610     template <class Iterator>
00611     void init(Iterator i, Iterator end)
00612     {
00613         vigra_precondition(end-i == SIZE,
00614             "TinyVector::init(): Sequence has wrong size.");
00615         Loop::assignCast(data_, i);
00616     }
00617 
00618         /** Initialize with constant value
00619         */
00620     void init(value_type initial)
00621     {
00622         Loop::assignScalar(data_, initial);
00623     }
00624 
00625         /** Component-wise add-assignment
00626         */
00627     template <class T1, class D1, class D2>
00628     DERIVED & operator+=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
00629     {
00630         Loop::add(data_, r.begin());
00631         return static_cast<DERIVED &>(*this);
00632     }
00633 
00634         /** Component-wise subtract-assignment
00635         */
00636     template <class T1, class D1, class D2>
00637     DERIVED & operator-=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
00638     {
00639         Loop::sub(data_, r.begin());
00640         return static_cast<DERIVED &>(*this);
00641     }
00642 
00643         /** Component-wise multiply-assignment
00644         */
00645     template <class T1, class D1, class D2>
00646     DERIVED & operator*=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
00647     {
00648         Loop::mul(data_, r.begin());
00649         return static_cast<DERIVED &>(*this);
00650     }
00651 
00652         /** Component-wise divide-assignment
00653         */
00654     template <class T1, class D1, class D2>
00655     DERIVED & operator/=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
00656     {
00657         Loop::div(data_, r.begin());
00658         return static_cast<DERIVED &>(*this);
00659     }
00660 
00661         /** Component-wise scalar multiply-assignment
00662         */
00663     DERIVED & operator*=(double r)
00664     {
00665         Loop::mulScalar(data_, r);
00666         return static_cast<DERIVED &>(*this);
00667     }
00668 
00669         /** Component-wise scalar divide-assignment
00670         */
00671     DERIVED & operator/=(double r)
00672     {
00673         Loop::divScalar(data_, r);
00674         return static_cast<DERIVED &>(*this);
00675     }
00676 
00677         /** Calculate magnitude.
00678         */
00679     NormType magnitude() const
00680     {
00681          return sqrt(static_cast<typename
00682               SquareRootTraits<SquaredNormType>::SquareRootArgument>(squaredMagnitude()));
00683     }
00684 
00685         /** Calculate squared magnitude.
00686         */
00687     SquaredNormType squaredMagnitude() const
00688     {
00689         return Loop::squaredNorm(data_);
00690     }
00691 
00692         /** Return the minimal element.
00693         */
00694     VALUETYPE const & minimum() const
00695     {
00696         return Loop::minimum(data_);
00697     }
00698 
00699         /** Return the maximal element.
00700         */
00701     VALUETYPE const & maximum() const
00702     {
00703         return Loop::maximum(data_);
00704     }
00705 
00706         /** Access component by index.
00707         */
00708     reference operator[](difference_type i)
00709     {
00710         VIGRA_ASSERT_INSIDE(i);
00711         return data_[i];
00712     }
00713 
00714         /** Get component by index.
00715         */
00716     const_reference operator[](difference_type i) const
00717     {
00718         VIGRA_ASSERT_INSIDE(i);
00719         return data_[i];
00720     }
00721 
00722         /** Get random access iterator to begin of vector.
00723         */
00724     iterator begin() { return data_; }
00725         /** Get random access iterator past-the-end of vector.
00726         */
00727     iterator end() { return data_ + SIZE; }
00728 
00729         /** Get const random access iterator to begin of vector.
00730         */
00731     const_iterator begin() const { return data_; }
00732 
00733         /** Get const random access iterator past-the-end of vector.
00734         */
00735     const_iterator end() const { return data_ + SIZE; }
00736 
00737         /** Size of TinyVector vector always equals the template parameter SIZE.
00738         */
00739     size_type size() const { return SIZE; }
00740 
00741     pointer data() { return data_; }
00742 
00743     const_pointer data() const { return data_; }
00744 
00745   protected:
00746   
00747     DATA data_;
00748 };
00749 
00750 /** \brief Class for fixed size vectors.
00751     \ingroup RangesAndPoints
00752 
00753     This class contains an array of size SIZE of the specified VALUETYPE.
00754     The interface conforms to STL vector, except that there are no functions
00755     that change the size of a TinyVector.
00756 
00757     \ref TinyVectorOperators "Arithmetic operations"
00758     on TinyVectors are defined as component-wise applications of these
00759     operations. Addition and subtraction of two TinyVectors
00760     (+=, -=, +, -, unary -), multiplication and division of an
00761     TinyVector with a double, and NumericTraits/PromoteTraits are defined,
00762     so that TinyVector fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra".
00763 
00764     VIGRA algorithms typically use \ref vigra::VectorAccessor to access
00765     TinyVectors as a whole, or specific components of them.
00766 
00767     See also:<br>
00768     <UL style="list-style-image:url(documents/bullet.gif)">
00769         <LI> \ref vigra::TinyVectorBase
00770         <LI> \ref vigra::TinyVectorView
00771         <LI> \ref TinyVectorTraits
00772         <LI> \ref TinyVectorOperators
00773     </UL>
00774 
00775     <b>\#include</b> <vigra/tinyvector.hxx><br>
00776     Namespace: vigra
00777 **/
00778 template <class T, int SIZE>
00779 class TinyVector
00780 : public TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> >
00781 {
00782     typedef TinyVectorBase<T, SIZE, T[SIZE], TinyVector<T, SIZE> > BaseType;
00783     typedef typename BaseType::Loop Loop;
00784 
00785   public:
00786 
00787     typedef typename BaseType::value_type value_type;
00788     typedef typename BaseType::reference reference;
00789     typedef typename BaseType::const_reference const_reference;
00790     typedef typename BaseType::pointer pointer;
00791     typedef typename BaseType::const_pointer const_pointer;
00792     typedef typename BaseType::iterator iterator;
00793     typedef typename BaseType::const_iterator const_iterator;
00794     typedef typename BaseType::size_type size_type;
00795     typedef typename BaseType::difference_type difference_type;
00796     typedef typename BaseType::scalar_multiplier scalar_multiplier;
00797     typedef typename BaseType::SquaredNormType SquaredNormType;
00798     typedef typename BaseType::NormType NormType;
00799     
00800     enum ReverseCopyTag { ReverseCopy };
00801 
00802         /** Construction with constant value.
00803         
00804             Initializes all vector elements with the given value.
00805         */
00806     explicit TinyVector(value_type const & initial)
00807     : BaseType()
00808     {
00809         Loop::assignScalar(BaseType::begin(), initial);
00810     }
00811 
00812         /** Construction with Diff2D.
00813         
00814             Use only when <tt>SIZE == 2</tt>.
00815         */
00816     explicit TinyVector(Diff2D const & initial)
00817     : BaseType()
00818     {
00819         BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial.x);
00820         BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial.y);
00821     }
00822 
00823         /** Construction with explicit values.
00824             Call only if SIZE == 2
00825         */
00826     TinyVector(value_type const & i1, value_type const & i2)
00827     : BaseType()
00828     {
00829         BaseType::data_[0] = i1;
00830         BaseType::data_[1] = i2;
00831     }
00832 
00833         /** Construction with explicit values.
00834             Call only if SIZE == 3
00835         */
00836     TinyVector(value_type const & i1, value_type const & i2, value_type const & i3)
00837     : BaseType()
00838     {
00839         BaseType::data_[0] = i1;
00840         BaseType::data_[1] = i2;
00841         BaseType::data_[2] = i3;
00842     }
00843 
00844         /** Construction with explicit values.
00845             Call only if SIZE == 4
00846         */
00847     TinyVector(value_type const & i1, value_type const & i2,
00848                value_type const & i3, value_type const & i4)
00849     : BaseType()
00850     {
00851         BaseType::data_[0] = i1;
00852         BaseType::data_[1] = i2;
00853         BaseType::data_[2] = i3;
00854         BaseType::data_[3] = i4;
00855     }
00856 
00857         /** Construction with explicit values.
00858             Call only if SIZE == 5
00859         */
00860     TinyVector(value_type const & i1, value_type const & i2,
00861                value_type const & i3, value_type const & i4,
00862                value_type const & i5)
00863     : BaseType()
00864     {
00865         BaseType::data_[0] = i1;
00866         BaseType::data_[1] = i2;
00867         BaseType::data_[2] = i3;
00868         BaseType::data_[3] = i4;
00869         BaseType::data_[4] = i5;
00870     }
00871     
00872        /** Default constructor (initializes all elements with zero).
00873         */
00874     TinyVector()
00875     : BaseType()
00876     {
00877         Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero());
00878     }
00879 
00880         /** Construct without initializing the vector elements.
00881         */
00882     explicit TinyVector(SkipInitializationTag)
00883     : BaseType()
00884     {}
00885 
00886     explicit TinyVector(detail::DontInit)
00887     : BaseType()
00888     {}
00889 
00890         /** Copy constructor.
00891         */
00892     TinyVector(TinyVector const & r)
00893     : BaseType()
00894     {
00895         Loop::assign(BaseType::data_, r.data_);
00896     }
00897 
00898         /** Constructor from C array.
00899         */
00900     explicit TinyVector(const_pointer data)
00901     : BaseType()
00902     {
00903         Loop::assign(BaseType::data_, data);
00904     }
00905 
00906         /** Constructor by reverse copy from C array.
00907             
00908             Usage:
00909             \code
00910             TinyVector<int, 3> v(1,2,3);
00911             TinyVector<int, 3> reverse(v.begin(), TinyVector<int, 3>::ReverseCopy);
00912             \endcode
00913         */
00914     explicit TinyVector(const_pointer data, ReverseCopyTag)
00915     : BaseType()
00916     {
00917         Loop::reverseAssign(BaseType::data_, data+SIZE-1);
00918     }
00919 
00920         /** Copy with type conversion.
00921         */
00922     template <class U, class DATA, class DERIVED>
00923     TinyVector(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r)
00924     : BaseType()
00925     {
00926         Loop::assignCast(BaseType::data_, r.begin());
00927     }
00928 
00929         /** Copy assignment.
00930         */
00931     TinyVector & operator=(TinyVector const & r)
00932     {
00933         Loop::assign(BaseType::data_, r.data_);
00934         return *this;
00935     }
00936 
00937         /** Copy assignment with type conversion.
00938         */
00939     template <class U, class DATA, class DERIVED>
00940     TinyVector & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r)
00941     {
00942         Loop::assignCast(BaseType::data_, r.begin());
00943         return *this;
00944     }
00945 
00946         /** Assignment from Diff2D.
00947         
00948             Use only when <tt>SIZE == 2</tt>.
00949         */
00950     TinyVector & operator=(Diff2D const & r)
00951     {
00952         BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(r.x);
00953         BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(r.y);
00954         return *this;
00955     }
00956 
00957         /** Assignment from scalar. Will set all entries to the given value.
00958         */
00959     TinyVector & operator=(value_type const & v)
00960     {
00961         Loop::assignScalar(BaseType::begin(), v);
00962         return *this;
00963     }
00964 
00965         /** Copy from a TinyVector with a different number of elements.
00966         
00967             Only the first <tt>min(SIZE, USIZE)</tt> elements are copied.
00968         */
00969     template <class U, int USIZE, class DATA, class DERIVED>
00970     TinyVector & copy(TinyVectorBase<U, USIZE, DATA, DERIVED> const & r)
00971     {
00972         static const int minSize = USIZE < SIZE
00973                                         ? USIZE
00974                                         : SIZE;
00975         
00976         typedef typename detail::LoopType<minSize>::type MinLoop;
00977         MinLoop::assignCast(BaseType::data_, r.begin());
00978         return *this;
00979     }
00980 };
00981 
00982 /** \brief Wrapper for fixed size vectors.
00983 
00984     This class wraps an array of size SIZE of the specified VALUETYPE.
00985     Thus, the array can be accessed with an interface similar to
00986     that of std::vector (except that there are no functions
00987     that change the size of a TinyVectorView). The TinyVectorView
00988     does <em>not</em> assume ownership of the given memory.
00989 
00990     \ref TinyVectorOperators "Arithmetic operations"
00991     on TinyVectorViews are defined as component-wise applications of these
00992     operations. Addition and subtraction of two TinyVectorViews
00993     (+=, -=, +, -, unary -), multiplication and division of an
00994     TinyVectorViews with a double, and NumericTraits/PromoteTraits are defined,
00995     so that TinyVectorView fulfills the requirements of \ref LinearAlgebraConcept "Linear Algebra".
00996 
00997     VIGRA algorithms typically use \ref vigra::VectorAccessor to access
00998     TinyVectorViews as a whole, or specific components of them.
00999 
01000     <b>See also:</b>
01001     <ul>
01002         <li> \ref vigra::TinyVectorBase
01003         <li> \ref vigra::TinyVector
01004         <li> \ref TinyVectorTraits
01005         <li> \ref TinyVectorOperators
01006     </ul>
01007 
01008     <b>\#include</b> <vigra/tinyvector.hxx><br>
01009     Namespace: vigra
01010 **/
01011 template <class T, int SIZE>
01012 class TinyVectorView
01013 : public TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> >
01014 {
01015     typedef TinyVectorBase<T, SIZE, T *, TinyVectorView<T, SIZE> > BaseType;
01016     typedef typename BaseType::Loop Loop;
01017 
01018   public:
01019 
01020     typedef typename BaseType::value_type value_type;
01021     typedef typename BaseType::reference reference;
01022     typedef typename BaseType::const_reference const_reference;
01023     typedef typename BaseType::pointer pointer;
01024     typedef typename BaseType::const_pointer const_pointer;
01025     typedef typename BaseType::iterator iterator;
01026     typedef typename BaseType::const_iterator const_iterator;
01027     typedef typename BaseType::size_type size_type;
01028     typedef typename BaseType::difference_type difference_type;
01029     typedef typename BaseType::scalar_multiplier scalar_multiplier;
01030     typedef typename BaseType::SquaredNormType SquaredNormType;
01031     typedef typename BaseType::NormType NormType;
01032 
01033         /** Default constructor
01034             (pointer to wrapped data is NULL).
01035         */
01036     TinyVectorView()
01037     : BaseType()
01038     {
01039         BaseType::data_ = 0;
01040     }
01041 
01042         /** Construct view for given data array
01043         */
01044     TinyVectorView(const_pointer data)
01045     : BaseType()
01046     {
01047         BaseType::data_ = const_cast<pointer>(data);
01048     }
01049 
01050         /** Copy constructor (shallow copy).
01051         */
01052     TinyVectorView(TinyVectorView const & other)
01053     : BaseType()
01054     {
01055         BaseType::data_ = const_cast<pointer>(other.data_);
01056     }
01057 
01058         /** Construct view from other TinyVector.
01059         */
01060     template <class DATA, class DERIVED>
01061     TinyVectorView(TinyVectorBase<T, SIZE, DATA, DERIVED> const & other)
01062     : BaseType()
01063     {
01064         BaseType::data_ = const_cast<pointer>(other.data());
01065     }
01066 
01067         /** Copy the data (not the pointer) of the rhs.
01068         */
01069    TinyVectorView & operator=(TinyVectorView const & r)
01070     {
01071         Loop::assign(BaseType::data_, r.begin());
01072         return *this;
01073     }
01074 
01075         /** Copy the data of the rhs with cast.
01076         */
01077     template <class U, class DATA, class DERIVED>
01078     TinyVectorView & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r)
01079     {
01080         Loop::assignCast(BaseType::data_, r.begin());
01081         return *this;
01082     }
01083 };
01084 
01085 /********************************************************/
01086 /*                                                      */
01087 /*                     TinyVector Comparison            */
01088 /*                                                      */
01089 /********************************************************/
01090 
01091 /** \addtogroup TinyVectorOperators Functions for TinyVector
01092 
01093     \brief Implement basic arithmetic and equality for TinyVector.
01094 
01095     These functions fulfill the requirements of a Linear Space (vector space).
01096     Return types are determined according to \ref TinyVectorTraits.
01097 
01098     <b>\#include</b> <vigra/tinyvector.hxx><br>
01099     Namespace: vigra
01100 */
01101 //@{
01102     /// component-wise equal
01103 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01104 inline bool
01105 operator==(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01106            TinyVectorBase<V2, SIZE, D3, D4> const & r)
01107 {
01108     return !(l != r);
01109 }
01110 
01111     /// component-wise not equal
01112 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01113 inline bool
01114 operator!=(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01115            TinyVectorBase<V2, SIZE, D3, D4> const & r)
01116 {
01117     typedef typename detail::LoopType<SIZE>::type ltype;
01118     return ltype::notEqual(l.begin(), r.begin());
01119 }
01120 
01121     /// component-wise lexicographical comparison
01122 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01123 inline bool
01124 operator<(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01125           TinyVectorBase<V2, SIZE, D3, D4> const & r)
01126 {
01127     typedef typename detail::LoopType<SIZE>::type ltype;
01128     return ltype::less(l.begin(), r.begin());
01129 }
01130 
01131 /********************************************************/
01132 /*                                                      */
01133 /*                     TinyVector Output                */
01134 /*                                                      */
01135 /********************************************************/
01136 
01137     /// stream output
01138 template <class V1, int SIZE, class DATA, class DERIVED>
01139 std::ostream &
01140 operator<<(std::ostream & out, TinyVectorBase<V1, SIZE, DATA, DERIVED> const & l)
01141 {
01142     out << "(";
01143     int i;
01144     for(i=0; i<SIZE-1; ++i)
01145         out << l[i] << ", ";
01146     out << l[i] << ")";
01147     return out;
01148 }
01149 //@}
01150 
01151 /********************************************************/
01152 /*                                                      */
01153 /*                      TinyVector-Traits               */
01154 /*                                                      */
01155 /********************************************************/
01156 
01157 /** \page TinyVectorTraits Numeric and Promote Traits of TinyVector
01158     The numeric and promote traits for TinyVectors follow
01159     the general specifications for \ref NumericPromotionTraits.
01160     They are implemented in terms of the traits of the basic types by
01161     partial template specialization:
01162 
01163     \code
01164 
01165     template <class T, int SIZE>
01166     struct NumericTraits<TinyVector<T, SIZE> >
01167     {
01168         typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
01169         typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
01170 
01171         typedef typename NumericTraits<T>::isIntegral isIntegral;
01172         typedef VigraFalseType isScalar;
01173         typedef typename NumericTraits<T>::isSigned isSigned;
01174 
01175         // etc.
01176     };
01177 
01178     template <class T, int SIZE>
01179     struct NormTraits<TinyVector<T, SIZE> >
01180     {
01181         typedef TinyVector<T, SIZE> Type;
01182         typedef typename Type::SquaredNormType    SquaredNormType;
01183         typedef typename Type::NormType           NormType;
01184     };
01185 
01186     template <class T1, class T2, SIZE>
01187     struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> >
01188     {
01189         typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
01190     };
01191     \endcode
01192 
01193     <b>\#include</b> <vigra/tinyvector.hxx><br>
01194     Namespace: vigra
01195 
01196     On compilers that don't support partial template specialization (e.g.
01197     MS VisualC++), the traits classes are explicitly specialized for
01198     <TT>TinyVector<VALUETYPE, SIZE></TT> with
01199     <TT>VALUETYPE = unsigned char | int | float | double</TT> and <TT>SIZE = 2 | 3 | 4</TT>.
01200 
01201 */
01202 
01203 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION)
01204 
01205 template <class T, int SIZE>
01206 struct NumericTraits<TinyVector<T, SIZE> >
01207 {
01208     typedef TinyVector<T, SIZE> Type;
01209     typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
01210     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
01211     typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;
01212     typedef T ValueType;
01213 
01214     typedef typename NumericTraits<T>::isIntegral isIntegral;
01215     typedef VigraFalseType isScalar;
01216     typedef typename NumericTraits<T>::isSigned isSigned;
01217     typedef VigraTrueType isOrdered;
01218     typedef VigraFalseType isComplex;
01219 
01220     static TinyVector<T, SIZE> zero()
01221     {
01222         return TinyVector<T, SIZE>(NumericTraits<T>::zero());
01223     }
01224     static TinyVector<T, SIZE> one()
01225     {
01226         return TinyVector<T, SIZE>(NumericTraits<T>::one());
01227     }
01228     static TinyVector<T, SIZE> nonZero()
01229     {
01230         return TinyVector<T, SIZE>(NumericTraits<T>::nonZero());
01231     }
01232 
01233     static TinyVector<T, SIZE> min()
01234     {
01235         return TinyVector<T, SIZE>(NumericTraits<T>::min());
01236     }
01237     static TinyVector<T, SIZE> max()
01238     {
01239         return TinyVector<T, SIZE>(NumericTraits<T>::max());
01240     }
01241 
01242     template <class D1, class D2>
01243     static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
01244     {
01245         return Promote(v);
01246     }
01247 
01248     template <class D1, class D2>
01249     static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
01250     {
01251         return RealPromote(v);
01252     }
01253 
01254     template <class D1, class D2>
01255     static TinyVector<T, SIZE>
01256     fromPromote(TinyVectorBase<typename NumericTraits<T>::Promote, SIZE, D1, D2> const & v)
01257     {
01258         TinyVector<T, SIZE> res(detail::dontInit());
01259         typedef typename detail::LoopType<SIZE>::type ltype;
01260         ltype::fromPromote(res.begin(), v.begin());
01261         return res;
01262     }
01263 
01264     template <class D1, class D2>
01265     static TinyVector<T, SIZE>
01266     fromRealPromote(TinyVectorBase<typename NumericTraits<T>::RealPromote, SIZE, D1, D2> const & v)
01267     {
01268         TinyVector<T, SIZE> res(detail::dontInit());
01269         typedef typename detail::LoopType<SIZE>::type ltype;
01270         ltype::fromRealPromote(res.begin(), v.begin());
01271         return res;
01272     }
01273 };
01274 
01275 template <class T, int SIZE>
01276 struct NumericTraits<TinyVectorView<T, SIZE> >
01277 : public NumericTraits<TinyVector<T, SIZE> >
01278 {
01279     typedef TinyVector<T, SIZE> Type;
01280     typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
01281     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPromote;
01282     typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;
01283     typedef T ValueType;
01284 
01285     typedef typename NumericTraits<T>::isIntegral isIntegral;
01286     typedef VigraFalseType isScalar;
01287     typedef typename NumericTraits<T>::isSigned isSigned;
01288     typedef VigraFalseType isOrdered;
01289     typedef VigraFalseType isComplex;
01290 };
01291 
01292 template <class T, int SIZE>
01293 struct NormTraits<TinyVector<T, SIZE> >
01294 {
01295     typedef TinyVector<T, SIZE> Type;
01296     typedef typename Type::SquaredNormType    SquaredNormType;
01297     typedef typename Type::NormType           NormType;
01298 };
01299 
01300 template <class T, int SIZE>
01301 struct NormTraits<TinyVectorView<T, SIZE> >
01302 {
01303     typedef TinyVector<T, SIZE> Type;
01304     typedef typename Type::SquaredNormType    SquaredNormType;
01305     typedef typename Type::NormType           NormType;
01306 };
01307 
01308 template <class T1, class T2, int SIZE>
01309 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVector<T2, SIZE> >
01310 {
01311     typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
01312 };
01313 
01314 template <class T1, class T2, int SIZE>
01315 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVectorView<T2, SIZE> >
01316 {
01317     typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
01318 };
01319 
01320 template <class T1, class T2, int SIZE>
01321 struct PromoteTraits<TinyVectorView<T1, SIZE>, TinyVector<T2, SIZE> >
01322 {
01323     typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
01324 };
01325 
01326 template <class T1, class T2, int SIZE>
01327 struct PromoteTraits<TinyVector<T1, SIZE>, TinyVectorView<T2, SIZE> >
01328 {
01329     typedef TinyVector<typename PromoteTraits<T1, T2>::Promote, SIZE> Promote;
01330 };
01331 
01332 template <class T, int SIZE>
01333 struct PromoteTraits<TinyVector<T, SIZE>, double >
01334 {
01335     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
01336 };
01337 
01338 template <class T, int SIZE>
01339 struct PromoteTraits<double, TinyVector<T, SIZE> >
01340 {
01341     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
01342 };
01343 
01344 template <class T, int SIZE>
01345 struct PromoteTraits<TinyVectorView<T, SIZE>, double >
01346 {
01347     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
01348 };
01349 
01350 template <class T, int SIZE>
01351 struct PromoteTraits<double, TinyVectorView<T, SIZE> >
01352 {
01353     typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promote;
01354 };
01355 
01356 template<class T, int SIZE>
01357 struct CanSkipInitialization<TinyVectorView<T, SIZE> >
01358 {
01359     typedef typename CanSkipInitialization<T>::type type;
01360     static const bool value = type::asBool;
01361 };
01362 
01363 template<class T, int SIZE>
01364 struct CanSkipInitialization<TinyVector<T, SIZE> >
01365 {
01366     typedef typename CanSkipInitialization<T>::type type;
01367     static const bool value = type::asBool;
01368 };
01369 
01370 
01371 
01372 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01373 
01374 
01375 #define TINYVECTOR_NUMTRAITS(T, SIZE) \
01376 template<>\
01377 struct NumericTraits<TinyVector<T, SIZE> >\
01378 {\
01379     typedef TinyVector<T, SIZE> Type;\
01380     typedef TinyVector<NumericTraits<T>::Promote, SIZE> Promote;\
01381     typedef TinyVector<NumericTraits<T>::RealPromote, SIZE> RealPromote;\
01382     typedef TinyVector<NumericTraits<T>::ComplexPromote, SIZE> ComplexPromote;\
01383     typedef T ValueType; \
01384     typedef NumericTraits<T>::isIntegral isIntegral;\
01385     typedef VigraFalseType isScalar;\
01386     typedef NumericTraits<T>::isSigned isSigned; \
01387     typedef VigraFalseType isOrdered;\
01388     typedef VigraFalseType isComplex;\
01389     \
01390     static TinyVector<T, SIZE> zero() { \
01391         return TinyVector<T, SIZE>(NumericTraits<T>::zero()); \
01392     }\
01393     static TinyVector<T, SIZE> one() { \
01394         return TinyVector<T, SIZE>(NumericTraits<T>::one()); \
01395     }\
01396     static TinyVector<T, SIZE> nonZero() { \
01397         return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); \
01398     }\
01399     \
01400     static Promote toPromote(TinyVector<T, SIZE> const & v) { \
01401         return Promote(v); \
01402     }\
01403     static RealPromote toRealPromote(TinyVector<T, SIZE> const & v) { \
01404         return RealPromote(v); \
01405     }\
01406     static TinyVector<T, SIZE> fromPromote(Promote const & v) { \
01407         TinyVector<T, SIZE> res;\
01408         TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\
01409         Promote::const_iterator s = v.begin();\
01410         for(; d != dend; ++d, ++s)\
01411             *d = NumericTraits<T>::fromPromote(*s);\
01412         return res;\
01413     }\
01414     static TinyVector<T, SIZE> fromRealPromote(RealPromote const & v) {\
01415         TinyVector<T, SIZE> res;\
01416         TinyVector<T, SIZE>::iterator d = res.begin(), dend = res.end();\
01417         RealPromote::const_iterator s = v.begin();\
01418         for(; d != dend; ++d, ++s)\
01419             *d = NumericTraits<T>::fromRealPromote(*s);\
01420         return res;\
01421     }\
01422 }; \
01423 template<>\
01424 struct NormTraits<TinyVector<T, SIZE> >\
01425 {\
01426     typedef TinyVector<T, SIZE> Type;\
01427     typedef Type::SquaredNormType           SquaredNormType; \
01428     typedef Type::NormType NormType; \
01429 };
01430 
01431 #define TINYVECTOR_PROMTRAITS1(type1, SIZE) \
01432 template<> \
01433 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type1, SIZE> > \
01434 { \
01435     typedef TinyVector<PromoteTraits<type1, type1>::Promote, SIZE> Promote; \
01436     static Promote toPromote(TinyVector<type1, SIZE> const & v) { \
01437         return static_cast<Promote>(v); } \
01438 };
01439 
01440 #define TINYVECTOR_PROMTRAITS2(type1, type2, SIZE) \
01441 template<> \
01442 struct PromoteTraits<TinyVector<type1, SIZE>, TinyVector<type2, SIZE> > \
01443 { \
01444     typedef TinyVector<PromoteTraits<type1, type2>::Promote, SIZE> Promote; \
01445     static Promote toPromote(TinyVector<type1, SIZE> const & v) { \
01446         return static_cast<Promote>(v); } \
01447     static Promote toPromote(TinyVector<type2, SIZE> const & v) { \
01448        return static_cast<Promote>(v); } \
01449 };
01450 
01451 #define TINYVECTOR_TRAITS(SIZE) \
01452 TINYVECTOR_NUMTRAITS(unsigned char, SIZE)\
01453 TINYVECTOR_NUMTRAITS(int, SIZE)\
01454 TINYVECTOR_NUMTRAITS(float, SIZE)\
01455 TINYVECTOR_NUMTRAITS(double, SIZE)\
01456 TINYVECTOR_PROMTRAITS1(unsigned char, SIZE)\
01457 TINYVECTOR_PROMTRAITS1(int, SIZE)\
01458 TINYVECTOR_PROMTRAITS1(float, SIZE)\
01459 TINYVECTOR_PROMTRAITS1(double, SIZE)\
01460 TINYVECTOR_PROMTRAITS2(float, unsigned char, SIZE)\
01461 TINYVECTOR_PROMTRAITS2(unsigned char, float, SIZE)\
01462 TINYVECTOR_PROMTRAITS2(int, unsigned char, SIZE)\
01463 TINYVECTOR_PROMTRAITS2(unsigned char, int, SIZE)\
01464 TINYVECTOR_PROMTRAITS2(int, float, SIZE)\
01465 TINYVECTOR_PROMTRAITS2(float, int, SIZE)\
01466 TINYVECTOR_PROMTRAITS2(double, unsigned char, SIZE)\
01467 TINYVECTOR_PROMTRAITS2(unsigned char, double, SIZE)\
01468 TINYVECTOR_PROMTRAITS2(int, double, SIZE)\
01469 TINYVECTOR_PROMTRAITS2(double, int, SIZE)\
01470 TINYVECTOR_PROMTRAITS2(double, float, SIZE)\
01471 TINYVECTOR_PROMTRAITS2(float, double, SIZE)
01472 
01473 TINYVECTOR_TRAITS(2)
01474 TINYVECTOR_TRAITS(3)
01475 TINYVECTOR_TRAITS(4)
01476 
01477 #undef TINYVECTOR_NUMTRAITS
01478 #undef TINYVECTOR_PROMTRAITS1
01479 #undef TINYVECTOR_PROMTRAITS2
01480 #undef TINYVECTOR_TRAITS
01481 
01482 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01483 
01484 
01485 /********************************************************/
01486 /*                                                      */
01487 /*                      TinyVector-Arithmetic           */
01488 /*                                                      */
01489 /********************************************************/
01490 
01491 /** \addtogroup TinyVectorOperators
01492  */
01493 //@{
01494 
01495     /// component-wise addition
01496 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01497 inline
01498 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
01499 operator+(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01500           TinyVectorBase<V2, SIZE, D3, D4> const & r)
01501 {
01502     return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) += r;
01503 }
01504 
01505     /// component-wise subtraction
01506 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01507 inline
01508 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
01509 operator-(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01510           TinyVectorBase<V2, SIZE, D3, D4> const & r)
01511 {
01512     return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) -= r;
01513 }
01514 
01515     /// component-wise multiplication
01516 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01517 inline
01518 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
01519 operator*(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01520           TinyVectorBase<V2, SIZE, D3, D4> const & r)
01521 {
01522     return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) *= r;
01523 }
01524 
01525     /// component-wise division
01526 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01527 inline
01528 typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promote
01529 operator/(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01530           TinyVectorBase<V2, SIZE, D3, D4> const & r)
01531 {
01532     return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZE> >::Promote(l) /= r;
01533 }
01534 
01535     /// component-wise left scalar multiplication
01536 template <class V, int SIZE, class D1, class D2>
01537 inline
01538 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
01539 operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r)
01540 {
01541     return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *= v;
01542 }
01543 
01544     /// component-wise right scalar multiplication
01545 template <class V, int SIZE, class D1, class D2>
01546 inline
01547 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
01548 operator*(TinyVectorBase<V, SIZE, D1, D2> const & l, double v)
01549 {
01550     return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) *= v;
01551 }
01552 
01553     /// component-wise scalar division
01554 template <class V, int SIZE, class D1, class D2>
01555 inline
01556 typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
01557 operator/(TinyVectorBase<V, SIZE, D1, D2> const & l, double v)
01558 {
01559     return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) /= v;
01560 }
01561 
01562     /// component-wise scalar division without type promotion
01563 template <class V, int SIZE, class D1, class D2>
01564 inline
01565 TinyVector<V, SIZE>
01566 div(TinyVectorBase<V, SIZE, D1, D2> const & l, V v)
01567 {
01568     TinyVector<V, SIZE> result(l);
01569     typedef typename detail::LoopType<SIZE>::type Loop;
01570     Loop::divScalar(result.data(), v);
01571     return result;
01572 }
01573 
01574 
01575     /** Unary negation (construct TinyVector with negative values)
01576     */
01577 template <class V, int SIZE, class D1, class D2>
01578 inline
01579 TinyVector<V, SIZE>
01580 operator-(TinyVectorBase<V, SIZE, D1, D2> const & v)
01581 {
01582     TinyVector<V, SIZE> res(detail::dontInit());
01583     typedef typename detail::LoopType<SIZE>::type ltype;
01584     ltype::neg(res.begin(), v.begin());
01585     return res;
01586 }
01587 
01588     /// component-wise absolute value
01589 template <class V, int SIZE, class D1, class D2>
01590 inline
01591 TinyVector<V, SIZE>
01592 abs(TinyVectorBase<V, SIZE, D1, D2> const & v)
01593 {
01594     TinyVector<V, SIZE> res(detail::dontInit());
01595     typedef typename detail::LoopType<SIZE>::type ltype;
01596     ltype::abs(res.begin(), v.begin());
01597     return res;
01598 }
01599 
01600     /** Apply ceil() function to each vector component.
01601     */
01602 template <class V, int SIZE, class D1, class D2>
01603 inline
01604 TinyVector<V, SIZE>
01605 ceil(TinyVectorBase<V, SIZE, D1, D2> const & v)
01606 {
01607     TinyVector<V, SIZE> res(detail::dontInit());
01608     typedef typename detail::LoopType<SIZE>::type ltype;
01609     ltype::ceil(res.begin(), v.begin());
01610     return res;
01611 }
01612 
01613     /** Apply floor() function to each vector component.
01614     */
01615 template <class V, int SIZE, class D1, class D2>
01616 inline
01617 TinyVector<V, SIZE>
01618 floor(TinyVectorBase<V, SIZE, D1, D2> const & v)
01619 {
01620     TinyVector<V, SIZE> res(detail::dontInit());
01621     typedef typename detail::LoopType<SIZE>::type ltype;
01622     ltype::floor(res.begin(), v.begin());
01623     return res;
01624 }
01625 
01626     /** Apply sqrt() function to each vector component.
01627     */
01628 template <class V, int SIZE, class D1, class D2>
01629 inline
01630 TinyVector<V, SIZE>
01631 sqrt(TinyVectorBase<V, SIZE, D1, D2> const & v)
01632 {
01633     TinyVector<V, SIZE> res(detail::dontInit());
01634     typedef typename detail::LoopType<SIZE>::type ltype;
01635     ltype::sqrt(res.begin(), v.begin());
01636     return res;
01637 }
01638 
01639 using std::pow;
01640 
01641     /** Apply pow() function to each vector component.
01642     */
01643 template <class V, int SIZE, class D1, class D2, class E>
01644 inline
01645 TinyVector<V, SIZE>
01646 pow(TinyVectorBase<V, SIZE, D1, D2> const & v, E exponent)
01647 {
01648     TinyVector<V, SIZE> res(v);
01649     typedef typename detail::LoopType<SIZE>::type ltype;
01650     ltype::power(res.begin(), exponent);
01651     return res;
01652 }
01653 
01654     /// cross product
01655 template <class V1, class D1, class D2, class V2, class D3, class D4>
01656 inline
01657 TinyVector<typename PromoteTraits<V1, V2>::Promote, 3>
01658 cross(TinyVectorBase<V1, 3, D1, D2> const & r1,
01659       TinyVectorBase<V2, 3, D3, D4> const & r2)
01660 {
01661     typedef TinyVector<typename PromoteTraits<V1, V2>::Promote, 3>
01662             Res;
01663     return  Res(r1[1]*r2[2] - r1[2]*r2[1],
01664                 r1[2]*r2[0] - r1[0]*r2[2],
01665                 r1[0]*r2[1] - r1[1]*r2[0]);
01666 }
01667 
01668     /// dot product
01669 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01670 inline
01671 typename PromoteTraits<V1, V2>::Promote
01672 dot(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01673     TinyVectorBase<V2, SIZE, D3, D4> const & r)
01674 {
01675     typedef typename detail::LoopType<SIZE>::type ltype;
01676     return ltype::dot(l.begin(), r.begin());
01677 }
01678 
01679     /// sum of the vector's elements
01680 template <class V, int SIZE, class D1, class D2>
01681 inline
01682 typename NumericTraits<V>::Promote
01683 sum(TinyVectorBase<V, SIZE, D1, D2> const & l)
01684 {
01685     typename NumericTraits<V>::Promote res = l[0];
01686     for(int k=1; k<SIZE; ++k)
01687         res += l[k];
01688     return res;
01689 }
01690 
01691     /// cumulative sum of the vector's elements
01692 template <class V, int SIZE, class D1, class D2>
01693 inline
01694 TinyVector<typename NumericTraits<V>::Promote, SIZE>
01695 cumsum(TinyVectorBase<V, SIZE, D1, D2> const & l)
01696 {
01697     TinyVector<typename NumericTraits<V>::Promote, SIZE> res(l);
01698     for(int k=1; k<SIZE; ++k)
01699         res[k] += res[k-1];
01700     return res;
01701 }
01702 
01703     /// product of the vector's elements
01704 template <class V, int SIZE, class D1, class D2>
01705 inline
01706 typename NumericTraits<V>::Promote
01707 prod(TinyVectorBase<V, SIZE, D1, D2> const & l)
01708 {
01709     typename NumericTraits<V>::Promote res = l[0];
01710     for(int k=1; k<SIZE; ++k)
01711         res *= l[k];
01712     return res;
01713 }
01714 
01715     /// cumulative product of the vector's elements
01716 template <class V, int SIZE, class D1, class D2>
01717 inline
01718 TinyVector<typename NumericTraits<V>::Promote, SIZE>
01719 cumprod(TinyVectorBase<V, SIZE, D1, D2> const & l)
01720 {
01721     TinyVector<typename NumericTraits<V>::Promote, SIZE> res(l);
01722     for(int k=1; k<SIZE; ++k)
01723         res[k] *= res[k-1];
01724     return res;
01725 }
01726 
01727 using std::min;
01728 
01729     /// element-wise minimum
01730 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01731 inline
01732 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE>
01733 min(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01734     TinyVectorBase<V2, SIZE, D3, D4> const & r)
01735 {
01736     typedef typename detail::LoopType<SIZE>::type ltype;
01737     TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l);
01738     ltype::min(res.begin(), r.begin());
01739     return res;
01740 }
01741 
01742 // we also have to overload min for like-typed argument to prevent match of std::min()
01743 template <class V1, int SIZE, class D1, class D2>
01744 inline
01745 TinyVector<V1, SIZE>
01746 min(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01747     TinyVectorBase<V1, SIZE, D1, D2> const & r)
01748 {
01749     typedef typename detail::LoopType<SIZE>::type ltype;
01750     TinyVector<V1, SIZE> res(l);
01751     ltype::min(res.begin(), r.begin());
01752     return res;
01753 }
01754 
01755 template <class V1, int SIZE>
01756 inline
01757 TinyVector<V1, SIZE>
01758 min(TinyVector<V1, SIZE> const & l,
01759     TinyVector<V1, SIZE> const & r)
01760 {
01761     typedef typename detail::LoopType<SIZE>::type ltype;
01762     TinyVector<V1, SIZE> res(l);
01763     ltype::min(res.begin(), r.begin());
01764     return res;
01765 }
01766 
01767     /// minimum element
01768 template <class V, int SIZE, class D1, class D2>
01769 inline
01770 V const &
01771 min(TinyVectorBase<V, SIZE, D1, D2> const & l)
01772 {
01773     return l.minimum();
01774 }
01775 
01776 using std::max;
01777 
01778     /// element-wise maximum
01779 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01780 inline
01781 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE>
01782 max(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01783     TinyVectorBase<V2, SIZE, D3, D4> const & r)
01784 {
01785     typedef typename detail::LoopType<SIZE>::type ltype;
01786     TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l);
01787     ltype::max(res.begin(), r.begin());
01788     return res;
01789 }
01790 
01791 // we also have to overload max for like-typed argument to prevent match of std::max()
01792 template <class V1, int SIZE, class D1, class D2>
01793 inline
01794 TinyVector<V1, SIZE>
01795 max(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01796     TinyVectorBase<V1, SIZE, D1, D2> const & r)
01797 {
01798     typedef typename detail::LoopType<SIZE>::type ltype;
01799     TinyVector<V1, SIZE> res(l);
01800     ltype::max(res.begin(), r.begin());
01801     return res;
01802 }
01803 
01804 template <class V1, int SIZE>
01805 inline
01806 TinyVector<V1, SIZE>
01807 max(TinyVector<V1, SIZE> const & l,
01808     TinyVector<V1, SIZE> const & r)
01809 {
01810     typedef typename detail::LoopType<SIZE>::type ltype;
01811     TinyVector<V1, SIZE> res(l);
01812     ltype::max(res.begin(), r.begin());
01813     return res;
01814 }
01815 
01816     /// maximum element
01817 template <class V, int SIZE, class D1, class D2>
01818 inline
01819 V const &
01820 max(TinyVectorBase<V, SIZE, D1, D2> const & l)
01821 {
01822     return l.maximum();
01823 }
01824 
01825     /// squared norm
01826 template <class V1, int SIZE, class D1, class D2>
01827 inline
01828 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType
01829 squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t)
01830 {
01831     return t.squaredMagnitude();
01832 }
01833 
01834     /// squared norm
01835 template <class V, int SIZE>
01836 inline
01837 typename TinyVector<V, SIZE>::SquaredNormType
01838 squaredNorm(TinyVector<V, SIZE> const & t)
01839 {
01840     return t.squaredMagnitude();
01841 }
01842 //@}
01843 
01844 // mask cl.exe shortcomings [end]
01845 #if defined(_MSC_VER)
01846 #pragma warning( pop )
01847 #endif
01848 
01849 } // namespace vigra
01850 #undef VIGRA_ASSERT_INSIDE
01851 #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.9.0 (Tue Nov 6 2012)