1 // This is core/vnl/vnl_vector.h
2 #ifndef vnl_vector_h_
3 #define vnl_vector_h_
4 //:
5 // \file
6 // \author Andrew W. Fitzgibbon
7 //
8 // \verbatim
9 // Modifications
10 // Comments re-written by Tim Cootes, for his sins.
11 //   Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line
12 //   Mar.2009 - Peter Vanroose - added arg_min() and arg_max()
13 //   Oct.2010 - Peter Vanroose - mutators and setters now return *this
14 // \endverbatim
15 #include <iosfwd>
16 #include <vnl/vnl_error.h>
17 
18 #include <vcl_compiler.h>
19 #ifdef _MSC_VER
20 #  include <vcl_msvc_warnings.h>
21 #endif
22 #include <vnl/vnl_tag.h>
23 #include <vnl/vnl_c_vector.h>
24 #include <vnl/vnl_config.h>
25 #include <vnl/vnl_error.h>
26 #include "vnl/vnl_export.h"
27 #ifndef NDEBUG
28 # if VNL_CONFIG_CHECK_BOUNDS
29 #include <cassert>
30 # endif
31 #else
32 # undef VNL_CONFIG_CHECK_BOUNDS
33 # define VNL_CONFIG_CHECK_BOUNDS 0
34 # undef ERROR_CHECKING
35 #endif
36 
37 template <class T> class vnl_vector;
38 template <class T> class vnl_matrix;
39 
40 //----------------------------------------------------------------------
41 
42 #define v vnl_vector<T>
43 #define m vnl_matrix<T>
44 template <class T> VNL_EXPORT T      dot_product(v const&, v const&);
45 template <class T> VNL_EXPORT T      inner_product(v const&, v const&);
46 template <class T> VNL_EXPORT T      bracket(v const &, m const &, v const &);
47 template <class T> VNL_EXPORT T      cos_angle(v const&, v const& );
48 template <class T> VNL_EXPORT double angle(v const&, v const&);
49 template <class T> VNL_EXPORT m      outer_product(v const&, v const&);
50 template <class T> VNL_EXPORT v      operator+(T, v const&);
51 template <class T> VNL_EXPORT v      operator-(T, v const&);
52 template <class T> VNL_EXPORT v      operator*(T, v const&);
53 // also exists as method: template <class T> VNL_EXPORT v      operator*(m const&, v const&);
54 template <class T> VNL_EXPORT v      operator*(v const&, m const&);
55 template <class T> VNL_EXPORT v      element_product(v const&,v const&);
56 template <class T> VNL_EXPORT v      element_quotient(v const&,v const&);
57 template <class T> VNL_EXPORT T      vnl_vector_ssd(v const&, v const&);
58 template <class T> VNL_EXPORT void   swap(v &, v &);
59 #undef v
60 #undef m
61 
62 //----------------------------------------------------------------------
63 
64 //: Mathematical vector class, templated by type of element.
65 // The vnl_vector<T> class implements one-dimensional arithmetic
66 // vectors to be used with the vnl_matrix<T> class. vnl_vector<T>
67 // has size fixed by constructor time or changed by assignment
68 // operator.
69 // For faster, non-mallocing vectors with size known at compile
70 // time, use vnl_vector_fixed* or vnl_T_n (e.g. vnl_double_3).
71 //
72 // NOTE: Vectors are indexed from zero!  Thus valid elements are [0,size()-1].
73 template<class T>
74 class VNL_EXPORT vnl_vector
75 {
76  public:
77   friend class vnl_matrix<T>;
78 
79   //: Creates an empty vector. O(1).
vnl_vector()80   vnl_vector() : num_elmts(0) , data(nullptr) {}
81 
82   //: Creates a vector containing n uninitialized elements.
83   explicit vnl_vector(size_t len);
84 
85   //: Creates a vector containing n elements, all set to v0.
86   vnl_vector(size_t len, T const& v0);
87 
88   //: Creates a vector containing len elements, with the first n
89   // elements taken from the array values[]. O(n).
90   vnl_vector(size_t len, size_t n, T const values[]);
91 
92   //: Creates a vector containing len elements, initialized with values from
93   // a data block.
94   vnl_vector(T const* data_block,size_t n);
95 
96   //: Copy constructor.
97   vnl_vector(vnl_vector<T> const&);
98 
99 #ifndef VXL_DOXYGEN_SHOULD_SKIP_THIS
100 // <internal>
101   // These constructors are here so that operator* etc can take
102   // advantage of the C++ return value optimization.
103   vnl_vector(vnl_vector<T> const &, vnl_vector<T> const &, vnl_tag_add); // v + v
104   vnl_vector(vnl_vector<T> const &, vnl_vector<T> const &, vnl_tag_sub); // v - v
105   vnl_vector(vnl_vector<T> const &, T,                     vnl_tag_mul); // v * s
106   vnl_vector(vnl_vector<T> const &, T,                     vnl_tag_div); // v / s
107   vnl_vector(vnl_vector<T> const &, T,                     vnl_tag_add); // v + s
108   vnl_vector(vnl_vector<T> const &, T,                     vnl_tag_sub); // v - s
109   vnl_vector(vnl_matrix<T> const &, vnl_vector<T> const &, vnl_tag_mul); // M * v
110   vnl_vector(vnl_vector<T> const &, vnl_matrix<T> const &, vnl_tag_mul); // v * M
vnl_vector(vnl_vector<T> & that,vnl_tag_grab)111   vnl_vector(vnl_vector<T> &that, vnl_tag_grab)
112     : num_elmts(that.num_elmts), data(that.data)
113   { that.num_elmts=0; that.data=nullptr; } // "*this" now uses "that"'s data.
114 // </internal>
115 #endif
116 
117   //: Destructor
118 #ifdef __INTEL_COMPILER
119 #pragma warning disable 444 //destructor for base class "itk::Array<>" is not virtual
120 #endif
121   /** This destructor is not virtual for performance reasons. However, this
122    * means that subclasses cannot allocate memory. */
123   ~vnl_vector();
124 
125   //: Return the length, number of elements, dimension of this vector.
size()126   size_t size() const { return this->num_elmts; }
127 
128   //: Put value at given position in vector.
129   inline void put(size_t i, T const& v);
130 
131   //: Get value at element i
132   inline T get(size_t  i) const;
133 
134   //: Set all values to v
135   vnl_vector& fill(T const& v);
136 
137   //: Sets elements to ptr[i]
138   //  Note: ptr[i] must be valid for i=0..size()-1
139   vnl_vector& copy_in(T const * ptr);
140 
141   //: Copy elements to ptr[i]
142   //  Note: ptr[i] must be valid for i=0..size()-1
143   void copy_out(T *) const; // from vector to array[].
144 
145   //: Sets elements to ptr[i]
146   //  Note: ptr[i] must be valid for i=0..size()-1
set(T const * ptr)147   vnl_vector& set(T const *ptr) { return copy_in(ptr); }
148 
149   //: Return reference to the element at specified index.
150   // There are assert style boundary checks - #define NDEBUG to turn them off.
operator()151   T       & operator()(size_t i)
152   {
153 #if VNL_CONFIG_CHECK_BOUNDS
154     assert(i<size());   // Check the index is valid.
155 #endif
156     return data[i];
157   }
158   //: Return reference to the element at specified index. No range checking.
159   // There are assert style boundary checks - #define NDEBUG to turn them off.
operator()160   T const & operator()(size_t i) const
161   {
162 #if VNL_CONFIG_CHECK_BOUNDS
163     assert(i<size());   // Check the index is valid
164 #endif
165     return data[i];
166   }
167 
168   //: Return reference to the element at specified index. No range checking.
169   T       & operator[](size_t i) { return data[i]; }
170   //: Return reference to the element at specified index. No range checking.
171   T const & operator[](size_t i) const { return data[i]; }
172 
173   //: Set all elements to value v
174   vnl_vector<T>& operator=(T const&v) { fill(v); return *this; }
175 
176   //: Copy operator
177   vnl_vector<T>& operator=(vnl_vector<T> const& rhs);
178 
179   //: Add scalar value to all elements
180   vnl_vector<T>& operator+=(T );
181 
182   //: Subtract scalar value from all elements
183   vnl_vector<T>& operator-=(T value) { return *this += T(-value); }
184 
185   //: Multiply all elements by scalar
186   vnl_vector<T>& operator*=(T );
187 
188   //: Divide all elements by scalar
189   vnl_vector<T>& operator/=(T );
190 
191   //: Add rhs to this and return *this
192   vnl_vector<T>& operator+=(vnl_vector<T> const& rhs);
193 
194   //: Subtract rhs from this and return *this
195   vnl_vector<T>& operator-=(vnl_vector<T> const& rhs);
196 
197   //: *this = M*(*this) where M is a suitable matrix.
198   //  this is treated as a column vector
199   vnl_vector<T>& pre_multiply(vnl_matrix<T> const& M);
200 
201   //: *this = (*this)*M where M is a suitable matrix.
202   //  this is treated as a row vector
203   vnl_vector<T>& post_multiply(vnl_matrix<T> const& M);
204 
205   //: *this = (*this)*M where M is a suitable matrix.
206   //  this is treated as a row vector
207   vnl_vector<T>& operator*=(vnl_matrix<T> const& m) { return this->post_multiply(m); }
208 
209   //: Unary plus operator
210   // Return new vector = (*this)
211   vnl_vector<T> operator+() const { return *this; }
212 
213   //: Unary minus operator
214   // Return new vector = -1*(*this)
215   vnl_vector<T> operator-() const;
216 
217   vnl_vector<T> operator+(T v) const { return vnl_vector<T>(*this, v, vnl_tag_add()); }
218   vnl_vector<T> operator-(T v) const { return vnl_vector<T>(*this, v, vnl_tag_sub()); }
219   vnl_vector<T> operator*(T v) const { return vnl_vector<T>(*this, v, vnl_tag_mul()); }
220   vnl_vector<T> operator/(T v) const { return vnl_vector<T>(*this, v, vnl_tag_div()); }
221 
222   vnl_vector<T> operator+(vnl_vector<T> const& v) const { return vnl_vector<T>(*this, v, vnl_tag_add()); }
223   vnl_vector<T> operator-(vnl_vector<T> const& v) const { return vnl_vector<T>(*this, v, vnl_tag_sub()); }
224   vnl_vector<T> operator*(vnl_matrix<T> const& M) const { return vnl_vector<T>(*this, M, vnl_tag_mul()); }
225 
226   //--------------------------------------------------------------------------------
227 
228   //: Access the contiguous block storing the elements in the vector. O(1).
229   //  data_block()[0] is the first element of the vector
data_block()230   T const* data_block() const { return data; }
231 
232   //: Access the contiguous block storing the elements in the vector. O(1).
233   //  data_block()[0] is the first element of the vector
data_block()234   T      * data_block() { return data; }
235 
236   //: Type defs for iterators
237   typedef T element_type;
238   typedef size_t  size_type;
239 
240   //: Type defs for iterators
241   typedef T       *iterator;
242   //: Iterator pointing to start of data
begin()243   iterator begin() { return data; }
244 
245   //: Iterator pointing to element beyond end of data
end()246   iterator end() { return data+num_elmts; }
247 
248   //: Const iterator type
249   typedef T const *const_iterator;
250   //: Iterator pointing to start of data
begin()251   const_iterator begin() const { return data; }
252   //: Iterator pointing to element beyond end of data
end()253   const_iterator end() const { return data+num_elmts; }
254 
255   //: Return a reference to this.
256   // Useful in code which would prefer not to know if its argument
257   // is a vector, vector_ref or a vector_fixed.  Note that it doesn't
258   // return a vector_ref, so it's only useful in templates or macros.
as_ref()259   vnl_vector<T> const& as_ref() const { return *this; }
260 
261   //: Return a reference to this.
as_ref()262   vnl_vector<T>&       as_ref()       { return *this; }
263 
264   //: Applies function to elements
265   vnl_vector<T> apply(T (*f)(T)) const;
266   //: Applies function to elements
267   vnl_vector<T> apply(T (*f)(T const&)) const;
268 
269   //: Returns a subvector specified by the start index and length. O(n).
270   vnl_vector<T> extract(size_t len, size_t start=0) const;
271 
272   //: Replaces elements with index beginning at start, by values of v. O(n).
273   vnl_vector<T>& update(vnl_vector<T> const&, size_t start=0);
274 
275   // norms etc
276   typedef typename vnl_c_vector<T>::abs_t abs_t;
277 
278   //: Return sum of squares of elements
squared_magnitude()279   abs_t squared_magnitude() const { return vnl_c_vector<T>::two_nrm2(begin(), size()); }
280 
281   //: Return magnitude (length) of vector
magnitude()282   abs_t magnitude() const { return two_norm(); }
283 
284   //: Return sum of absolute values of the elements
one_norm()285   abs_t one_norm() const { return vnl_c_vector<T>::one_norm(begin(), size()); }
286 
287   //: Return sqrt of sum of squares of values of elements
two_norm()288   abs_t two_norm() const { return vnl_c_vector<T>::two_norm(begin(), size()); }
289 
290   //: Return largest absolute element value
inf_norm()291   abs_t inf_norm() const { return vnl_c_vector<T>::inf_norm(begin(), size()); }
292 
293   //: Normalise by dividing through by the magnitude
normalize()294   vnl_vector<T>& normalize() { vnl_c_vector<T>::normalize(begin(), size()); return *this; }
295 
296   // These next 6 functions are should really be helper functions since they aren't
297   // really proper functions on a vector in a philosophical sense.
298 
299   //: Root Mean Squares of values
rms()300   abs_t rms() const { return vnl_c_vector<T>::rms_norm(begin(), size()); }
301 
302   //: Smallest value
min_value()303   T min_value() const { return vnl_c_vector<T>::min_value(begin(), size()); }
304 
305   //: Largest value
max_value()306   T max_value() const { return vnl_c_vector<T>::max_value(begin(), size()); }
307 
308   //: Location of smallest value
arg_min()309   size_t arg_min() const { return vnl_c_vector<T>::arg_min(begin(), size()); }
310 
311   //: Location of largest value
arg_max()312   size_t arg_max() const { return vnl_c_vector<T>::arg_max(begin(), size()); }
313 
314   //: Mean of values in vector
mean()315   T mean() const { return vnl_c_vector<T>::mean(begin(), size()); }
316 
317   //: Sum of values in a vector
sum()318   T sum() const { return vnl_c_vector<T>::sum(begin(), size()); }
319 
320   //: Reverse the order of the elements
321   //  Element i swaps with element size()-1-i
322   vnl_vector<T>& flip();
323 
324   //: Reverse the order of the elements from index b to 1-e, inclusive.
325   //  When b = 0 and e = size(), this is equivalent to flip();
326   vnl_vector<T>& flip(const size_t &b, const size_t &e);
327 
328   //: Roll the vector forward by the specified shift.
329   //  The shift is cyclical, such that the elements which
330   //  are displaced from the end reappear at the beginning.
331   //  Negative shifts and shifts >= the length of the array are supported.
332   //  A new vector is returned; the underlying data is unchanged.
333   vnl_vector<T> roll(const int &shift) const;
334 
335   //: Roll the vector forward by the specified shift.
336   //  The shift is cyclical, such that the elements which
337   //  are displaced from the end reappear at the beginning.
338   //  Negative shifts and shifts >= the length of the array are supported.
339   //
340   vnl_vector& roll_inplace(const int &shift);
341 
342   //: Set this to that and that to this
343   void swap(vnl_vector<T> & that);
344 
345   //: Check that size()==sz if not, abort();
346   // This function does or tests nothing if NDEBUG is defined
assert_size(size_t VXL_USED_IN_DEBUG (sz))347   void assert_size(size_t VXL_USED_IN_DEBUG(sz) ) const {
348 #ifndef NDEBUG
349     assert_size_internal(sz);
350 #endif
351   }
352 
353   //: Check that this is finite if not, abort();
354   // This function does or tests nothing if NDEBUG is defined
assert_finite()355   void assert_finite() const {
356 #ifndef NDEBUG
357     assert_finite_internal();
358 #endif
359   }
360 
361   //: Return true if it's finite
362   bool is_finite() const;
363 
364   //: Return true iff all the entries are zero.
365   bool is_zero() const;
366 
367   //: Return true iff the size is zero.
empty()368   bool empty() const { return !data || !num_elmts; }
369 
370   //:  Return true if all elements of vectors are equal, within given tolerance
371   bool is_equal(vnl_vector<T> const& rhs, double tol) const;
372 
373   //: Return true if *this == v
374   bool operator_eq(vnl_vector<T> const& v) const;
375 
376   //: Equality test
377   bool operator==(vnl_vector<T> const &that) const { return  this->operator_eq(that); }
378 
379   //: Inequality test
380   bool operator!=(vnl_vector<T> const &that) const { return !this->operator_eq(that); }
381 
382   //: Resize to n elements.
383   // This is a destructive resize, in that the old data is lost if size() != \a n before the call.
384   // If size() is already \a n, this is a null operation.
385   bool set_size(size_t n);
386 
387   //: Make the vector as if it had been default-constructed.
388   void clear();
389 
390   //: Read from text stream
391   bool read_ascii(std::istream& s);
392 
393   //: Read from text stream
394   static vnl_vector<T> read(std::istream& s);
395 
396  protected:
397   size_t num_elmts;           // Number of elements (length)
398   T* data;                      // Pointer to the actual data
399 
400   void assert_size_internal(size_t sz) const;
401   void assert_finite_internal() const;
402 
403   void destroy();
404 };
405 
406 
407 // Definitions of inline functions
408 
409 
410 //: Gets the element at specified index and return its value. O(1).
411 // Range check is performed.
412 
413 template <class T>
414 inline T vnl_vector<T>
get(size_t i)415 ::get(size_t i) const
416 {
417 #if VNL_CONFIG_CHECK_BOUNDS
418   if (i >= this->size())     // If invalid index specified
419     vnl_error_vector_index("get", i);  // Raise exception
420 #endif
421   return this->data[i];
422 }
423 
424 //: Puts the value at specified index. O(1).
425 // Range check is performed.
426 
427 template <class T>
428 inline void vnl_vector<T>
put(size_t i,T const & v)429 ::put(size_t i, T const& v)
430 {
431 #if VNL_CONFIG_CHECK_BOUNDS
432   if (i >= this->size())     // If invalid index specified
433     vnl_error_vector_index("put", i); // Raise exception
434 #endif
435   this->data[i] = v;    // Assign data value
436 }
437 
438 //: multiply matrix and (column) vector. O(m*n).
439 // \relatesalso vnl_vector
440 // \relatesalso vnl_matrix
441 template<class T>
442 inline vnl_vector<T> operator*(vnl_matrix<T> const& m, vnl_vector<T> const& v)
443 {
444   return vnl_vector<T>(m, v, vnl_tag_mul());
445 }
446 
447 //: add scalar and vector. O(n).
448 // \relatesalso vnl_vector
449 template<class T>
450 inline vnl_vector<T> operator+(T s, vnl_vector<T> const& v)
451 {
452   return vnl_vector<T>(v, s, vnl_tag_add());
453 }
454 
455 //: subtract vector from scalar. O(n).
456 // \relatesalso vnl_vector
457 template<class T>
458 inline vnl_vector<T> operator-(T s, vnl_vector<T> const& v)
459 {
460   return vnl_vector<T>(-v, s, vnl_tag_add());
461 }
462 
463 //: multiply scalar and vector. O(n).
464 // \relatesalso vnl_vector
465 template<class T>
466 inline vnl_vector<T> operator*(T s, vnl_vector<T> const& v)
467 {
468   return vnl_vector<T>(v, s, vnl_tag_mul());
469 }
470 
471 //: Interchange the two vectors
472 // \relatesalso vnl_vector
473 template<class T>
swap(vnl_vector<T> & a,vnl_vector<T> & b)474 inline void swap(vnl_vector<T> &a, vnl_vector<T> &b) { a.swap(b); }
475 
476 //: Euclidean Distance between two vectors.
477 // Sum of Differences squared.
478 // \relatesalso vnl_vector
479 template<class T>
vnl_vector_ssd(vnl_vector<T> const & v1,vnl_vector<T> const & v2)480 inline T vnl_vector_ssd(vnl_vector<T> const& v1, vnl_vector<T> const& v2)
481 {
482 #ifndef NDEBUG
483   if (v1.size() != v2.size())
484     vnl_error_vector_dimension("vnl_vector_ssd", v1.size(), v2.size());
485 #endif
486   return vnl_c_vector<T>::euclid_dist_sq(v1.begin(), v2.begin(), v1.size());
487 }
488 
489 // Non-vector functions which are nevertheless very useful.
490 
491 //: Write vector to a std::ostream
492 // \relatesalso vnl_vector
493 template <class T> VNL_EXPORT std::ostream& operator<<(std::ostream &, vnl_vector<T> const&);
494 //: Read vector from a std::istream
495 // \relatesalso vnl_vector
496 template <class T> VNL_EXPORT std::istream& operator>>(std::istream &, vnl_vector<T>      &);
497 
498 #endif // vnl_vector_h_
499