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