source: trunk/yat/utility/vector.h @ 703

Last change on this file since 703 was 703, checked in by Jari Häkkinen, 16 years ago

Addresses #65 and #170.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.8 KB
Line 
1#ifndef _theplu_yat_utility_vector_
2#define _theplu_yat_utility_vector_
3
4// $Id: vector.h 703 2006-12-18 00:47:44Z jari $
5
6/*
7  Copyright (C) 2003 Daniel Dalevi, Peter Johansson
8  Copyright (C) 2004 Jari Häkkinen, Peter Johansson
9  Copyright (C) 2005 Jari Häkkinen, Peter Johansson, Markus Ringnér
10  Copyright (C) 2006 Jari Häkkinen
11
12  This file is part of the yat library, http://lev.thep.lu.se/trac/yat
13
14  The yat library is free software; you can redistribute it and/or
15  modify it under the terms of the GNU General Public License as
16  published by the Free Software Foundation; either version 2 of the
17  License, or (at your option) any later version.
18
19  The yat library is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23
24  You should have received a copy of the GNU General Public License
25  along with this program; if not, write to the Free Software
26  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27  02111-1307, USA.
28*/
29
30#include "Exception.h"
31
32#include <iostream>
33#include <vector>
34#include <utility>
35
36#include <gsl/gsl_vector.h>
37#include <gsl/gsl_sort_vector.h>
38
39namespace theplu {
40namespace yat {
41namespace utility {
42
43  class matrix;
44
45  /**
46     This is the yat interface to GSL vector. 'double' is the only
47     type supported, maybe we should add a 'complex' type as well in
48     the future.
49
50     \par File streams:
51     Reading and writing vectors to file streams are of course
52     supported. These are implemented without using GSL functionality,
53     and thus binary read and write to streams are not supported.
54
55     \par Vector views:
56     GSL vector views are supported and these are disguised as
57     ordinary utility::vectors. A support function is added,
58     utility::vector::isview(), that can be used to check if a vector
59     object is a view. Note that view vectors do not own the
60     underlying data, and a view is not valid if the vector owing the
61     data is deallocated.
62
63     \par
64     Currently there is no restriction on how a vector is used in
65     cases when the vector is a const view into another vector or
66     matrix. To avoid unexpected runtime errors, the programmer must
67     declare const view vectors as const in order to get compile time
68     diagnostics about improper use of a const view vector object. An
69     example of improper use of a const view vector is assignment of
70     values to an element in the object. If the const view object was
71     declared const the assigment will be caught by the compiler
72     whereas it will cause a (un-catchable) runtime error. Example:
73     @code
74  const vector vm(13,1.0);
75  vector v1(vm,2,4);       // bad code! not const!
76  v1(0)=-123;              // accepted by compiler, runtime abort will occur
77  const vector v2(vm,2,4); // proper code
78  v2(0)=-123;              // not acceptable for the compiler
79     @endcode
80
81     @note Missing support to underlying GSL vector features can in
82     principle be included to this class if requested by the user
83     community.
84  */
85
86  class vector
87  {
88  public:
89
90    ///
91    /// The default constructor.
92    ///
93    vector(void);
94
95    ///
96    /// Constructor. Allocates memory space for \a n elements, and
97    /// sets all elements to \a init_value.
98    ///
99    vector(size_t n, double init_value=0);
100
101    ///
102    /// The copy constructor.
103    ///
104    /// @note If the object to be copied is a vector view, the values
105    /// of the view will be copied, i.e. the view is not copied.
106    ///
107    vector(const vector& other);
108
109    ///
110    /// Vector view constructor.
111    ///
112    /// Create a view of vector \a v, with starting index \a offset,
113    /// size \a n, and an optional \a stride.
114    ///
115    /// A vector view can be used as any vector with the difference
116    /// that changes made to the view will also change the object that
117    /// is viewed. Also, using the copy constructor will create a new
118    /// vector object that is a copy of whatever is viewed. If a copy
119    /// of the view is needed then you should use this constructor to
120    /// obtain a copy.
121    ///
122    /// @note If the object viewed by the view goes out of scope or is
123    /// deleted, the view becomes invalid and the result of further
124    /// use is undefined.
125    ///
126    vector(vector& v, size_t offset, size_t n, size_t stride=1);
127
128    ///
129    /// Vector const view constructor.
130    ///
131    /// Create a view of vector \a v, with starting index \a offset,
132    /// size \a n, and an optional \a stride.
133    ///
134    /// A vector view can be used as any const vector. Using the copy
135    /// constructor will create a new vector object that is a copy of
136    /// whatever is viewed. If a copy of the view is needed then you
137    /// should use this constructor to obtain a copy.
138    ///
139    /// @note If the object viewed by the view goes out of scope or is
140    /// deleted, the view becomes invalid and the result of further
141    /// use is undefined.
142    ///
143    vector(const vector& v, size_t offset, size_t n, size_t stride=1);
144
145    ///
146    /// Matrix row/column view constructor.
147    ///
148    /// Create a row/column vector view of matrix \a m, pointing at
149    /// row/column \a i. The parameter \a row is used to set whether
150    /// the view should be a row or column view. If \a row is set to
151    /// true, the view will be a row view (default behaviour), and,
152    /// naturally, a column view otherwise.
153    ///
154    /// A vector view can be used as any vector with the difference
155    /// that changes made to the view will also change the object that
156    /// is viewed. Also, using the copy constructor will create a new
157    /// vector object that is a copy of whatever is viewed. If a copy
158    /// of the view is needed then you should use the vector view
159    /// constructor to obtain a copy.
160    ///
161    /// @note If the object viewed by the view goes out of scope or is
162    /// deleted, the view becomes invalid and the result of further
163    /// use is undefined.
164    ///
165    vector(matrix& m, size_t i, bool row=true);
166
167    ///
168    /// Matrix row/column const view constructor.
169    ///
170    /// Create a row/column vector view of matrix \a m, pointing at
171    /// row/column \a i. The parameter \a row is used to set whether
172    /// the view should be a row or column view. If \a row is set to
173    /// true, the view will be a row view (default behaviour), and,
174    /// naturally, a column view otherwise.
175    ///
176    /// A const vector view can be used as any const vector. Using the
177    /// copy constructor will create a new vector object that is a
178    /// copy of whatever is viewed. If a copy of the view is needed
179    /// then you should use the vector view constructor to obtain a
180    /// copy.
181    ///
182    /// @note If the object viewed by the view goes out of scope or is
183    /// deleted, the view becomes invalid and the result of further
184    /// use is undefined.
185    ///
186    vector(const matrix& m, size_t i, bool row=true);
187
188    ///
189    /// The istream constructor.
190    ///
191    /// Either elements should be separated
192    /// with white space characters (default), or elements should be separated
193    /// by the delimiter \a sep. When delimiter \a sep is used empty elements
194    /// are stored as NaN's (except that empty lines are ignored). The
195    /// end of input to the vector is at end of file marker.
196    ///
197    explicit vector(std::istream &, char sep='\0')
198      throw(utility::IO_error, std::exception);
199
200    ///
201    /// The destructor.
202    ///
203    ~vector(void);
204
205    ///
206    /// Vector addition, \f$ this_i = this_i + other_i \; \forall i \f$.
207    ///
208    /// @return GSL_SUCCESS on normal exit.
209    ///
210    // Jari, group as vector_operators
211    inline int add(const vector& other) { return gsl_vector_add(v_,other.v_); }
212
213    ///
214    /// Add a constant to a vector, \f$ this_i = this_i + term \;
215    /// \forall i \f$.
216    ///
217    /// @return GSL_SUCCESS on normal exit.
218    ///
219    // Jari, group as vector_operators
220    inline int add(double term) { return gsl_vector_add_constant(v_,term); }
221
222    ///
223    /// This function performs element-wise division, \f$ this_i =
224    /// this_i/other_i \; \forall i \f$.
225    ///
226    /// @return GSL_SUCCESS on normal exit.
227    ///
228    // Jari, doxygen group as Vector operators
229    inline int div(const vector& other) { return gsl_vector_div(v_,other.v_); }
230
231    ///
232    /// @return A const pointer to the internal GSL vector,
233    ///
234    inline const gsl_vector* gsl_vector_p(void) const { return proxy_v_; }
235
236    ///
237    /// @return A pointer to the internal GSL vector,
238    ///
239    inline gsl_vector* gsl_vector_p(void) { return v_; }
240
241    ///
242    /// @return True if all elements in the vector is zero, false
243    /// othwerwise;
244    ///
245    inline bool isnull(void) const { return gsl_vector_isnull(proxy_v_); }
246
247    ///
248    /// Check if the vector object is a view (sub-vector) to another
249    /// vector.
250    ///
251    /// @return True if the object is a view, false othwerwise.
252    ///
253    inline bool isview(void) const { return view_ || view_const_; }
254
255    ///
256    /// @return The maximum value of the vector.
257    ///
258    // Jari, doxygen group as Finding maximum and minimum elements
259    inline double max(void) const { return gsl_vector_max(proxy_v_); }
260
261    ///
262    /// @return The element index to the maximum value of the
263    /// vector. The lowest index has precedence.
264    ///
265    // Jari, doxygen group as Finding maximum and minimum elements
266    inline size_t
267    max_index(void) const { return gsl_vector_max_index(proxy_v_); }
268
269    ///
270    /// @return The minimum value of the vector.
271    ///
272    // Jari, doxygen group as Finding maximum and minimum elements
273    inline double min(void) const { return gsl_vector_min(proxy_v_); }
274
275    ///
276    /// @return The element index to the minimum value of the
277    /// vector. The lowest index has precedence.
278    ///
279    // Jari, doxygen group as Finding maximum and minimum elements
280    inline size_t
281    min_index(void) const { return gsl_vector_min_index(proxy_v_); }
282
283    ///
284    /// @return The minimum and maximum values of the vector, as the
285    /// \a first and \a second member of the returned \a pair,
286    /// respectively.
287    ///
288    // Jari, doxygen group as Finding maximum and minimum elements
289    std::pair<double,double> minmax(void) const;
290
291    ///
292    /// @return The indecies to the minimum and maximum values of the
293    /// vector, as the \a first and \a second member of the returned
294    /// \a pair, respectively. The lowest index has precedence.
295    ///
296    // Jari, doxygen group as Finding maximum and minimum elements
297    std::pair<size_t,size_t> minmax_index(void) const;
298
299    ///
300    /// This function performs element-wise multiplication, \f$ this_i =
301    /// this_i * other_i \; \forall i \f$.
302    ///
303    /// @return GSL_SUCCESS on normal exit.
304    ///
305    // Jari, doxygen group as Vector operators
306    inline int mul(const vector& other) { return gsl_vector_mul(v_,other.v_); }
307
308    ///
309    /// Reverse the order of elements in the vector.
310    ///
311    /// @return GSL_SUCCESS on normal exit.
312    ///
313    // Jari, doxygen group as Exchanging elements
314    inline int reverse(void) { return gsl_vector_reverse(v_);}
315
316    ///
317    /// Rescale vector, \f$ this_i = this_i * factor \; \forall i \f$.
318    ///
319    /// @return GSL_SUCCESS on normal exit.
320    ///
321    // Jari, doxygen group as Vector operators
322    inline int scale(double factor) { return gsl_vector_scale(v_,factor); }
323
324    ///
325    /// Set element values to values in \a vec. This function is
326    /// needed for assignment of viewed elements.
327    ///
328    /// @return Whatever GSL returns.
329    ///
330    /// @note No check on size is done.
331    ///
332    /// @see const vector& operator=(const vector&)
333    ///
334    inline int set(const vector& vec) { return gsl_vector_memcpy(v_,vec.v_); }
335
336    ///
337    /// Set all elements to \a value.
338    ///
339    // Jari, doxygen group as Initializing vector elements
340    inline void set_all(const double& value) { gsl_vector_set_all(v_,value); }
341
342    ///
343    /// Makes a basis vector by setting all elements to
344    /// zero except the \a i-th element which is set to
345    /// one.
346    ///
347    // Jari, doxygen group as Initializing vector elements
348    inline void set_basis(const size_t i) { gsl_vector_set_basis(v_,i); }
349   
350    ///
351    /// Set all elements to zero.
352    ///
353    // Jari, doxygen group as Initializing vector elements
354    inline void set_zero(void) { gsl_vector_set_zero(v_); }
355
356    ///
357    /// @return the number of elements in the vector.
358    ///
359    inline size_t size(void) const { return proxy_v_->size; }
360
361    ///
362    /// Sort the elements in the vector.
363    ///
364    /// Bug in gsl: if vector contains NaN an infinite loop is entered.
365    ///
366    // Markus to Jari, doxygen group as Exchanging elements ????
367    inline void sort(void) { gsl_sort_vector(v_); }
368
369    ///
370    /// Vector subtraction, \f$ this_i = this_i - other_i \; \forall i \f$.
371    ///
372    /// @return GSL_SUCCESS on normal exit.
373    ///
374    // Jari, doxygen group as Vector operators
375    inline int sub(const vector& other) { return gsl_vector_sub(v_,other.v_); }
376
377    ///
378    /// Calculate the sum of all vector elements.
379    ///
380    /// @return The sum.
381    ///
382    double sum(void) const;
383
384    ///
385    /// Swap vector elements by copying. The two vectors must have the
386    /// same length.
387    ///
388    /// @return GSL_SUCCESS on normal exit.
389    ///
390    inline int swap(vector& other) { return gsl_vector_swap(v_,other.v_); }
391
392    ///
393    /// Exchange elements \a i and \a j.
394    ///
395    /// @return GSL_SUCCESS on normal exit.
396    ///
397    // Jari, doxygen group as Exchanging elements
398    inline int
399    swap_elements(size_t i,size_t j) { return gsl_vector_swap_elements(v_,i,j);}
400
401    ///
402    /// Element access operator.
403    ///
404    /// @return Reference to element \a i.
405    ///
406    // Jari, doxygen group as Accessing vector elements
407    inline double& operator()(size_t i) { return *gsl_vector_ptr(v_,i); }
408
409    ///
410    /// Const element access operator.
411    ///
412    /// @return The value of element \a i.
413    ///
414    // Jari, doxygen group as Accessing vector elements
415    inline const double&
416    operator()(size_t i) const { return *gsl_vector_const_ptr(proxy_v_,i); }
417
418    ///
419    /// Element access operator.
420    ///
421    /// @return Reference to element \a i.
422    ///
423    // Jari, doxygen group as Accessing vector elements
424    inline double& operator[](size_t i) { return *gsl_vector_ptr(v_,i); }
425
426    ///
427    /// Const element access operator.
428    ///
429    /// @return The value of element \a i.
430    ///
431    // Jari, doxygen group as Accessing vector elements
432    inline const double&
433    operator[](size_t i) const { return *gsl_vector_const_ptr(proxy_v_,i); }
434
435    ///
436    /// @return The dot product.
437    ///
438    double operator*(const vector&) const;
439
440    ///
441    /// Comparison operator. Takes linear time.
442    ///
443    /// @return True if the sequence of the elements in the vectors
444    /// are element/wise equal.
445    ///
446    bool operator==(const vector&) const;
447
448    ///
449    /// The assignment operator. There is no requirements on
450    /// dimensions, i.e. the vector is remapped in memory if
451    /// necessary. This implies that in general views cannot be
452    /// assigned using this operator. Views will be mutated into
453    /// normal vectors. The only exception to this behaviour on views
454    /// is when self-assignemnt is done, since self-assignment is
455    /// ignored.
456    ///
457    /// @return A const reference to the resulting vector.
458    ///
459    /// @see int set(const vector&)
460    ///
461    const vector& operator=(const vector&);
462
463    ///
464    /// Addition and assign operator.
465    ///
466    /// @return A const reference to the resulting vector.
467    ///
468    const vector& operator+=(const vector&);
469
470    ///
471    /// Subtract and assign operator.
472    ///
473    /// @return A const reference to the resulting vector.
474    ///
475    const vector& operator-=(const vector&);
476
477    ///
478    /// Multiply with scalar and assign operator.
479    ///
480    /// @return A const reference to the resulting vector.
481    ///
482    const vector& operator*=(const double);
483
484
485  private:
486
487    ///
488    /// Create a new copy of the internal GSL vector.
489    ///
490    /// Necessary memory for the new GSL vector is allocated and the
491    /// caller is responsible for freeing the allocated memory.
492    ///
493    /// @return A pointer to a copy of the internal GSL vector.
494    ///
495    gsl_vector* create_gsl_vector_copy(void) const;
496
497    gsl_vector* v_;
498    const gsl_vector* v_const_;
499    gsl_vector_view* view_;
500    gsl_vector_const_view* view_const_;
501    // proxy_v_ is used to access the proper underlying v_ or v_const_
502    // in all const member functions.
503    const gsl_vector* proxy_v_;
504  };
505
506  ///
507  /// The output operator for the vector class.
508  ///
509  std::ostream& operator<<(std::ostream&, const vector& );
510
511
512}}} // of namespace utility, yat, and theplu
513
514#endif
Note: See TracBrowser for help on using the repository browser.