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