ADMB Documentation  -a65f1c97
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
eigenv.cpp
Go to the documentation of this file.
1 
11 #define EIGEN_VECTORS
12 
13 #include <fvar.hpp>
14 #ifndef OPT_LIB
15  #include <cassert>
16  #include <climits>
17 #endif
18 
19 #ifdef ISZERO
20  #undef ISZERO
21 #endif
22 #define ISZERO(d) ((d)==0.0)
23 
24 #if !defined(EIGEN_VECTORS)
25 # define EIGEN_VECTORS
26 #endif
27 
28 #ifdef EIGEN_VECTORS
29  void tri_dagv(const dmatrix& m,const dvector& d,const dvector& e);
30 #else
31  void tri_dag(const dmatrix& m,const dvector& d,const dvector& e);
32 #endif
33 #ifdef EIGEN_VECTORS
34  void get_eigenv(const dvector& d,const dvector& e,const dmatrix& z);
35 #else
36  void get_eigen(const dvector& d,const dvector& e,const dmatrix& z);
37 #endif
38 
44 dmatrix eigenvectors(const dmatrix& m) //,_CONST dvector& diag)
45 {
46  if (m.rowsize()!=m.colsize())
47  {
48  cerr << "Error -- non square matrix passed to dvector"
49  " eigen(const dmatrix& m)" << endl;
50  ad_exit(1);
51  }
52 
53  dmatrix m1=symmetrize(m);
54 #if !defined(OPT_LIB) && (__cplusplus >= 201103L)
55  int n = [](unsigned int rowsize) -> int
56  {
57  assert(rowsize <= INT_MAX);
58  return static_cast<int>(rowsize);
59  } (m1.rowsize());
60 #else
61  int n = static_cast<int>(m1.rowsize());
62 #endif
63  m1.colshift(1); // set minimum column and row indices to 1
64  m1.rowshift(1);
65  dvector diag(1,n);
66  dvector off_diag(1,n);
67 
68  #ifdef EIGEN_VECTORS
69  tri_dagv(m1,diag,off_diag);
70  #else
71  tri_dag(m1,diag,off_diag);
72  #endif
73 
74  #ifdef EIGEN_VECTORS
75  get_eigenv(diag,off_diag,m1); // eigenvalues are returned in diag
76  #else
77  get_eigen(diag,off_diag,m1); // eigenvalues are returned in diag
78  #endif
79  return m1;
80 }
81 
88 dmatrix eigenvectors(const dmatrix& m,const dvector& _diag)
89  //,_CONST dvector& diag)
90 {
91  ADUNCONST(dvector,diag)
92  if (m.rowsize()!=m.colsize())
93  {
94  cerr << "Error -- non square matrix passed to dvector"
95  " eigen(_CONST dmatrix& m)" << endl;
96  ad_exit(1);
97  }
98 
99  dmatrix m1=symmetrize(m);
100 #if !defined(OPT_LIB) && (__cplusplus >= 201103L)
101  int n = [](unsigned int rowsize) -> int
102  {
103  assert(rowsize <= INT_MAX);
104  return static_cast<int>(rowsize);
105  } (m1.rowsize());
106 #else
107  int n = static_cast<int>(m1.rowsize());
108 #endif
109  m1.colshift(1); // set minimum column and row indices to 1
110  m1.rowshift(1);
111  diag.shift(1);
112  if (diag.size()!=m.rowsize())
113  {
114  cerr << "incompatible sizes in vector and matrix passed to"
115  " dmatrix eigenvector routine" << endl;
116  }
117  dvector off_diag(1,n);
118 
119  #ifdef EIGEN_VECTORS
120  tri_dagv(m1,diag,off_diag);
121  #else
122  tri_dag(m1,diag,off_diag);
123  #endif
124 
125  #ifdef EIGEN_VECTORS
126  get_eigenv(diag,off_diag,m1); // eigenvalues are returned in diag
127  #else
128  get_eigen(diag,off_diag,m1); // eigenvalues are returned in diag
129  #endif
130  return m1;
131 }
132 
133 
144 #ifdef EIGEN_VECTORS
145  void tri_dagv(const dmatrix& _m,const dvector& _d,const dvector& _e)
146 #else
147  void tri_dagv(const dmatrix& _m,const dvector& _d,const dvector& _e)
148 #endif
149 {
150  dvector& d = (dvector&) _d;
151  dvector& e = (dvector&) _e;
152  dmatrix& m = (dmatrix&) _m;
153  if (m.rowsize() != m.colsize())
154  {
155  cerr << "Error -- non square matrix passed to "
156  "void tridag(const dmatrix& m)\n";
157  ad_exit(1);
158  }
159  if (m.rowsize() != d.size() || m.rowsize() != e.size()
160  || d.indexmin() != 1 || e.indexmin() !=1 )
161  {
162  cerr <<"Error -- incorrect vector size passed to "
163  "void tridag(const dmatrix& m)\n";
164  ad_exit(1);
165  }
166 #if !defined(OPT_LIB) && (__cplusplus >= 201103L)
167  int n = [](unsigned int rowsize) -> int
168  {
169  assert(rowsize <= INT_MAX);
170  return static_cast<int>(rowsize);
171  } (m.rowsize());
172 #else
173  int n = static_cast<int>(m.rowsize());
174 #endif
175  int l,k,j,i;
176  double scale,hh,h,g,f;
177 
178  for (i=n;i>=2;i--)
179  {
180  l=i-1;
181  h=scale=0.0;
182  if (l > 1)
183  {
184  for (k=1;k<=l;k++)
185  scale += fabs(m[i][k]);
186  if (scale == 0.0)
187  e[i]=m[i][l];
188  else
189  {
190  for (k=1;k<=l;k++)
191  {
192  m[i][k] /= scale;
193  h += m[i][k]*m[i][k];
194  }
195  f=m[i][l];
196  g = f>0 ? -sqrt(h) : sqrt(h);
197  e[i]=scale*g;
198  h -= f*g;
199  m[i][l]=f-g;
200  f=0.0;
201  for (j=1;j<=l;j++)
202  {
203  #ifdef EIGEN_VECTORS
204  /* Next statement can be omitted if eigenvectors not wanted */
205  m[j][i]=m[i][j]/h;
206  #endif
207  g=0.0;
208  for (k=1;k<=j;k++)
209  g += m[j][k]*m[i][k];
210  for (k=j+1;k<=l;k++)
211  g += m[k][j]*m[i][k];
212  e[j]=g/h;
213  f += e[j]*m[i][j];
214  }
215  hh=f/(h+h);
216  for (j=1;j<=l;j++)
217  {
218  f=m[i][j];
219  e[j]=g=e[j]-hh*f;
220  for (k=1;k<=j;k++)
221  m[j][k] -= (f*e[k]+g*m[i][k]);
222  }
223  }
224  }
225  else
226  {
227  e[i]=m[i][l];
228  }
229  d[i]=h;
230  }
231  /* Next statement can be omitted if eigenvectors not wanted */
232  d[1]=0.0;
233  e[1]=0.0;
234  /* Contents of this loop can be omitted if eigenvectors not
235  wanted except for statement d[i]=a[i][i]; */
236  #ifdef EIGEN_VECTORS
237  for (i=1;i<=n;i++)
238  {
239  l=i-1;
240  if (!ISZERO(d[i]))
241  {
242  for (j=1;j<=l;j++)
243  {
244  g=0.0;
245  for (k=1;k<=l;k++)
246  g += m[i][k]*m[k][j];
247  for (k=1;k<=l;k++)
248  m[k][j] -= g*m[k][i];
249  }
250  }
251  d[i]=m[i][i];
252  m[i][i]=1.0;
253  for (j=1;j<=l;j++) m[j][i]=m[i][j]=0.0;
254  }
255  #endif
256 }
257 
263 double SIGNV(const double x, double y)
264 {
265  if (y<0)
266  {
267  return -fabs(x);
268  }
269  else
270  {
271  return fabs(x);
272  }
273 }
274 
284 #ifdef EIGEN_VECTORS
285  void get_eigenv(const dvector& _d,const dvector& _e,const dmatrix& _z)
286 #else
287  void get_eigen(const dvector& _d,const dvector& _e,const dmatrix& _z)
288 #endif
289 {
290  dvector& d = (dvector&) _d;
291  dvector& e = (dvector&) _e;
292  dmatrix& z = (dmatrix&) _z;
293 #if !defined(OPT_LIB) && (__cplusplus >= 201103L)
294  int n = [](unsigned int size) -> int
295  {
296  assert(size <= INT_MAX);
297  return static_cast<int>(size);
298  } (d.size());
299 #else
300  int n = static_cast<int>(d.size());
301 #endif
302  int m,l,iter,i;
303  double s,r,p,g,f,dd,c,b;
304 
305  for (i=2;i<=n;i++) e[i-1]=e[i];
306  e[n]=0.0;
307  for (l=1;l<=n;l++) {
308  iter=0;
309  do {
310  for (m=l;m<=n-1;m++) {
311  dd=fabs(d[m])+fabs(d[m+1]);
312  if (fabs(e[m])+dd == dd) break;
313  }
314  if (m != l)
315  {
316  if (iter++ == 30)
317  {
318  cerr << "Maximum number of iterations exceeded in"
319  " dvector eigen(const dmatrix& m)\n";
320  ad_exit(1);
321  }
322  g=(d[l+1]-d[l])/(2.0*e[l]);
323  r=sqrt((g*g)+1.0);
324  g=d[m]-d[l]+e[l]/(g+SIGNV(r,g));
325  s=c=1.0;
326  p=0.0;
327  for (i=m-1;i>=l;i--) {
328  f=s*e[i];
329  b=c*e[i];
330  if (fabs(f) >= fabs(g)) {
331  c=g/f;
332  r=sqrt((c*c)+1.0);
333  e[i+1]=f*r;
334  c *= (s=1.0/r);
335  } else {
336  s=f/g;
337  r=sqrt((s*s)+1.0);
338  e[i+1]=g*r;
339  s *= (c=1.0/r);
340  }
341  g=d[i+1]-p;
342  r=(d[i]-g)*s+2.0*c*b;
343  p=s*r;
344  d[i+1]=g+p;
345  g=c*r-b;
346  /* Next loop can be omitted if eigenvectors not wanted */
347  #ifdef EIGEN_VECTORS
348  for (int k=1;k<=n;k++)
349  {
350  f=z[k][i+1];
351  z[k][i+1]=s*z[k][i]+c*f;
352  z[k][i]=c*z[k][i]-s*f;
353  }
354  #endif
355  }
356  d[l]=d[l]-p;
357  e[l]=g;
358  e[m]=0.0;
359  }
360  } while (m != l);
361  }
362 }
363 #undef EIGEN_VECTORS
#define x
#define ADUNCONST(type, obj)
Creates a shallow copy of obj that is not CONST.
Definition: fvar.hpp:140
Vector of double precision numbers.
Definition: dvector.h:50
int indexmin() const
Get minimum valid index.
Definition: dvector.h:199
df1_two_variable fabs(const df1_two_variable &x)
Definition: df12fun.cpp:891
exitptr ad_exit
Definition: gradstrc.cpp:53
unsigned int colsize() const
Definition: fvar.hpp:2948
void get_eigen(const dvar_vector &d, const dvar_vector &e, const dvar_matrix &z)
Eigenvalues.
Definition: dveigen.cpp:187
void get_eigenv(const dvar_vector &d, const dvar_vector &e, const dvar_matrix &z)
Eigenvalues and eigenvectors.
Definition: dveigenv.cpp:236
dmatrix symmetrize(const dmatrix &matrix)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: dmat12.cpp:14
prnstream & endl(prnstream &)
dmatrix eigenvectors(const banded_symmetric_dmatrix &_SS, const dvector &_e)
Description not yet available.
Definition: dmat28.cpp:442
d3_array sqrt(const d3_array &arr3)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: d3arr2c.cpp:11
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Description not yet available.
Definition: fvar.hpp:2819
unsigned int size() const
Get number of elements in array.
Definition: dvector.h:209
void tri_dag(const dvar_matrix &, const dvar_vector &, const dvar_vector &)
Householder transformation for eigenvalue computation.
Definition: dveigen.cpp:54
void rowshift(int min)
Changes the range of valid indices for the rows.
Definition: dmat9.cpp:48
void tri_dagv(const dvar_matrix &, const dvar_vector &, const dvar_vector &)
Householder transformation for eivenvector computation.
Definition: dveigenv.cpp:93
void colshift(int min)
Description not yet available.
Definition: dmat9.cpp:68
unsigned int rowsize() const
Definition: fvar.hpp:2934
dvariable SIGNV(const prevariable &x, const prevariable &y)
Change sign.
Definition: dveigenv.cpp:213
#define ISZERO(d)
Definition: eigenv.cpp:22