c_jama_svd.h

JAMA SVD file modified for my purpose, then bidiagonalization commented. M_:k denotes MATLAB M(:,k) in comments beginning with initials PZ - Zoltan Prohaszka, 2013-05-11 06:17 pm

Download (21 kB)

 
1
   /** Singular Value Decomposition. 
2
   
3
                                U,S,V=svd(A);get...():      A=U*S*V^_T_ 
4
5
   <P>
6
   For an m-by-n matrix A with m >= n, the singular value decomposition is
7
   an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and
8
   an n-by-n orthogonal matrix V so that A = U*S*V'.
9
   <P>
10
   The singular values, sigma[k] = S[k][k], are ordered so that
11
   sigma[0] >= sigma[1] >= ... >= sigma[n-1].
12
   <P>
13
   The singular value decompostion always exists, so the constructor will
14
   never fail.  The matrix condition number and the effective numerical
15
   rank can be computed from this decomposition.
16
17
   <p>
18
        (Adapted from JAMA, a Java Matrix Library, developed by jointly 
19
        by the Mathworks and NIST; see  http://math.nist.gov/javanumerics/jama).
20
   */
21
22
23
#ifdef JAMA_DYNAMIC
24
        int m, n;
25
        int nu,minm;
26
#else
27
                #define nu   MIN(m,n)
28
                #define minm MIN(m+1,n)
29
#endif
30
        JamaArray2(Real,m,nu) U;
31
        JamaArray2(Real,n,n)  V;
32
        JamaArray1(Real,minm) s;
33
34
35
PUBLIC
36
37
38
   member(SVD) (const JamaArray2(Real,m,n) &Arg) {
39
                 SVD0(Arg,1,1);
40
         }
41
   member(SVD) (const JamaArray2(Real,m,n) &Arg,int wantu,int wantv) {
42
                 SVD0(Arg,wantu,wantv);
43
         }
44
45
   void member(SVD0) (const JamaArray2(Real,m,n) &Arg,int wantu,int wantv) {
46
47
        //allocation
48
#ifdef JAMA_DYNAMIC
49
                m = Arg.NROWS();
50
                n = Arg.NCOLS();
51
                nu = MIN(m,n);//length of diagonal
52
                minm=MIN(m+1,n);//width of bidiagonal matrix.
53
54
      //s = JamaArray1(Real,minm)(minm); 
55
      //U = JamaArray2(Real,m,nu)(m, nu);//,   (0)
56
      //V = JamaArray2(Real,n,n)(n,n);
57
                RESIZE1(Real, s, minm);
58
                RESIZE2(Real, U, m ,nu);
59
                RESIZE2(Real, V, n, n);
60
                JamaArray1(Real,n) e(n); //PZ: e serves as storage for upper diagonal elements and also temporarily storage of last portion of rows. 
61
                                             //PZ: thus, minm-1 elements would be not enough. 
62
                                               //e[0]=D[0][1]
63
                JamaArray1(Real,m) work(m); 
64
                JamaArray2(Real,m,n) A(COPY(Arg));
65
        //end of allocation
66
                for (int i_=0;i_<m;i_++) {
67
                        for (int j_=0;j_<nu;j_++) {
68
                                $ U[i_][j_] = 0;
69
                        }
70
                }
71
#else
72
73
        //allocation
74
                memset(&U,0,sizeof(U));
75
76
      JamaArray1(Real,n) e;
77
      JamaArray1(Real,m) work;
78
79
                JamaArray2(Real,m,n) A;//(Arg.copy());
80
                memcpy(&A,&Arg,sizeof(A));
81
        //end of allocation
82
        
83
#endif
84
85
        if(m<n){
86
                throw("not safe operation!!!");
87
        }
88
89
//      int wantu = 1;                                          /* boolean */
90
//      int wantv = 1;                                          /* boolean */
91
          int i=0, j=0, k=0;
92
93
      // Reduce A to bidiagonal form, storing the diagonal elements
94
      // in s and the super-diagonal elements in e.
95
96
                  /* PZ:
97
98
                                        final result:
99
                                        
100
                                        Arg= M(U(:,m-1))*M(U(:,m-2)*...M(U(:,0))*D*( M(V(:,m-1))*M(V(:,m-2)*...M(V(:,0)) )^T
101
102
                                        where mirroring hauseholder transformation
103
                                            M(v)=I-2*v*v^T/||v||^2, but mirror plane vectors are constructed that
104
                                                                  U(k,k)=2*||U(:,k)||^2, thus M_k=I-U(:,k)*U(:,k)^T/U(k,k)
105
106
            and for all k, B[k][k]=s[k], B[k][k+1]=e[k], and B is 0 at all other locations. 
107
108
          Arrays U and V are not matrices, rather collection of vectors.
109
           
110
                                         during the operation, the first columns of U and V are filled, 
111
                                         while the bottom left portion of A remains inportant as other 
112
                                           parts would be zero-ed out. This is not administrated in matrix A. 
113
             
114
           For the kth iteration, the column transformation leaves the first k-1 rows the same, 
115
                                         and the kth row transformation leaves the first k column the same. 
116
117
                                         s[k] and e[k] is also filled successively, but unfilled portion of e[k]
118
                                         is used as temporary variable. 
119
120
                                */
121
122
      int nct = MIN(m-1,n);//PZ number of column transformations
123
      int nrt = MAX(0,MIN(n-2,m));//PZ: number of row transformations
124
      for (k = 0; k < MAX(nct,nrt); k++) {//PZ: for each element in the diagonal
125
         if (k < nct) {
126
127
            // Compute the transformation for the k-th column and
128
            // place the k-th diagonal in s[k].
129
            // Compute 2-norm of k-th column without under/overflow.
130
131
                                         //PZ: s[k]=|A[k:end][k]|*sign(A[k,k])
132
                                         //PZ  if(s[k]!=0) {A[k:end,k]/=s[k]; A[k][k]+=1}
133
                                         //PZ  s[k]*=-1;
134
135
                                         //PZ azaz if(norm(A_:k)>0) {A_:k=A_:k/norm(A_:k)+I_:k}
136
                                         //         else 
137
            $ s[k] = 0;
138
            for (i = k; i < m; i++) {
139
               $ s[k] = hypot_($ s[k],$ A[i][k]);
140
            }
141
            if ($ s[k] != 0.0) {
142
               if ($ A[k][k] < 0.0) {//PZ: two possible mirror vectors arose. one result -I_:k, other +I_:k after mirroring A_:k
143
                  $ s[k] = -$ s[k]; //PZ: this chooses the longer one, to avoid numeric instability if A_:k is very near to I_:k
144
               }
145
               for (i = k; i < m; i++) {
146
                  $ A[i][k] /= $ s[k];
147
               }
148
               $ A[k][k] += 1.0;//PZ: A_:k contains the vector perpendicular to the desired mirroring
149
            }
150
            $ s[k] = -$ s[k];//PZ: Mirror(A_:k) original=s_k*I_:k. The sign depends on the choosen vector
151
         }
152
          
153
         for (j = k+1; j < n; j++) {
154
            if ((k < nct) && ($ s[k] != 0.0))  {
155
156
            // Apply the transformation. //PZ: mirroring to the plane perp. to A_:k
157
158
               Real t(0.0);
159
               for (i = k; i < m; i++) {
160
                  t += $ A[i][k]*$ A[i][j];
161
               }//PZ: t=A[K:end][k]^_T_*A[k:end][j]
162
               t = -t/$ A[k][k];
163
                                                         //PZ: t=-A[K:end][k]^_T_*A[k:end][j]/A[k][k]
164
               for (i = k; i < m; i++) {
165
                  $ A[i][j] += t*$ A[i][k];
166
               }
167
                                                         //PZ: A[k:end][j]-=A[k:end][k]*(A[K:end][k]^_T_*A[k:end][j])/A[k][k]
168
                                                         //PZ: A[k:end][j]=A[k:end][j]-A[k:end][k]*(A[K:end][k]^_T_*A[k:end][j])/A[k][k]
169
                                                         //PZ: A_:j=(I -A_:k*A_:k^T/A_kk)*A_:j
170
                                                         //PZ: since A_kk = 2*||A_:k||^2, thus the transformation is I-2*A_:k*A_:k^T/||A_:k||^2 and is orthogonal. 
171
            }
172
173
            // Place the k-th row of A into e for the
174
            // subsequent calculation of the row transformation.
175
176
            $ e[j] = $ A[k][j];
177
         }
178
         if (wantu & (k < nct)) {
179
180
            // Place the transformation in U for subsequent back
181
            // multiplication.
182
183
            for (i = k; i < m; i++) {
184
               $ U[i][k] = $ A[i][k];//PZ: the non-unit length normal vector of the mirroring plane, U_kk is twice the length squared
185
            }
186
         }
187
         if (k < nrt) {
188
189
            // Compute the k-th row transformation and place the
190
            // k-th super-diagonal in e[k].
191
            // Compute 2-norm without under/overflow.
192
            $ e[k] = 0;
193
            for (i = k+1; i < n; i++) {
194
               $ e[k] = hypot_($ e[k],$ e[i]);
195
            }
196
            if ($ e[k] != 0.0) {
197
               if ($ e[k+1] < 0.0) {//PZ: Same formulation as for row transformations
198
                  $ e[k] = -$ e[k];
199
               }
200
               for (i = k+1; i < n; i++) {
201
                  $ e[i] /= $ e[k];
202
               }
203
               $ e[k+1] += 1.0;
204
            }
205
            $ e[k] = -$ e[k];
206
            if ((k+1 < m) & ($ e[k] != 0.0)) {
207
208
            // Apply the transformation.
209
210
               for (i = k+1; i < m; i++) {
211
                  $ work[i] = 0.0;
212
               }
213
               for (j = k+1; j < n; j++) {
214
                  for (i = k+1; i < m; i++) {
215
                     $ work[i] += $ e[j]*$ A[i][j];
216
                  }
217
               }
218
               for (j = k+1; j < n; j++) {
219
                  Real t(-$ e[j]/$ e[k+1]);
220
                  for (i = k+1; i < m; i++) {
221
                     $ A[i][j] += t*$ work[i];
222
                  }
223
               }
224
            }
225
            if (wantv) {
226
227
            // Place the transformation in V for subsequent
228
            // back multiplication.
229
230
               for (i = k+1; i < n; i++) {
231
                  $ V[i][k] = $ e[i];//PZ the non-uniform mirroring vector
232
               }
233
            }
234
         }
235
      }
236
237
      // Set up the final bidiagonal matrix or order p.
238
239
      int p = MIN(n,m+1);
240
      if (nct < n) {
241
         $ s[nct] = $ A[nct][nct];
242
      }
243
      if (m < p) {//PZ: if(n>m && p==m+1)
244
         $ s[p-1] = 0.0; //PZ: s[m]=0.0
245
      }
246
      if (nrt+1 < p) {
247
         $ e[nrt] = $ A[nrt][p-1];
248
      }
249
      $ e[p-1] = 0.0;
250
251
      // If required, generate U.
252
253
      if (wantu) {
254
                                //PZ: transform the collection of mirror-plane normal vectors into a single orthogonal transformation
255
         for (j = nct; j < nu; j++) {
256
            for (i = 0; i < m; i++) {
257
               $ U[i][j] = 0.0;
258
            }
259
            $ U[j][j] = 1.0;
260
         }
261
         for (k = nct-1; k >= 0; k--) {
262
            if ($ s[k] != 0.0) {
263
               for (j = k+1; j < nu; j++) {
264
                  Real t(0.0);
265
                  for (i = k; i < m; i++) {
266
                     t += $ U[i][k]*$ U[i][j];
267
                  }
268
                  t = -t/$ U[k][k];
269
                  for (i = k; i < m; i++) {
270
                     $ U[i][j] += t*$ U[i][k];
271
                  }
272
               }
273
                                                         
274
               for (i = k; i < m; i++ ) {
275
                  $ U[i][k] = -$ U[i][k];
276
               }
277
               $ U[k][k] = (Real) (1.0 + $ U[k][k] );
278
               for (i = 0; i < k-1; i++) {
279
                  $ U[i][k] = 0.0;
280
               }
281
            } else {
282
                                                        //PZ:  U_:k=I_:k
283
               for (i = 0; i < m; i++) {
284
                  $ U[i][k] = 0.0;
285
               }
286
               $ U[k][k] = 1.0;
287
            }
288
         }
289
      }
290
291
      // If required, generate V.
292
293
      if (wantv) {
294
                                //PZ: transform the collection of mirror-plane normal vectors into a single orthogonal transformation
295
296
         for (k = n-1; k >= 0; k--) {//PZ step back on each column
297
            if ((k < nrt) && ($ e[k] != 0.0)) {
298
               for (j = k+1; j < nu; j++) {//for all column to the right
299
                  Real t(0.0);
300
                  for (i = k+1; i < n; i++) {
301
                     t += $ V[i][k]*$ V[i][j];
302
                  }
303
                                                                        //substract the kth column from all righter...
304
                  t = t/$ V[k+1][k];
305
                  for (i = k+1; i < n; i++) {
306
                     $ V[i][j] -= t*$ V[i][k];
307
                  }
308
               }
309
            }
310
                                                //PZ write the kth. unit vector
311
            for (i = 0; i < n; i++) {
312
               $ V[i][k] = 0.0;
313
            }
314
            $ V[k][k] = 1.0;
315
         }
316
      }
317
318
      // Main iteration loop for the singular values.
319
320
    //PZ: at this point, if wantu=1 and wantv=1, then   Arg=U*D*V^T. 
321
                        //PZ: for all aplicable k, D[k][k]=s[k], D[k][k+1]=e[k]
322
                        
323
324
      int pp = p-1;
325
      int iter = 0;
326
      Real eps = EPSILON(Real);
327
      while (p > 0) {
328
         int k=0;
329
                 int kase=0;
330
331
         // Here is where a test for too many iterations would go.
332
333
         // This section of the program inspects for
334
         // negligible elements in the s and e arrays.  On
335
         // completion the variables kase and k are set as follows.
336
337
                     //                                                                action:
338
         // kase = 1     if s(p) and e[k-1] are negligible and k<p         Deflate negligible s(p).
339
         // kase = 2     if s(k) is negligible and k<p                     Split at negligible s(k).
340
         // kase = 3     if e[k-1] is negligible, k<p, and
341
         //              s(k), ..., s(p) are not negligible (qr step).     QR
342
         // kase = 4     if e(p-1) is negligible (convergence).            store singular value
343
344
         for (k = p-2; k >= -1; k--) {
345
            if (k == -1) {
346
               break;
347
            }
348
            if (ABS($ e[k]) <= eps*(ABS($ s[k]) + ABS($ s[k+1]))) {
349
               $ e[k] = 0.0;
350
               break;
351
            }
352
         }
353
         if (k == p-2) {
354
            kase = 4;
355
         } else {
356
            int ks;
357
            for (ks = p-1; ks >= k; ks--) {
358
               if (ks == k) {
359
                  break;
360
               }
361
               Real t=(Real)( (ks != p ? ABS($ e[ks]) : 0.) + 
362
                          (ks != k+1 ? ABS($ e[ks-1]) : 0.));
363
               if (ABS($ s[ks]) <= eps*t)  {
364
                  $ s[ks] = 0.0;
365
                  break;
366
               }
367
            }
368
            if (ks == k) {
369
               kase = 3;
370
            } else if (ks == p-1) {
371
               kase = 1;
372
            } else {
373
               kase = 2;
374
               k = ks;
375
            }
376
         }
377
         k++;
378
379
         // Perform the task indicated by kase.
380
381
         switch (kase) {
382
383
            // Deflate negligible s(p).
384
385
            case 1: {
386
               Real f($ e[p-2]);
387
               $ e[p-2] = 0.0;
388
               for (j = p-2; j >= k; j--) {
389
                  Real t( hypot_($ s[j],f));
390
                  Real cs($ s[j]/t);
391
                  Real sn(f/t);
392
                  $ s[j] = t;
393
                  if (j != k) {
394
                     f = -sn*$ e[j-1];
395
                     $ e[j-1] = cs*$ e[j-1];
396
                  }
397
                  if (wantv) {
398
                     for (i = 0; i < n; i++) {
399
                        t = cs*$ V[i][j] + sn*$ V[i][p-1];
400
                        $ V[i][p-1] = -sn*$ V[i][j] + cs*$ V[i][p-1];
401
                        $ V[i][j] = t;
402
                     }
403
                  }
404
               }
405
            }
406
            break;
407
408
            // Split at negligible s(k).
409
410
            case 2: {
411
               Real f($ e[k-1]);
412
               $ e[k-1] = 0.0;
413
               for (j = k; j < p; j++) {
414
                  Real t(hypot_($ s[j],f));
415
                  Real cs( $ s[j]/t);
416
                  Real sn(f/t);
417
                  $ s[j] = t;
418
                  f = -sn*$ e[j];
419
                  $ e[j] = cs*$ e[j];
420
                  if (wantu) {
421
                     for (i = 0; i < m; i++) {
422
                        t = cs*$ U[i][j] + sn*$ U[i][k-1];
423
                        $ U[i][k-1] = -sn*$ U[i][j] + cs*$ U[i][k-1];
424
                        $ U[i][j] = t;
425
                     }
426
                  }
427
               }
428
            }
429
            break;
430
431
            // Perform one qr step.
432
433
            case 3: {
434
435
               // Calculate the shift.
436
   
437
               Real scale = MAX(MAX(MAX(MAX(
438
                       ABS($ s[p-1]),ABS($ s[p-2])),ABS($ e[p-2])), 
439
                       ABS($ s[k])),ABS($ e[k]));
440
               Real sp = $ s[p-1]/scale;//PZ: calculating 1/scale would not include numeric overflow....?
441
               Real spm1 = $ s[p-2]/scale;
442
               Real epm1 = $ e[p-2]/scale;
443
               Real sk = $ s[k]/scale;
444
               Real ek = $ e[k]/scale;
445
               Real b = (Real)(((spm1 + sp)*(spm1 - sp) + epm1*epm1)/2.0);
446
               Real c = (sp*epm1)*(sp*epm1);
447
               Real shift = 0.0;
448
               if ((b != 0.0) || (c != 0.0)) {
449
                  shift = sqrt(b*b + c);
450
                  if (b < 0.0) {
451
                     shift = -shift;
452
                  }
453
                  shift = c/(b + shift);
454
               }
455
               Real f = (sk + sp)*(sk - sp) + shift;
456
               Real g = sk*ek;
457
   
458
               // Chase zeros.
459
   
460
               for (j = k; j < p-1; j++) {
461
                  Real t = hypot_(f,g);
462
                  Real cs = f/t;
463
                  Real sn = g/t;
464
                  if (j != k) {
465
                     $ e[j-1] = t;
466
                  }
467
                  f = cs*$ s[j] + sn*$ e[j];
468
                  $ e[j] = cs*$ e[j] - sn*$ s[j];
469
                  g = sn*$ s[j+1];
470
                  $ s[j+1] = cs*$ s[j+1];
471
                  if (wantv) {
472
                     for (i = 0; i < n; i++) {
473
                        t = cs*$ V[i][j] + sn*$ V[i][j+1];
474
                        $ V[i][j+1] = -sn*$ V[i][j] + cs*$ V[i][j+1];
475
                        $ V[i][j] = t;
476
                     }
477
                  }
478
                  t = hypot_(f,g);
479
                  cs = f/t;
480
                  sn = g/t;
481
                  $ s[j] = t;
482
                  f = cs*$ e[j] + sn*$ s[j+1];
483
                  $ s[j+1] = -sn*$ e[j] + cs*$ s[j+1];
484
                  g = sn*$ e[j+1];
485
                  $ e[j+1] = cs*$ e[j+1];
486
                  if (wantu && (j < m-1)) {
487
                     for (i = 0; i < m; i++) {
488
                        t = cs*$ U[i][j] + sn*$ U[i][j+1];
489
                        $ U[i][j+1] = -sn*$ U[i][j] + cs*$ U[i][j+1];
490
                        $ U[i][j] = t;
491
                     }
492
                  }
493
               }
494
               $ e[p-2] = f;
495
               iter = iter + 1;
496
            }
497
            break;
498
499
            // Convergence.
500
501
            case 4: {
502
503
               // Make the singular values positive.
504
   
505
               if ($ s[k] <= 0.0) {
506
                  $ s[k] = (Real)($ s[k] < 0.0 ? -$ s[k] : 0.0);
507
                  if (wantv) {
508
                     for (i = 0; i <= pp; i++) {
509
                        $ V[i][k] = -$ V[i][k];
510
                     }
511
                  }
512
               }
513
   
514
               // Order the singular values by bubble sort
515
   
516
               while (k < pp) {
517
                  if ($ s[k] >= $ s[k+1]) {
518
                     break;//nothing to do
519
                  }
520
                                                                        //PZ exchange s[k <> k+1], U[:,k<>k+1], V[:,k<>k+1], 
521
                  Real t = $ s[k];
522
                  $ s[k] = $ s[k+1];
523
                  $ s[k+1] = t;
524
                  if (wantv && (k < n-1)) {
525
                     for (i = 0; i < n; i++) {
526
                        t = $ V[i][k+1]; $ V[i][k+1] = $ V[i][k]; $ V[i][k] = t;
527
                     }
528
                  }
529
                  if (wantu && (k < m-1)) {
530
                     for (i = 0; i < m; i++) {
531
                        t = $ U[i][k+1]; $ U[i][k+1] = $ U[i][k]; $ U[i][k] = t;
532
                     }
533
                  }
534
                  k++;
535
               }
536
               iter = 0;
537
               p--;
538
            }
539
            break;
540
         }
541
      }
542
   }
543
544
545
//   void member(getU) (JamaArray2(Real,m,minm) &A) 
546
   void member(getU) (JamaArray2(Real,m,nu) &A) //PZ
547
   {
548
//             int minm = MIN(m+1,n);
549
//                RESIZE2(Real,A,m,minm);
550
                RESIZE2(Real,A,m,nu);//PZ
551
//#ifdef __cplusplus
552
//          A = JamaArray2(Real,m,minm)(m, minm);
553
//#endif
554
          for (int i=0; i<m; i++)
555
                  for (int j=0; j<nu; j++)
556
                        $ A[i][j] = $ U[i][j];
557
           
558
   }
559
560
         //PZ: getLastColumnOfU
561
   void getLastColumnOfU(JamaArray1(Real,m) &u) {
562
           RESIZE1(Real,u,m);
563
564
                 if(m==n||($ s[nu-1])==0.0){
565
                   for(int i=0;i<m;i++) {
566
                                        $ u[i]= $ U[i][nu-1];
567
                         }                        
568
                 }else{
569
                         //m>n
570
                         //need to calculate one null vector of U
571
                         //return one normalized column of 1-U*U^T
572
                                JamaArray2(Real,m,m) A;
573
                                A=-U*(U^_T_);
574
                                for(int i=0;i<m;i++){
575
                                        $ A[i][i]+=1.0;
576
                                }
577
                                int M=m;
578
                                int N=n;
579
                                int NU=nu;
580
581
                                                //largest element in V_1
582
                                                Real max_=0.0;
583
                                                int maxi=-1;
584
                                                int maxj=-1;
585
                                                for(int i=0;i<M;i++){
586
                                                        for(int j=0;j<M;j++){
587
                                                                Real s=$ A[i][j];s*=s;
588
                                                                if(s>max_){
589
                                                                        max_=s;maxi=i;maxj=j;
590
                                                                }
591
                                                        }
592
                                                }
593
                                                //normalize its row
594
                                                Real l=0.0;
595
                                                        for(int j=0;j<M;j++){
596
                                                                Real &s=$ A[maxi][j];
597
                                                                l+=s*s;//hypot would be safe for extra large numbers near overflow limit...
598
                                                        }
599
                                                        l=1.0/sqrt(l);
600
                                                //put in V
601
                                                        for(int j=0;j<M;j++){
602
                                                                $ u[j]=l* $ A[maxi][j];
603
                                                        }
604
605
                                
606
                 }
607
   }
608
609
610
   /* Return the right singular vectors */
611
612
   void member(getV) (JamaArray2(Real,n,n) &A) 
613
   {
614
           RESIZE2(Real,A,n,n);
615
             A = V;
616
   }
617
618
   void getLastColumnOfV(JamaArray1(Real,n) &v) {
619
           RESIZE1(Real,v,n);
620
           for(int i=0;i<n;i++) {
621
                $ v[i]= $ V[i][n-1];
622
           }                        
623
   }
624
625
   /** Return the one-dimensional array of singular values */
626
627
//   void member(getSingularValues) (JamaArray1(Real,minm) &x) 
628
   void member(getSingularValues) (JamaArray1(Real,nu) &x) //PZ
629
   {
630
                 RESIZE1(Real,x,nu);//PZ
631
632
//                  for (int j=0; j<minm; j++)
633
                  for (int j=0; j<nu; j++)//PZ
634
                           $ x[j] = $ s[j];
635
   }
636
637
   /** Return the diagonal matrix of singular values
638
   @return     S
639
   */
640
641
//   void member(getS) (JamaArray2(Real,n,n) &A) {
642
   void member(getS) (JamaArray2(Real,nu,n) &A) {//PZ
643
//                RESIZE2(Real,A,n,n);
644
                RESIZE2(Real,A,nu,n);//PZ
645
//#ifdef __cplusplus
646
//             A = JamaArray2(Real,n,n)(n,n);
647
//#endif
648
      for (int i = 0; i < nu; i++) {
649
         for (int j = 0; j < n; j++) {
650
            $ A[i][j] = 0.0;
651
         }
652
         $ A[i][i] = $ s[i];
653
      }
654
   }
655
656
   /** Two norm  (max(S)) */
657
658
   Real member(norm2) () {
659
      return $ s[0];
660
   }
661
662
   /** Two norm of condition number (max(S)/min(S)) */
663
664
   Real member(cond) () {
665
      return $ s[0]/$ s[MIN(m,n)-1];
666
   }
667
668
   /** Effective numerical matrix rank
669
   @return     Number of nonnegligible singular values.
670
   */
671
672
   int member(rank) () 
673
   {
674
      //Real eps = pow(2.0,-52.0); // Ez nagyon fugg a hasznalt tipustol!!! kell az epsilon konverzio
675
      Real eps = EPSILON(Real);
676
      Real tol = MAX(m,n)*$ s[0]*eps;
677
      int r = 0;
678
      for (int i = 0; i < s.DIM(); i++) {
679
         if ($ s[i] > tol) {
680
            r++;
681
         }
682
      }
683
      return r;
684
   }
685