1 /*
2 * Vector, VectorView, ConstVectorView classes wrap the gsl vector routines;
3 * "views" mimic the semantic of C++ references: any operation performed
4 * on a "view" is actually performed on the "viewed object"
5 *
6 * Authors:
7 * Marco Cecchetti <mrcekets at gmail.com>
8 *
9 * Copyright 2008 authors
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it either under the terms of the GNU Lesser General Public
13 * License version 2.1 as published by the Free Software Foundation
14 * (the "LGPL") or, at your option, under the terms of the Mozilla
15 * Public License Version 1.1 (the "MPL"). If you do not alter this
16 * notice, a recipient may use your version of this file under either
17 * the MPL or the LGPL.
18 *
19 * You should have received a copy of the LGPL along with this library
20 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * You should have received a copy of the MPL along with this library
23 * in the file COPYING-MPL-1.1
24 *
25 * The contents of this file are subject to the Mozilla Public License
26 * Version 1.1 (the "License"); you may not use this file except in
27 * compliance with the License. You may obtain a copy of the License at
28 * http://www.mozilla.org/MPL/
29 *
30 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
31 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
32 * the specific language governing rights and limitations.
33 */
38 #ifndef _NL_VECTOR_H_
39 #define _NL_VECTOR_H_
41 #include <cassert>
42 #include <algorithm> // for std::swap
43 #include <vector>
44 #include <sstream>
45 #include <string>
48 #include <gsl/gsl_vector.h>
49 #include <gsl/gsl_blas.h>
52 namespace Geom { namespace NL {
54 namespace detail
55 {
57 class BaseVectorImpl
58 {
59 public:
60 double const& operator[](size_t i) const
61 {
62 return *gsl_vector_const_ptr(m_vector, i);
63 }
65 const gsl_vector* get_gsl_vector() const
66 {
67 return m_vector;
68 }
69 bool is_zero() const
70 {
71 return gsl_vector_isnull(m_vector);
72 }
74 bool is_positive() const
75 {
76 return gsl_vector_ispos(m_vector);
77 }
79 bool is_negative() const
80 {
81 return gsl_vector_isneg(m_vector);
82 }
84 bool is_non_negative() const
85 {
86 for ( size_t i = 0; i < size(); ++i )
87 {
88 if ( (*this)[i] < 0 ) return false;
89 }
90 return true;
91 }
93 double max() const
94 {
95 return gsl_vector_max(m_vector);
96 }
98 double min() const
99 {
100 return gsl_vector_min(m_vector);
101 }
103 size_t max_index() const
104 {
105 return gsl_vector_max_index(m_vector);
106 }
108 size_t min_index() const
109 {
110 return gsl_vector_min_index(m_vector);
111 }
113 size_t size() const
114 {
115 return m_size;
116 }
118 std::string str() const;
120 virtual ~BaseVectorImpl()
121 {
122 }
124 protected:
125 size_t m_size;
126 gsl_vector* m_vector;
128 }; // end class BaseVectorImpl
131 inline
132 bool operator== (BaseVectorImpl const& v1, BaseVectorImpl const& v2)
133 {
134 if (v1.size() != v2.size()) return false;
136 for (size_t i = 0; i < v1.size(); ++i)
137 {
138 if (v1[i] != v2[i]) return false;
139 }
140 return true;
141 }
143 template< class charT >
144 inline
145 std::basic_ostream<charT> &
146 operator<< (std::basic_ostream<charT> & os, const BaseVectorImpl & _vector)
147 {
148 if (_vector.size() == 0 ) return os;
149 os << "[" << _vector[0];
150 for (unsigned int i = 1; i < _vector.size(); ++i)
151 {
152 os << ", " << _vector[i];
153 }
154 os << "]";
155 return os;
156 }
158 inline
159 std::string BaseVectorImpl::str() const
160 {
161 std::ostringstream oss;
162 oss << (*this);
163 return oss.str();
164 }
166 inline
167 double dot(BaseVectorImpl const& v1, BaseVectorImpl const& v2)
168 {
169 double result;
170 gsl_blas_ddot(v1.get_gsl_vector(), v2.get_gsl_vector(), &result);
171 return result;
172 }
175 class VectorImpl : public BaseVectorImpl
176 {
177 public:
178 typedef BaseVectorImpl base_type;
180 public:
181 void set_all(double x)
182 {
183 gsl_vector_set_all(m_vector, x);
184 }
186 void set_basis(size_t i)
187 {
188 gsl_vector_set_basis(m_vector, i);
189 }
191 using base_type::operator[];
193 double & operator[](size_t i)
194 {
195 return *gsl_vector_ptr(m_vector, i);
196 }
198 using base_type::get_gsl_vector;
200 gsl_vector* get_gsl_vector()
201 {
202 return m_vector;
203 }
205 void swap_elements(size_t i, size_t j)
206 {
207 gsl_vector_swap_elements(m_vector, i, j);
208 }
210 void reverse()
211 {
212 gsl_vector_reverse(m_vector);
213 }
215 VectorImpl & scale(double x)
216 {
217 gsl_vector_scale(m_vector, x);
218 return (*this);
219 }
221 VectorImpl & translate(double x)
222 {
223 gsl_vector_add_constant(m_vector, x);
224 return (*this);
225 }
227 VectorImpl & operator+=(base_type const& _vector)
228 {
229 gsl_vector_add(m_vector, _vector.get_gsl_vector());
230 return (*this);
231 }
233 VectorImpl & operator-=(base_type const& _vector)
234 {
235 gsl_vector_sub(m_vector, _vector.get_gsl_vector());
236 return (*this);
237 }
239 }; // end class VectorImpl
241 } // end namespace detail
244 using detail::operator==;
245 using detail::operator<<;
247 class Vector : public detail::VectorImpl
248 {
249 public:
250 typedef detail::VectorImpl base_type;
252 public:
253 Vector(size_t n)
254 {
255 m_size = n;
256 m_vector = gsl_vector_alloc(n);
257 }
259 Vector(size_t n, double x)
260 {
261 m_size = n;
262 m_vector = gsl_vector_alloc(n);
263 gsl_vector_set_all(m_vector, x);
264 }
266 // create a vector with n elements all set to zero
267 // but the i-th that is set to 1
268 Vector(size_t n, size_t i)
269 {
270 m_size = n;
271 m_vector = gsl_vector_alloc(n);
272 gsl_vector_set_basis(m_vector, i);
273 }
275 Vector(Vector const& _vector)
276 : base_type()
277 {
278 m_size = _vector.size();
279 m_vector = gsl_vector_alloc(size());
280 gsl_vector_memcpy(m_vector, _vector.m_vector);
281 }
283 explicit
284 Vector(base_type::base_type const& _vector)
285 {
286 m_size = _vector.size();
287 m_vector = gsl_vector_alloc(size());
288 gsl_vector_memcpy(m_vector, _vector.get_gsl_vector());
289 }
291 virtual ~Vector()
292 {
293 gsl_vector_free(m_vector);
294 }
297 Vector & operator=(Vector const& _vector)
298 {
299 assert( size() == _vector.size() );
300 gsl_vector_memcpy(m_vector, _vector.m_vector);
301 return (*this);
302 }
304 Vector & operator=(base_type::base_type const& _vector)
305 {
306 assert( size() == _vector.size() );
307 gsl_vector_memcpy(m_vector, _vector.get_gsl_vector());
308 return (*this);
309 }
311 Vector & scale(double x)
312 {
313 return static_cast<Vector&>( base_type::scale(x) );
314 }
316 Vector & translate(double x)
317 {
318 return static_cast<Vector&>( base_type::translate(x) );
319 }
321 Vector & operator+=(base_type::base_type const& _vector)
322 {
323 return static_cast<Vector&>( base_type::operator+=(_vector) );
324 }
326 Vector & operator-=(base_type::base_type const& _vector)
327 {
328 return static_cast<Vector&>( base_type::operator-=(_vector) );
329 }
331 friend
332 void swap(Vector & v1, Vector & v2);
333 friend
334 void swap_any(Vector & v1, Vector & v2);
336 }; // end class Vector
339 // warning! these operations invalidate any view of the passed vector objects
340 inline
341 void swap(Vector & v1, Vector & v2)
342 {
343 assert( v1.size() == v2.size() );
344 std::swap(v1.m_vector, v2.m_vector);
345 }
347 inline
348 void swap_any(Vector & v1, Vector & v2)
349 {
350 std::swap(v1.m_vector, v2.m_vector);
351 std::swap(v1.m_size, v2.m_size);
352 }
355 class ConstVectorView : public detail::BaseVectorImpl
356 {
357 public:
358 typedef detail::BaseVectorImpl base_type;
360 public:
361 ConstVectorView(const base_type & _vector, size_t n, size_t offset = 0)
362 : m_vector_view( gsl_vector_const_subvector(_vector.get_gsl_vector(), offset, n) )
363 {
364 m_size = n;
365 m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
366 }
368 ConstVectorView(const base_type & _vector, size_t n, size_t offset , size_t stride)
369 : m_vector_view( gsl_vector_const_subvector_with_stride(_vector.get_gsl_vector(), offset, stride, n) )
370 {
371 m_size = n;
372 m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
373 }
375 ConstVectorView(const double* _vector, size_t n, size_t offset = 0)
376 : m_vector_view( gsl_vector_const_view_array(_vector + offset, n) )
377 {
378 m_size = n;
379 m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
380 }
382 ConstVectorView(const double* _vector, size_t n, size_t offset, size_t stride)
383 : m_vector_view( gsl_vector_const_view_array_with_stride(_vector + offset, stride, n) )
384 {
385 m_size = n;
386 m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
387 }
389 explicit
390 ConstVectorView(gsl_vector_const_view _gsl_vector_view)
391 : m_vector_view(_gsl_vector_view)
392 {
393 m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
394 m_size = m_vector->size;
395 }
397 explicit
398 ConstVectorView(const std::vector<double>& _vector)
399 : m_vector_view( gsl_vector_const_view_array(&(_vector[0]), _vector.size()) )
400 {
401 m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
402 m_size = _vector.size();
403 }
405 ConstVectorView(const ConstVectorView & _vector)
406 : base_type(),
407 m_vector_view(_vector.m_vector_view)
408 {
409 m_size = _vector.size();
410 m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
411 }
413 ConstVectorView(const base_type & _vector)
414 : m_vector_view(gsl_vector_const_subvector(_vector.get_gsl_vector(), 0, _vector.size()))
415 {
416 m_size = _vector.size();
417 m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
418 }
420 private:
421 gsl_vector_const_view m_vector_view;
423 }; // end class ConstVectorView
428 class VectorView : public detail::VectorImpl
429 {
430 public:
431 typedef detail::VectorImpl base_type;
433 public:
434 VectorView(base_type & _vector, size_t n, size_t offset = 0, size_t stride = 1)
435 {
436 m_size = n;
437 if (stride == 1)
438 {
439 m_vector_view
440 = gsl_vector_subvector(_vector.get_gsl_vector(), offset, n);
441 m_vector = &(m_vector_view.vector);
442 }
443 else
444 {
445 m_vector_view
446 = gsl_vector_subvector_with_stride(_vector.get_gsl_vector(), offset, stride, n);
447 m_vector = &(m_vector_view.vector);
448 }
449 }
451 VectorView(double* _vector, size_t n, size_t offset = 0, size_t stride = 1)
452 {
453 m_size = n;
454 if (stride == 1)
455 {
456 m_vector_view
457 = gsl_vector_view_array(_vector + offset, n);
458 m_vector = &(m_vector_view.vector);
459 }
460 else
461 {
462 m_vector_view
463 = gsl_vector_view_array_with_stride(_vector + offset, stride, n);
464 m_vector = &(m_vector_view.vector);
465 }
467 }
469 VectorView(const VectorView & _vector)
470 : base_type()
471 {
472 m_size = _vector.size();
473 m_vector_view = _vector.m_vector_view;
474 m_vector = &(m_vector_view.vector);
475 }
477 VectorView(Vector & _vector)
478 {
479 m_size = _vector.size();
480 m_vector_view = gsl_vector_subvector(_vector.get_gsl_vector(), 0, size());
481 m_vector = &(m_vector_view.vector);
482 }
484 explicit
485 VectorView(gsl_vector_view _gsl_vector_view)
486 : m_vector_view(_gsl_vector_view)
487 {
488 m_vector = &(m_vector_view.vector);
489 m_size = m_vector->size;
490 }
492 explicit
493 VectorView(std::vector<double> & _vector)
494 {
495 m_size = _vector.size();
496 m_vector_view = gsl_vector_view_array(&(_vector[0]), _vector.size());
497 m_vector = &(m_vector_view.vector);
498 }
500 VectorView & operator=(VectorView const& _vector)
501 {
502 assert( size() == _vector.size() );
503 gsl_vector_memcpy(m_vector, _vector.get_gsl_vector());
504 return (*this);
505 }
507 VectorView & operator=(base_type::base_type const& _vector)
508 {
509 assert( size() == _vector.size() );
510 gsl_vector_memcpy(m_vector, _vector.get_gsl_vector());
511 return (*this);
512 }
514 VectorView & scale(double x)
515 {
516 return static_cast<VectorView&>( base_type::scale(x) );
517 }
519 VectorView & translate(double x)
520 {
521 return static_cast<VectorView&>( base_type::translate(x) );
522 }
524 VectorView & operator+=(base_type::base_type const& _vector)
525 {
526 return static_cast<VectorView&>( base_type::operator+=(_vector) );
527 }
529 VectorView & operator-=(base_type::base_type const& _vector)
530 {
531 return static_cast<VectorView&>( base_type::operator-=(_vector) );
532 }
534 friend
535 void swap_view(VectorView & v1, VectorView & v2);
537 private:
538 gsl_vector_view m_vector_view;
540 }; // end class VectorView
543 inline
544 void swap_view(VectorView & v1, VectorView & v2)
545 {
546 assert( v1.size() == v2.size() );
547 std::swap(v1.m_vector_view, v2.m_vector_view); // not swap m_vector too
548 }
551 } } // end namespaces
554 #endif /*_NL_VECTOR_H_*/
556 /*
557 Local Variables:
558 mode:c++
559 c-file-style:"stroustrup"
560 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
561 indent-tabs-mode:nil
562 fill-column:99
563 End:
564 */
565 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :