1
#ifndef _RHEOLEF_TENSOR_SVD_ALGO_H
2
#define _RHEOLEF_TENSOR_SVD_ALGO_H
4
/// This file is part of Rheolef.
6
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
8
/// Rheolef is free software; you can redistribute it and/or modify
9
/// it under the terms of the GNU General Public License as published by
10
/// the Free Software Foundation; either version 2 of the License, or
11
/// (at your option) any later version.
13
/// Rheolef is distributed in the hope that it will be useful,
14
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
/// GNU General Public License for more details.
18
/// You should have received a copy of the GNU General Public License
19
/// along with Rheolef; if not, write to the Free Software
20
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
/// =========================================================================
27
inline const T MIN(const T &a, const T &b)
28
{return b < a ? (b) : (a);}
30
inline const T MAX(const T &a, const T &b)
31
{return b > a ? (b) : (a);}
33
inline const T SIGN(const T &a, const T &b)
34
{return b >= 0 ? (a >= 0 ? a : -a) : (a >= 0 ? -a : a);}
36
inline const T SQR(const T a) {return a*a;}
39
T pythag(const T& a, const T& b)
43
if (absa > absb) return absa*::sqrt(1.0+SQR(absb/absa));
44
else return (absb == 0.0 ? 0.0 : absb*::sqrt(1.0+SQR(absa/absb)));
47
template <class Matrix1, class Matrix2, class Vector, class T, class Size>
49
svdcmp (Matrix1& a, Vector& w, Matrix2& v, Size anrow, Size ancol, T dummy)
52
int i,its,j,jj,k,l,nm;
53
T anorm,c,f,g,h,s,scale,x,y,z;
57
T rv1 [n]; // automatically allocated and destroyed
64
for (k=i;k<m;k++) scale += std::fabs(a[k][i]);
71
g = -SIGN(::sqrt(s),f);
75
for (s=0.0,k=i;k<m;k++) s += a[k][i]*a[k][j];
77
for (k=i;k<m;k++) a[k][j] += f*a[k][i];
79
for (k=i;k<m;k++) a[k][i] *= scale;
84
if (i+1 <= m && i != n) {
85
for (k=l-1;k<n;k++) scale += std::fabs(a[i][k]);
92
g = -SIGN(::sqrt(s),f);
95
for (k=l-1;k<n;k++) rv1[k]=a[i][k]/h;
97
for (s=0.0,k=l-1;k<n;k++) s += a[j][k]*a[i][k];
98
for (k=l-1;k<n;k++) a[j][k] += s*rv1[k];
100
for (k=l-1;k<n;k++) a[i][k] *= scale;
103
anorm=MAX(anorm,(std::fabs(w[i])+std::fabs(rv1[i])));
105
for (i=n-1;i>=0;i--) {
109
v[j][i]=(a[i][j]/a[i][l])/g;
111
for (s=0.0,k=l;k<n;k++) s += a[i][k]*v[k][j];
112
for (k=l;k<n;k++) v[k][j] += s*v[k][i];
115
for (j=l;j<n;j++) v[i][j]=v[j][i]=0.0;
121
for (i=MIN(m,n)-1;i>=0;i--) {
124
for (j=l;j<n;j++) a[i][j]=0.0;
128
for (s=0.0,k=l;k<m;k++) s += a[k][i]*a[k][j];
130
for (k=i;k<m;k++) a[k][j] += f*a[k][i];
132
for (j=i;j<m;j++) a[j][i] *= g;
133
} else for (j=i;j<m;j++) a[j][i]=0.0;
136
for (k=n-1;k>=0;k--) {
137
for (its=0;its<30;its++) {
141
if (std::fabs(rv1[l])+anorm == anorm) {
145
if (std::fabs(w[nm])+anorm == anorm) break;
150
for (i=l-1;i<k+1;i++) {
153
if (std::fabs(f)+anorm == anorm) break;
172
for (j=0;j<n;j++) v[j][k] = -v[j][k];
176
if (its == 29) error_macro("no convergence in 30 svdcmp iterations");
182
f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
184
f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
186
for (j=l;j<=nm;j++) {
200
for (jj=0;jj<n;jj++) {
215
for (jj=0;jj<m;jj++) {
228
}// namespace rheolef
229
#endif // _RHEOLEF_TENSOR_SVD_ALGO_H