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

vigra/tinyvector.hxx |

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

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.7.1 (3 Dec 2010)