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