TooN 2.0.0-beta8
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     typedef typename Base::template VLayout<Size, Precision>::PointerType PointerType;
00132   // sneaky hack: only one of these constructors will work with any given base
00133   // class but they don't generate errors unless the user tries to use one of them
00134   // although the error message may be less than helpful - maybe this can be changed?
00135 
00136     /// @name Constructors
00137     //@{
00138 
00139     /// Default constructor for vectors.  For fixed-sized vectors,
00140     /// this does nothing, i.e. does not guarantee to initialise the
00141     /// vector to any particular values.  For dynamically sized
00142     /// vectors, this sets the vector to have a length of 0 which
00143     /// renders the vector useless because vectors can't be resized
00144     inline Vector(){}
00145 
00146     /// Constructor for dynamically-size vectors.  This can also be
00147     /// used for statically sized vectors in which case the argument
00148     /// is ignored.  The values of the vector are uninitialised
00149     explicit inline Vector(int size_in) : Base::template VLayout<Size, Precision>(size_in) {}
00150 
00151     /// Constructor used when constructing a vector which references
00152     /// other data, e.g.
00153     /// @code 
00154     /// double[] d = {1,2,3};
00155     /// Vector<3,double,Reference> v(d);
00156     /// @endcode
00157     explicit inline Vector(PointerType data) : Base::template VLayout<Size, Precision> (data) {}
00158 
00159 
00160     /// Constructor used when constructing a dynamic vector which references
00161     /// other data, e.g.
00162     /// @code 
00163     /// double[] d = {1,2,3};
00164     /// Vector<Dynamic,double,Reference> v(d,3);
00165     /// @endcode
00166     inline Vector(PointerType data, int size_in) : Base::template VLayout<Size, Precision> (data, size_in) {}
00167 
00168     /// internal constructor
00169     inline Vector(PointerType data_in, int size_in, int stride_in, Internal::Slicing)
00170   : Base::template VLayout<Size, Precision>(data_in, size_in, stride_in) {}
00171     
00172     using Base::template VLayout<Size, Precision>::size;
00173     using Base::template VLayout<Size, Precision>::try_destructive_resize;
00174 
00175     /// construction from Operator object
00176     ///
00177     /// This is used to implement return value optimisation for
00178     /// vectors created from the product of a matrix and a vector, or
00179     /// another object like Ones
00180     template <class Op>
00181     inline Vector(const Operator<Op>& op)
00182         : Base::template VLayout<Size, Precision> (op)
00183     {
00184         op.eval(*this);
00185     }
00186 
00187     // Copy construction is a very special case. Copy construction goes all the
00188     // way down to the bottom. GenericVBase has no idea how to copy itself.
00189     // However, the underlying allocator objects do.  In the case of static sized
00190     // objects, C++ automatically copies the data.  For slice objects, C++ copies
00191     // all parts (pointer and size), which is correct.  For dynamically sized
00192     // non-slice objects the copying has to be done by hand.
00193     
00194     // inline Vector(const Vector&from);
00195 
00196     /// constructor from arbitrary vector
00197     template<int Size2, typename Precision2, typename Base2>
00198     inline Vector(const Vector<Size2,Precision2,Base2>& from):
00199         Base::template VLayout<Size, Precision>(from.size()) {
00200         operator=(from);
00201     }
00202 
00203     /// @}
00204 
00205 #ifdef DOXYGEN_INCLUDE_ONLY_FOR_DOCS
00206 
00207     /// @name Accessing elements
00208     /// @{
00209 
00210     /// access an element of the vector
00211     ///
00212     /// can be used as an l-value ie
00213     /// @code
00214     /// Vector<3> v;
00215     /// v[0] = 10;
00216     /// @endcode
00217     ///
00218     /// @internal
00219     /// This method is not defined by Vector: it is inherited.
00220     Precision& operator[] (int i);
00221 
00222     /**
00223         @overload
00224     */
00225     const Precision& operator[] (int i) const;
00226 
00227     /// @}
00228 
00229 #endif
00230 
00231     /// @name Assignment
00232     /// @{
00233 
00234     /// operator = from copy
00235     /// A size mismatch is a fatal error, unless the destination
00236     /// is resizable.
00237     inline Vector& operator= (const Vector& from){
00238         try_destructive_resize(from.size());
00239         SizeMismatch<Size,Size>::test(size(), from.size());
00240         const int s=size();
00241         for(int i=0; i<s; i++){
00242             (*this)[i]=from[i];
00243         }
00244         return *this;
00245     }
00246 
00247     /// operator = another Vector
00248     /// A size mismatch is a fatal error, unless the destination
00249     /// is resizable.
00250     template<int Size2, typename Precision2, typename Base2>
00251     Vector<Size,Precision,Base >& operator= (const Vector<Size2, Precision2, Base2>& from){
00252         try_destructive_resize(from.size());
00253         SizeMismatch<Size,Size2>::test(size(), from.size());
00254         const int s=size();
00255         for(int i=0; i<s; i++){
00256             (*this)[i]=from[i];
00257         }
00258         return *this;
00259     }
00260 
00261     /// assignment from an Operator object
00262     /// Assignment from sized operators causes a resize
00263     /// of Resizable Vectors. Assignment from unsized
00264     /// operators dows not.
00265     template <class Op>
00266     inline Vector & operator=(const Operator<Op>& op){
00267         try_destructive_resize(op);
00268         op.eval(*this);
00269         return *this;
00270     }
00271     /// @}
00272 
00273     /// @name Operators on the vector
00274     /// @{
00275 
00276     /// divide this vector by a constant
00277     Vector& operator/=(const Precision& rhs) {
00278         for(int i=0; i<size(); i++)
00279             (*this)[i]/=rhs;
00280         return *this;
00281     }
00282     
00283     /// multiply 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     /// add another vector onto this one
00291     template<int Size2, class Precision2, class Base2>
00292     Vector& operator+=(const Vector<Size2, Precision2, Base2>& rhs) {
00293         SizeMismatch<Size,Size2>::test(size(),rhs.size());
00294         for(int i=0; i<size(); i++)
00295             (*this)[i]+=rhs[i];
00296         return *this;
00297     }
00298     
00299     /// add an Operator object onto this vector
00300     ///
00301     /// this is used to handle cases such as:
00302     /// @code
00303     /// Vector<3> v;
00304     /// v+=Ones
00305     /// @endcode
00306     template<class Op>
00307     Vector& operator+=(const Operator<Op>& op)
00308     {
00309         op.plusequals(*this);
00310         return *this;
00311     }       
00312 
00313     template<class Op>
00314     Vector& operator-=(const Operator<Op>& op)
00315     {
00316         op.minusequals(*this);
00317         return *this;
00318     }       
00319 
00320     /// subtract another vector from this one
00321     template<int Size2, class Precision2, class Base2>
00322     Vector& operator-=(const Vector<Size2, Precision2, Base2>& rhs) {
00323         SizeMismatch<Size,Size2>::test(size(),rhs.size());
00324         for(int i=0; i<size(); i++)
00325             (*this)[i]-=rhs[i];
00326         return *this;
00327     }
00328 
00329     /// @}
00330 
00331     /// @name Comparison
00332     /// @{
00333 
00334     /// Test for equality with another vector
00335     template<int Size2, class Precision2, class Base2>
00336     bool operator==(const Vector<Size2, Precision2, Base2>& rhs) const {
00337         SizeMismatch<Size,Size2>::test(size(),rhs.size());
00338         for(int i=0; i<size(); i++)
00339           if((*this)[i]!=rhs[i])
00340             return 0;
00341         return 1;
00342     }
00343 
00344     /// Test for inequality with another vector
00345     template<int Size2, class Precision2, class Base2>
00346     bool operator!=(const Vector<Size2, Precision2, Base2>& rhs) const {
00347         SizeMismatch<Size,Size2>::test(size(),rhs.size());
00348         for(int i=0; i<size(); i++)
00349           if((*this)[i]!=rhs[i])
00350             return 1;
00351         return 0;
00352     }
00353 
00354     /// @}
00355 
00356     /// @name Misc
00357     /// @{
00358 
00359     /// return me as a non const reference - useful for temporaries
00360     Vector& ref()
00361     {
00362         return *this;
00363     }
00364 
00365 #ifdef DOXYGEN_INCLUDE_ONLY_FOR_DOCS
00366 
00367     /// What is the size of this vector?
00368     int size() const;
00369     
00370     /// Resize the vector. This is only provided if the vector is
00371     /// declared as Resizable. Existing elements are retained, new
00372     /// elements are uninitialized. Resizing has the same efficiency
00373     /// guarantees as <code>std::vector</code>.
00374     /// @param s The new size.
00375     ///
00376     /// @internal
00377     /// This method is not defined by Vector: it is inherited.
00378     void resize(int s);
00379 
00380     /// Return a pointer to the first element of the vector. This method
00381     /// is only provided for non-slice vectors, i.e. a subset of the cases
00382     /// where the memory is guaranteed to be contiguous.
00383     ///
00384     /// @internal
00385     /// This method is not defined by Vector: it is inherited.
00386     Precision* get_data_ptr();
00387 
00388 
00389 
00390     /// @}
00391 
00392     /// @name Reshaping, sub-vectors and matrices
00393     //@{
00394     /**
00395        Convert this vector into a 1-by-Size matrix, i.e. a matrix which has this
00396        vector as its only row.
00397        @code
00398        Vector<3> a = makeVector(1,2,3);
00399        Matrix<1,3> m = a.as_row();  // now m = [1 2 3]
00400        @endcode
00401        @internal
00402        This method is not defined by Vector: it is inherited.
00403     */
00404     Matrix<1, Size, Precision> as_row();
00405   
00406     /**
00407        Convert this vector into a Size-by-1 matrix, i.e. a matrix which has this
00408        vector as its only column.
00409        @code
00410        Vector<3> a = makeVector(1,2,3);
00411        Matrix<3,1> m = a.as_col();   // now m = [1 2 3]'
00412        @endcode
00413        @internal
00414        This method is not defined by Vector: it is inherited.
00415     */
00416     Matrix<Size, 1, Precision> as_col();
00417   
00418     /**
00419        Convert this vector into a Diagonal Size-by-Size matrix, i.e. a matrix which is
00420        zero everywhere except on the diagonal and the diagonal contains the values from this vector
00421        @code
00422        Vector<3> v = makeVector(1,2,3);
00423        Vector<3> v2 = makeVector(2,3,4);
00424        Vector<3> v3 = v.as_diagonal() * v2; // now v3 = (2,6,12)
00425        @endcode
00426        @internal
00427        This method is not defined by Vector: it is inherited.
00428     */
00429     DiagonalMatrix<Size,Precision> as_diagonal();
00430 
00431     /**
00432        Extract a sub-vector. The vector extracted will be begin at element Start
00433        and will contain the next Length elements.
00434        @code
00435        Vector<5> a = makeVector(1,2,3,4,5);
00436        Extract the three elements starting from element 2
00437        Vector<3> b = a.slice<2,3>();  /// b = [3 4 5]
00438        @endcode
00439        @internal
00440        This method is not defined by Vector: it is inherited.
00441     */
00442     template<Start, Length>
00443     const Vector<Length,Precision>& slice() const;
00444   
00445     /**
00446        Extract a sub-vector. The vector extracted will be begin at element Start
00447        and will contain the next Length elements. This version can be used as an
00448        l-value as well as an r-value
00449        @code
00450        Vector<5> a = makeVector(1,2,3,4,5);
00451        Vector<2> b = makeVector(8,9);
00452        // replace the two elements starting from element 1 with b
00453        a.slice<1, 2>() = b;       /// now a = [1 8 9 4 5]
00454        @endcode
00455        @internal
00456        This method is not defined by Vector: it is inherited.
00457     */
00458     template<Start, Length>
00459     Vector<Length,Precision>& slice();
00460   
00461     /**
00462        Extract a sub-vector with runtime parameters.
00463        The vector extracted will be begin at element start and will contain the next
00464        length elements.
00465        @code
00466        Vector<5> a = makeVector(1,2,3,4,5);
00467        Extract the three elements starting from element 2
00468        Vector<> b = a.slice(2,3);  /// b = [3 4 5]
00469        @endcode
00470        @internal
00471        This method is not defined by Vector: it is inherited.
00472     */
00473     template<Start, Length>
00474     const Vector<Length,Precision>& slice() const;
00475   
00476     /**
00477        Extract a sub-vector with runtime parameters, which can be used as an
00478        l-value.
00479        The vector extracted will be begin at element start and will contain the next
00480        length elements.
00481        @code
00482        Vector<5> a = makeVector(1,2,3,4,5);
00483        Extract the three elements starting from element 2
00484        a.slice(2,3)[0] = 17;  /// a -> [1 2 17 4 5]
00485        @endcode
00486        @internal
00487        This method is not defined by Vector: it is inherited.
00488     */
00489     template<Start, Length>
00490     Vector<Length,Precision>& slice();
00491     //@}
00492 
00493 #endif
00494 
00495 };
00496 
00497 }