core/vnl/vnl_vector.h
Go to the documentation of this file.
00001 // This is core/vnl/vnl_vector.h
00002 #ifndef vnl_vector_h_
00003 #define vnl_vector_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \author Andrew W. Fitzgibbon
00010 //
00011 // \verbatim
00012 // Modifications
00013 // Comments re-written by Tim Cootes, for his sins.
00014 //   Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line
00015 //   Mar.2004 - Peter Vanroose - deprecated fixed-size constructors now compile only when VNL_CONFIG_LEGACY_METHODS==1
00016 //   Mar.2009 - Peter Vanroose - added arg_min() and arg_max()
00017 //   Oct.2010 - Peter Vanroose - mutators and setters now return *this
00018 // \endverbatim
00019 
00020 #include <vcl_iosfwd.h>
00021 #include <vnl/vnl_tag.h>
00022 #include <vnl/vnl_c_vector.h>
00023 #include <vnl/vnl_config.h>
00024 #ifndef NDEBUG
00025 # include <vnl/vnl_error.h>
00026 # if VNL_CONFIG_CHECK_BOUNDS
00027 #  include <vcl_cassert.h>
00028 # endif
00029 #else
00030 # undef VNL_CONFIG_CHECK_BOUNDS
00031 # define VNL_CONFIG_CHECK_BOUNDS 0
00032 # undef ERROR_CHECKING
00033 #endif
00034 #if VNL_CONFIG_LEGACY_METHODS
00035 # include <vcl_deprecated.h>
00036 #endif
00037 
00038 export template <class T> class vnl_vector;
00039 export template <class T> class vnl_matrix;
00040 
00041 //----------------------------------------------------------------------
00042 
00043 #define v vnl_vector<T>
00044 #define m vnl_matrix<T>
00045 template <class T> T      dot_product(v const&, v const&);
00046 template <class T> T      inner_product(v const&, v const&);
00047 template <class T> T      bracket(v const &, m const &, v const &);
00048 template <class T> T      cos_angle(v const&, v const& );
00049 template <class T> double angle(v const&, v const&);
00050 template <class T> m      outer_product(v const&, v const&);
00051 template <class T> v      operator+(T, v const&);
00052 template <class T> v      operator-(T, v const&);
00053 template <class T> v      operator*(T, v const&);
00054 // also exists as method: template <class T> v      operator*(m const&, v const&);
00055 template <class T> v      operator*(v const&, m const&);
00056 template <class T> v      element_product(v const&,v const&);
00057 template <class T> v      element_quotient(v const&,v const&);
00058 template <class T> T      vnl_vector_ssd(v const&, v const&);
00059 template <class T> void   swap(v &, v &);
00060 #undef v
00061 #undef m
00062 
00063 //----------------------------------------------------------------------
00064 
00065 //: Mathematical vector class, templated by type of element.
00066 // The vnl_vector<T> class implements one-dimensional arithmetic
00067 // vectors to be used with the vnl_matrix<T> class. vnl_vector<T>
00068 // has size fixed by constructor time or changed by assignment
00069 // operator.
00070 // For faster, non-mallocing vectors with size known at compile
00071 // time, use vnl_vector_fixed* or vnl_T_n (e.g. vnl_double_3).
00072 //
00073 // NOTE: Vectors are indexed from zero!  Thus valid elements are [0,size()-1].
00074 template<class T>
00075 class vnl_vector
00076 {
00077  public:
00078   friend class vnl_matrix<T>;
00079 
00080   //: Creates an empty vector. O(1).
00081   vnl_vector() : num_elmts(0) , data(0) {}
00082 
00083   //: Creates vector containing n elements.
00084   // Elements are not initialized.
00085   explicit vnl_vector(unsigned len);
00086 
00087   //: Creates vector of len elements, all set to v0
00088   vnl_vector(unsigned len, T const& v0);
00089 
00090   //: Creates a vector of specified length and initialize first n elements with values. O(n).
00091   vnl_vector(unsigned len, int n, T const values[]);
00092 
00093 #if VNL_CONFIG_LEGACY_METHODS // these constructors are deprecated and should not be used
00094   //: Creates a vector of length 2 and initializes with the arguments, px,py.
00095   //  Requires that len==2.
00096   //  Consider using vnl_vector_fixed<T,2> instead!
00097   // \deprecated
00098   vnl_vector(unsigned len, T const& px, T const& py);
00099 
00100   //: Creates a vector of length 3 and initializes with the arguments, px,py,pz.
00101   //  Requires that len==3.
00102   //  Consider using vnl_vector_fixed<T,3> instead!
00103   // \deprecated
00104   vnl_vector(unsigned len, T const& px, T const& py, T const& pz);
00105 
00106   //: Creates a vector of length 4 and initializes with the arguments.
00107   //  Requires that len==4.
00108   //  Consider using vnl_vector_fixed<T,4> instead!
00109   // \deprecated
00110   vnl_vector(unsigned len, T const& px, T const& py, T const& pz, T const& pw);
00111 #endif
00112 
00113   //: Create n element vector and copy data from data_block
00114   vnl_vector(T const* data_block,unsigned int n);
00115 
00116   //: Copy constructor
00117   vnl_vector(vnl_vector<T> const&);
00118 
00119 #ifndef VXL_DOXYGEN_SHOULD_SKIP_THIS
00120 // <internal>
00121   // These constructors are here so that operator* etc can take
00122   // advantage of the C++ return value optimization.
00123   vnl_vector(vnl_vector<T> const &, vnl_vector<T> const &, vnl_tag_add); // v + v
00124   vnl_vector(vnl_vector<T> const &, vnl_vector<T> const &, vnl_tag_sub); // v - v
00125   vnl_vector(vnl_vector<T> const &, T,                     vnl_tag_mul); // v * s
00126   vnl_vector(vnl_vector<T> const &, T,                     vnl_tag_div); // v / s
00127   vnl_vector(vnl_vector<T> const &, T,                     vnl_tag_add); // v + s
00128   vnl_vector(vnl_vector<T> const &, T,                     vnl_tag_sub); // v - s
00129   vnl_vector(vnl_matrix<T> const &, vnl_vector<T> const &, vnl_tag_mul); // M * v
00130   vnl_vector(vnl_vector<T> const &, vnl_matrix<T> const &, vnl_tag_mul); // v * M
00131   vnl_vector(vnl_vector<T> &that, vnl_tag_grab)
00132     : num_elmts(that.num_elmts), data(that.data)
00133   { that.num_elmts=0; that.data=0; } // "*this" now uses "that"'s data.
00134 // </internal>
00135 #endif
00136 
00137   //: Destructor
00138   ~vnl_vector();
00139 
00140   //: Return the length, number of elements, dimension of this vector.
00141   unsigned size() const { return num_elmts; }
00142 
00143   //: Put value at given position in vector.
00144   inline void put(unsigned int i, T const&);
00145 
00146   //: Get value at element i
00147   inline T get(unsigned int i) const;
00148 
00149   //: Set all values to v
00150   vnl_vector& fill(T const& v);
00151 
00152   //: Sets elements to ptr[i]
00153   //  Note: ptr[i] must be valid for i=0..size()-1
00154   vnl_vector& copy_in(T const * ptr);
00155 
00156   //: Copy elements to ptr[i]
00157   //  Note: ptr[i] must be valid for i=0..size()-1
00158   void copy_out(T *) const; // from vector to array[].
00159 
00160   //: Sets elements to ptr[i]
00161   //  Note: ptr[i] must be valid for i=0..size()-1
00162   vnl_vector& set(T const *ptr) { return copy_in(ptr); }
00163 
00164   //: Return reference to the element at specified index.
00165   // There are assert style boundary checks - #define NDEBUG to turn them off.
00166   T       & operator()(unsigned int i)
00167   {
00168 #if VNL_CONFIG_CHECK_BOUNDS
00169     assert(i<size());   // Check the index is valid.
00170 #endif
00171     return data[i];
00172   }
00173   //: Return reference to the element at specified index. No range checking.
00174   // There are assert style boundary checks - #define NDEBUG to turn them off.
00175   T const & operator()(unsigned int i) const
00176   {
00177 #if VNL_CONFIG_CHECK_BOUNDS
00178     assert(i<size());   // Check the index is valid
00179 #endif
00180     return data[i];
00181   }
00182 
00183   //: Return reference to the element at specified index. No range checking.
00184   T       & operator[](unsigned int i) { return data[i]; }
00185   //: Return reference to the element at specified index. No range checking.
00186   T const & operator[](unsigned int i) const { return data[i]; }
00187 
00188   //: Set all elements to value v
00189   vnl_vector<T>& operator=(T const&v) { fill(v); return *this; }
00190 
00191   //: Copy operator
00192   vnl_vector<T>& operator=(vnl_vector<T> const& rhs);
00193 
00194   //: Add scalar value to all elements
00195   vnl_vector<T>& operator+=(T );
00196 
00197   //: Subtract scalar value from all elements
00198   vnl_vector<T>& operator-=(T value) { return *this += T(-value); }
00199 
00200   //: Multiply all elements by scalar
00201   vnl_vector<T>& operator*=(T );
00202 
00203   //: Divide all elements by scalar
00204   vnl_vector<T>& operator/=(T );
00205 
00206   //: Add rhs to this and return *this
00207   vnl_vector<T>& operator+=(vnl_vector<T> const& rhs);
00208 
00209   //: Subtract rhs from this and return *this
00210   vnl_vector<T>& operator-=(vnl_vector<T> const& rhs);
00211 
00212   //: *this = M*(*this) where M is a suitable matrix.
00213   //  this is treated as a column vector
00214   vnl_vector<T>& pre_multiply(vnl_matrix<T> const& M);
00215 
00216   //: *this = (*this)*M where M is a suitable matrix.
00217   //  this is treated as a row vector
00218   vnl_vector<T>& post_multiply(vnl_matrix<T> const& M);
00219 
00220   //: *this = (*this)*M where M is a suitable matrix.
00221   //  this is treated as a row vector
00222   vnl_vector<T>& operator*=(vnl_matrix<T> const& m) { return this->post_multiply(m); }
00223 
00224   //: Unary plus operator
00225   // Return new vector = (*this)
00226   vnl_vector<T> operator+() const { return *this; }
00227 
00228   //: Unary minus operator
00229   // Return new vector = -1*(*this)
00230   vnl_vector<T> operator-() const;
00231 
00232   vnl_vector<T> operator+(T v) const { return vnl_vector<T>(*this, v, vnl_tag_add()); }
00233   vnl_vector<T> operator-(T v) const { return vnl_vector<T>(*this, v, vnl_tag_sub()); }
00234   vnl_vector<T> operator*(T v) const { return vnl_vector<T>(*this, v, vnl_tag_mul()); }
00235   vnl_vector<T> operator/(T v) const { return vnl_vector<T>(*this, v, vnl_tag_div()); }
00236 
00237   vnl_vector<T> operator+(vnl_vector<T> const& v) const { return vnl_vector<T>(*this, v, vnl_tag_add()); }
00238   vnl_vector<T> operator-(vnl_vector<T> const& v) const { return vnl_vector<T>(*this, v, vnl_tag_sub()); }
00239   vnl_vector<T> operator*(vnl_matrix<T> const& M) const { return vnl_vector<T>(*this, M, vnl_tag_mul()); }
00240 
00241   //--------------------------------------------------------------------------------
00242 
00243   //: Access the contiguous block storing the elements in the vector. O(1).
00244   //  data_block()[0] is the first element of the vector
00245   T const* data_block() const { return data; }
00246 
00247   //: Access the contiguous block storing the elements in the vector. O(1).
00248   //  data_block()[0] is the first element of the vector
00249   T      * data_block() { return data; }
00250 
00251   //: Type defs for iterators
00252   typedef T element_type;
00253   typedef unsigned  size_type;
00254 
00255   //: Type defs for iterators
00256   typedef T       *iterator;
00257   //: Iterator pointing to start of data
00258   iterator begin() { return data; }
00259 
00260   //: Iterator pointing to element beyond end of data
00261   iterator end() { return data+num_elmts; }
00262 
00263   //: Const iterator type
00264   typedef T const *const_iterator;
00265   //: Iterator pointing to start of data
00266   const_iterator begin() const { return data; }
00267   //: Iterator pointing to element beyond end of data
00268   const_iterator end() const { return data+num_elmts; }
00269 
00270   //: Return a reference to this.
00271   // Useful in code which would prefer not to know if its argument
00272   // is a vector, vector_ref or a vector_fixed.  Note that it doesn't
00273   // return a vector_ref, so it's only useful in templates or macros.
00274   vnl_vector<T> const& as_ref() const { return *this; }
00275 
00276   //: Return a reference to this.
00277   vnl_vector<T>&       as_ref()       { return *this; }
00278 
00279   //: Applies function to elements
00280   vnl_vector<T> apply(T (*f)(T)) const;
00281   //: Applies function to elements
00282   vnl_vector<T> apply(T (*f)(T const&)) const;
00283 
00284   //: Returns a subvector specified by the start index and length. O(n).
00285   vnl_vector<T> extract(unsigned int len, unsigned int start=0) const;
00286 
00287   //: Replaces elements with index beginning at start, by values of v. O(n).
00288   vnl_vector<T>& update(vnl_vector<T> const&, unsigned int start=0);
00289 
00290   // norms etc
00291   typedef typename vnl_c_vector<T>::abs_t abs_t;
00292 
00293   //: Return sum of squares of elements
00294   abs_t squared_magnitude() const { return vnl_c_vector<T>::two_nrm2(begin(), size()); }
00295 
00296   //: Return magnitude (length) of vector
00297   abs_t magnitude() const { return two_norm(); }
00298 
00299   //: Return sum of absolute values of the elements
00300   abs_t one_norm() const { return vnl_c_vector<T>::one_norm(begin(), size()); }
00301 
00302   //: Return sqrt of sum of squares of values of elements
00303   abs_t two_norm() const { return vnl_c_vector<T>::two_norm(begin(), size()); }
00304 
00305   //: Return largest absolute element value
00306   abs_t inf_norm() const { return vnl_c_vector<T>::inf_norm(begin(), size()); }
00307 
00308   //: Normalise by dividing through by the magnitude
00309   vnl_vector<T>& normalize() { vnl_c_vector<T>::normalize(begin(), size()); return *this; }
00310 
00311   // These next 6 functions are should really be helper functions since they aren't
00312   // really proper functions on a vector in a philosophical sense.
00313 
00314   //: Root Mean Squares of values
00315   abs_t rms() const { return vnl_c_vector<T>::rms_norm(begin(), size()); }
00316 
00317   //: Smallest value
00318   T min_value() const { return vnl_c_vector<T>::min_value(begin(), size()); }
00319 
00320   //: Largest value
00321   T max_value() const { return vnl_c_vector<T>::max_value(begin(), size()); }
00322 
00323   //: Location of smallest value
00324   unsigned arg_min() const { return vnl_c_vector<T>::arg_min(begin(), size()); }
00325 
00326   //: Location of largest value
00327   unsigned arg_max() const { return vnl_c_vector<T>::arg_max(begin(), size()); }
00328 
00329   //: Mean of values in vector
00330   T mean() const { return vnl_c_vector<T>::mean(begin(), size()); }
00331 
00332   //: Sum of values in a vector
00333   T sum() const { return vnl_c_vector<T>::sum(begin(), size()); }
00334 
00335   //: Reverse the order of the elements
00336   //  Element i swaps with element size()-1-i
00337   vnl_vector& flip();
00338 
00339   //: Set this to that and that to this
00340   void swap(vnl_vector<T> & that);
00341 
00342 #if VNL_CONFIG_LEGACY_METHODS // these methods are deprecated and should not be used
00343   //: Return first element of vector
00344   // \deprecated
00345   T& x() const { VXL_DEPRECATED("vnl_vector<T>::x()"); return data[0]; }
00346   //: Return second element of vector
00347   // \deprecated
00348   T& y() const { VXL_DEPRECATED("vnl_vector<T>::y()"); return data[1]; }
00349   //: Return third element of vector
00350   // \deprecated
00351   T& z() const { VXL_DEPRECATED("vnl_vector<T>::z()"); return data[2]; }
00352   //: Return fourth element of vector
00353   // \deprecated
00354   T& t() const { VXL_DEPRECATED("vnl_vector<T>::t()"); return data[3]; }
00355   //: Set the first element (with bound checking)
00356   // \deprecated
00357   void set_x(T const&xx) { VXL_DEPRECATED("vnl_vector<T>::set_x()"); if (size() >= 1) data[0] = xx; }
00358   //: Set the second element (with bound checking)
00359   // \deprecated
00360   void set_y(T const&yy) { VXL_DEPRECATED("vnl_vector<T>::set_y()"); if (size() >= 2) data[1] = yy; }
00361   //: Set the third element (with bound checking)
00362   // \deprecated
00363   void set_z(T const&zz) { VXL_DEPRECATED("vnl_vector<T>::set_z()"); if (size() >= 3) data[2] = zz; }
00364   //: Set the fourth element (with bound checking)
00365   // \deprecated
00366   void set_t(T const&tt) { VXL_DEPRECATED("vnl_vector<T>::set_t()"); if (size() >= 4) data[3] = tt; }
00367 #endif // VNL_CONFIG_LEGACY_METHODS
00368 
00369   //: Check that size()==sz if not, abort();
00370   // This function does or tests nothing if NDEBUG is defined
00371   void assert_size(unsigned sz) const {
00372 #ifndef NDEBUG
00373     assert_size_internal(sz);
00374 #endif
00375   }
00376 
00377   //: Check that this is finite if not, abort();
00378   // This function does or tests nothing if NDEBUG is defined
00379   void assert_finite() const {
00380 #ifndef NDEBUG
00381     assert_finite_internal();
00382 #endif
00383   }
00384 
00385   //: Return true if it's finite
00386   bool is_finite() const;
00387 
00388   //: Return true iff all the entries are zero.
00389   bool is_zero() const;
00390 
00391   //: Return true iff the size is zero.
00392   bool empty() const { return !data || !num_elmts; }
00393 
00394   //:  Return true if all elements of vectors are equal, within given tolerance
00395   bool is_equal(vnl_vector<T> const& rhs, double tol) const;
00396   
00397   //: Return true if *this == v
00398   bool operator_eq(vnl_vector<T> const& v) const;
00399 
00400   //: Equality test
00401   bool operator==(vnl_vector<T> const &that) const { return  this->operator_eq(that); }
00402 
00403   //: Inequality test
00404   bool operator!=(vnl_vector<T> const &that) const { return !this->operator_eq(that); }
00405 
00406   //: Resize to n elements.
00407   // This is a destructive resize, in that the old data is lost if size() != \a n before the call.
00408   // If size() is already \a n, this is a null operation.
00409   bool set_size(unsigned n);
00410 
00411   //: Make the vector as if it had been default-constructed.
00412   void clear();
00413 
00414   //: Read from text stream
00415   bool read_ascii(vcl_istream& s);
00416 
00417   //: Read from text stream
00418   static vnl_vector<T> read(vcl_istream& s);
00419 
00420  protected:
00421   unsigned num_elmts;           // Number of elements (length)
00422   T* data;                      // Pointer to the actual data
00423 
00424 #if VCL_HAS_SLICED_DESTRUCTOR_BUG
00425   // Since this bug exists, we need a flag that can be set during
00426   // construction to tell our destructor whether we own data.
00427   char vnl_vector_own_data;
00428 #endif
00429 
00430   void assert_size_internal(unsigned sz) const;
00431   void assert_finite_internal() const;
00432 
00433   void destroy();
00434 
00435 #if VCL_NEED_FRIEND_FOR_TEMPLATE_OVERLOAD
00436 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00437 # define v vnl_vector<T>
00438 # define m vnl_matrix<T>
00439 #endif // DOXYGEN_SHOULD_SKIP_THIS
00440   friend T      dot_product      VCL_NULL_TMPL_ARGS (v const&, v const&);
00441   friend T      inner_product    VCL_NULL_TMPL_ARGS (v const&, v const&);
00442   friend T      bracket          VCL_NULL_TMPL_ARGS (v const&, m const&, v const&);
00443   friend T      cos_angle        VCL_NULL_TMPL_ARGS (v const&, v const&);
00444   friend double angle            VCL_NULL_TMPL_ARGS (v const&, v const&);
00445   friend m      outer_product    VCL_NULL_TMPL_ARGS (v const&, v const&);
00446   friend v      operator+        VCL_NULL_TMPL_ARGS (T const,  v const&);
00447   friend v      operator-        VCL_NULL_TMPL_ARGS (T const,  v const&);
00448   friend v      operator*        VCL_NULL_TMPL_ARGS (T const,  v const&);
00449   friend v      operator*        VCL_NULL_TMPL_ARGS (m const&, v const&);
00450   friend v      element_product  VCL_NULL_TMPL_ARGS (v const&, v const&);
00451   friend v      element_quotient VCL_NULL_TMPL_ARGS (v const&, v const&);
00452 # undef v
00453 # undef m
00454 #endif
00455 
00456   // inline function template instantiation hack for gcc 2.97 -- fsm
00457   static void inline_function_tickler();
00458 };
00459 
00460 
00461 // Definitions of inline functions
00462 
00463 
00464 //: Gets the element at specified index and return its value. O(1).
00465 // Range check is performed.
00466 
00467 template <class T>
00468 inline T vnl_vector<T>::get(unsigned int index) const
00469 {
00470 #ifdef ERROR_CHECKING
00471   if (index >= this->num_elmts)     // If invalid index specified
00472     vnl_error_vector_index("get", index);  // Raise exception
00473 #endif
00474   return this->data[index];
00475 }
00476 
00477 //: Puts the value at specified index. O(1).
00478 // Range check is performed.
00479 
00480 template <class T>
00481 inline void vnl_vector<T>::put(unsigned int index, T const& value)
00482 {
00483 #ifdef ERROR_CHECKING
00484   if (index >= this->num_elmts)     // If invalid index specified
00485     vnl_error_vector_index("put", index); // Raise exception
00486 #endif
00487   this->data[index] = value;    // Assign data value
00488 }
00489 
00490 //: multiply matrix and (column) vector. O(m*n).
00491 // \relatesalso vnl_vector
00492 // \relatesalso vnl_matrix
00493 template<class T>
00494 inline vnl_vector<T> operator*(vnl_matrix<T> const& m, vnl_vector<T> const& v)
00495 {
00496   return vnl_vector<T>(m, v, vnl_tag_mul());
00497 }
00498 
00499 //: add scalar and vector. O(n).
00500 // \relatesalso vnl_vector
00501 template<class T>
00502 inline vnl_vector<T> operator+(T s, vnl_vector<T> const& v)
00503 {
00504   return vnl_vector<T>(v, s, vnl_tag_add());
00505 }
00506 
00507 //: subtract vector from scalar. O(n).
00508 // \relatesalso vnl_vector
00509 template<class T>
00510 inline vnl_vector<T> operator-(T s, vnl_vector<T> const& v)
00511 {
00512   return vnl_vector<T>(-v, s, vnl_tag_add());
00513 }
00514 
00515 //: multiply scalar and vector. O(n).
00516 // \relatesalso vnl_vector
00517 template<class T>
00518 inline vnl_vector<T> operator*(T s, vnl_vector<T> const& v)
00519 {
00520   return vnl_vector<T>(v, s, vnl_tag_mul());
00521 }
00522 
00523 //: Interchange the two vectors
00524 // \relatesalso vnl_vector
00525 template<class T>
00526 inline void swap(vnl_vector<T> &a, vnl_vector<T> &b) { a.swap(b); }
00527 
00528 //: Euclidean Distance between two vectors.
00529 // Sum of Differences squared.
00530 // \relatesalso vnl_vector
00531 template<class T>
00532 inline T vnl_vector_ssd(vnl_vector<T> const& v1, vnl_vector<T> const& v2)
00533 {
00534 #ifndef NDEBUG
00535   if (v1.size() != v2.size())
00536     vnl_error_vector_dimension("vnl_vector_ssd", v1.size(), v2.size());
00537 #endif
00538   return vnl_c_vector<T>::euclid_dist_sq(v1.begin(), v2.begin(), v1.size());
00539 }
00540 
00541 // Non-vector functions which are nevertheless very useful.
00542 
00543 //: Write vector to a vcl_ostream
00544 // \relatesalso vnl_vector
00545 export template <class T> vcl_ostream& operator<<(vcl_ostream &, vnl_vector<T> const&);
00546 //: Read vector from a vcl_istream
00547 // \relatesalso vnl_vector
00548 export template <class T> vcl_istream& operator>>(vcl_istream &, vnl_vector<T>      &);
00549 
00550 #endif // vnl_vector_h_