NumLinAlg.cxx
Go to the documentation of this file.
1 
14 #include "NumLinAlg.h"
15 
16 #include <fstream>
17 #include <iostream>
18 #include <iomanip>
19 #include <cmath>
20 #include <cfloat>
21 #include <cassert>
22 
23 #include <cstdlib>
24 
25 using std::ofstream;
26 using std::ifstream;
27 using std::setw;
28 using std::setprecision;
29 using std::cout;
30 using std::endl;
31 using std::vector;
32 using std::abs;
33 
34 namespace hippodraw {
35  namespace Numeric {
36 
37 std::vector< double >
38 operator + ( const std::vector< double >& x,
39  const std::vector< double >& y )
40 {
41  int nrows = x.size();
42  vector< double > z;
43 
44  z.resize( nrows, 0.0 );
45 
46  for ( int i = 0; i < nrows; i++)
47  z[i] = x[i] + y[i];
48 
49  return z;
50 }
51 
52 std::vector< double >
53 operator - ( const std::vector< double >& x,
54  const std::vector< double >& y )
55 {
56  int nrows = x.size();
57  vector< double > z;
58 
59  z.resize( nrows, 0.0 );
60 
61  for ( int i = 0; i < nrows; i++)
62  z[i] = x[i] - y[i];
63 
64  return z;
65 }
66 
67 std::vector< double >
68 operator - ( const std::vector< double >& y )
69 {
70  int nrows = y.size();
71  vector< double > z;
72 
73  z.resize( nrows, 0.0 );
74 
75  for ( int i = 0; i < nrows; i++ )
76  z[i] = - y[i];
77 
78  return z;
79 }
80 
81 std::vector< vector< double > >
82 operator + ( const std::vector< std::vector< double > >&A,
83  const std::vector< std::vector< double > >&B )
84 {
85  int nrows = A.size();
86  int ncols = A[0].size();
87 
88  vector< vector< double > > C( nrows );
89  for( int i = 0; i < nrows; i++ )
90  C[i].resize( ncols, 0.0 );
91 
92  for (int i = 0; i < nrows; i++)
93  for (int j = 0; j < ncols; j++)
94  C[i][j] = A[i][j] + B[i][j];
95 
96  return C;
97 }
98 
99 std::vector< vector< double > >
100 operator - ( const std::vector< std::vector< double > >&A,
101  const std::vector< std::vector< double > >&B )
102 {
103  int nrows = A.size();
104  int ncols = A[0].size();
105 
106  vector< vector< double > > C( nrows );
107  for( int i = 0; i < nrows; i++ )
108  C[i].resize( ncols, 0.0 );
109 
110  for (int i = 0; i < nrows; i++)
111  for (int j = 0; j < ncols; j++)
112  C[i][j] = A[i][j] - B[i][j];
113 
114  return C;
115 }
116 
117 
118 std::vector< double >
119 operator * ( double a, const std::vector< double >& x )
120 {
121  int nrows = x.size();
122  vector< double > y;
123 
124  y.resize( nrows, 0.0 );
125 
126  for ( int i = 0; i < nrows; i++)
127  y[i] = a * x[i];
128 
129  return y;
130 }
131 
132 std::vector< double >
133 operator / ( const std::vector< double >& x, double a )
134 {
135  int nrows = x.size();
136  vector< double > y;
137 
138  assert( abs( a ) > DBL_EPSILON );
139 
140  y.resize( nrows, 0.0 );
141 
142  for ( int i = 0; i < nrows; i++)
143  y[i] = x[i] / a;
144 
145  return y;
146 }
147 
148 std::vector< std::vector< double > >
149 operator * ( double a, const std::vector< std::vector< double > >&A )
150 {
151  int nrows = A.size();
152  int ncols = A[0].size();
153 
154  vector< vector< double > > B( nrows );
155  for( int i = 0; i < nrows; i++ )
156  B[i].resize( ncols, 0.0 );
157 
158  for (int i = 0; i < nrows; i++)
159  for (int j = 0; j < ncols; j++)
160  B[i][j] = a * A[i][j];
161 
162  return B;
163 }
164 
165 std::vector< std::vector< double > >
166 operator / ( const std::vector< std::vector< double > >& A, double a )
167 {
168  int nrows = A.size();
169  int ncols = A[0].size();
170 
171  assert( abs( a ) > DBL_EPSILON );
172 
173  vector< vector< double > > B( nrows );
174  for( int i = 0; i < nrows; i++ )
175  B[i].resize( ncols, 0.0 );
176 
177  for (int i = 0; i < nrows; i++)
178  for (int j = 0; j < ncols; j++)
179  B[i][j] = A[i][j]/a;
180 
181  return B;
182 }
183 
184 std::vector< double >
185 operator * ( const std::vector< std::vector< double > >& A,
186  const std::vector< double >& x )
187 {
188  int nrows = A.size();
189  int ncols = A[0].size();
190  vector< double > y;
191 
192  y.resize( nrows, 0.0 );
193 
194  for (int i = 0; i < nrows; i++)
195  for (int j = 0; j < ncols; j++)
196  y[i] += A[i][j] * x[j];
197 
198  return y;
199 }
200 
201 std::vector< double >
202 operator * ( const std::vector< double >& x,
203  const std::vector< std::vector< double > >& A )
204 {
205  int nrows = A.size();
206  int ncols = A[0].size();
207  vector< double > y;
208 
209  y.resize( ncols, 0.0 );
210 
211  for (int j = 0; j < ncols; j++)
212  for (int i = 0; i < nrows; i++)
213  y[j] += A[i][j] * x[i];
214 
215  return y;
216 }
217 
218 std::vector< vector< double > >
219 operator * ( const std::vector< std::vector< double > >&A,
220  const std::vector< std::vector< double > >&B )
221 {
222  int m = A.size();
223  int r = A[0].size();
224  int n = B[0].size();
225 
226  vector< vector< double > > C( m );
227  for( int i = 0; i < m; i++ )
228  C[i].resize( n, 0.0 );
229 
230  for (int i = 0; i < m; i++)
231  for (int j = 0; j < n; j++)
232  for (int k = 0; k < r; k++)
233  C[i][j] += A[i][k] * B[k][j];
234 
235  return C;
236 }
237 
238 double
239 innerProduct( const std::vector< double > & a,
240  const std::vector< double > & b )
241 {
242  double prod = 0.0;
243 
244  for ( unsigned int i = 0; i < a.size(); i++ )
245  prod += a[i] * b[i];
246 
247  return prod;
248 }
249 
250 
251 vector< vector< double > >
252 outerProduct ( const std::vector< double >& a,
253  const std::vector< double >& b )
254 {
255  vector< vector< double> > C( a.size() );
256  for( unsigned int i = 0; i < a.size(); i++ )
257  C[i].resize( b.size() );
258 
259  for( unsigned int i = 0; i < a.size(); i++ )
260  for( unsigned int j = 0; j < b.size(); j++ )
261  C[i][j] = a[i] * b[j];
262 
263  return C;
264 }
265 
266 
267 double
268 quadraticProduct( const std::vector< std::vector< double > > & A,
269  const std::vector< double > x )
270 {
271  double prod = 0.0;
272  unsigned int n = A.size();
273 
274  assert ( x.size() == n );
275 
276  for ( unsigned int i = 0; i < n; i++ )
277  for ( unsigned int j = 0; j < n; j++ )
278  prod += x[i] * A[i][j] * x[j];
279 
280  return prod;
281 }
282 
283 
284 double
285 norm ( const std::vector< double > & a )
286 {
287  return sqrt( innerProduct( a, a ) );
288 }
289 
290 
291 int
292 cholFactor ( std::vector < std::vector< double > > & A )
293 {
294  unsigned int n = A.size();
295 
296  for ( unsigned int i = 0; i < n ; ++i )
297  for ( unsigned int j = 0; j <= i ; ++j)
298  {
299  double sum = A[i][j];
300 
301  A[j][i] = 0;
302 
303  for ( unsigned int k = 0; k < j; ++k )
304  sum -= A[i][k] * A[j][k];
305 
306  if (i == j)
307  {
308  if (sum < 0) return EXIT_FAILURE;
309 
310  sum = sqrt (sum);
311 
312  if ( fabs(sum) < DBL_EPSILON ) return EXIT_FAILURE;
313 
314  A[i][j] = sum;
315  }
316  else
317  A[i][j] = sum / A[j][j];
318  }
319 
320  return EXIT_SUCCESS;
321 }
322 
323 
324 int
325 cholBackSolve ( const std::vector < std::vector< double > > & L,
326  std::vector< double > & x,
327  const std::vector< double > & b )
328 {
329  unsigned int n = L.size();
330 
331  double sum;
332 
333  // Solving L y = b
334  for ( unsigned int i = 0; i < n ; i++)
335  {
336  sum = b [i];
337  for ( unsigned int j = 0; j < i ; ++j)
338  sum -= x[j] * L[i][j];
339  x[i] = sum / L[i][i];
340  }
341 
342  // Solving L' x = y
343  for ( int i = n - 1; i >= 0; i-- )
344  {
345  sum = x[i];
346  for ( unsigned int j = i + 1; j < n ; j++)
347  sum -= x[j] * L[j][i];
348  x[i] = sum / L[i][i];
349  }
350 
351  return EXIT_SUCCESS;
352 }
353 
354 
355 int
356 invertMatrix ( const std::vector < std::vector< double > > & A,
357  std::vector < std::vector < double > > & Ainv )
358 {
359  unsigned int n = A.size();
360  vector< double > x, b;
361  vector< vector< double > > L;
362 
363  // Set appropriate sizes for the vectors and matrices
364  x.resize( n, 0.0 );
365  b.resize( n, 0.0 );
366 
367  L.resize( n );
368  Ainv.resize( n );
369 
370  for ( unsigned int i = 0; i < n; i++ )
371  {
372  L[i].clear ();
373  L[i].resize ( n, 0.0 );
374 
375  Ainv[i].clear ();
376  Ainv[i].resize ( n, 0.0 );
377  }
378 
379  for ( unsigned int i = 0; i < n; i++ )
380  for ( unsigned int j = 0; j < n; j++ )
381  L[i][j] = A[i][j];
382 
383  // Do a cholesky factorization writing the lower triangular factor
384  // in the lower triangular part of L and setting the upper part as 0
385  cholFactor( L );
386 
387  for ( unsigned int j = 0; j < n; j++ )
388  {
389  // Set up right hand side i.e. set b = ei
390  for ( unsigned int i = 0; i < n; i++ )
391  b[i] = ( i == j ) ? 1 : 0;
392 
393  // LL'x= b is being solved here
394  cholBackSolve( L, x, b );
395 
396  // This x constitutes the j th coloumn of the inverse
397  for ( unsigned int i = 0; i < n; i++ )
398  Ainv[i][j] = x[i] ;
399  }
400 
401  return EXIT_SUCCESS;
402 }
403 
404 int
405 eye ( std::vector < std::vector < double > >& I, int n )
406 {
407  I.resize( n );
408  for( int i = 0; i < n; i++ )
409  {
410  I[i].clear();
411  I[i].resize( n, 0.0 );
412  }
413 
414  for( int i = 0; i < n; i++ )
415  I[i][i] = 1.0;
416 
417  return EXIT_SUCCESS;
418 }
419 
420 int
421 write ( const std::vector < double > & a )
422 {
423  unsigned int n = a.size();
424 
425  for ( unsigned int i = 0; i < n; ++i )
426  cout << setprecision( 15 ) << a[i] << endl;
427  cout << endl;
428 
429  return EXIT_SUCCESS;
430 }
431 
432 
433 int
434 write ( const std::vector < std::vector < double > > & A )
435 {
436  unsigned int n = A.size();
437 
438  for ( unsigned int i = 0; i < n; ++i )
439  {
440  for ( unsigned int j = 0; j < n; ++j )
441  cout << setw( 8 ) << setprecision( 4 ) << A[i][j];
442  cout << endl;
443  }
444 
445  cout << endl;
446 
447  return EXIT_SUCCESS;
448 }
449 
450 
451 int
452 allocateMatrix ( std::vector < std::vector < double > > & A,
453  int m, int n )
454 {
455  A.resize( m );
456  for( int i = 0; i < m; i++ )
457  {
458  A[i].clear();
459  A[i].resize( n, 0.0 );
460  }
461 
462  return EXIT_SUCCESS;
463 }
464 
465 
466 int
467 allocateVector ( std::vector < double > & x, int n )
468 {
469  x.clear();
470  x.resize( n, 0.0 );
471 
472  return EXIT_SUCCESS;
473 }
474 
475 
476 /* The driver main subroutine to check a few of above function.
477  Test with the following matlab code:
478  n = 4; L = tril( randn(n,n), -1 ) + eye(n,n); A = L' * L; B = randn(n , n); x = randn(n , 1); y = randn(n , 1); save test.txt -ascii A B x y;
479  Then perform the operations as stated in the following program.
480 */
481 /*int main()
482 {
483  int n = 4;
484  vector< double > x, y, z;
485  vector< vector < double > > A, B, Ainv;
486  ifstream fin( "test.txt" );
487 
488  if( !fin )
489  {
490  cout << " Could not open the file for reading " << endl;
491  return EXIT_SUCCESS;
492  }
493 
494  allocateMatrix( A, n, n );
495  allocateMatrix( B, n, n );
496  allocateVector( x, n );
497  allocateVector( y, n );
498 
499  for( int i = 0; i < n; i++ )
500  for( int j = 0; j < n; j++ )
501  fin >> A[i][j];
502 
503  for( int i = 0; i < n; i++ )
504  for( int j = 0; j < n; j++ )
505  fin >> B[i][j];
506 
507  for( int i = 0; i < n; i++ )
508  fin >> x[i];
509 
510  for( int i = 0; i < n; i++ )
511  fin >> y[i];
512 
513  fin.close();
514 
515  //cout << "x + 3.14 * x + y /1.4141 - 2.8 * A * x - y + (y' * A)'= " << endl;
516  //write( x + 3.141 * x + y / 1.4141 - 2.8 * A * x - y + y * A );
517 
518  //cout << "A + 3.14 * B + A /1.4141 - A * B + 65.0 * x * y' - B = " << endl;
519  //write( A + 3.14 * B + A /1.4141 - A * B + 65.0 * x * y ) - B );
520 
521  //cout << "inv(A) = " << endl;
522  //invertMatrix( A, Ainv );
523  //write( Ainv );
524 
525 
526  double temp = ( 1 + innerProduct( y, B * y ) / ys ) / ys;
527 
528  t1 = ( outerProduct(s, y) * B)/ys + ( m_M * outerProduct(y , s) ) / ys;
529  t2 = temp * outerProduct( s, s );
530  B = B - t1 + t2;
531 
532 
533  return EXIT_SUCCESS;
534 }
535 */
536 
537 } // namespace Numeric
538 } // namespace hippodraw
std::vector< double > operator-(const std::vector< double > &x, const std::vector< double > &y)
Given two vectors x and y this function performs operation z = x - y.
Definition: NumLinAlg.cxx:53
unsigned int i
Collection of linear algebra functions.
std::vector< double > operator+(const std::vector< double > &x, const std::vector< double > &y)
Given two vectors x and y this function performs operation z = x + y.
Definition: NumLinAlg.cxx:38
double innerProduct(const std::vector< double > &a, const std::vector< double > &b)
Computes the dot or the inner product of two vectors(i.e.
Definition: NumLinAlg.cxx:239
int allocateMatrix(std::vector< std::vector< double > > &A, int m, int n)
Allocates a matrix of size m x n.
Definition: NumLinAlg.cxx:452
int cholFactor(std::vector< std::vector< double > > &A)
The subroutine which does cholesky factorization of a given Symmetric positive definite matrix (say) ...
Definition: NumLinAlg.cxx:292
vector< vector< double > > outerProduct(const std::vector< double > &a, const std::vector< double > &b)
Computes the outer product of two vectors (i.e.
Definition: NumLinAlg.cxx:252
int cholBackSolve(const std::vector< std::vector< double > > &L, std::vector< double > &x, const std::vector< double > &b)
Solves the equation LL&#39;x = b where L is lower triangular matrix.
Definition: NumLinAlg.cxx:325
int eye(std::vector< std::vector< double > > &I, int n)
Creates an n x n identity matrix for M.
Definition: NumLinAlg.cxx:405
std::vector< double > operator*(double a, const std::vector< double > &x)
Given a scalar a and a vector x this function performs operation y = ax.
Definition: NumLinAlg.cxx:119
int invertMatrix(const std::vector< std::vector< double > > &A, std::vector< std::vector< double > > &Ainv)
Inverts a SPD matrix a to get inverse Ainv using the cholesky factorization.
Definition: NumLinAlg.cxx:356
double quadraticProduct(const std::vector< std::vector< double > > &A, const std::vector< double > x)
Calculates the vector-matrix-vector product x&#39;*A*x.
Definition: NumLinAlg.cxx:268
double norm(const std::vector< double > &a)
Computes the two norm of the vector.
Definition: NumLinAlg.cxx:285
std::vector< double > operator/(const std::vector< double > &x, double a)
Given a scalar and a vector x this function performs operation y = x/a.
Definition: NumLinAlg.cxx:133
int write(const std::vector< double > &a)
Given the vector it writes it to std stream.
Definition: NumLinAlg.cxx:421
int allocateVector(std::vector< double > &x, int n)
Allocates a vector of size n.
Definition: NumLinAlg.cxx:467

Generated for HippoDraw Class Library by doxygen