Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
SVD3x3.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 #include "SVD3x3.hh"
26 
27 
28 #ifdef WIN32
29 # define _USE_MATH_DEFINES
30 #endif //WIN32
31 #include <math.h>
32 
33 //#include <Base/Common/BIASpragma.hh>
34 
35 using namespace BIAS;
36 using namespace std;
37 
38 #define SVD_MAX_ITERATIONS 40
39 
41 {
42  A_.newsize(3, 3);
43  S_.newsize(3);
44  U_.newsize(3, 3);
45  VT_.newsize(3, 3);
46  ZeroThreshold_=DEFAULT_DOUBLE_ZERO_THRESHOLD;
47  Decomposed_=false;
48 }
49 
50 SVD3x3::SVD3x3(const Matrix <double> & M, double ZeroThreshold)
51 {
52  A_.newsize(3, 3);
53  S_.newsize(3);
54  U_.newsize(3, 3);
55  VT_.newsize(3, 3);
56  Compute(M, ZeroThreshold);
57 }
58 
59 #define PYTHAG(a,b) (fabs(a) > fabs(b) ? \
60 fabs(a)*sqrt(1.0+(fabs(b)/fabs(a))*(fabs(b)/fabs(a))) : \
61 (fabs(b) > 0 ? fabs(b)*sqrt(1.0+(fabs(a)/fabs(b))*(fabs(a)/fabs(b))) : 0.0))
62 
63 #define MAX(a,b) ((a) > (b) ? (a) : (b))
64 
65 #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
66 
67 /** this function is based on svdcmp from the numerical recipes in C */
68 int SVD3x3::Compute(const Matrix<double> & M, double ZeroThreshold)
69 {
70  BIASASSERT(M.num_rows()==3);
71  BIASASSERT(M.num_cols()==3);
72 
73  Decomposed_=false;
74  ZeroThreshold_ = ZeroThreshold;
75  U_=A_=M;
76  int res=0;
77  double **a=U_.GetDataArray1(), **v=VT_.GetDataArray1();
78  double *w=S_.GetData()-1;
79  int flag=0, i=0, its=0, j=0, jj=0 , k=0, l=0, nm=0;
80  double c=0.0, f=0.0, h=0.0, s=0.0, x=0.0, y=0.0, z=0.0;
81  double norma=0.0, g=0.0, sc=0.0;
82  double tmp[4];
83 
84  for (i=1; i<=3; i++) {
85  l=i+1;
86  tmp[i]=sc*g;
87  g=s=sc=0.0;
88  if (i <= 3) {
89  for (k=i; k<=3; k++)
90  sc += fabs(a[k][i]);
91  if (sc) {
92  for (k=i; k<=3; k++) {
93  a[k][i] /= sc;
94  // here s and a[k][i] are exactly the same for O2 and O3
95  s += a[k][i]*a[k][i];
96  // s is now slightly different for O2 and O3 !
97  }
98  f=a[i][i];
99  g = -SIGN(sqrt(s),f);
100  h=f*g-s;
101  a[i][i]=f-g;
102  if (i != 3) {
103  for (j=l; j<=3; j++) {
104  for (s=0.0,k=i; k<=3; k++)
105  s += a[k][i]*a[k][j];
106  f=s/h;
107  for (k=i; k<=3; k++)
108  a[k][j] += f*a[k][i];
109  }
110  }
111  for (k=i; k<=3; k++)
112  a[k][i] *= sc;
113  }
114  }
115  w[i]=sc*g;
116  g=s=sc=0.0;
117  if (i < 3) {
118  for (k=l; k<=3; k++)
119  sc += fabs(a[i][k]);
120  if (sc) {
121  for (k=l; k<=3; k++) {
122  a[i][k] /= sc;
123  s += a[i][k]*a[i][k];
124  }
125  f=a[i][l];
126  g = -SIGN(sqrt(s),f);
127  h=f*g-s;
128  a[i][l]=f-g;
129  for (k=l; k<=3; k++)
130  tmp[k]=a[i][k]/h;
131  if (i != 3) {
132  for (j=l; j<=3; j++) {
133  for (s=0.0,k=l; k<=3; k++)
134  s += a[j][k]*a[i][k];
135  for (k=l; k<=3; k++)
136  a[j][k] += s*tmp[k];
137  }
138  }
139  for (k=l; k<=3; k++)
140  a[i][k] *= sc;
141  }
142  }
143  norma=MAX(norma,(fabs(w[i])+fabs(tmp[i])));
144  }
145  for (i=3; i>=1; i--) {
146  if (i < 3) {
147  if (g) {
148  for (j=l; j<=3; j++)
149  v[i][j]=(a[i][j]/a[i][l])/g;
150  for (j=l; j<=3; j++) {
151  for (s=0.0,k=l; k<=3; k++)
152  s += a[i][k]*v[j][k];
153  for (k=l; k<=3; k++)
154  v[j][k] += s*v[i][k];
155  }
156  }
157  for (j=l; j<=3; j++)
158  v[i][j]=v[j][i]=0.0;
159  }
160  v[i][i]=1.0;
161  g=tmp[i];
162  l=i;
163  }
164  for (i=3; i>=1; i--) {
165  l=i+1;
166  g=w[i];
167  if (i < 3)
168  for (j=l; j<=3; j++)
169  a[i][j]=0.0;
170  if (g) {
171  g=1.0/g;
172  if (i != 3) {
173  for (j=l; j<=3; j++) {
174  for (s=0.0, k=l; k<=3; k++)
175  s += a[k][i]*a[k][j];
176  f=(s/a[i][i])*g;
177  for (k=i; k<=3; k++)
178  a[k][j] += f*a[k][i];
179  }
180  }
181  for (j=i; j<=3; j++)
182  a[j][i] *= g;
183  } else {
184  for (j=i; j<=3; j++)
185  a[j][i]=0.0;
186  }
187  ++a[i][i];
188  }
189  for (k=3; k>=1; k--) {
190  for (its=1; its<=SVD_MAX_ITERATIONS; its++) {
191  flag=1;
192  for (l=k;l>=1;l--) {
193  nm=l-1;
194  if (fabs(tmp[l])+norma == norma) {
195  // for l==k==2 we never reach this point, because lhs and rhs
196  // differ here by 1e-18 !
197  flag=0;
198  break;
199  }
200  if (fabs(w[nm])+norma == norma)
201  break;
202  }
203  if (flag) {
204  c=0.0;
205  s=1.0;
206  for (i=l; i<=k; i++) {
207  f=s*tmp[i];
208  if (fabs(f)+norma != norma) {
209  g=w[i];
210  h=PYTHAG(f,g);
211  w[i]=h;
212  h=1.0/h;
213  c=g*h;
214  s=(-f*h);
215  for (j=1; j<=3; j++) {
216  y=a[j][nm];
217  z=a[j][i];
218  a[j][nm]=y*c+z*s;
219  a[j][i]=z*c-y*s;
220  }
221  }
222  }
223  }
224  z=w[k];
225  // check for negative singular values and adapt them and V accordingly
226  if (l == k) {
227  if (z < 0.0) {
228  w[k] = -z;
229  for (j=1; j<=3; j++)
230  v[k][j]=(-v[k][j]);
231  }
232  break;
233  }
234  if (its == SVD_MAX_ITERATIONS) {
235  BIASERR("No convergence in "<<SVD_MAX_ITERATIONS<<" iterations");
236  res=-1;
237  break;
238  }
239  x=w[l];
240  nm=k-1;
241  y=w[nm];
242  g=tmp[nm];
243  h=tmp[k];
244  f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
245  g=PYTHAG(f,1.0);
246  f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
247  c=s=1.0;
248  for (j=l; j<=nm; j++) {
249  i=j+1;
250  g=tmp[i];
251  y=w[i];
252  h=s*g;
253  g=c*g;
254  z=PYTHAG(f,h);
255  tmp[j]=z;
256  c=f/z;
257  s=h/z;
258  f=x*c+g*s;
259  g=g*c-x*s;
260  h=y*s;
261  y=y*c;
262  for (jj=1; jj<=3; jj++) {
263  x=v[j][jj];
264  z=v[i][jj];
265  v[j][jj]=x*c+z*s;
266  v[i][jj]=z*c-x*s;
267  }
268  z=PYTHAG(f,h);
269  w[j]=z;
270  if (z) {
271  z=1.0/z;
272  c=f*z;
273  s=h*z;
274  }
275  f=(c*g)+(s*y);
276  x=(c*y)-(s*g);
277  for (jj=1; jj<=3; jj++) {
278  y=a[jj][j];
279  z=a[jj][i];
280  a[jj][j]=y*c+z*s;
281  a[jj][i]=z*c-y*s;
282  }
283  }
284  tmp[l]=0.0;
285  tmp[k]=f;
286  w[k]=x;
287  }
288  }
289 
290  // now sort singular values
291  // we wouldnt need the fabs here if svd always worked correctly,
292  // for most reasonable ordering in case of fail, check for sign
293  i = (fabs(S_[0]) < fabs(S_[1])) ? 1 : 0;
294  if (fabs(S_[i]) < fabs(S_[2]))
295  i = 2;
296  if (i != 0)
297  _Swap(0, i);
298  if (fabs(S_[1]) < fabs(S_[2]))
299  _Swap(1, 2);
300 
301  if (res==0) Decomposed_=true;
302 
303  return res;
304 }
305 #undef SIGN
306 #undef MAX
307 #undef PYTHAG
308 
309 
310 
Subscript num_cols() const
Definition: cmat.h:320
int Compute(const Matrix< double > &M, double ZeroThreshold=DEFAULT_DOUBLE_ZERO_THRESHOLD)
set a new matrix and compute its decomposition.
Definition: SVD3x3.cpp:68
Subscript num_rows() const
Definition: cmat.h:319