TooN 2.1
|
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 }