CppNoddy  0.92
Loading...
Searching...
No Matches
SparseVector.cpp
Go to the documentation of this file.
1/// \file SparseVector.cpp
2/// Implementation of the SparseVector class -- a sparse, variable size, vector object.
3/// The sparse & dense vectors do not share a common base because the
4/// sparse class encapsulates an STL map and operator[] assigns entries to
5/// the map. Hence get/set methods are used here.
6
7#include <complex>
8#include <map>
9#include <cmath>
10#include <algorithm>
11
12#include <SparseVector.h>
13#include <Exceptions.h>
14#include <Functors.h>
15
16namespace CppNoddy {
17 template <typename _Type>
18 SparseVector<_Type>::SparseVector(const std::size_t& max) : ZERO(0.0), MAX_SIZE(max)
19 {}
20
21 template <typename _Type>
23 *this = source;
24 }
25
26 template <typename _Type>
28 if(this == &source)
29 return * this;
30 MAP_VEC = source.MAP_VEC;
31 ZERO = source.ZERO;
32 MAX_SIZE = source.MAX_SIZE;
33 return *this;
34 }
35
36 template <typename _Type>
38 for(iter pos = MAP_VEC.begin(); pos != MAP_VEC.end(); ++pos) {
39 pos -> second *= m;
40 }
41 return *this;
42 }
43
44 template <typename _Type>
46#ifdef PARANOID
47 if(X.size() != size()) {
48 std::string problem;
49 problem = " The SparseVector.operator-= method is trying to use \n";
50 problem += " two vectors of unequal length \n";
51 throw ExceptionGeom(problem, size(), X.size());
52 }
53#endif
54 citer pos_ro = X.MAP_VEC.begin();
55 iter pos_rw = MAP_VEC.begin();
56 do {
57 std::size_t index_rw = pos_rw -> first;
58 std::size_t index_ro = pos_ro -> first;
59 if(index_rw == index_ro) {
60 // element in both vectors
61 pos_rw -> second -= pos_ro -> second;
62 ++pos_rw;
63 ++pos_ro;
64 }
65 if(index_rw > index_ro) {
66 // element is in X but not 'this'
67 set
68 (index_ro) = -(pos_ro -> second);
69 ++pos_ro;
70 }
71 if(index_rw < index_ro) {
72 // element is in 'this' but not X
73 ++pos_rw;
74 }
75 } while(pos_ro != X.MAP_VEC.end() && pos_rw != MAP_VEC.end());
76 if(pos_ro != X.MAP_VEC.end()) {
77 // need to finish the X data
78 do {
79 set
80 (pos_ro -> first) = -(pos_ro -> second);
81 ++pos_ro;
82 } while(pos_ro != X.MAP_VEC.end());
83 }
84 return *this;
85 }
86
87 template <typename _Type>
89#ifdef PARANOID
90 if(X.size() != size()) {
91 std::string problem;
92 problem = " The SparseVector.operator+= method is trying to use \n";
93 problem += " two vectors of unequal length \n";
94 throw ExceptionGeom(problem, size(), X.size());
95 }
96#endif
97 citer pos_ro = X.MAP_VEC.begin();
98 iter pos_rw = MAP_VEC.begin();
99 do {
100 std::size_t index_rw = pos_rw -> first;
101 std::size_t index_ro = pos_ro -> first;
102 if(index_rw == index_ro) {
103 // element in both vectors
104 pos_rw -> second += pos_ro -> second;
105 ++pos_rw;
106 ++pos_ro;
107 }
108 if(index_rw > index_ro) {
109 // element is in X but not 'this'
110 set
111 (index_ro) = pos_ro -> second;
112 ++pos_ro;
113 }
114 if(index_rw < index_ro) {
115 // element is in 'this' but not X
116 ++pos_rw;
117 }
118 } while(pos_ro != X.MAP_VEC.end() && pos_rw != MAP_VEC.end());
119 if(pos_ro != X.MAP_VEC.end()) {
120 // need to finish the X data
121 do {
122 set
123 (pos_ro -> first) = pos_ro -> second;
124 ++pos_ro;
125 } while(pos_ro != X.MAP_VEC.end());
126 }
127 return *this;
128 }
129
130 template <typename _Type>
132#ifdef PARANOID
133 if(X.size() != size()) {
134 std::string problem;
135 problem = " The SparseVector.operator+ method is trying to use \n";
136 problem += " two vectors of unequal length \n";
137 throw ExceptionGeom(problem, size(), X.size());
138 }
139#endif
140 SparseVector<_Type> temp(*this);
141 temp += X;
142 return temp;
143 }
144
145 template <typename _Type>
147#ifdef PARANOID
148 if(X.size() != size()) {
149 std::string problem;
150 problem = " The SparseVector.operator- method is trying to use \n";
151 problem += " two vectors of unequal length \n";
152 throw ExceptionGeom(problem, size(), X.size());
153 }
154#endif
155 SparseVector<_Type> temp(*this);
156 temp -= X;
157 return temp;
158 }
159
160 template <typename _Type>
162 SparseVector<_Type> temp(*this);
163 temp *= -1.0;
164 return temp;
165 }
166
167 template <typename _Type>
169 SparseVector<_Type> temp(*this);
170 temp *= m;
171 return temp;
172 }
173
174
175 template <typename _Type>
176 void SparseVector<_Type>::resize(const std::size_t& length) {
177 MAX_SIZE = length;
178 }
179
180 template <typename _Type>
182 MAP_VEC.clear();
183 }
184
185 template <typename _Type>
186 const _Type SparseVector<_Type>::dot(const SparseVector<_Type>& X) const {
187#ifdef PARANOID
188 if(X.size() != size()) {
189 std::string problem;
190 problem = " The SparseVector.dot method is trying to use \n";
191 problem += " two vectors of unequal length \n";
192 throw ExceptionGeom(problem, size(), X.size());
193 }
194#endif
195 SparseVector<_Type> temp(X);
196 _Type sum(0.0);
197 for(iter pos = temp.MAP_VEC.begin(); pos != temp.MAP_VEC.end(); ++pos) {
198 std::size_t index = pos -> first;
199 /// \todo Using a 'get' (aka find) here is slooow
200 /// - obviously this can be improved.
201 // the get method returns 0.0 if not stored
202 temp[ index ] *= get(index);
203 }
204 return sum;
205 }
206
207 template <typename _Type>
209 // Accumulate the ABS values of the container entries
210 // using a fuction object.
211 double sum(0.0);
212 for(citer pos = MAP_VEC.begin(); pos != MAP_VEC.end(); ++pos) {
213 sum += std::abs(pos -> second);
214 }
215 return sum;
216 }
217
218 template <typename _Type>
220 // Accumulate the ABS values of the container entries SQUARED
221 // using a fuction object.
222 double sum(0.0);
223 for(citer pos = MAP_VEC.begin(); pos != MAP_VEC.end(); ++pos) {
224 sum += std::pow(std::abs(pos -> second), 2);
225 }
226 return sum;
227 }
228
229 template <typename _Type>
231 double max(0.0);
232 // Return the maximum (abs) element in the vector
233 for(citer pos = MAP_VEC.begin(); pos != MAP_VEC.end(); ++pos) {
234 if(std::abs(pos -> second) > max) {
235 max = std::abs(pos -> second);
236 }
237 }
238 return max;
239 }
240
241 template <typename _Type>
242 void SparseVector<_Type>::scale(const _Type& scale) {
243 for(iter pos = MAP_VEC.begin(); pos != MAP_VEC.end(); ++pos) {
244 pos -> second *= scale;
245 }
246 }
247
248 template <typename _Type>
250 (const SparseVector<_Type>& X) {
251 *this += X;
252 }
253
254 template <typename _Type>
256 *this -= X;
257 }
258
259 template <typename _Type>
260 std::size_t SparseVector<_Type>::nearest_index(const _Type& value) const {
261 citer location(MAP_VEC.begin());
262 _Type min_diff(location -> second - value);
263 citer start(++location);
264 for(citer pos = start; pos != MAP_VEC.end(); ++pos) {
265 _Type diff(pos -> second - value);
266 if(std::abs(diff) < std::abs(min_diff)) {
267 min_diff = diff;
268 location = pos;
269 }
270 }
271 return location -> first;
272 }
273
274 template <typename _Type>
276 citer location(MAP_VEC.begin());
277 double max(std::abs(location -> second));
278 citer start(++location);
279 for(citer pos = start; pos != MAP_VEC.end(); ++pos) {
280 if(std::abs(pos -> second) > max) {
281 max = std::abs(pos -> second);
282 location = pos;
283 }
284 }
285 return location -> first;
286 }
287
288 template <typename _Type>
290 citer location(MAP_VEC.begin());
291 double min(std::abs(location -> second));
292 citer start(++location);
293 for(citer pos = start; pos != MAP_VEC.end(); ++pos) {
294 if(std::abs(pos -> second) < min) {
295 min = std::abs(pos -> second);
296 location = pos;
297 }
298 }
299 return location -> first;
300 }
301
302 template <typename _Type>
303 void SparseVector<_Type>::swap(const std::size_t& i,
304 const std::size_t& j) {
305#ifdef PARANOID
306 if(i >= size() || j >= size()) {
307 std::string problem;
308 problem = " The SparseVector.swap method is trying to access \n";
309 problem += " outside the container. \n";
310 throw ExceptionRange(problem, size(), std::max(i, j));
311 }
312#endif
313 std::swap<_Type>(MAP_VEC[ i ], MAP_VEC[ j ]);
314 }
315
316 template <typename _Type>
318 std::cout.precision(6);
319 if(MAP_VEC.begin() == MAP_VEC.end()) {
320 std::cout << "[ Empty vector ]\n";
321 } else {
322 for(citer pos = MAP_VEC.begin(); pos != MAP_VEC.end(); ++pos) {
323 std::cout << "[ " << pos -> first << " ]" << " = " << pos -> second << " ";
324 }
325 std::cout << "\n";
326 }
327 }
328
329
330#if defined(PETSC_D)
331 template <>
332 void SparseVector<double>::get_petsc( PetscScalar* storage, PetscInt* cols ) {
333 citer pos;
334 std::size_t i(0);
335 //
336 // start at the begining of this row
337 pos = MAP_VEC.begin();
338 do {
339 // store the value and column
340 storage[ i ] = pos -> second;
341 cols[ i ] = pos -> first;
342 // increment the iterator
343 ++pos;
344 // increment the array index
345 ++i;
346 } while(pos != MAP_VEC.end());
347 }
348#endif
349
350#if defined(PETSC_Z)
351 template <>
352 void SparseVector<std::complex<double> >::get_petsc( PetscScalar* storage, PetscInt* cols ) {
353 citer pos;
354 std::size_t i(0);
355 //
356 // start at the begining of this row
357 pos = MAP_VEC.begin();
358 do {
359 // store the value and column
360 storage[ i ] = std::real(pos -> second) + PETSC_i * std::imag(pos -> second);
361 cols[ i ] = pos -> first;
362 // increment the iterator
363 ++pos;
364 // increment the array index
365 ++i;
366 } while(pos != MAP_VEC.end());
367 }
368#endif
369
370
371 // the templated versions we require are:
372 template class SparseVector<double>
373 ;
374 template class SparseVector<std::complex<double> >
375 ;
376
377} // end namespace
378
The collection of CppNoddy exceptions.
Some Function Objects that CppNoddy makes use of in algorithms applied to STL containers.
A templated SparseVector class – a sparse, variable size, vector object.
An exception class to be thrown when a container of incorrect geometry used in any class/method.
Definition: Exceptions.h:47
An exception to indicate that a CppNoddy container has been accessed with index/indices outside the m...
Definition: Exceptions.h:117
An SparseVector class – a sparse vector object.
Definition: SparseVector.h:20
void sub(const SparseVector< _Type > &X)
Subtract a vector, element wise.
SparseVector(const std::size_t &max)
Constructor for a non-filled vector, to be filled by the user.
double inf_norm() const
Infinity norm.
void scale(const _Type &scale)
Scale each element of the vector.
void resize(const std::size_t &length)
Resize the maximum length of the sparse vector.
SparseVector< _Type > & operator*=(const _Type &m)
Overloading *= for scalar multiplication.
void dump() const
Output the sparse vector's contents.
double two_norm() const
l2-norm.
std::size_t size() const
Find the (max) size of the vector.
Definition: SparseVector.h:318
const _Type dot(const SparseVector< _Type > &x) const
A dot product.
void swap(const std::size_t &i, const std::size_t &j)
Swap elements i and j.
void add(const SparseVector< _Type > &X)
Add a vector, element wise.
SparseVector< _Type > & operator-=(const SparseVector< _Type > &X)
Overloading -= for sparse vectors.
SparseVector< _Type > operator*(const _Type &m) const
Overloading multiplication for a scalar.
SparseVector< _Type > & operator+=(const SparseVector< _Type > &X)
Overloading += for sparse vectors.
std::size_t maxabs_index() const
Find the index of the maximum element in the vector.
SparseVector & operator=(const SparseVector &source)
Assignment operator.
SparseVector< _Type > operator+() const
Overloading for +.
Definition: SparseVector.h:351
std::size_t minabs_index() const
Find the index of the maximum element in the vector.
std::size_t nearest_index(const _Type &value) const
Find the index of the element NEAREST in value to that specified.
SparseVector< _Type > operator-() const
Overloading for -.
double one_norm() const
l1-norm.
void clear()
Remove all elements from the sparse vector.
A collection of OO numerical routines aimed at simple (typical) applied problems in continuum mechani...

© 2012

R.E. Hewitt