source: trunk/yat/utility/vector.cc @ 810

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

Changed to obey the general wisdom: If you write the same code snipet more than 2 times, make it a function.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.9 KB
Line 
1// $Id: vector.cc 810 2007-03-15 23:31:22Z jari $
2
3/*
4  Copyright (C) 2003 Daniel Dalevi, Peter Johansson
5  Copyright (C) 2004 Jari Häkkinen, Peter Johansson
6  Copyright (C) 2005 Jari Häkkinen, Peter Johansson, Markus Ringnér
7  Copyright (C) 2006, 2007 Jari Häkkinen, Peter Johansson
8
9  This file is part of the yat library, http://lev.thep.lu.se/trac/yat
10
11  The yat library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License as
13  published by the Free Software Foundation; either version 2 of the
14  License, or (at your option) any later version.
15
16  The yat library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24  02111-1307, USA.
25*/
26
27#include "vector.h"
28#include "matrix.h"
29#include "utility.h"
30
31#include <cassert>
32#include <cmath>
33#include <iostream>
34#include <sstream>
35#include <utility>
36#include <vector>
37
38namespace theplu {
39namespace yat {
40namespace utility {
41
42
43  vector::vector(void)
44    : v_(NULL), view_(NULL), view_const_(NULL), proxy_v_(NULL)
45  {
46  }
47
48
49  vector::vector(size_t n, double init_value)
50    : v_(gsl_vector_alloc(n)), view_(NULL), view_const_(NULL),
51      proxy_v_(v_)
52  {
53    if (!v_)
54      throw utility::GSL_error("vector::vector failed to allocate memory");
55
56    set_all(init_value);
57  }
58
59
60  vector::vector(const vector& other)
61    : v_(other.create_gsl_vector_copy()), view_(NULL),
62      view_const_(NULL), proxy_v_(v_)
63  {
64  }
65
66
67  vector::vector(vector& v, size_t offset, size_t n, size_t stride)
68    : view_const_(NULL)
69  {
70    view_ = new gsl_vector_view(gsl_vector_subvector_with_stride(v.v_,offset,
71                                                                 stride,n));
72    if (!view_)
73      throw utility::GSL_error("vector::vector failed to setup view");
74    proxy_v_ = v_ = &(view_->vector);
75  }
76
77
78  vector::vector(const vector& v, size_t offset, size_t n, size_t stride)
79    : v_(NULL), view_(NULL)
80  {
81    view_const_ = new gsl_vector_const_view(
82                   gsl_vector_const_subvector_with_stride(v.v_,offset,stride,n));
83    if (!view_const_)
84      throw utility::GSL_error("vector::vector failed to setup view");
85    proxy_v_ = &(view_const_->vector);
86  }
87
88
89  vector::vector(matrix& m, size_t i, bool row)
90    : view_const_(NULL)
91  {
92    view_=new gsl_vector_view(row ?
93                              gsl_matrix_row   (m.gsl_matrix_p(),i) :
94                              gsl_matrix_column(m.gsl_matrix_p(),i)  );
95    if (!view_)
96      throw utility::GSL_error("vector::vector failed to setup view");
97    proxy_v_ = v_ = &(view_->vector);
98  }
99
100
101  vector::vector(const matrix& m, size_t i, bool row)
102    : v_(NULL), view_(NULL)
103  {
104    view_const_ = new gsl_vector_const_view(row ?
105                                   gsl_matrix_const_row   (m.gsl_matrix_p(),i) :
106                                   gsl_matrix_const_column(m.gsl_matrix_p(),i) );
107    if (!view_const_)
108      throw utility::GSL_error("vector::vector failed to setup view");
109    proxy_v_ = &(view_const_->vector);
110  }
111
112
113  vector::vector(std::istream& is, char sep)
114    throw (utility::IO_error, std::exception)
115    : view_(NULL), view_const_(NULL)
116  {
117    // read the data file and store in stl vectors (dynamically
118    // expandable)
119    std::vector<std::vector<double> > data_matrix;
120    u_int nof_columns=0;
121    u_int nof_rows=0;
122    std::string line;
123    while(getline(is, line, '\n')) {
124      // Empty lines
125      if (!line.size())
126          continue;
127      nof_rows++;
128
129      std::vector<double> v;
130      std::string element;
131      std::stringstream ss(line);
132      bool ok=true;
133      while(ok) {
134        if(sep=='\0')
135          ok=(ss>>element);
136        else 
137          ok=getline(ss, element, sep);
138        if(!ok)
139          break;       
140
141        if(utility::is_double(element)) {
142          v.push_back(atof(element.c_str()));
143        }
144        else if (!element.size() || utility::is_nan(element)) {
145          v.push_back(std::numeric_limits<double>::quiet_NaN());
146        }
147        else {
148          std::stringstream ss("Warning: '");
149          ss << element << "' is not an integer.";
150          throw IO_error(ss.str());
151        }
152      } 
153      if(sep!='\0' && line[line.size()-1]==sep) // add NaN for final separator
154          v.push_back(std::numeric_limits<double>::quiet_NaN());
155      if (!nof_columns)
156        nof_columns=v.size();
157      else if (nof_rows && (nof_columns>1)) {
158        std::ostringstream s;
159        s << "vector::vector(std::istream&) data file error:\n"
160          << "    File has inconsistent number of rows (" << nof_rows
161          << ") and columns (" << nof_columns
162          << ").\n    Expected a row or a column vector.";
163        throw utility::IO_error(s.str());
164      }
165      else if (v.size()!=nof_columns) {
166        std::ostringstream s;
167        s << "vector::vector(std::istream&) data file error:\n"
168          << "    Line " << nof_rows << " has " << v.size()
169          << " columns; expected " << nof_columns << " column.";
170        throw utility::IO_error(s.str());
171      }
172      data_matrix.push_back(v);
173    }
174
175    // manipulate the state of the stream to be good
176    is.clear(std::ios::goodbit);
177    // convert the data to a gsl vector
178    proxy_v_ = v_ = gsl_vector_alloc(nof_rows*nof_columns);
179    if (!v_)
180      throw utility::GSL_error("vector::vector failed to allocate memory");
181    size_t n=0;
182    // if gsl error handler disabled, out of bounds index will not
183    // abort the program.
184    for (size_t i=0; i<nof_rows; i++)
185      for (size_t j=0; j<nof_columns; j++) 
186        gsl_vector_set( v_, n++, data_matrix[i][j] );
187  }
188
189
190  vector::~vector(void)
191  {
192    delete_allocated_memory();
193  }
194
195
196  const vector& vector::clone(const vector& other)
197  {
198    if (this!=&other) {
199
200      delete_allocated_memory();
201
202      if (other.view_) {
203        view_ = new gsl_vector_view(*other.view_);
204        proxy_v_ = v_ = &(view_->vector);
205      }
206      else if (other.view_const_) {
207        view_const_ = new gsl_vector_const_view(*other.view_const_);
208        proxy_v_ = &(view_const_->vector);
209        v_=NULL;
210      }
211      else if (other.v_)
212        proxy_v_ = v_ = other.create_gsl_vector_copy();
213
214    }
215    return *this;
216  } 
217
218
219  gsl_vector* vector::create_gsl_vector_copy(void) const
220  {
221    gsl_vector* vec = gsl_vector_alloc(size());
222    if (!vec)
223      throw utility::GSL_error("vector::create_gsl_vector_copy failed to allocate memory");
224    if (gsl_vector_memcpy(vec, proxy_v_))
225      throw utility::GSL_error("vector::create_gsl_matrix_copy dimension mis-match");
226    return vec;
227  }
228
229
230  void vector::delete_allocated_memory(void)
231  {
232    if (view_)
233      delete view_;
234    else if (view_const_)
235      delete view_const_;
236    else if (v_)
237      gsl_vector_free(v_);
238    proxy_v_=v_=NULL;
239  }
240
241
242  void vector::div(const vector& other)
243  {
244    assert(v_);
245    int status=gsl_vector_div(v_,other.gsl_vector_p());
246    if (status)
247      throw utility::GSL_error(std::string("vector::div",status));
248  }
249
250
251  bool vector::equal(const vector& other, const double d) const
252  {
253    if (this==&other)
254      return true;
255    if (size()!=other.size())
256      return false;
257    // if gsl error handler disabled, out of bounds index will not
258    // abort the program.
259    for (size_t i=0; i<size(); ++i)
260      // The two last condition checks are needed for NaN detection
261      if (fabs( (*this)(i)-other(i) ) > d ||
262          (*this)(i)!=(*this)(i) || other(i)!=other(i))
263        return false;
264    return true;
265  }
266
267
268  const gsl_vector* vector::gsl_vector_p(void) const
269  {
270    return proxy_v_;
271  }
272
273
274  gsl_vector* vector::gsl_vector_p(void)
275  {
276    return v_;
277  }
278
279
280  bool vector::isview(void) const
281  {
282    return view_ || view_const_;
283  }
284
285
286  void vector::mul(const vector& other)
287  {
288    assert(v_);
289    int status=gsl_vector_mul(v_,other.gsl_vector_p());
290    if (status)
291      throw utility::GSL_error(std::string("vector::mul",status));
292  }
293
294
295  void vector::resize(size_t n, double init_value)
296  {
297    delete_allocated_memory();
298    proxy_v_ = v_ = gsl_vector_alloc(n);
299    if (!v_)
300      throw utility::GSL_error("vector::vector failed to allocate memory");
301    set_all(init_value);
302  } 
303
304
305  void vector::reverse(void)
306  {
307    assert(v_);
308    gsl_vector_reverse(v_);
309  }
310
311
312  void vector::set(const vector& vec)
313  {
314    assert(v_);
315    if (gsl_vector_memcpy(v_,vec.gsl_vector_p()))
316      throw utility::GSL_error("vector::set dimension mis-match");
317  }
318
319
320  void vector::set_all(const double& value)
321  {
322    assert(v_);
323    gsl_vector_set_all(v_,value);
324  }
325
326
327  size_t vector::size(void) const
328  {
329    if (!proxy_v_)
330      return 0;
331    return proxy_v_->size;
332  }
333
334
335  void vector::swap(size_t i, size_t j)
336  {
337    assert(v_);
338    int status=gsl_vector_swap_elements(v_, i, j);
339    if (status)
340      throw utility::GSL_error(std::string("vector::swap_elements",status));
341  }
342
343
344  double& vector::operator()(size_t i)
345  {
346    assert(v_);
347    double* d=gsl_vector_ptr(v_, i);
348    if (!d)
349      throw utility::GSL_error("vector::operator()",GSL_EINVAL);
350    return *d;
351  }
352
353
354  const double& vector::operator()(size_t i) const
355  {
356    const double* d=gsl_vector_const_ptr(proxy_v_, i);
357    if (!d)
358      throw utility::GSL_error("vector::operator()",GSL_EINVAL);
359    return *d;
360  }
361
362
363  double& vector::operator[](size_t i)
364  {
365    return this->operator()(i);
366  }
367
368
369  const double& vector::operator[](size_t i) const
370  {
371    return this->operator()(i);
372  }
373
374
375  bool vector::operator==(const vector& other) const
376  {
377    return equal(other);
378  }
379
380
381  bool vector::operator!=(const vector& other) const
382  {
383    return !equal(other);
384  }
385
386
387  double vector::operator*( const vector &other ) const
388  {
389    double res = 0.0;;
390    for ( size_t i = 0; i < size(); ++i ) 
391      res += other(i) * (*this)(i);
392    return res;
393  }
394
395
396  const vector& vector::operator=( const vector& other )
397  {
398    set(other);
399    return *this;
400  } 
401
402
403  const vector& vector::operator+=(const vector& other)
404  {
405    assert(v_);
406    int status=gsl_vector_add(v_, other.gsl_vector_p());
407    if (status)
408      throw utility::GSL_error(std::string("vector::add", status));
409    return *this;
410  }
411
412
413  const vector& vector::operator+=(double d)
414  {
415    assert(v_);
416    gsl_vector_add_constant(v_, d);
417    return *this;
418  }
419
420
421  const vector& vector::operator-=(const vector& other)
422  {
423    assert(v_);
424    int status=gsl_vector_sub(v_, other.gsl_vector_p());
425    if (status)
426      throw utility::GSL_error(std::string("vector::sub", status));
427    return *this;
428  }
429
430
431  const vector& vector::operator-=(const double d)
432  {
433    assert(v_);
434    gsl_vector_add_constant(v_, -d);
435    return *this;
436  }
437
438
439  const vector& vector::operator*=(const double d)
440  {
441    assert(v_);
442    gsl_vector_scale(v_, d);
443    return *this;
444  }
445
446
447  bool isnull(const vector& v)
448  {
449    return gsl_vector_isnull(v.gsl_vector_p());
450  }
451
452
453  double max(const vector& v)
454  {
455    return gsl_vector_max(v.gsl_vector_p());
456  }
457
458
459  size_t max_index(const vector& v)
460  {
461    return gsl_vector_max_index(v.gsl_vector_p());
462  }
463
464
465  double min(const vector& v)
466  {
467    return gsl_vector_min(v.gsl_vector_p());
468  }
469
470
471  size_t min_index(const vector& v)
472  {
473    return gsl_vector_min_index(v.gsl_vector_p());
474  }
475
476
477  std::pair<double,double> minmax(const vector& v)
478  {
479    std::pair<double,double> minmax;
480    gsl_vector_minmax(v.gsl_vector_p(), &minmax.first, &minmax.second);
481    return minmax;
482  }
483
484
485  std::pair<size_t,size_t> minmax_index(const vector& v)
486  {
487    std::pair<size_t,size_t> minmax;
488    gsl_vector_minmax_index(v.gsl_vector_p(), &minmax.first, &minmax.second);
489    return minmax;
490  }
491
492
493  bool nan(const vector& templat, vector& flag)
494  {
495    size_t rows=templat.size();
496    if (rows!=flag.size())
497      flag.clone(vector(rows,1.0));
498    else
499      flag.set_all(1.0);
500    bool nan=false;
501    for (size_t i=0; i<rows; i++)
502      if (std::isnan(templat(i))) {
503        flag(i)=0;
504        nan=true;
505      }
506    return nan;
507  }
508
509
510  void set_basis(vector& v, size_t i)
511  {
512    assert(v.gsl_vector_p());
513    gsl_vector_set_basis(v.gsl_vector_p(),i);
514  }
515
516
517  void sort(vector& v)
518  {
519    assert(v.gsl_vector_p());
520    gsl_sort_vector(v.gsl_vector_p());
521  }
522
523
524  double sum(const vector& v)
525  {
526    double sum = 0;
527    size_t vsize=v.size();
528    for (size_t i=0; i<vsize; ++i)
529      sum += v[i];
530    return sum;
531  }
532
533
534  void swap(vector& v, vector& w)
535  {
536    assert(v.gsl_vector_p()); assert(w.gsl_vector_p());
537    int status=gsl_vector_swap(v.gsl_vector_p(),w.gsl_vector_p());
538    if (status)
539      throw utility::GSL_error(std::string("swap(vector&,vector&)",status));
540  }
541
542
543  std::ostream& operator<<(std::ostream& s, const vector& a)
544  {
545    s.setf(std::ios::dec);
546    s.precision(12);
547    for (size_t j = 0; j < a.size(); ++j) {
548      s << a[j];
549      if ( (j+1)<a.size() )
550        s << s.fill();
551    }
552    return s;
553  }
554
555}}} // of namespace utility, yat, and thep
Note: See TracBrowser for help on using the repository browser.