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