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

vigra/tinyvector.hxx

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