Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / lapack / slaed9.c
1 #include "clapack.h"
2
3 /* Table of constant values */
4
5 static integer c__1 = 1;
6
7 /* Subroutine */ int slaed9_(integer *k, integer *kstart, integer *kstop, 
8         integer *n, real *d__, real *q, integer *ldq, real *rho, real *dlamda, 
9          real *w, real *s, integer *lds, integer *info)
10 {
11     /* System generated locals */
12     integer q_dim1, q_offset, s_dim1, s_offset, i__1, i__2;
13     real r__1;
14
15     /* Builtin functions */
16     double sqrt(doublereal), r_sign(real *, real *);
17
18     /* Local variables */
19     integer i__, j;
20     real temp;
21     extern doublereal snrm2_(integer *, real *, integer *);
22     extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *, 
23             integer *), slaed4_(integer *, integer *, real *, real *, real *, 
24             real *, real *, integer *);
25     extern doublereal slamc3_(real *, real *);
26     extern /* Subroutine */ int xerbla_(char *, integer *);
27
28
29 /*  -- LAPACK routine (version 3.1) -- */
30 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
31 /*     November 2006 */
32
33 /*     .. Scalar Arguments .. */
34 /*     .. */
35 /*     .. Array Arguments .. */
36 /*     .. */
37
38 /*  Purpose */
39 /*  ======= */
40
41 /*  SLAED9 finds the roots of the secular equation, as defined by the */
42 /*  values in D, Z, and RHO, between KSTART and KSTOP.  It makes the */
43 /*  appropriate calls to SLAED4 and then stores the new matrix of */
44 /*  eigenvectors for use in calculating the next level of Z vectors. */
45
46 /*  Arguments */
47 /*  ========= */
48
49 /*  K       (input) INTEGER */
50 /*          The number of terms in the rational function to be solved by */
51 /*          SLAED4.  K >= 0. */
52
53 /*  KSTART  (input) INTEGER */
54 /*  KSTOP   (input) INTEGER */
55 /*          The updated eigenvalues Lambda(I), KSTART <= I <= KSTOP */
56 /*          are to be computed.  1 <= KSTART <= KSTOP <= K. */
57
58 /*  N       (input) INTEGER */
59 /*          The number of rows and columns in the Q matrix. */
60 /*          N >= K (delation may result in N > K). */
61
62 /*  D       (output) REAL array, dimension (N) */
63 /*          D(I) contains the updated eigenvalues */
64 /*          for KSTART <= I <= KSTOP. */
65
66 /*  Q       (workspace) REAL array, dimension (LDQ,N) */
67
68 /*  LDQ     (input) INTEGER */
69 /*          The leading dimension of the array Q.  LDQ >= max( 1, N ). */
70
71 /*  RHO     (input) REAL */
72 /*          The value of the parameter in the rank one update equation. */
73 /*          RHO >= 0 required. */
74
75 /*  DLAMDA  (input) REAL array, dimension (K) */
76 /*          The first K elements of this array contain the old roots */
77 /*          of the deflated updating problem.  These are the poles */
78 /*          of the secular equation. */
79
80 /*  W       (input) REAL array, dimension (K) */
81 /*          The first K elements of this array contain the components */
82 /*          of the deflation-adjusted updating vector. */
83
84 /*  S       (output) REAL array, dimension (LDS, K) */
85 /*          Will contain the eigenvectors of the repaired matrix which */
86 /*          will be stored for subsequent Z vector calculation and */
87 /*          multiplied by the previously accumulated eigenvectors */
88 /*          to update the system. */
89
90 /*  LDS     (input) INTEGER */
91 /*          The leading dimension of S.  LDS >= max( 1, K ). */
92
93 /*  INFO    (output) INTEGER */
94 /*          = 0:  successful exit. */
95 /*          < 0:  if INFO = -i, the i-th argument had an illegal value. */
96 /*          > 0:  if INFO = 1, an eigenvalue did not converge */
97
98 /*  Further Details */
99 /*  =============== */
100
101 /*  Based on contributions by */
102 /*     Jeff Rutter, Computer Science Division, University of California */
103 /*     at Berkeley, USA */
104
105 /*  ===================================================================== */
106
107 /*     .. Local Scalars .. */
108 /*     .. */
109 /*     .. External Functions .. */
110 /*     .. */
111 /*     .. External Subroutines .. */
112 /*     .. */
113 /*     .. Intrinsic Functions .. */
114 /*     .. */
115 /*     .. Executable Statements .. */
116
117 /*     Test the input parameters. */
118
119     /* Parameter adjustments */
120     --d__;
121     q_dim1 = *ldq;
122     q_offset = 1 + q_dim1;
123     q -= q_offset;
124     --dlamda;
125     --w;
126     s_dim1 = *lds;
127     s_offset = 1 + s_dim1;
128     s -= s_offset;
129
130     /* Function Body */
131     *info = 0;
132
133     if (*k < 0) {
134         *info = -1;
135     } else if (*kstart < 1 || *kstart > max(1,*k)) {
136         *info = -2;
137     } else if (max(1,*kstop) < *kstart || *kstop > max(1,*k)) {
138         *info = -3;
139     } else if (*n < *k) {
140         *info = -4;
141     } else if (*ldq < max(1,*k)) {
142         *info = -7;
143     } else if (*lds < max(1,*k)) {
144         *info = -12;
145     }
146     if (*info != 0) {
147         i__1 = -(*info);
148         xerbla_("SLAED9", &i__1);
149         return 0;
150     }
151
152 /*     Quick return if possible */
153
154     if (*k == 0) {
155         return 0;
156     }
157
158 /*     Modify values DLAMDA(i) to make sure all DLAMDA(i)-DLAMDA(j) can */
159 /*     be computed with high relative accuracy (barring over/underflow). */
160 /*     This is a problem on machines without a guard digit in */
161 /*     add/subtract (Cray XMP, Cray YMP, Cray C 90 and Cray 2). */
162 /*     The following code replaces DLAMDA(I) by 2*DLAMDA(I)-DLAMDA(I), */
163 /*     which on any of these machines zeros out the bottommost */
164 /*     bit of DLAMDA(I) if it is 1; this makes the subsequent */
165 /*     subtractions DLAMDA(I)-DLAMDA(J) unproblematic when cancellation */
166 /*     occurs. On binary machines with a guard digit (almost all */
167 /*     machines) it does not change DLAMDA(I) at all. On hexadecimal */
168 /*     and decimal machines with a guard digit, it slightly */
169 /*     changes the bottommost bits of DLAMDA(I). It does not account */
170 /*     for hexadecimal or decimal machines without guard digits */
171 /*     (we know of none). We use a subroutine call to compute */
172 /*     2*DLAMBDA(I) to prevent optimizing compilers from eliminating */
173 /*     this code. */
174
175     i__1 = *n;
176     for (i__ = 1; i__ <= i__1; ++i__) {
177         dlamda[i__] = slamc3_(&dlamda[i__], &dlamda[i__]) - dlamda[i__];
178 /* L10: */
179     }
180
181     i__1 = *kstop;
182     for (j = *kstart; j <= i__1; ++j) {
183         slaed4_(k, &j, &dlamda[1], &w[1], &q[j * q_dim1 + 1], rho, &d__[j], 
184                 info);
185
186 /*        If the zero finder fails, the computation is terminated. */
187
188         if (*info != 0) {
189             goto L120;
190         }
191 /* L20: */
192     }
193
194     if (*k == 1 || *k == 2) {
195         i__1 = *k;
196         for (i__ = 1; i__ <= i__1; ++i__) {
197             i__2 = *k;
198             for (j = 1; j <= i__2; ++j) {
199                 s[j + i__ * s_dim1] = q[j + i__ * q_dim1];
200 /* L30: */
201             }
202 /* L40: */
203         }
204         goto L120;
205     }
206
207 /*     Compute updated W. */
208
209     scopy_(k, &w[1], &c__1, &s[s_offset], &c__1);
210
211 /*     Initialize W(I) = Q(I,I) */
212
213     i__1 = *ldq + 1;
214     scopy_(k, &q[q_offset], &i__1, &w[1], &c__1);
215     i__1 = *k;
216     for (j = 1; j <= i__1; ++j) {
217         i__2 = j - 1;
218         for (i__ = 1; i__ <= i__2; ++i__) {
219             w[i__] *= q[i__ + j * q_dim1] / (dlamda[i__] - dlamda[j]);
220 /* L50: */
221         }
222         i__2 = *k;
223         for (i__ = j + 1; i__ <= i__2; ++i__) {
224             w[i__] *= q[i__ + j * q_dim1] / (dlamda[i__] - dlamda[j]);
225 /* L60: */
226         }
227 /* L70: */
228     }
229     i__1 = *k;
230     for (i__ = 1; i__ <= i__1; ++i__) {
231         r__1 = sqrt(-w[i__]);
232         w[i__] = r_sign(&r__1, &s[i__ + s_dim1]);
233 /* L80: */
234     }
235
236 /*     Compute eigenvectors of the modified rank-1 modification. */
237
238     i__1 = *k;
239     for (j = 1; j <= i__1; ++j) {
240         i__2 = *k;
241         for (i__ = 1; i__ <= i__2; ++i__) {
242             q[i__ + j * q_dim1] = w[i__] / q[i__ + j * q_dim1];
243 /* L90: */
244         }
245         temp = snrm2_(k, &q[j * q_dim1 + 1], &c__1);
246         i__2 = *k;
247         for (i__ = 1; i__ <= i__2; ++i__) {
248             s[i__ + j * s_dim1] = q[i__ + j * q_dim1] / temp;
249 /* L100: */
250         }
251 /* L110: */
252     }
253
254 L120:
255     return 0;
256
257 /*     End of SLAED9 */
258
259 } /* slaed9_ */