TooN 2.0.0-beta8
|
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 }