1 /* svdecomp - SVD decomposition routines. */
2 /* Taken from Numerical Recipies. */
3 /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
4 /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
5 /* You may give out copies of this software; for conditions see the */
6 /* file COPYING included with this distribution. */
10 static double PYTHAG(a
, b
)
13 double at
= fabs(a
), bt
= fabs(b
), ct
, result
;
15 if (at
> bt
) { ct
= bt
/ at
; result
= at
* sqrt(1.0 + ct
* ct
); }
16 else if (bt
> 0.0) { ct
= at
/ bt
; result
= bt
* sqrt(1.0 + ct
* ct
); }
21 #define SWAPD(a, b) (temp = (a), (a) = (b), (b) = temp)
23 static sort_sv(m
, n
, k
, a
, w
, v
)
31 for (i
= k
; (i
< n
- 1) && (w
[i
] < w
[i
+1]); i
++) {
33 for (j
= 0; j
< m
; j
++) SWAPD(a
[j
][i
], a
[j
][i
+1]);
34 for (j
= 0; j
< n
; j
++) SWAPD(v
[j
][i
], v
[j
][i
+1]);
38 static double maxarg1
, maxarg2
;
39 #define Max(a, b) (maxarg1 = (a), maxarg2 = (b), (maxarg1) > (maxarg2) ? (maxarg1) : (maxarg2))
40 #define SIGN(a, b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
47 int flag
, i
, its
, j
, jj
, k
, l
, nm
;
48 double c
, f
, h
, s
, x
, y
, z
;
49 double anorm
= 0.0, g
= 0.0, scale
= 0.0;
52 if (m
< n
) return(FALSE
); /* flag an error if m < n */
56 /* Householder reduction to bidiagonal form */
57 for (i
= 0; i
< n
; i
++) {
59 /* left-hand reduction */
64 for (k
= i
; k
< m
; k
++) scale
+= fabs(a
[k
][i
]);
66 for (k
= i
; k
< m
; k
++) {
68 s
+= a
[k
][i
] * a
[k
][i
];
71 g
= -SIGN(sqrt(s
), f
);
75 for (j
= l
; j
< n
; j
++) {
76 for (s
= 0.0, k
= i
; k
< m
; k
++) s
+= a
[k
][i
] * a
[k
][j
];
78 for (k
= i
; k
< m
; k
++) a
[k
][j
] += f
* a
[k
][i
];
81 for (k
= i
; k
< m
; k
++) a
[k
][i
] *= scale
;
86 /* right-hand reduction */
88 if (i
< m
&& i
!= n
- 1) {
89 for (k
= l
; k
< n
; k
++) scale
+= fabs(a
[i
][k
]);
91 for (k
= l
; k
< n
; k
++) {
93 s
+= a
[i
][k
] * a
[i
][k
];
96 g
= -SIGN(sqrt(s
), f
);
99 for (k
= l
; k
< n
; k
++) rv1
[k
] = a
[i
][k
] / h
;
101 for (j
= l
; j
< m
; j
++) {
102 for (s
= 0.0, k
= l
; k
< n
; k
++) s
+= a
[j
][k
] * a
[i
][k
];
103 for (k
= l
; k
< n
; k
++) a
[j
][k
] += s
* rv1
[k
];
106 for (k
= l
; k
< n
; k
++) a
[i
][k
] *= scale
;
109 anorm
= Max(anorm
, (fabs(w
[i
]) + fabs(rv1
[i
])));
112 /* accumulate the right-hand transformation */
113 for (i
= n
- 1; i
>= 0; i
--) {
116 for (j
= l
; j
< n
; j
++)
117 v
[j
][i
] = (a
[i
][j
] / a
[i
][l
]) / g
;
118 for (j
= l
; j
< n
; j
++) {
119 for (s
= 0.0, k
= l
; k
< n
; k
++) s
+= a
[i
][k
] * v
[k
][j
];
120 for (k
= l
; k
< n
; k
++) v
[k
][j
] += s
* v
[k
][i
];
123 for (j
= l
; j
< n
; j
++) v
[i
][j
] = v
[j
][i
] = 0.0;
130 /* accumulate the left-hand transformation */
131 for (i
= n
- 1; i
>= 0; i
--) {
135 for (j
= l
; j
< n
; j
++) a
[i
][j
] = 0.0;
139 for (j
= l
; j
< n
; j
++) {
140 for (s
= 0.0, k
= l
; k
< m
; k
++) s
+= a
[k
][i
] * a
[k
][j
];
141 f
= (s
/ a
[i
][i
]) * g
;
142 for (k
= i
; k
< m
; k
++) a
[k
][j
] += f
* a
[k
][i
];
145 for (j
= i
; j
< m
; j
++) a
[j
][i
] *= g
;
148 for (j
= i
; j
< m
; j
++) a
[j
][i
] = 0.0;
153 /* diagonalize the bidiagonal form */
154 for (k
= n
- 1; k
>= 0; k
--) { /* loop over singular values */
155 for (its
= 0; its
< 30; its
++) { /* loop over allowed iterations */
157 for (l
= k
; l
>= 0; l
--) { /* test for splitting */
159 if (fabs(rv1
[l
]) + anorm
== anorm
) {
163 if (fabs(w
[nm
]) + anorm
== anorm
) break;
168 for (i
= l
; i
<= k
; i
++) {
170 if (fabs(f
) + anorm
!= anorm
) {
176 sprintf(s
, "h = %f, f = %f, g = %f\n", f
, g
);
182 for (j
= 0; j
< m
; j
++) {
185 a
[j
][nm
] = y
* c
+ z
* s
;
186 a
[j
][i
] = z
* c
- y
* s
;
192 if (l
== k
) { /* convergence */
193 if (z
< 0.0) { /* make singular value nonnegative */
195 for (j
= 0; j
< n
; j
++) v
[j
][k
] = (-v
[j
][k
]);
197 sort_sv(m
, n
, k
, a
, w
, v
);
202 return(FALSE
); /* return an error flag */
205 /* shift from bottom 2 x 2 minor */
211 f
= ((y
- z
) * (y
+ z
) + (g
- h
) * (g
+ h
)) / (2.0 * h
* y
);
213 f
= ((x
- z
) * (x
+ z
) + h
* ((y
/ (f
+ SIGN(g
, f
))) - h
)) / x
;
215 /* next QR transformation */
217 for (j
= l
; j
<= nm
; j
++) {
231 for (jj
= 0; jj
< n
; jj
++) {
234 v
[jj
][j
] = x
* c
+ z
* s
;
235 v
[jj
][i
] = z
* c
- x
* s
;
244 f
= (c
* g
) + (s
* y
);
245 x
= (c
* y
) - (s
* g
);
246 for (jj
= 0; jj
< m
; jj
++) {
249 a
[jj
][j
] = y
* c
+ z
* s
;
250 a
[jj
][i
] = z
* c
- y
* s
;