KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsl_vector.h
Go to the documentation of this file.
1 
7 /*
8  * $Id: gsl_vector.h 17393 2014-08-23 20:19:14Z predoehl $
9  */
10 
11 #ifndef GSL_VECTOR_WRAP_H_KJBLIB_UARIZONAVISION
12 #define GSL_VECTOR_WRAP_H_KJBLIB_UARIZONAVISION
13 
14 #include <l/l_sys_sys.h>
15 #include <m_cpp/m_cpp_incl.h>
16 #include "gsl_cpp/gsl_util.h"
17 
18 #include <iterator>
19 
20 #ifdef KJB_HAVE_GSL
21 #include "gsl/gsl_vector.h" /* no need for extern "C" */
22 #else
23 
24 #warning "GNU GSL is absent, so GNU GSL wrapper will not work properly."
25 
26 /* Suprisingly, it seems we must define a nominal fake vector here, because the
27  * compiler apparently does a lot of inlining and it sees through most
28  * transparent ruses. So I'm basically giving it a working vector
29  * implementation, although the class Gsl_Vector itself should not be able to
30  * be instantiated (it should throw Missing_dependency in all ctors).
31  *
32  * (Later) I'm not sure this is really necessary, but if not it is no worse
33  * than a harmless delusion.
34  */
35 struct gsl_vector {
36  double* p; size_t size;
37  gsl_vector( size_t n ) : p( new double[ n ] ), size( n ) {}
38  ~gsl_vector() { delete[] p; }
39  double& at( size_t n ) { return p[n % size]; }
40  const double& at( size_t n ) const { return p[n % size]; }
41 };
42 #define gsl_vector_alloc(x) (new gsl_vector(x)) /* don't actually use this! */
43 /*
44  * It is sad but true: because multimin foists upon us raw, unwrapped
45  * gsl_vectors in its callback functions, it is simply easiest to use the
46  * native access methods. So it is also easiest to provide fake stand-ins when
47  * the library is absent. That is why the macros below are defined: they
48  * stand in when we compile without the library.
49  * Although the code below looks plausible, remember IT WILL NEVER BE EXECUTED.
50  * This is just elaborate scenery.
51  */
52 #define gsl_vector_set(w,i,x) ((w)->at(i)=(x))
53 #define gsl_vector_get(w,i) ((w)->at(i))
54 
55 #endif
56 
57 #if ! defined( KJB_HAVE_ISNAN ) || ! defined( KJB_HAVE_FINITE )
58 #warning "This code tests for NAN and finite values but your system lacks"
59 #warning "this feature. Method Gsl_Vector::is_normal will always return true."
60 #endif
61 
62 #include <ostream>
63 #include <cmath> /* required for isnormal(3) macro */
64 
65 namespace kjb {
66 
78 class Gsl_Vector {
79 
80  gsl_vector* m_vec;
81 
82  /*
83  * this private method should be called shortly after each invocation of
84  * gsl_vector_alloc() because we would like to maintain the invariant that
85  * m_vec is never allowed to remain equal to NULL.
86  */
87  void throw_if_null()
88  {
89  ETX_2( 00 == m_vec, "Memory allocation failure for Gsl_Vector" );
90  }
91 
92  // called by the at() methods
93  void check_bounds( size_t index ) const
94  {
95  /*
96  * GCC complains about this test: "that could never happen!!"
97  if ( index < 0 )
98  {
99  KJB_THROW( Index_out_of_bounds );
100  }
101  */
102  if ( size() <= index )
103  {
105  }
106  }
107 
108 public:
109 
111  Gsl_Vector( size_t dims )
112  : m_vec( gsl_vector_alloc( dims ) )
113  {
114 #ifdef KJB_HAVE_GSL
115  throw_if_null();
116 #else
117  KJB_THROW_2( Missing_dependency, "GNU GSL" );
118 #endif
119  }
120 
121 
123  explicit Gsl_Vector( const kjb::Vector& kv )
124  : m_vec( gsl_vector_alloc( kv.size() ) )
125  {
126 #ifdef KJB_HAVE_GSL
127  throw_if_null();
128  size_t KVSZ = std::max( kv.size(), 0 );
129  for( size_t iii = 0; iii < KVSZ; ++iii )
130  {
131  at( iii ) = kv.at( iii );
132  }
133 #else
134  KJB_THROW_2( Missing_dependency, "GNU GSL" );
135 #endif
136  }
137 
138 
140  Gsl_Vector( const Gsl_Vector& src )
141  : m_vec( gsl_vector_alloc( src.size() ) )
142  {
143 #ifdef KJB_HAVE_GSL
144  throw_if_null();
145  GSL_ETX( gsl_vector_memcpy( m_vec, src.m_vec ) );
146 #else
147  KJB_THROW_2( Missing_dependency, "GNU GSL" );
148 #endif
149  }
150 
151 
153  Gsl_Vector( const gsl_vector& vec_to_be_copied )
154  : m_vec( gsl_vector_alloc( vec_to_be_copied.size ) )
155  {
156 #ifdef KJB_HAVE_GSL
157  throw_if_null();
158  GSL_ETX( gsl_vector_memcpy( m_vec, &vec_to_be_copied ) );
159 #else
160  KJB_THROW_2( Missing_dependency, "GNU GSL" );
161 #endif
162  }
163 
164 
167  {
168 #ifdef KJB_HAVE_GSL
169  if ( m_vec != src.m_vec )
170  {
171  if ( size() == src.size() )
172  {
173  GSL_ETX( gsl_vector_memcpy( m_vec, src.m_vec ) );
174  }
175  else
176  {
177  Gsl_Vector clone( src ); // copy ctor makes a duplicate
178  swap( clone ); // then, become that duplicate
179  }
180  }
181 #endif
182  return *this;
183  }
184 
185  double* begin()
186  {
187 #ifdef KJB_HAVE_GSL
188  return gsl_vector_ptr( m_vec, 0 );
189 #else
190  return 00;
191 #endif
192  }
193 
194  const double* begin() const
195  {
196 #ifdef KJB_HAVE_GSL
197  return gsl_vector_const_ptr( m_vec, 0 );
198 #else
199  return 00;
200 #endif
201  }
202 
203  double* end()
204  {
205 #ifdef KJB_HAVE_GSL
206  return gsl_vector_ptr( m_vec, size() );
207 #else
208  return 00;
209 #endif
210  }
211 
212  const double* end() const
213  {
214 #ifdef KJB_HAVE_GSL
215  return gsl_vector_const_ptr( m_vec, size() );
216 #else
217  return 00;
218 #endif
219  }
220 
221 
223  void swap( Gsl_Vector& v )
224  {
225  using std::swap;
226  KJB(ASSERT( m_vec ));
227  KJB(ASSERT( v.m_vec ));
228  swap( m_vec, v.m_vec );
229  }
230 
231 
234  {
235  KJB(ASSERT( m_vec ));
236 #ifdef KJB_HAVE_GSL
237  gsl_vector_free( m_vec );
238 #else
239  delete m_vec;
240 #endif
241  }
242 
243 
245  template < class Iterator >
246  Gsl_Vector( Iterator begin, Iterator end )
247  : m_vec( gsl_vector_alloc( std::distance( begin, end ) ) )
248  {
249 #ifdef KJB_HAVE_GSL
250  throw_if_null();
251  size_t iii = 0;
252  for( Iterator cur = begin; cur != end; ++cur )
253  {
254  at( iii++ ) = *cur;
255  }
256 #else
257  KJB_THROW_2( Missing_dependency, "GNU GSL" );
258 #endif
259  }
260 
261 
263  size_t size() const
264  {
265  KJB(ASSERT( m_vec ));
266  return m_vec -> size;
267  }
268 
269 
270  /*
271  * Because of the transparent convert-to-pointer operator, we lose the
272  * ability to set the vector using square brackets, because square brackets
273  * are ambiguous -- are they an implicit pointer dereference, or do they
274  * refer to operator[] applied to the object?
275  * But you can still use at().
276  *
277  double operator[]( size_t index ) const
278  {
279  KJB(ASSERT( m_vec ));
280  return gsl_vector_get( m_vec, index );
281  }
282 
283  double& operator[]( size_t index )
284  {
285  KJB(ASSERT( m_vec );
286  return *gsl_vector_ptr( m_vec, index );
287  }
288  */
289 
290 
292  double at( size_t index ) const
293  {
294  KJB(ASSERT( m_vec ));
295 #ifdef KJB_HAVE_GSL
296  check_bounds( index );
297  return gsl_vector_get( m_vec, index );
298 #else
299  return m_vec -> at( index );
300 #endif
301  }
302 
303 
305  double& at( size_t index )
306  {
307  KJB(ASSERT( m_vec ));
308 #ifdef KJB_HAVE_GSL
309  check_bounds( index );
310  return *gsl_vector_ptr( m_vec, index );
311 #else
312  return m_vec -> at( index );
313 #endif
314  }
315 
316 
318  double& front()
319  {
320  KJB(ASSERT( m_vec ));
321  return at( 0 );
322  }
323 
324 
326  double front() const
327  {
328  KJB(ASSERT( m_vec ));
329  return at( 0 );
330  }
331 
332 
334  double& back()
335  {
336  KJB(ASSERT( m_vec ));
337  return at( size() - 1 );
338  }
339 
340 
342  double back() const
343  {
344  KJB(ASSERT( m_vec ));
345  return at( size() - 1 );
346  }
347 
348 
350  Gsl_Vector& set_all( double val )
351  {
352  KJB(ASSERT( m_vec ));
353 #ifdef KJB_HAVE_GSL
354  gsl_vector_set_all( m_vec, val );
355 #endif
356  return *this;
357  }
358 
359 
362  {
363  KJB(ASSERT( m_vec ));
364 #ifdef KJB_HAVE_GSL
365  gsl_vector_set_zero( m_vec );
366 #endif
367  return *this;
368  }
369 
370 
377  Gsl_Vector& set_basis( size_t index )
378  {
379  KJB(ASSERT( m_vec ));
380 #ifdef KJB_HAVE_GSL
381  GSL_ETX( gsl_vector_set_basis( m_vec, index ) );
382 #endif
383  return *this;
384  }
385 
386 
396  operator gsl_vector*()
397  {
398  return m_vec;
399  }
400 
401 
403  kjb::Vector vec() const
404  {
405  kjb::Vector kv( size() );
406  for( size_t iii = 0; iii < size(); ++iii )
407  {
408  kv.at( iii ) = at( iii );
409  }
410  return kv;
411  }
412 
413 
430  Gsl_Vector ew_multiply( const Gsl_Vector& that ) const
431  {
432  if ( size() != that.size() )
433  {
435  }
436  Gsl_Vector product( *this ); // copy this vector
437 #ifdef KJB_HAVE_GSL
438  GSL_ETX( gsl_vector_mul( product.m_vec, that.m_vec ) );
439 #endif
440  return product;
441  }
442 
443 
447  double sum() const
448  {
449  double sum_vec = 0;
450  for( size_t iii = 0; iii < size(); ++iii )
451  {
452  sum_vec += at( iii );
453  }
454  return sum_vec;
455  }
456 
457 
461  double dot( const Gsl_Vector& that ) const
462  {
463  Gsl_Vector this_x_that( ew_multiply( that ) );
464  return this_x_that.sum();
465  }
466 
467 
471  double l2_norm() const
472  {
473  using std::sqrt;
474  return sqrt( dot( *this ) );
475  }
476 
477 
490  bool is_normal() const
491  {
492  if ( 0 == m_vec )
493  {
494  return true;
495  }
496  for( size_t iii = 0; iii < size(); ++iii )
497  {
498  double x = at( iii );
499  // The following uses KJB-lib wraps on the lower level facilities.
500  // On systems lacking these capabilities, all values seem normal.
501  if ( isnand( x ) || ! finite( x ) )
502  {
503  return false;
504  }
505  }
506  return true;
507  }
508 
509 
512  {
513 #ifdef KJB_HAVE_GSL
514  if ( that.size() != size() )
515  {
517  }
518  GSL_ETX( gsl_vector_add( m_vec, that.m_vec ) );
519 #endif
520  return *this;
521  }
522 
523 
525  Gsl_Vector operator+( const Gsl_Vector& that ) const
526  {
527  Gsl_Vector vsum( *this );
528  return vsum += that;
529  }
530 
531 
534  {
535 #ifdef KJB_HAVE_GSL
536  if ( that.size() != size() )
537  {
539  }
540  GSL_ETX( gsl_vector_sub( m_vec, that.m_vec ) );
541 #endif
542  return *this;
543  }
544 
545 
547  Gsl_Vector operator-( const Gsl_Vector& that ) const
548  {
549  Gsl_Vector vdif( *this );
550  return vdif -= that;
551  }
552 
553 
560  {
561 #ifdef KJB_HAVE_GSL
562  GSL_ETX( gsl_vector_scale( m_vec, scalar ) );
563 #endif
564  return *this;
565  }
566 
567 
569  Gsl_Vector& operator*=( double scalar )
570  {
571  return ow_multiply_vector_by_scalar( scalar );
572  }
573 
574 
577  {
578 #ifdef KJB_HAVE_GSL
579  GSL_ETX( gsl_vector_reverse( m_vec ) );
580 #endif
581  return *this;
582  }
583 
584 
586  Gsl_Vector operator*( double scalar ) const
587  {
588  Gsl_Vector product( *this );
589  return product *= scalar;
590  }
591 
592 
594  Gsl_Vector& operator+=( double scalar )
595  {
596 #ifdef KJB_HAVE_GSL
597  GSL_ETX( gsl_vector_add_constant( m_vec, scalar ) );
598 #endif
599  return *this;
600  }
601 
602 
604  Gsl_Vector operator+( double scalar ) const
605  {
606  Gsl_Vector vsum( *this );
607  return vsum += scalar;
608  }
609 
611  Gsl_Vector& operator-=( double scalar )
612  {
613  return operator+=( -scalar );
614  }
615 
616 
618  Gsl_Vector operator-( double scalar ) const
619  {
620  Gsl_Vector vsum( *this );
621  return vsum -= scalar;
622  }
623 
624 
627  {
628  return *this*-1.0;
629  }
630 
631 
633  double max() const
634  {
635 #ifdef KJB_HAVE_GSL
636  KJB(ASSERT( m_vec ));
637  return gsl_vector_max( m_vec );
638 #endif
639  }
640 
641 
643  double min() const
644  {
645 #ifdef KJB_HAVE_GSL
646  KJB(ASSERT( m_vec ));
647  return gsl_vector_min( m_vec );
648 #endif
649  }
650 
651 
652  /*
653  * There are more GSL vector operations that are not wrapped:
654  * fprintf, fscanf, fread, fwrite, additional math operations.
655  */
656 };
657 
658 
660 inline
661 Gsl_Vector operator*( double scalar, const Gsl_Vector& vector )
662 {
663  return vector * scalar;
664 }
665 
666 
667 } // namespace kjb
668 
669 
671 inline
672 std::ostream& operator<<( std::ostream& os, const kjb::Gsl_Vector& v )
673 {
674  for( size_t iii = 0; iii < v.size(); ++iii )
675  {
676  os << v.at( iii ) << '\n';
677  }
678  return os;
679 }
680 
690 inline
691 std::istream& operator>>( std::istream& is, kjb::Gsl_Vector& v )
692 {
693  // To repeat: v must already know what size it is supposed to be!
694  for( size_t iii = 0; iii < v.size(); ++iii )
695  {
696  is >> v.at( iii );
697  }
698  return is;
699 }
700 
701 
702 namespace std {
703 
710  template<>
711  inline void swap( kjb::Gsl_Vector& v1, kjb::Gsl_Vector& v2 )
712  {
713  v1.swap( v2 );
714  }
715 }
716 
717 
718 #endif /* GSL_VECTOR_WRAP_H_KJBLIB_UARIZONAVISION */
Definition: gsl_vector.h:35
Gsl_Vector & set_basis(size_t index)
Init to the (j+1)th column of identity matrix, given argument j.
Definition: gsl_vector.h:377
size_t size
Definition: gsl_vector.h:36
~Gsl_Vector()
dtor releases the resources in a vector
Definition: gsl_vector.h:233
Gsl_Vector & operator+=(double scalar)
add scalar to each elt. of this vector, in-place
Definition: gsl_vector.h:594
double * p
Definition: gsl_vector.h:36
Gsl_Vector operator-(const Gsl_Vector &that) const
Return the difference of two vectors of the same size.
Definition: gsl_vector.h:547
double sum() const
Return the sum of the elements of the vector.
Definition: gsl_vector.h:447
Gsl_Vector & operator=(const Gsl_Vector &src)
assignment operator
Definition: gsl_vector.h:166
Gsl_Vector(Iterator begin, Iterator end)
ctor constructs from a pair of input iterators
Definition: gsl_vector.h:246
Int_matrix::Value_type max(const Int_matrix &mat)
Return the maximum value in this matrix.
Definition: l_int_matrix.h:1397
Gsl_Vector & set_all(double val)
set all vector members to a given value
Definition: gsl_vector.h:350
size_type size() const
Alias to get_length(). Required to comply with stl Container concept.
Definition: m_vector.h:510
double & at(size_t n)
Definition: gsl_vector.h:39
const double * begin() const
Definition: gsl_vector.h:194
Object thrown when an index argument exceeds the size of a container.
Definition: l_exception.h:399
Object thrown when an argument is of the wrong size or dimensions.
Definition: l_exception.h:426
Gsl_Vector operator-(double scalar) const
Return copy of this vector w/ a scalar subtracted from each elt.
Definition: gsl_vector.h:618
Gsl_Vector & ow_reverse()
Reverse the order of the elements of the vector, in place.
Definition: gsl_vector.h:576
#define KJB(x)
Definition: l_util.h:9
Gsl_Vector operator-() const
Return copy of this vector with every element negated.
Definition: gsl_vector.h:626
Value_type & at(int i)
Safely subscript vector, e.g., A.at(10), to get an lvalue.
Definition: m_vector.h:991
#define KJB_THROW(ex)
Definition: l_exception.h:46
Gsl_Vector & ow_multiply_vector_by_scalar(double scalar)
Scale by a real value, like kjb_c::ow_multiply_vector_by_scalar.
Definition: gsl_vector.h:559
Gsl_Vector operator+(const Gsl_Vector &that) const
Return the sum of this vector and another vector of same size.
Definition: gsl_vector.h:525
#define ASSERT(condition, message)
Definition: Assert.h:45
Gsl_Vector & operator*=(double scalar)
Scale by a real value, like ow_multiply_vector_by_scalar.
Definition: gsl_vector.h:569
double front() const
access the first element of the vector, returning an rvalue
Definition: gsl_vector.h:326
This class implements vectors, in the linear-algebra sense, with real-valued elements.
Definition: m_vector.h:87
GSL utility stuff to help those using the C++ wrapper on GSL code.
Gsl_Vector(size_t dims)
ctor to build an uninitialized vector of a given size
Definition: gsl_vector.h:111
std::ostream & operator<<(std::ostream &os, const kjb::Gsl_Vector &v)
Print out a vector as a column of ASCII-rendered values + newlines.
Definition: gsl_vector.h:672
void swap(Gsl_Vector &v)
swap the contents of two vectors
Definition: gsl_vector.h:223
bool is_normal() const
Test whether all vector entries are "normal" values.
Definition: gsl_vector.h:490
#define gsl_vector_get(w, i)
Definition: gsl_vector.h:53
size_t dims(const Scene &scene, bool respect_changed=true, bool infer_head=true)
Computes the number of variables in this scene.
Definition: pt_scene.cpp:106
~gsl_vector()
Definition: gsl_vector.h:38
gsl_vector(size_t n)
Definition: gsl_vector.h:37
double * end()
Definition: gsl_vector.h:203
Gsl_Vector & operator-=(double scalar)
subtract scalar from each elt. of this vector, in-place
Definition: gsl_vector.h:611
Gsl_Vector & set_zero()
set all vector members to zero
Definition: gsl_vector.h:361
Gsl_Vector operator+(double scalar) const
Return copy of this vector with a scalar added to each elt.
Definition: gsl_vector.h:604
x
Definition: APPgetLargeConnectedEdges.m:100
size_t size() const
returns the size of the vector
Definition: gsl_vector.h:263
#define GSL_ETX(gsl_expr)
Definition: gsl_util.h:37
double dot(const Gsl_Vector &that) const
Return the dot product of two vectors.
Definition: gsl_vector.h:461
double at(size_t index) const
element access for the vector, returning an rvalue
Definition: gsl_vector.h:292
const double * end() const
Definition: gsl_vector.h:212
RAII wrapper for GSL vector objects.
Definition: gsl_vector.h:78
#define KJB_THROW_2(ex, msg)
Definition: l_exception.h:48
double max() const
return the maximum value in the vector
Definition: gsl_vector.h:633
void swap(kjb::Gsl_Multimin_fdf &m1, kjb::Gsl_Multimin_fdf &m2)
Swap two wrapped multimin objects.
Definition: gsl_multimin.h:693
Gsl_Vector operator*(double scalar) const
Scale by a real value and return the result.
Definition: gsl_vector.h:586
double * begin()
Definition: gsl_vector.h:185
#define ETX_2(a, msg)
Definition: l_exception.h:78
double & back()
access the last element of the vector, returning an lvalue
Definition: gsl_vector.h:334
const double & at(size_t n) const
Definition: gsl_vector.h:40
Gsl_Vector(const gsl_vector &vec_to_be_copied)
ctor copies an unwrapped GSL vector, does NOT take ownership.
Definition: gsl_vector.h:153
Gsl_Vector & operator+=(const Gsl_Vector &that)
Add a vector of the same size to this vector, elementwise.
Definition: gsl_vector.h:511
double & at(size_t index)
element access for the vector, returning an lvalue
Definition: gsl_vector.h:305
#define gsl_vector_alloc(x)
Definition: gsl_vector.h:42
double & front()
access the first element of the vector, returning an lvalue
Definition: gsl_vector.h:318
double min() const
return the minimum value in the vector
Definition: gsl_vector.h:643
Object thrown when a program lacks required resources or libraries.
Definition: l_exception.h:539
Gsl_Vector(const Gsl_Vector &src)
copy ctor
Definition: gsl_vector.h:140
kjb::Vector vec() const
Export contents in a KJB Vector (the C++ kind).
Definition: gsl_vector.h:403
Gsl_Vector & operator-=(const Gsl_Vector &that)
Subtract a vector of the same size from this vector, elementwise.
Definition: gsl_vector.h:533
Gsl_Vector(const kjb::Vector &kv)
conversion ctor makes a copy of a KJB vector
Definition: gsl_vector.h:123
Gsl_Vector operator*(double scalar, const Gsl_Vector &vector)
multiply scalar and vector, scalar written on the left side
Definition: gsl_vector.h:661
double back() const
access the last element of the vector, returning an rvalue
Definition: gsl_vector.h:342
double l2_norm() const
Return the L2 norm (the Euclidean norm) of the vector.
Definition: gsl_vector.h:471
std::istream & operator>>(std::istream &is, kjb::Gsl_Vector &v)
Read in ASCII-rendered, WS-delimited contents to a presized vector.
Definition: gsl_vector.h:691
Gsl_Vector ew_multiply(const Gsl_Vector &that) const
Perform element-wise multiplcation of two vectors, same size.
Definition: gsl_vector.h:430