ADMB Documentation  -a65f1c97
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
dmat42.cpp
Go to the documentation of this file.
1 /*
2  * $Id$
3  *
4  * Author: David Fournier
5  * Copyright (c) 2009-2012 ADMB Foundation
6  */
15 #include <fvar.hpp>
16 #ifndef OPT_LIB
17  #include <cassert>
18 #endif
19 
20 #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
21 
22 int svd(int m, int n, int withu, int withv, double eps, double tol,
23  const dmatrix& a, const dvector& _q,
24  const dmatrix& _u, const dmatrix& _v);
25 int svd_nlm(int m, int n, int withu, int withv, double eps, double tol,
26  const dmatrix& aa, const dvector& _q,
27  const dmatrix& _u, const dmatrix& _v);
28 int svd_mln(int m, int n, int withu, int withv, double eps, double tol,
29  const dmatrix& aa, const dvector& _q,
30  const dmatrix& _u, const dmatrix& _v);
31 
32 /*
33 static double pythag(double a, double b)
34 {
35  double fa=fabs(a);
36  double fb=fabs(b);
37  if (fa>fb)
38  return fa*sqrt(1.0+square(fb/fa));
39  else
40  return fb*sqrt(1.0+square(fa/fb));
41 }
42 */
43 
44 /*
45 class sing_val_decomp
46 {
47  dmatrix a;
48  dvector w;
49  dmatrix v;
50 public:
51  sing_val_decomp(const dmatrix& _a, const dvector & _w,const dmatrix& _v);
52  dmatrix get_u(void){return a;}
53  dvector get_w(void){return w;}
54  dmatrix get_v(void){return v;}
55 };
56 */
57 
63  const dmatrix& _v) :
64  a(_a), w(_w), v(_v)
65 {}
66 
72 {
73  if (_a.indexmin() !=1 )
74  {
75  cerr << "index error in singval_decomp" << endl;
76  ad_exit(1);
77  }
78  int m = _a.indexmax();
79  int n = _a(1).indexmax();
80  dmatrix a(1,m,1,n);
81  a=_a;
82  dvector w(1,n);
83  dmatrix u(1,m,1,n);
84  dmatrix v(1,n,1,n);
85 
86  double eps = 1.e-12;
87  double tol = eps;
88  int k = svd(m,n,1,1,eps,tol,a,w,u,v);
89  if(k!=0)
90  {
91  cerr << "Error in singval_decomp in iteration " << k << endl;
92  ad_exit(1);
93  }
94  return sing_val_decomp(u,w,v);
95 }
96 
118 int svd(int m,int n,int withu,int withv,double eps,double tol,
119  const dmatrix& aa, const dvector& _q,
120  const dmatrix& _u, const dmatrix& _v)
121 {
122  ADUNCONST(dmatrix,u)
123  ADUNCONST(dmatrix,v)
124  ADUNCONST(dvector,q)
125 
126  int urlb=u.rowmin();
127  int uclb=u.colmin();
128  u.rowshift(0);
129  u.colshift(0);
130  int vrlb=v.rowmin();
131  int vclb=v.colmin();
132  v.rowshift(0);
133  v.colshift(0);
134  int qlb=q.indexmin();
135  q.shift(0);
136  dmatrix a=aa;
137  int arlb=a.rowmin();
138  int aclb=a.colmin();
139  a.rowshift(0);
140  a.colshift(0);
141 
142  int k;
143  if(m>=n)
144  k = svd_nlm(m,n,withu,withv,eps,tol,a,q,u,v);
145  else
146  k = svd_mln(m,n,withu,withv,eps,tol,a,q,u,v);
147 
148  u.rowshift(urlb);
149  u.colshift(uclb);
150  v.rowshift(vrlb);
151  v.colshift(vclb);
152  q.shift(qlb);
153  a.rowshift(arlb);
154  a.colshift(aclb);
155 
156  return k;
157 }
158 
170 int svd_mln(int m, int n, int withu, int withv, double eps, double tol,
171  const dmatrix& aa, const dvector& _q,
172  const dmatrix& _u, const dmatrix& _v)
173 {
174  ADUNCONST(dmatrix,u)
175  ADUNCONST(dmatrix,v)
176  ADUNCONST(dvector,q)
177 
178  int i,j,k,l,l1,iter,retval;
179  double c,f,g,h,s,x,y,z;
180 
181 #ifndef OPT_LIB
182  assert(n > 0);
183 #endif
184 
185  double* e = (double*)calloc((size_t)n,sizeof(double));
186  retval = 0;
187 
188  u=aa;
189 
190 /* Householder's reduction to bidiagonal form. */
191  g = x = 0.0;
192  for (i=0;i<n;i++)
193  {
194  e[i] = g;
195  s = g = 0.0;
196  l = i+1;
197  if( i<m )
198  {
199  for (j=i;j<m;j++)
200  {
201  s += (u[j][i]*u[j][i]);
202  }
203  if (s < tol)
204  g = 0.0;
205  else
206  {
207  f = u[i][i];
208  g = (f < 0) ? sqrt(s) : -sqrt(s);
209  h = f * g - s;
210  u[i][i] = f - g;
211  for (j=l;j<n;j++)
212  {
213  s = 0.0;
214  for (k=i;k<m;k++)
215  {
216  s += (u[k][i] * u[k][j]);
217  }
218  f = s / h;
219  for (k=i;k<m;k++)
220  {
221  u[k][j] += (f * u[k][i]);
222  }
223  } /* end j */
224  } /* end s */
225  }
226  q[i] = g;
227  s = g = 0.0;
228  if( i<m && i!=n-1 )
229  {
230  for (j=l;j<n;j++)
231  {
232  s += (u[i][j] * u[i][j]);
233  }
234  if (s < tol)
235  g = 0.0;
236  else
237  {
238  f = u[i][i+1];
239  g = (f < 0) ? sqrt(s) : -sqrt(s);
240  h = f * g - s;
241  u[i][i+1] = f - g;
242  for (j=l;j<n;j++)
243  {
244  e[j] = u[i][j]/h;
245  }
246  for (j=l;j<m;j++)
247  {
248  s = 0.0;
249  for (k=l;k<n;k++)
250  {
251  s += (u[j][k] * u[i][k]);
252  }
253  for (k=l;k<n;k++)
254  {
255  u[j][k] += (s * e[k]);
256  }
257  } /* end j */
258  } /* end s */
259  } /* end if*/
260  y = fabs(q[i]) + fabs(e[i]);
261  if (y > x)
262  {
263  x = y;
264  }
265  } /* end i */
266 
267 /* accumulation of right-hand transformations */
268  if (withv)
269  {
270  //assert(l == n);
271  l = n;
272  for (i=n-1;i>=0;i--)
273  {
274  if ( i < n-2 )
275  {
276  if (g != 0.0)
277  {
278  h = u[i][i+1] * g;
279  for (j=l;j<n;j++)
280  {
281  v[j][i] = u[i][j]/h;
282  }
283  for (j=l;j<n;j++)
284  {
285  s = 0.0;
286  for (k=l;k<n;k++)
287  {
288  s += (u[i][k] * v[k][j]);
289  }
290  for (k=l;k<n;k++)
291  {
292  v[k][j] += (s * v[k][i]);
293  }
294  } /* end j */
295  } /* end g */
296  for (j=l;j<n;j++)
297  {
298  v[i][j] = v[j][i] = 0.0;
299  }
300  }
301  v[i][i] = 1.0;
302  g = e[i];
303  l = i;
304  } /* end i */
305  } /* end withv, parens added for clarity */
306 
307 /* accumulation of left-hand transformations */
308  if (withu) {
309  for (i=min(m,n)-1;i>=0;i--) {
310  l = i + 1;
311  g = q[i];
312  for (j=l;j<n;j++) /* upper limit was 'n' */
313  u[i][j] = 0.0;
314  if (g != 0.0) {
315  h = u[i][i] * g;
316  for (j=l;j<n;j++) { /* upper limit was 'n' */
317  s = 0.0;
318  for (k=l;k<m;k++)
319  s += (u[k][i] * u[k][j]);
320  f = s / h;
321  for (k=i;k<m;k++)
322  u[k][j] += (f * u[k][i]);
323  } /* end j */
324  for (j=i;j<m;j++)
325  u[j][i] /= g;
326  } /* end g */
327  else {
328  for (j=i;j<m;j++)
329  u[j][i] = 0.0;
330  }
331  u[i][i] += 1.0;
332  } /* end i*/
333  } /* end withu, parens added for clarity */
334 
335 /* diagonalization of the bidiagonal form */
336  eps *= x;
337  for (k=n-1;k>=0;k--) {
338  iter = 0;
339 test_f_splitting:
340  for (l=k;l>=0;l--) {
341  if (fabs(e[l]) <= eps) goto test_f_convergence;
342  if (fabs(q[l-1]) <= eps) goto cancellation;
343  } /* end l */
344 
345 /* cancellation of e[l] if l > 0 */
346 cancellation:
347  c = 0.0;
348  s = 1.0;
349  l1 = l - 1;
350  for (i=l;i<=k;i++) {
351  f = s * e[i];
352  e[i] *= c;
353  if (fabs(f) <= eps) goto test_f_convergence;
354  g = q[i];
355  h = q[i] = sqrt(f*f + g*g);
356  c = g / h;
357  s = -f / h;
358  if (withu) {
359  for (j=0;j<m;j++) {
360  y = u[j][l1];
361  z = u[j][i];
362  u[j][l1] = y * c + z * s;
363  u[j][i] = -y * s + z * c;
364  } /* end j */
365  } /* end withu, parens added for clarity */
366  } /* end i */
367 test_f_convergence:
368  z = q[k];
369  if (l == k) goto convergence;
370 
371 /* shift from bottom 2x2 minor */
372  iter++;
373  if (iter > 30) {
374  retval = k;
375  break;
376  }
377  x = q[l];
378  y = q[k-1];
379  g = e[k-1];
380  h = e[k];
381  f = ((y-z)*(y+z) + (g-h)*(g+h)) / (2*h*y);
382  g = sqrt(f*f + 1.0);
383  f = ((x-z)*(x+z) + h*(y/((f<0)?(f-g):(f+g))-h))/x;
384 /* next QR transformation */
385  c = s = 1.0;
386  for (i=l+1;i<=k;i++) {
387  g = e[i];
388  y = q[i];
389  h = s * g;
390  g *= c;
391  e[i-1] = z = sqrt(f*f+h*h);
392  c = f / z;
393  s = h / z;
394  f = x * c + g * s;
395  g = -x * s + g * c;
396  h = y * s;
397  y *= c;
398  if (withv) {
399  for (j=0;j<n;j++) {
400  x = v[j][i-1];
401  z = v[j][i];
402  v[j][i-1] = x * c + z * s;
403  v[j][i] = -x * s + z * c;
404  } /* end j */
405  } /* end withv, parens added for clarity */
406  q[i-1] = z = sqrt(f*f + h*h);
407  c = f/z;
408  s = h/z;
409  f = c * g + s * y;
410  x = -s * g + c * y;
411  if (withu) {
412  for (j=0;j<m;j++) {
413  y = u[j][i-1];
414  z = u[j][i];
415  u[j][i-1] = y * c + z * s;
416  u[j][i] = -y * s + z * c;
417  } /* end j */
418  } /* end withu, parens added for clarity */
419  } /* end i */
420  e[l] = 0.0;
421  e[k] = f;
422  q[k] = x;
423  goto test_f_splitting;
424 convergence:
425  if (z < 0.0) {
426 /* q[k] is made non-negative */
427  q[k] = - z;
428  if (withv) {
429  for (j=0;j<n;j++)
430  v[j][k] = -v[j][k];
431  } /* end withv, parens added for clarity */
432  } /* end z */
433  } /* end k */
434 
435  free(e);
436 
437  return retval;
438 }
439 
451 int svd_nlm(int m, int n, int withu, int withv, double eps, double tol,
452  const dmatrix& aa, const dvector& _q,
453  const dmatrix& _u, const dmatrix& _v)
454 {
455  ADUNCONST(dmatrix,u)
456  ADUNCONST(dmatrix,v)
457  ADUNCONST(dvector,q)
458 
459  int i,j,k,l,l1,iter,retval;
460  double c,f,g,h,s,x,y,z;
461 
462 #ifndef OPT_LIB
463  assert(n > 0);
464 #endif
465  double* e = (double *)calloc((size_t)n, sizeof(double));
466  retval = 0;
467 
468  u=aa;
469 /* Householder's reduction to bidiagonal form. */
470  g = x = 0.0;
471  for (i=0;i<n;i++)
472  {
473  e[i] = g;
474  s = 0.0;
475  l = i+1;
476  for (j=i;j<m;j++)
477  {
478  s += (u[j][i]*u[j][i]);
479  }
480  if (s < tol)
481  g = 0.0;
482  else
483  {
484  f = u[i][i];
485  g = (f < 0) ? sqrt(s) : -sqrt(s);
486  h = f * g - s;
487  u[i][i] = f - g;
488  for (j=l;j<n;j++)
489  {
490  s = 0.0;
491  for (k=i;k<m;k++)
492  {
493  s += (u[k][i] * u[k][j]);
494  }
495  f = s / h;
496  for (k=i;k<m;k++)
497  {
498  u[k][j] += (f * u[k][i]);
499  }
500  } /* end j */
501  } /* end s */
502  q[i] = g;
503  s = 0.0;
504  for (j=l;j<n;j++)
505  {
506  s += (u[i][j] * u[i][j]);
507  }
508  if (s < tol)
509  g = 0.0;
510  else
511  {
512  f = u[i][i+1];
513  g = (f < 0) ? sqrt(s) : -sqrt(s);
514  h = f * g - s;
515  u[i][i+1] = f - g;
516  for (j=l;j<n;j++)
517  {
518  e[j] = u[i][j]/h;
519  }
520  for (j=l;j<m;j++)
521  {
522  s = 0.0;
523  for (k=l;k<n;k++)
524  {
525  s += (u[j][k] * u[i][k]);
526  }
527  for (k=l;k<n;k++)
528  {
529  u[j][k] += (s * e[k]);
530  }
531  } /* end j */
532  } /* end s */
533  y = fabs(q[i]) + fabs(e[i]);
534  if (y > x)
535  {
536  x = y;
537  }
538  } /* end i */
539 
540 /* accumulation of right-hand transformations */
541  if (withv)
542  {
543  //assert(l == n);
544  l = n;
545  for (i=n-1;i>=0;i--)
546  {
547  if (g != 0.0)
548  {
549  h = u[i][i+1] * g;
550  for (j=l;j<n;j++)
551  {
552  v[j][i] = u[i][j]/h;
553  }
554  for (j=l;j<n;j++)
555  {
556  s = 0.0;
557  for (k=l;k<n;k++)
558  {
559  s += (u[i][k] * v[k][j]);
560  }
561  for (k=l;k<n;k++)
562  {
563  v[k][j] += (s * v[k][i]);
564  }
565  } /* end j */
566  } /* end g */
567  for (j=l;j<n;j++)
568  {
569  v[i][j] = v[j][i] = 0.0;
570  }
571  v[i][i] = 1.0;
572  g = e[i];
573  l = i;
574  } /* end i */
575  } /* end withv, parens added for clarity */
576 
577 /* accumulation of left-hand transformations */
578  if (withu) {
579  for (i=n-1;i>=0;i--) {
580  l = i + 1;
581  g = q[i];
582  for (j=l;j<n;j++) /* upper limit was 'n' */
583  u[i][j] = 0.0;
584  if (g != 0.0) {
585  h = u[i][i] * g;
586  for (j=l;j<n;j++) { /* upper limit was 'n' */
587  s = 0.0;
588  for (k=l;k<m;k++)
589  s += (u[k][i] * u[k][j]);
590  f = s / h;
591  for (k=i;k<m;k++)
592  u[k][j] += (f * u[k][i]);
593  } /* end j */
594  for (j=i;j<m;j++)
595  u[j][i] /= g;
596  } /* end g */
597  else {
598  for (j=i;j<m;j++)
599  u[j][i] = 0.0;
600  }
601  u[i][i] += 1.0;
602  } /* end i*/
603  } /* end withu, parens added for clarity */
604 
605 /* diagonalization of the bidiagonal form */
606  eps *= x;
607  for (k=n-1;k>=0;k--) {
608  iter = 0;
609 test_f_splitting:
610  for (l=k;l>=0;l--) {
611  if (fabs(e[l]) <= eps) goto test_f_convergence;
612  if (fabs(q[l-1]) <= eps) goto cancellation;
613  } /* end l */
614 
615 /* cancellation of e[l] if l > 0 */
616 cancellation:
617  c = 0.0;
618  s = 1.0;
619  l1 = l - 1;
620  for (i=l;i<=k;i++) {
621  f = s * e[i];
622  e[i] *= c;
623  if (fabs(f) <= eps) goto test_f_convergence;
624  g = q[i];
625  h = q[i] = sqrt(f*f + g*g);
626  c = g / h;
627  s = -f / h;
628  if (withu) {
629  for (j=0;j<m;j++) {
630  y = u[j][l1];
631  z = u[j][i];
632  u[j][l1] = y * c + z * s;
633  u[j][i] = -y * s + z * c;
634  } /* end j */
635  } /* end withu, parens added for clarity */
636  } /* end i */
637 test_f_convergence:
638  z = q[k];
639  if (l == k) goto convergence;
640 
641 /* shift from bottom 2x2 minor */
642  iter++;
643  if (iter > 30) {
644  retval = k;
645  break;
646  }
647  x = q[l];
648  y = q[k-1];
649  g = e[k-1];
650  h = e[k];
651  f = ((y-z)*(y+z) + (g-h)*(g+h)) / (2*h*y);
652  g = sqrt(f*f + 1.0);
653  f = ((x-z)*(x+z) + h*(y/((f<0)?(f-g):(f+g))-h))/x;
654 /* next QR transformation */
655  c = s = 1.0;
656  for (i=l+1;i<=k;i++) {
657  g = e[i];
658  y = q[i];
659  h = s * g;
660  g *= c;
661  e[i-1] = z = sqrt(f*f+h*h);
662  c = f / z;
663  s = h / z;
664  f = x * c + g * s;
665  g = -x * s + g * c;
666  h = y * s;
667  y *= c;
668  if (withv) {
669  for (j=0;j<n;j++) {
670  x = v[j][i-1];
671  z = v[j][i];
672  v[j][i-1] = x * c + z * s;
673  v[j][i] = -x * s + z * c;
674  } /* end j */
675  } /* end withv, parens added for clarity */
676  q[i-1] = z = sqrt(f*f + h*h);
677  c = f/z;
678  s = h/z;
679  f = c * g + s * y;
680  x = -s * g + c * y;
681  if (withu) {
682  for (j=0;j<m;j++) {
683  y = u[j][i-1];
684  z = u[j][i];
685  u[j][i-1] = y * c + z * s;
686  u[j][i] = -y * s + z * c;
687  } /* end j */
688  } /* end withu, parens added for clarity */
689  } /* end i */
690  e[l] = 0.0;
691  e[k] = f;
692  q[k] = x;
693  goto test_f_splitting;
694 convergence:
695  if (z < 0.0) {
696 /* q[k] is made non-negative */
697  q[k] = - z;
698  if (withv) {
699  for (j=0;j<n;j++)
700  v[j][k] = -v[j][k];
701  } /* end withv, parens added for clarity */
702  } /* end z */
703  } /* end k */
704 
705  free(e);
706 
707  return retval;
708 }
#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
Definition: fvar.hpp:2917
df1_two_variable fabs(const df1_two_variable &x)
Definition: df12fun.cpp:891
exitptr ad_exit
Definition: gradstrc.cpp:53
sing_val_decomp singval_decomp(const dmatrix &_a)
Singular value decomposition.
Definition: dmat42.cpp:71
prnstream & endl(prnstream &)
int svd_nlm(int m, int n, int withu, int withv, double eps, double tol, const dmatrix &aa, const dvector &_q, const dmatrix &_u, const dmatrix &_v)
Singular value decomposition.
Definition: dmat42.cpp:451
d3_array sqrt(const d3_array &arr3)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: d3arr2c.cpp:11
#define min(a, b)
Definition: cbivnorm.cpp:188
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Description not yet available.
Definition: fvar.hpp:9187
int colmin(void) const
Definition: fvar.hpp:2939
Description not yet available.
Definition: fvar.hpp:2819
int indexmax() const
Definition: fvar.hpp:2921
void rowshift(int min)
Changes the range of valid indices for the rows.
Definition: dmat9.cpp:48
#define w
double eps
Definition: ftweak.cpp:13
int svd(int m, int n, int withu, int withv, double eps, double tol, const dmatrix &a, const dvector &_q, const dmatrix &_u, const dmatrix &_v)
Singular value decomposition.
Definition: dmat42.cpp:118
void colshift(int min)
Description not yet available.
Definition: dmat9.cpp:68
int rowmin() const
Definition: fvar.hpp:2925
int svd_mln(int m, int n, int withu, int withv, double eps, double tol, const dmatrix &aa, const dvector &_q, const dmatrix &_u, const dmatrix &_v)
Singular value decomposition.
Definition: dmat42.cpp:170