TooN: internal/vector.hh Source File

TooN 2.0.0-beta8

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List

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 }