TooN 2.1
internal/vector.hh
00001 //-*- c++ -*-
00002 //
00003 // Copyright (C) 2009 Tom Drummond (twd20@cam.ac.uk),
00004 // Ed Rosten (er258@cam.ac.uk)
00005 //
00006 // This file is part of the TooN Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 2, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // You should have received a copy of the GNU General Public License along
00018 // with this library; see the file COPYING.  If not, write to the Free
00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00020 // USA.
00021 
00022 // As a special exception, you may use this file as part of a free software
00023 // library without restriction.  Specifically, if other files instantiate
00024 // templates or use macros or inline functions from this file, or you compile
00025 // this file and link it with other files to produce an executable, this
00026 // file does not by itself cause the resulting executable to be covered by
00027 // the GNU General Public License.  This exception does not however
00028 // invalidate any other reasons why the executable file might be covered by
00029 // the GNU General Public License.
00030 
00031 
00032 
00033 namespace TooN {
00034 
00035 
00036 /**
00037 @class TooN::Vector vector.hh TooN/toon.h
00038 A vector. 
00039 Support is provided for all the usual vector operations: 
00040 - elements can be accessed using the familiar [] notation with the index starting at 0
00041 - they can be added or subtracted
00042 - they can be printed or loaded from streams
00043 - they can be multiplied (on either side) or divided by a scalar on the right:
00044 - the vector dot product can be computed
00045 - subvectors can be extracted using the templated slice() member function
00046 - the vector cross product can be computed for statically sized 3-vectors
00047 
00048 See individual member function documentation for examples of usage.
00049 
00050 
00051 \par Statically- and dynamically-sized vectors
00052 
00053 The library provides classes for both statically- and
00054 dynamically-sized vectors. If you know what dimension of vector you're
00055 going to use (e.g. 3 to represent a point in 3D space), it's more
00056 efficient to statically sized vectors. The size of static vectors is
00057 determined at compile time; that of dynamically-sized vectors at
00058 run-time.
00059 
00060 To create a 3-dimensional vector, use:
00061 @code
00062 Vector<3> v;
00063 @endcode
00064 
00065 and to create a vector of some other dimensionality just replace 3
00066 with the positive integer of your choice, or some expression which the
00067 compiler can evaluate to an integer at compile time.
00068 
00069 The preferred way of initialising a vector is to use makeVector. The
00070 %makeVector function constructs a static vector initialised to the
00071 size and the contents of the comma-separated list of argments.  The
00072 %makeVector vectors are real Vectors and so can be used anywhere where
00073 a vector is needed, not just in initialisations. For example
00074 
00075 @code
00076 // Create a vector initialised to [1 2 3];
00077 Vector<3> v = makeVector(1, 2, 3);
00078 // Calculate the dot product with the vector [4 0 6]
00079 double dot = v * makeVector(4, 0, 6);
00080 @endcode
00081 
00082 Because the %make_Vector syntax creates actual vectors, compile-time
00083 checking is done to ensure that all vectors defined in this way have
00084 the correct number of elements.
00085 
00086 \par Dynamically-sized vectors
00087 
00088 To create a dynamically sized vector, use:
00089 @code
00090 Vector<> v(size);
00091 @endcode
00092 where size is an integer which will be evaluated at run time.
00093 
00094 Vector<> is actually a synonym for Vector<Dynamic> which is Vector<-1>
00095 being a template specialisation of Vector<N> with a special
00096 implementation that allows the size to be determined at runtime.
00097 
00098 
00099 \par Row vectors and column vectors
00100 
00101 This library makes no distinction between row vectors and column
00102 vectors. Vectors that appear on the left of a multiplication are
00103 treated as row vectors while those that appear on the right are
00104 treated as column vectors (thus <code>v1*v2</code> means the dot
00105 product). This means that sometimes you have to be careful to include
00106 prarentheses since it is possible to write obscure stuff like
00107 
00108 @code
00109 Vector<4> v4 = v1 * v2 * v3;
00110 @endcode
00111 
00112 which in the absence of any extra parentheses means 'compute the dot
00113 product between <code>v1</code> and <code>v2</code> and then multiply
00114 <code>v3</code> by this scalar and assign to <code>v4</code>'.
00115 
00116 If the row-column distinction is important, then vectors can be turned
00117 into matrices with one row or column by using as_row() or as_col():
00118 
00119 @code
00120 double d[3] = {1,2,3};
00121 Vector<3> v(d);
00122 Matrix<3,3> M = v.as_col() * v.as_row(); // creates a symmetric rank 1 matrix from v 
00123 @endcode
00124 
00125 @ingroup gLinAlg
00126 **/
00127 template<int Size=Dynamic, typename Precision=DefaultPrecision, typename Base=Internal::VBase>
00128 struct Vector : public Base::template VLayout<Size, Precision> {
00129 protected:
00130 public:
00131     
00132     ///Value of template Size parameter. Used by internal classes to reduce
00133     ///parameter list sizes.
00134     ///@internal
00135     static const int SizeParameter = Size;
00136 
00137     typedef typename Base::template VLayout<Size, Precision>::PointerType PointerType;
00138   // sneaky hack: only one of these constructors will work with any given base
00139   // class but they don't generate errors unless the user tries to use one of them
00140   // although the error message may be less than helpful - maybe this can be changed?
00141 
00142     /// @name Constructors
00143     //@{
00144 
00145     /// Default constructor for vectors.  For fixed-sized vectors,
00146     /// this does nothing, i.e. does not guarantee to initialise the
00147     /// vector to any particular values.  For dynamically sized
00148     /// vectors, this sets the vector to have a length of 0 which
00149     /// renders the vector useless because vectors can't be resized
00150     inline Vector(){}
00151 
00152     /// Constructor for dynamically-size vectors.  This can also be
00153     /// used for statically sized vectors in which case the argument
00154     /// is ignored.  The values of the vector are uninitialised
00155     explicit inline Vector(int size_in) : Base::template VLayout<Size, Precision>(size_in) {}
00156 
00157     /// Constructor used when constructing a vector which references
00158     /// other data, e.g.
00159     /// @code 
00160     /// double[] d = {1,2,3};
00161     /// Vector<3,double,Reference> v(d);
00162     /// @endcode
00163     explicit inline Vector(PointerType data) : Base::template VLayout<Size, Precision> (data) {}
00164 
00165 
00166     /// Constructor used when constructing a dynamic vector which references
00167     /// other data, e.g.
00168     /// @code 
00169     /// double[] d = {1,2,3};
00170     /// Vector<Dynamic,double,Reference> v(d,3);
00171     /// @endcode
00172     inline Vector(PointerType data, int size_in) : Base::template VLayout<Size, Precision> (data, size_in) {}
00173 
00174     /// internal constructor
00175     inline Vector(PointerType data_in, int size_in, int stride_in, Internal::Slicing)
00176   : Base::template VLayout<Size, Precision>(data_in, size_in, stride_in) {}
00177     
00178     using Base::template VLayout<Size, Precision>::size;
00179     using Base::template VLayout<Size, Precision>::try_destructive_resize;
00180 
00181     /// construction from Operator object
00182     ///
00183     /// This is used to implement return value optimisation for
00184     /// vectors created from the product of a matrix and a vector, or
00185     /// another object like Ones
00186     template <class Op>
00187     inline Vector(const Operator<Op>& op)
00188         : Base::template VLayout<Size, Precision> (op)
00189     {
00190         op.eval(*this);
00191     }
00192 
00193     // Copy construction is a very special case. Copy construction goes all the
00194     // way down to the bottom. GenericVBase has no idea how to copy itself.
00195     // However, the underlying allocator objects do.  In the case of static sized
00196     // objects, C++ automatically copies the data.  For slice objects, C++ copies
00197     // all parts (pointer and size), which is correct.  For dynamically sized
00198     // non-slice objects the copying has to be done by hand.
00199     
00200     // inline Vector(const Vector&from);
00201 
00202     /// constructor from arbitrary vector
00203     template<int Size2, typename Precision2, typename Base2>
00204     inline Vector(const Vector<Size2,Precision2,Base2>& from):
00205         Base::template VLayout<Size, Precision>(from.size()) {
00206         operator=(from);
00207     }
00208 
00209     /// @}
00210 
00211 #ifdef DOXYGEN_INCLUDE_ONLY_FOR_DOCS
00212 
00213     /// @name Accessing elements
00214     /// @{
00215 
00216     /// access an element of the vector
00217     ///
00218     /// can be used as an l-value ie
00219     /// @code
00220     /// Vector<3> v;
00221     /// v[0] = 10;
00222     /// @endcode
00223     ///
00224     /// @internal
00225     /// This method is not defined by Vector: it is inherited.
00226     Precision& operator[] (int i);
00227 
00228     /**
00229         @overload
00230     */
00231     const Precision& operator[] (int i) const;
00232 
00233     /// @}
00234 
00235 #endif
00236 
00237     
00238     /// @name Assignment
00239     /// @{
00240 
00241     /// operator = from copy
00242     /// A size mismatch is a fatal error, unless the destination
00243     /// is resizable.
00244     inline Vector& operator= (const Vector& from){
00245         try_destructive_resize(from.size());
00246         SizeMismatch<Size,Size>::test(size(), from.size());
00247         const int s=size();
00248         for(int i=0; i<s; i++){
00249             (*this)[i]=from[i];
00250         }
00251         return *this;
00252     }
00253 
00254     /// operator = another Vector
00255     /// A size mismatch is a fatal error, unless the destination
00256     /// is resizable.
00257     template<int Size2, typename Precision2, typename Base2>
00258     Vector<Size,Precision,Base >& operator= (const Vector<Size2, Precision2, Base2>& from){
00259         try_destructive_resize(from.size());
00260         SizeMismatch<Size,Size2>::test(size(), from.size());
00261         const int s=size();
00262         for(int i=0; i<s; i++){
00263             (*this)[i]=from[i];
00264         }
00265         return *this;
00266     }
00267 
00268     /// assignment from an Operator object
00269     /// Assignment from sized operators causes a resize
00270     /// of Resizable Vectors. Assignment from unsized
00271     /// operators dows not.
00272     template <class Op>
00273     inline Vector & operator=(const Operator<Op>& op){
00274         try_destructive_resize(op);
00275         op.eval(*this);
00276         return *this;
00277     }
00278     /// @}
00279 
00280     /// @name Operators on the vector
00281     /// @{
00282 
00283     /// divide this vector by a constant
00284     Vector& operator/=(const Precision rhs) {
00285         for(int i=0; i<size(); i++)
00286             (*this)[i]/=rhs;
00287         return *this;
00288     }
00289     
00290     /// multiply this vector by a constant
00291     Vector& operator*=(const Precision rhs) {
00292         for(int i=0; i<size(); i++)
00293             (*this)[i]*=rhs;
00294         return *this;
00295     }
00296     
00297     /// add another vector onto this one
00298     template<int Size2, class Precision2, class Base2>
00299     Vector& operator+=(const Vector<Size2, Precision2, Base2>& rhs) {
00300         SizeMismatch<Size,Size2>::test(size(),rhs.size());
00301         for(int i=0; i<size(); i++)
00302             (*this)[i]+=rhs[i];
00303         return *this;
00304     }
00305     
00306     /// add an Operator object onto this vector
00307     ///
00308     /// this is used to handle cases such as:
00309     /// @code
00310     /// Vector<3> v;
00311     /// v+=Ones
00312     /// @endcode
00313     template<class Op>
00314     Vector& operator+=(const Operator<Op>& op)
00315     {
00316         op.plusequals(*this);
00317         return *this;
00318     }       
00319 
00320     template<class Op>
00321     Vector& operator-=(const Operator<Op>& op)
00322     {
00323         op.minusequals(*this);
00324         return *this;
00325     }       
00326 
00327     /// subtract another vector from this one
00328     template<int Size2, class Precision2, class Base2>
00329     Vector& operator-=(const Vector<Size2, Precision2, Base2>& rhs) {
00330         SizeMismatch<Size,Size2>::test(size(),rhs.size());
00331         for(int i=0; i<size(); i++)
00332             (*this)[i]-=rhs[i];
00333         return *this;
00334     }
00335 
00336     /// @}
00337 
00338     /// @name Comparison
00339     /// @{
00340 
00341     /// Test for equality with another vector
00342     template<int Size2, class Precision2, class Base2>
00343     bool operator==(const Vector<Size2, Precision2, Base2>& rhs) const {
00344         SizeMismatch<Size,Size2>::test(size(),rhs.size());
00345         for(int i=0; i<size(); i++)
00346           if((*this)[i]!=rhs[i])
00347             return 0;
00348         return 1;
00349     }
00350 
00351     /// Test for inequality with another vector
00352     template<int Size2, class Precision2, class Base2>
00353     bool operator!=(const Vector<Size2, Precision2, Base2>& rhs) const {
00354         SizeMismatch<Size,Size2>::test(size(),rhs.size());
00355         for(int i=0; i<size(); i++)
00356           if((*this)[i]!=rhs[i])
00357             return 1;
00358         return 0;
00359     }
00360     
00361     
00362     template<class Op>
00363     bool operator!=(const Operator<Op>& op)
00364     {
00365         return op.notequal(*this);
00366     }       
00367     
00368     /// @}
00369 
00370     /// @name Misc
00371     /// @{
00372 
00373     /// return me as a non const reference - useful for temporaries
00374     Vector& ref()
00375     {
00376         return *this;
00377     }
00378 
00379 #ifdef DOXYGEN_INCLUDE_ONLY_FOR_DOCS
00380 
00381     /// What is the size of this vector?
00382     int size() const;
00383     
00384     /// Resize the vector. This is only provided if the vector is
00385     /// declared as Resizable. Existing elements are retained, new
00386     /// elements are uninitialized. Resizing has the same efficiency
00387     /// guarantees as <code>std::vector</code>.
00388     /// @param s The new size.
00389     ///
00390     /// @internal
00391     /// This method is not defined by Vector: it is inherited.
00392     void resize(int s);
00393 
00394     /// Return a pointer to the first element of the vector. This method
00395     /// is only provided for non-slice vectors, i.e. a subset of the cases
00396     /// where the memory is guaranteed to be contiguous.
00397     ///
00398     /// @internal
00399     /// This method is not defined by Vector: it is inherited.
00400     Precision* get_data_ptr();
00401 
00402 
00403 
00404     /// @}
00405 
00406     /// @name Reshaping, sub-vectors and matrices
00407     //@{
00408     /**
00409        Convert this vector into a 1-by-Size matrix, i.e. a matrix which has this
00410        vector as its only row.
00411        @code
00412        Vector<3> a = makeVector(1,2,3);
00413        Matrix<1,3> m = a.as_row();  // now m = [1 2 3]
00414        @endcode
00415        @internal
00416        This method is not defined by Vector: it is inherited.
00417     */
00418     Matrix<1, Size, Precision> as_row();
00419   
00420     /**
00421        Convert this vector into a Size-by-1 matrix, i.e. a matrix which has this
00422        vector as its only column.
00423        @code
00424        Vector<3> a = makeVector(1,2,3);
00425        Matrix<3,1> m = a.as_col();   // now m = [1 2 3]'
00426        @endcode
00427        @internal
00428        This method is not defined by Vector: it is inherited.
00429     */
00430     Matrix<Size, 1, Precision> as_col();
00431   
00432     /**
00433        Convert this vector into a Diagonal Size-by-Size matrix, i.e. a matrix which is
00434        zero everywhere except on the diagonal and the diagonal contains the values from this vector
00435        @code
00436        Vector<3> v = makeVector(1,2,3);
00437        Vector<3> v2 = makeVector(2,3,4);
00438        Vector<3> v3 = v.as_diagonal() * v2; // now v3 = (2,6,12)
00439        @endcode
00440        @internal
00441        This method is not defined by Vector: it is inherited.
00442     */
00443     DiagonalMatrix<Size,Precision> as_diagonal();
00444 
00445     /**
00446        Extract a sub-vector. The vector extracted will be begin at element Start
00447        and will contain the next Length elements.
00448        @code
00449        Vector<5> a = makeVector(1,2,3,4,5);
00450        Extract the three elements starting from element 2
00451        Vector<3> b = a.slice<2,3>();  /// b = [3 4 5]
00452        @endcode
00453        @internal
00454        This method is not defined by Vector: it is inherited.
00455     */
00456     template<Start, Length>
00457     const Vector<Length,Precision>& slice() const;
00458   
00459     /**
00460        Extract a sub-vector. The vector extracted will be begin at element Start
00461        and will contain the next Length elements. This version can be used as an
00462        l-value as well as an r-value
00463        @code
00464        Vector<5> a = makeVector(1,2,3,4,5);
00465        Vector<2> b = makeVector(8,9);
00466        // replace the two elements starting from element 1 with b
00467        a.slice<1, 2>() = b;       /// now a = [1 8 9 4 5]
00468        @endcode
00469        @internal
00470        This method is not defined by Vector: it is inherited.
00471     */
00472     template<Start, Length>
00473     Vector<Length,Precision>& slice();
00474   
00475     /**
00476        Extract a sub-vector with runtime parameters.
00477        The vector extracted will be begin at element start and will contain the next
00478        length elements.
00479        @code
00480        Vector<5> a = makeVector(1,2,3,4,5);
00481        Extract the three elements starting from element 2
00482        Vector<> b = a.slice(2,3);  /// b = [3 4 5]
00483        @endcode
00484        @internal
00485        This method is not defined by Vector: it is inherited.
00486     */
00487     template<Start, Length>
00488     const Vector<Length,Precision>& slice() const;
00489   
00490     /**
00491        Extract a sub-vector with runtime parameters, which can be used as an
00492        l-value.
00493        The vector extracted will be begin at element start and will contain the next
00494        length elements.
00495        @code
00496        Vector<5> a = makeVector(1,2,3,4,5);
00497        Extract the three elements starting from element 2
00498        a.slice(2,3)[0] = 17;  /// a -> [1 2 17 4 5]
00499        @endcode
00500        @internal
00501        This method is not defined by Vector: it is inherited.
00502     */
00503     template<Start, Length>
00504     Vector<Length,Precision>& slice();
00505     //@}
00506 
00507 #endif
00508 
00509 };
00510 
00511 }