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

vigra/tinyvector.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
00004 /*                                                                      */
00005 /*    This file is part of the VIGRA computer vision library.           */
00006 /*    The VIGRA Website is                                              */
00007 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
00008 /*    Please direct questions, bug reports, and contributions to        */
00009 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00010 /*        vigra@informatik.uni-hamburg.de                               */
00011 /*                                                                      */
00012 /*    Permission is hereby granted, free of charge, to any person       */
00013 /*    obtaining a copy of this software and associated documentation    */
00014 /*    files (the "Software"), to deal in the Software without           */
00015 /*    restriction, including without limitation the rights to use,      */
00016 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00017 /*    sell copies of the Software, and to permit persons to whom the    */
00018 /*    Software is furnished to do so, subject to the following          */
00019 /*    conditions:                                                       */
00020 /*                                                                      */
00021 /*    The above copyright notice and this permission notice shall be    */
00022 /*    included in all copies or substantial portions of the             */
00023 /*    Software.                                                         */
00024 /*                                                                      */
00025 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00026 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00027 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00028 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00029 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00030 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00031 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00032 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
00033 /*                                                                      */
00034 /************************************************************************/
00035 
00036 
00037 #ifndef VIGRA_TINYVECTOR_HXX
00038 #define VIGRA_TINYVECTOR_HXX
00039 
00040 #include <cmath>    // abs(double)
00041 #include <cstdlib>  // abs(int)
00042 #include <iosfwd>   // ostream
00043 #include "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> <vigra/tinyvector.hxx><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> <vigra/tinyvector.hxx><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> <vigra/tinyvector.hxx><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> <vigra/tinyvector.hxx><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> <vigra/tinyvector.hxx><br>
01008     Namespace: vigra
01009 
01010     On compilers that don't support partial 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     /// component-wise scalar division without type promotion
01365 template <class V, int SIZE, class D1, class D2>
01366 inline
01367 TinyVector<V, SIZE>
01368 div(TinyVectorBase<V, SIZE, D1, D2> const & l, V v)
01369 {
01370     TinyVector<V, SIZE> result(l);
01371     typedef typename detail::LoopType<SIZE>::type Loop;
01372     Loop::divScalar(result.data(), v);
01373     return result;
01374 }
01375 
01376 
01377     /** Unary negation (construct TinyVector with negative values)
01378     */
01379 template <class V, int SIZE, class D1, class D2>
01380 inline
01381 TinyVector<V, SIZE>
01382 operator-(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::neg(res.begin(), v.begin());
01387     return res;
01388 }
01389 
01390     /// component-wise absolute value
01391 template <class V, int SIZE, class D1, class D2>
01392 inline
01393 TinyVector<V, SIZE>
01394 abs(TinyVectorBase<V, SIZE, D1, D2> const & v)
01395 {
01396     TinyVector<V, SIZE> res(detail::dontInit());
01397     typedef typename detail::LoopType<SIZE>::type ltype;
01398     ltype::abs(res.begin(), v.begin());
01399     return res;
01400 }
01401 
01402     /** Apply ceil() function to each vector component.
01403     */
01404 template <class V, int SIZE, class D1, class D2>
01405 inline
01406 TinyVector<V, SIZE>
01407 ceil(TinyVectorBase<V, SIZE, D1, D2> const & v)
01408 {
01409     TinyVector<V, SIZE> res(detail::dontInit());
01410     typedef typename detail::LoopType<SIZE>::type ltype;
01411     ltype::ceil(res.begin(), v.begin());
01412     return res;
01413 }
01414 
01415     /** Apply floor() function to each vector component.
01416     */
01417 template <class V, int SIZE, class D1, class D2>
01418 inline
01419 TinyVector<V, SIZE>
01420 floor(TinyVectorBase<V, SIZE, D1, D2> const & v)
01421 {
01422     TinyVector<V, SIZE> res(detail::dontInit());
01423     typedef typename detail::LoopType<SIZE>::type ltype;
01424     ltype::floor(res.begin(), v.begin());
01425     return res;
01426 }
01427 
01428     /// cross product
01429 template <class V1, class D1, class D2, class V2, class D3, class D4>
01430 inline
01431 TinyVector<typename PromoteTraits<V1, V2>::Promote, 3>
01432 cross(TinyVectorBase<V1, 3, D1, D2> const & r1,
01433       TinyVectorBase<V2, 3, D3, D4> const & r2)
01434 {
01435     typedef TinyVector<typename PromoteTraits<V1, V2>::Promote, 3>
01436             Res;
01437     return  Res(r1[1]*r2[2] - r1[2]*r2[1],
01438                 r1[2]*r2[0] - r1[0]*r2[2],
01439                 r1[0]*r2[1] - r1[1]*r2[0]);
01440 }
01441 
01442     /// dot product
01443 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01444 inline
01445 typename PromoteTraits<V1, V2>::Promote
01446 dot(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01447     TinyVectorBase<V2, SIZE, D3, D4> const & r)
01448 {
01449     typedef typename detail::LoopType<SIZE>::type ltype;
01450     return ltype::dot(l.begin(), r.begin());
01451 }
01452 
01453     /// sum of the vector's elements
01454 template <class V, int SIZE, class D1, class D2>
01455 inline
01456 typename NumericTraits<V>::Promote
01457 sum(TinyVectorBase<V, SIZE, D1, D2> const & l)
01458 {
01459     typename NumericTraits<V>::Promote res = l[0];
01460     for(int k=1; k<SIZE; ++k)
01461         res += l[k];
01462     return res;
01463 }
01464 
01465     /// cumulative sum of the vector's elements
01466 template <class V, int SIZE, class D1, class D2>
01467 inline
01468 TinyVector<typename NumericTraits<V>::Promote, SIZE>
01469 cumsum(TinyVectorBase<V, SIZE, D1, D2> const & l)
01470 {
01471     TinyVector<typename NumericTraits<V>::Promote, SIZE> res(l);
01472     for(int k=1; k<SIZE; ++k)
01473         res[k] += res[k-1];
01474     return res;
01475 }
01476 
01477     /// product of the vector's elements
01478 template <class V, int SIZE, class D1, class D2>
01479 inline
01480 typename NumericTraits<V>::Promote
01481 prod(TinyVectorBase<V, SIZE, D1, D2> const & l)
01482 {
01483     typename NumericTraits<V>::Promote res = l[0];
01484     for(int k=1; k<SIZE; ++k)
01485         res *= l[k];
01486     return res;
01487 }
01488 
01489     /// cumulative sum of the vector's elements
01490 template <class V, int SIZE, class D1, class D2>
01491 inline
01492 TinyVector<typename NumericTraits<V>::Promote, SIZE>
01493 cumprod(TinyVectorBase<V, SIZE, D1, D2> const & l)
01494 {
01495     TinyVector<typename NumericTraits<V>::Promote, SIZE> res(l);
01496     for(int k=1; k<SIZE; ++k)
01497         res[k] *= res[k-1];
01498     return res;
01499 }
01500 
01501     /// element-wise minimum
01502 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01503 inline
01504 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE>
01505 min(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01506     TinyVectorBase<V2, SIZE, D3, D4> const & r)
01507 {
01508     TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l);
01509     for(int k=0; k<SIZE; ++k)
01510         if(r[k] < res[k])
01511             res[k] = r[k];
01512     return res;
01513 }
01514 
01515     /// element-wise maximum
01516 template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
01517 inline
01518 TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE>
01519 max(TinyVectorBase<V1, SIZE, D1, D2> const & l,
01520     TinyVectorBase<V2, SIZE, D3, D4> const & r)
01521 {
01522     TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l);
01523     for(int k=0; k<SIZE; ++k)
01524         if(res[k] < r[k])
01525             res[k] = r[k];
01526     return res;
01527 }
01528 
01529     /// squared norm
01530 template <class V1, int SIZE, class D1, class D2>
01531 inline
01532 typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType
01533 squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t)
01534 {
01535     return t.squaredMagnitude();
01536 }
01537 
01538     /// squared norm
01539 template <class V, int SIZE>
01540 inline
01541 typename TinyVector<V, SIZE>::SquaredNormType
01542 squaredNorm(TinyVector<V, SIZE> const & t)
01543 {
01544     return t.squaredMagnitude();
01545 }
01546 //@}
01547 
01548 
01549 } // namespace vigra
01550 #undef VIGRA_ASSERT_INSIDE
01551 #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.8.0 (20 Sep 2011)