/src/igraph/vendor/lapack/dnaitr.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -- translated by f2c (version 20191129). |
2 | | You must link the resulting object file with libf2c: |
3 | | on Microsoft Windows system, link with libf2c.lib; |
4 | | on Linux or Unix systems, link with .../path/to/libf2c.a -lm |
5 | | or, if you install libf2c.a in a standard place, with -lf2c -lm |
6 | | -- in that order, at the end of the command line, as in |
7 | | cc *.o -lf2c -lm |
8 | | Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., |
9 | | |
10 | | http://www.netlib.org/f2c/libf2c.zip |
11 | | */ |
12 | | |
13 | | #include "f2c.h" |
14 | | |
15 | | /* Table of constant values */ |
16 | | |
17 | | static integer c__1 = 1; |
18 | | static logical c_false = FALSE_; |
19 | | static doublereal c_b25 = 1.; |
20 | | static doublereal c_b47 = 0.; |
21 | | static doublereal c_b50 = -1.; |
22 | | static integer c__2 = 2; |
23 | | |
24 | | /* ----------------------------------------------------------------------- |
25 | | \BeginDoc |
26 | | |
27 | | \Name: dnaitr |
28 | | |
29 | | \Description: |
30 | | Reverse communication interface for applying NP additional steps to |
31 | | a K step nonsymmetric Arnoldi factorization. |
32 | | |
33 | | Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T |
34 | | |
35 | | with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. |
36 | | |
37 | | Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T |
38 | | |
39 | | with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. |
40 | | |
41 | | where OP and B are as in dnaupd. The B-norm of r_{k+p} is also |
42 | | computed and returned. |
43 | | |
44 | | \Usage: |
45 | | call dnaitr |
46 | | ( IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, |
47 | | IPNTR, WORKD, INFO ) |
48 | | |
49 | | \Arguments |
50 | | IDO Integer. (INPUT/OUTPUT) |
51 | | Reverse communication flag. |
52 | | ------------------------------------------------------------- |
53 | | IDO = 0: first call to the reverse communication interface |
54 | | IDO = -1: compute Y = OP * X where |
55 | | IPNTR(1) is the pointer into WORK for X, |
56 | | IPNTR(2) is the pointer into WORK for Y. |
57 | | This is for the restart phase to force the new |
58 | | starting vector into the range of OP. |
59 | | IDO = 1: compute Y = OP * X where |
60 | | IPNTR(1) is the pointer into WORK for X, |
61 | | IPNTR(2) is the pointer into WORK for Y, |
62 | | IPNTR(3) is the pointer into WORK for B * X. |
63 | | IDO = 2: compute Y = B * X where |
64 | | IPNTR(1) is the pointer into WORK for X, |
65 | | IPNTR(2) is the pointer into WORK for Y. |
66 | | IDO = 99: done |
67 | | ------------------------------------------------------------- |
68 | | When the routine is used in the "shift-and-invert" mode, the |
69 | | vector B * Q is already available and do not need to be |
70 | | recompute in forming OP * Q. |
71 | | |
72 | | BMAT Character*1. (INPUT) |
73 | | BMAT specifies the type of the matrix B that defines the |
74 | | semi-inner product for the operator OP. See dnaupd. |
75 | | B = 'I' -> standard eigenvalue problem A*x = lambda*x |
76 | | B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x |
77 | | |
78 | | N Integer. (INPUT) |
79 | | Dimension of the eigenproblem. |
80 | | |
81 | | K Integer. (INPUT) |
82 | | Current size of V and H. |
83 | | |
84 | | NP Integer. (INPUT) |
85 | | Number of additional Arnoldi steps to take. |
86 | | |
87 | | NB Integer. (INPUT) |
88 | | Blocksize to be used in the recurrence. |
89 | | Only work for NB = 1 right now. The goal is to have a |
90 | | program that implement both the block and non-block method. |
91 | | |
92 | | RESID Double precision array of length N. (INPUT/OUTPUT) |
93 | | On INPUT: RESID contains the residual vector r_{k}. |
94 | | On OUTPUT: RESID contains the residual vector r_{k+p}. |
95 | | |
96 | | RNORM Double precision scalar. (INPUT/OUTPUT) |
97 | | B-norm of the starting residual on input. |
98 | | B-norm of the updated residual r_{k+p} on output. |
99 | | |
100 | | V Double precision N by K+NP array. (INPUT/OUTPUT) |
101 | | On INPUT: V contains the Arnoldi vectors in the first K |
102 | | columns. |
103 | | On OUTPUT: V contains the new NP Arnoldi vectors in the next |
104 | | NP columns. The first K columns are unchanged. |
105 | | |
106 | | LDV Integer. (INPUT) |
107 | | Leading dimension of V exactly as declared in the calling |
108 | | program. |
109 | | |
110 | | H Double precision (K+NP) by (K+NP) array. (INPUT/OUTPUT) |
111 | | H is used to store the generated upper Hessenberg matrix. |
112 | | |
113 | | LDH Integer. (INPUT) |
114 | | Leading dimension of H exactly as declared in the calling |
115 | | program. |
116 | | |
117 | | IPNTR Integer array of length 3. (OUTPUT) |
118 | | Pointer to mark the starting locations in the WORK for |
119 | | vectors used by the Arnoldi iteration. |
120 | | ------------------------------------------------------------- |
121 | | IPNTR(1): pointer to the current operand vector X. |
122 | | IPNTR(2): pointer to the current result vector Y. |
123 | | IPNTR(3): pointer to the vector B * X when used in the |
124 | | shift-and-invert mode. X is the current operand. |
125 | | ------------------------------------------------------------- |
126 | | |
127 | | WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) |
128 | | Distributed array to be used in the basic Arnoldi iteration |
129 | | for reverse communication. The calling program should not |
130 | | use WORKD as temporary workspace during the iteration !!!!!! |
131 | | On input, WORKD(1:N) = B*RESID and is used to save some |
132 | | computation at the first step. |
133 | | |
134 | | INFO Integer. (OUTPUT) |
135 | | = 0: Normal exit. |
136 | | > 0: Size of the spanning invariant subspace of OP found. |
137 | | |
138 | | \EndDoc |
139 | | |
140 | | ----------------------------------------------------------------------- |
141 | | |
142 | | \BeginLib |
143 | | |
144 | | \Local variables: |
145 | | xxxxxx real |
146 | | |
147 | | \References: |
148 | | 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in |
149 | | a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), |
150 | | pp 357-385. |
151 | | 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly |
152 | | Restarted Arnoldi Iteration", Rice University Technical Report |
153 | | TR95-13, Department of Computational and Applied Mathematics. |
154 | | |
155 | | \Routines called: |
156 | | dgetv0 ARPACK routine to generate the initial vector. |
157 | | ivout ARPACK utility routine that prints integers. |
158 | | second ARPACK utility routine for timing. |
159 | | dmout ARPACK utility routine that prints matrices |
160 | | dvout ARPACK utility routine that prints vectors. |
161 | | dlabad LAPACK routine that computes machine constants. |
162 | | dlamch LAPACK routine that determines machine constants. |
163 | | dlascl LAPACK routine for careful scaling of a matrix. |
164 | | dlanhs LAPACK routine that computes various norms of a matrix. |
165 | | dgemv Level 2 BLAS routine for matrix vector multiplication. |
166 | | daxpy Level 1 BLAS that computes a vector triad. |
167 | | dscal Level 1 BLAS that scales a vector. |
168 | | dcopy Level 1 BLAS that copies one vector to another . |
169 | | ddot Level 1 BLAS that computes the scalar product of two vectors. |
170 | | dnrm2 Level 1 BLAS that computes the norm of a vector. |
171 | | |
172 | | \Author |
173 | | Danny Sorensen Phuong Vu |
174 | | Richard Lehoucq CRPC / Rice University |
175 | | Dept. of Computational & Houston, Texas |
176 | | Applied Mathematics |
177 | | Rice University |
178 | | Houston, Texas |
179 | | |
180 | | \Revision history: |
181 | | xx/xx/92: Version ' 2.4' |
182 | | |
183 | | \SCCS Information: @(#) |
184 | | FILE: naitr.F SID: 2.4 DATE OF SID: 8/27/96 RELEASE: 2 |
185 | | |
186 | | \Remarks |
187 | | The algorithm implemented is: |
188 | | |
189 | | restart = .false. |
190 | | Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; |
191 | | r_{k} contains the initial residual vector even for k = 0; |
192 | | Also assume that rnorm = || B*r_{k} || and B*r_{k} are already |
193 | | computed by the calling program. |
194 | | |
195 | | betaj = rnorm ; p_{k+1} = B*r_{k} ; |
196 | | For j = k+1, ..., k+np Do |
197 | | 1) if ( betaj < tol ) stop or restart depending on j. |
198 | | ( At present tol is zero ) |
199 | | if ( restart ) generate a new starting vector. |
200 | | 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; |
201 | | p_{j} = p_{j}/betaj |
202 | | 3) r_{j} = OP*v_{j} where OP is defined as in dnaupd |
203 | | For shift-invert mode p_{j} = B*v_{j} is already available. |
204 | | wnorm = || OP*v_{j} || |
205 | | 4) Compute the j-th step residual vector. |
206 | | w_{j} = V_{j}^T * B * OP * v_{j} |
207 | | r_{j} = OP*v_{j} - V_{j} * w_{j} |
208 | | H(:,j) = w_{j}; |
209 | | H(j,j-1) = rnorm |
210 | | rnorm = || r_(j) || |
211 | | If (rnorm > 0.717*wnorm) accept step and go back to 1) |
212 | | 5) Re-orthogonalization step: |
213 | | s = V_{j}'*B*r_{j} |
214 | | r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || |
215 | | alphaj = alphaj + s_{j}; |
216 | | 6) Iterative refinement step: |
217 | | If (rnorm1 > 0.717*rnorm) then |
218 | | rnorm = rnorm1 |
219 | | accept step and go back to 1) |
220 | | Else |
221 | | rnorm = rnorm1 |
222 | | If this is the first time in step 6), go to 5) |
223 | | Else r_{j} lies in the span of V_{j} numerically. |
224 | | Set r_{j} = 0 and rnorm = 0; go to 1) |
225 | | EndIf |
226 | | End Do |
227 | | |
228 | | \EndLib |
229 | | |
230 | | ----------------------------------------------------------------------- |
231 | | |
232 | | Subroutine */ int igraphdnaitr_(integer *ido, char *bmat, integer *n, integer *k, |
233 | | integer *np, integer *nb, doublereal *resid, doublereal *rnorm, |
234 | | doublereal *v, integer *ldv, doublereal *h__, integer *ldh, integer * |
235 | | ipntr, doublereal *workd, integer *info) |
236 | 0 | { |
237 | | /* Initialized data */ |
238 | |
|
239 | 0 | IGRAPH_F77_SAVE logical first = TRUE_; |
240 | | |
241 | | /* System generated locals */ |
242 | 0 | integer h_dim1, h_offset, v_dim1, v_offset, i__1, i__2; |
243 | 0 | doublereal d__1, d__2; |
244 | | |
245 | | /* Builtin functions */ |
246 | 0 | double sqrt(doublereal); |
247 | | |
248 | | /* Local variables */ |
249 | 0 | integer i__; |
250 | 0 | IGRAPH_F77_SAVE integer j; |
251 | 0 | IGRAPH_F77_SAVE real t0, t1, t2, t3, t4, t5; |
252 | 0 | integer jj; |
253 | 0 | IGRAPH_F77_SAVE integer ipj, irj; |
254 | 0 | integer nbx = 0; |
255 | 0 | IGRAPH_F77_SAVE integer ivj; |
256 | 0 | IGRAPH_F77_SAVE doublereal ulp; |
257 | 0 | doublereal tst1; |
258 | 0 | extern doublereal igraphddot_(integer *, doublereal *, integer *, doublereal *, |
259 | 0 | integer *); |
260 | 0 | IGRAPH_F77_SAVE integer ierr, iter; |
261 | 0 | IGRAPH_F77_SAVE doublereal unfl, ovfl; |
262 | 0 | integer nopx = 0; |
263 | 0 | IGRAPH_F77_SAVE integer itry; |
264 | 0 | extern doublereal igraphdnrm2_(integer *, doublereal *, integer *); |
265 | 0 | doublereal temp1; |
266 | 0 | IGRAPH_F77_SAVE logical orth1, orth2, step3, step4; |
267 | 0 | IGRAPH_F77_SAVE doublereal betaj; |
268 | 0 | extern /* Subroutine */ int igraphdscal_(integer *, doublereal *, doublereal *, |
269 | 0 | integer *), igraphdgemv_(char *, integer *, integer *, doublereal *, |
270 | 0 | doublereal *, integer *, doublereal *, integer *, doublereal *, |
271 | 0 | doublereal *, integer *); |
272 | 0 | integer infol; |
273 | 0 | extern /* Subroutine */ int igraphdcopy_(integer *, doublereal *, integer *, |
274 | 0 | doublereal *, integer *), igraphdaxpy_(integer *, doublereal *, |
275 | 0 | doublereal *, integer *, doublereal *, integer *), igraphdmout_(integer |
276 | 0 | *, integer *, integer *, doublereal *, integer *, integer *, char |
277 | 0 | *, ftnlen); |
278 | 0 | doublereal xtemp[2]; |
279 | 0 | real tmvbx = 0; |
280 | 0 | extern /* Subroutine */ int igraphdvout_(integer *, integer *, doublereal *, |
281 | 0 | integer *, char *, ftnlen); |
282 | 0 | IGRAPH_F77_SAVE doublereal wnorm; |
283 | 0 | extern /* Subroutine */ int igraphivout_(integer *, integer *, integer *, |
284 | 0 | integer *, char *, ftnlen), igraphdgetv0_(integer *, char *, integer *, |
285 | 0 | logical *, integer *, integer *, doublereal *, integer *, |
286 | 0 | doublereal *, doublereal *, integer *, doublereal *, integer *), igraphdlabad_(doublereal *, doublereal *); |
287 | 0 | IGRAPH_F77_SAVE doublereal rnorm1; |
288 | 0 | extern doublereal igraphdlamch_(char *); |
289 | 0 | extern /* Subroutine */ int igraphdlascl_(char *, integer *, integer *, |
290 | 0 | doublereal *, doublereal *, integer *, integer *, doublereal *, |
291 | 0 | integer *, integer *); |
292 | 0 | extern doublereal igraphdlanhs_(char *, integer *, doublereal *, integer *, |
293 | 0 | doublereal *); |
294 | 0 | extern /* Subroutine */ int igraphsecond_(real *); |
295 | 0 | integer logfil = 0, ndigit, nitref = 0, mnaitr = 0; |
296 | 0 | real titref = 0, tnaitr = 0; |
297 | 0 | IGRAPH_F77_SAVE integer msglvl; |
298 | 0 | IGRAPH_F77_SAVE doublereal smlnum; |
299 | 0 | integer nrorth = 0; |
300 | 0 | IGRAPH_F77_SAVE logical rstart; |
301 | 0 | integer nrstrt = 0; |
302 | 0 | real tmvopx = 0; |
303 | | |
304 | | |
305 | | /* %----------------------------------------------------% |
306 | | | Include files for debugging and timing information | |
307 | | %----------------------------------------------------% |
308 | | |
309 | | |
310 | | %------------------% |
311 | | | Scalar Arguments | |
312 | | %------------------% |
313 | | |
314 | | |
315 | | %-----------------% |
316 | | | Array Arguments | |
317 | | %-----------------% |
318 | | |
319 | | |
320 | | %------------% |
321 | | | Parameters | |
322 | | %------------% |
323 | | |
324 | | |
325 | | %---------------% |
326 | | | Local Scalars | |
327 | | %---------------% |
328 | | |
329 | | |
330 | | %-----------------------% |
331 | | | Local Array Arguments | |
332 | | %-----------------------% |
333 | | |
334 | | |
335 | | %----------------------% |
336 | | | External Subroutines | |
337 | | %----------------------% |
338 | | |
339 | | |
340 | | %--------------------% |
341 | | | External Functions | |
342 | | %--------------------% |
343 | | |
344 | | |
345 | | %---------------------% |
346 | | | Intrinsic Functions | |
347 | | %---------------------% |
348 | | |
349 | | |
350 | | %-----------------% |
351 | | | Data statements | |
352 | | %-----------------% |
353 | | |
354 | | Parameter adjustments */ |
355 | 0 | --workd; |
356 | 0 | --resid; |
357 | 0 | v_dim1 = *ldv; |
358 | 0 | v_offset = 1 + v_dim1; |
359 | 0 | v -= v_offset; |
360 | 0 | h_dim1 = *ldh; |
361 | 0 | h_offset = 1 + h_dim1; |
362 | 0 | h__ -= h_offset; |
363 | 0 | --ipntr; |
364 | | |
365 | | /* Function Body |
366 | | |
367 | | %-----------------------% |
368 | | | Executable Statements | |
369 | | %-----------------------% */ |
370 | |
|
371 | 0 | if (first) { |
372 | | |
373 | | /* %-----------------------------------------% |
374 | | | Set machine-dependent constants for the | |
375 | | | the splitting and deflation criterion. | |
376 | | | If norm(H) <= sqrt(OVFL), | |
377 | | | overflow should not occur. | |
378 | | | REFERENCE: LAPACK subroutine dlahqr | |
379 | | %-----------------------------------------% */ |
380 | |
|
381 | 0 | unfl = igraphdlamch_("safe minimum"); |
382 | 0 | ovfl = 1. / unfl; |
383 | 0 | igraphdlabad_(&unfl, &ovfl); |
384 | 0 | ulp = igraphdlamch_("precision"); |
385 | 0 | smlnum = unfl * (*n / ulp); |
386 | 0 | first = FALSE_; |
387 | 0 | } |
388 | |
|
389 | 0 | if (*ido == 0) { |
390 | | |
391 | | /* %-------------------------------% |
392 | | | Initialize timing statistics | |
393 | | | & message level for debugging | |
394 | | %-------------------------------% */ |
395 | |
|
396 | 0 | igraphsecond_(&t0); |
397 | 0 | msglvl = mnaitr; |
398 | | |
399 | | /* %------------------------------% |
400 | | | Initial call to this routine | |
401 | | %------------------------------% */ |
402 | |
|
403 | 0 | *info = 0; |
404 | 0 | step3 = FALSE_; |
405 | 0 | step4 = FALSE_; |
406 | 0 | rstart = FALSE_; |
407 | 0 | orth1 = FALSE_; |
408 | 0 | orth2 = FALSE_; |
409 | 0 | j = *k + 1; |
410 | 0 | ipj = 1; |
411 | 0 | irj = ipj + *n; |
412 | 0 | ivj = irj + *n; |
413 | 0 | } |
414 | | |
415 | | /* %-------------------------------------------------% |
416 | | | When in reverse communication mode one of: | |
417 | | | STEP3, STEP4, ORTH1, ORTH2, RSTART | |
418 | | | will be .true. when .... | |
419 | | | STEP3: return from computing OP*v_{j}. | |
420 | | | STEP4: return from computing B-norm of OP*v_{j} | |
421 | | | ORTH1: return from computing B-norm of r_{j+1} | |
422 | | | ORTH2: return from computing B-norm of | |
423 | | | correction to the residual vector. | |
424 | | | RSTART: return from OP computations needed by | |
425 | | | dgetv0. | |
426 | | %-------------------------------------------------% */ |
427 | |
|
428 | 0 | if (step3) { |
429 | 0 | goto L50; |
430 | 0 | } |
431 | 0 | if (step4) { |
432 | 0 | goto L60; |
433 | 0 | } |
434 | 0 | if (orth1) { |
435 | 0 | goto L70; |
436 | 0 | } |
437 | 0 | if (orth2) { |
438 | 0 | goto L90; |
439 | 0 | } |
440 | 0 | if (rstart) { |
441 | 0 | goto L30; |
442 | 0 | } |
443 | | |
444 | | /* %-----------------------------% |
445 | | | Else this is the first step | |
446 | | %-----------------------------% |
447 | | |
448 | | %--------------------------------------------------------------% |
449 | | | | |
450 | | | A R N O L D I I T E R A T I O N L O O P | |
451 | | | | |
452 | | | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | |
453 | | %--------------------------------------------------------------% */ |
454 | 0 | L1000: |
455 | |
|
456 | 0 | if (msglvl > 1) { |
457 | 0 | igraphivout_(&logfil, &c__1, &j, &ndigit, "_naitr: generating Arnoldi vect" |
458 | 0 | "or number", (ftnlen)40); |
459 | 0 | igraphdvout_(&logfil, &c__1, rnorm, &ndigit, "_naitr: B-norm of the curren" |
460 | 0 | "t residual is", (ftnlen)41); |
461 | 0 | } |
462 | | |
463 | | /* %---------------------------------------------------% |
464 | | | STEP 1: Check if the B norm of j-th residual | |
465 | | | vector is zero. Equivalent to determing whether | |
466 | | | an exact j-step Arnoldi factorization is present. | |
467 | | %---------------------------------------------------% */ |
468 | |
|
469 | 0 | betaj = *rnorm; |
470 | 0 | if (*rnorm > 0.) { |
471 | 0 | goto L40; |
472 | 0 | } |
473 | | |
474 | | /* %---------------------------------------------------% |
475 | | | Invariant subspace found, generate a new starting | |
476 | | | vector which is orthogonal to the current Arnoldi | |
477 | | | basis and continue the iteration. | |
478 | | %---------------------------------------------------% */ |
479 | | |
480 | 0 | if (msglvl > 0) { |
481 | 0 | igraphivout_(&logfil, &c__1, &j, &ndigit, "_naitr: ****** RESTART AT STEP " |
482 | 0 | "******", (ftnlen)37); |
483 | 0 | } |
484 | | |
485 | | /* %---------------------------------------------% |
486 | | | ITRY is the loop variable that controls the | |
487 | | | maximum amount of times that a restart is | |
488 | | | attempted. NRSTRT is used by stat.h | |
489 | | %---------------------------------------------% */ |
490 | |
|
491 | 0 | betaj = 0.; |
492 | 0 | ++nrstrt; |
493 | 0 | itry = 1; |
494 | 0 | L20: |
495 | 0 | rstart = TRUE_; |
496 | 0 | *ido = 0; |
497 | 0 | L30: |
498 | | |
499 | | /* %--------------------------------------% |
500 | | | If in reverse communication mode and | |
501 | | | RSTART = .true. flow returns here. | |
502 | | %--------------------------------------% */ |
503 | |
|
504 | 0 | igraphdgetv0_(ido, bmat, &itry, &c_false, n, &j, &v[v_offset], ldv, &resid[1], |
505 | 0 | rnorm, &ipntr[1], &workd[1], &ierr); |
506 | 0 | if (*ido != 99) { |
507 | 0 | goto L9000; |
508 | 0 | } |
509 | 0 | if (ierr < 0) { |
510 | 0 | ++itry; |
511 | 0 | if (itry <= 3) { |
512 | 0 | goto L20; |
513 | 0 | } |
514 | | |
515 | | /* %------------------------------------------------% |
516 | | | Give up after several restart attempts. | |
517 | | | Set INFO to the size of the invariant subspace | |
518 | | | which spans OP and exit. | |
519 | | %------------------------------------------------% */ |
520 | | |
521 | 0 | *info = j - 1; |
522 | 0 | igraphsecond_(&t1); |
523 | 0 | tnaitr += t1 - t0; |
524 | 0 | *ido = 99; |
525 | 0 | goto L9000; |
526 | 0 | } |
527 | | |
528 | 0 | L40: |
529 | | |
530 | | /* %---------------------------------------------------------% |
531 | | | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | |
532 | | | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | |
533 | | | when reciprocating a small RNORM, test against lower | |
534 | | | machine bound. | |
535 | | %---------------------------------------------------------% */ |
536 | |
|
537 | 0 | igraphdcopy_(n, &resid[1], &c__1, &v[j * v_dim1 + 1], &c__1); |
538 | 0 | if (*rnorm >= unfl) { |
539 | 0 | temp1 = 1. / *rnorm; |
540 | 0 | igraphdscal_(n, &temp1, &v[j * v_dim1 + 1], &c__1); |
541 | 0 | igraphdscal_(n, &temp1, &workd[ipj], &c__1); |
542 | 0 | } else { |
543 | | |
544 | | /* %-----------------------------------------% |
545 | | | To scale both v_{j} and p_{j} carefully | |
546 | | | use LAPACK routine SLASCL | |
547 | | %-----------------------------------------% */ |
548 | |
|
549 | 0 | igraphdlascl_("General", &i__, &i__, rnorm, &c_b25, n, &c__1, &v[j * v_dim1 |
550 | 0 | + 1], n, &infol); |
551 | 0 | igraphdlascl_("General", &i__, &i__, rnorm, &c_b25, n, &c__1, &workd[ipj], |
552 | 0 | n, &infol); |
553 | 0 | } |
554 | | |
555 | | /* %------------------------------------------------------% |
556 | | | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | |
557 | | | Note that this is not quite yet r_{j}. See STEP 4 | |
558 | | %------------------------------------------------------% */ |
559 | |
|
560 | 0 | step3 = TRUE_; |
561 | 0 | ++nopx; |
562 | 0 | igraphsecond_(&t2); |
563 | 0 | igraphdcopy_(n, &v[j * v_dim1 + 1], &c__1, &workd[ivj], &c__1); |
564 | 0 | ipntr[1] = ivj; |
565 | 0 | ipntr[2] = irj; |
566 | 0 | ipntr[3] = ipj; |
567 | 0 | *ido = 1; |
568 | | |
569 | | /* %-----------------------------------% |
570 | | | Exit in order to compute OP*v_{j} | |
571 | | %-----------------------------------% */ |
572 | |
|
573 | 0 | goto L9000; |
574 | 0 | L50: |
575 | | |
576 | | /* %----------------------------------% |
577 | | | Back from reverse communication; | |
578 | | | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | |
579 | | | if step3 = .true. | |
580 | | %----------------------------------% */ |
581 | |
|
582 | 0 | igraphsecond_(&t3); |
583 | 0 | tmvopx += t3 - t2; |
584 | 0 | step3 = FALSE_; |
585 | | |
586 | | /* %------------------------------------------% |
587 | | | Put another copy of OP*v_{j} into RESID. | |
588 | | %------------------------------------------% */ |
589 | |
|
590 | 0 | igraphdcopy_(n, &workd[irj], &c__1, &resid[1], &c__1); |
591 | | |
592 | | /* %---------------------------------------% |
593 | | | STEP 4: Finish extending the Arnoldi | |
594 | | | factorization to length j. | |
595 | | %---------------------------------------% */ |
596 | |
|
597 | 0 | igraphsecond_(&t2); |
598 | 0 | if (*(unsigned char *)bmat == 'G') { |
599 | 0 | ++nbx; |
600 | 0 | step4 = TRUE_; |
601 | 0 | ipntr[1] = irj; |
602 | 0 | ipntr[2] = ipj; |
603 | 0 | *ido = 2; |
604 | | |
605 | | /* %-------------------------------------% |
606 | | | Exit in order to compute B*OP*v_{j} | |
607 | | %-------------------------------------% */ |
608 | |
|
609 | 0 | goto L9000; |
610 | 0 | } else if (*(unsigned char *)bmat == 'I') { |
611 | 0 | igraphdcopy_(n, &resid[1], &c__1, &workd[ipj], &c__1); |
612 | 0 | } |
613 | 0 | L60: |
614 | | |
615 | | /* %----------------------------------% |
616 | | | Back from reverse communication; | |
617 | | | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | |
618 | | | if step4 = .true. | |
619 | | %----------------------------------% */ |
620 | |
|
621 | 0 | if (*(unsigned char *)bmat == 'G') { |
622 | 0 | igraphsecond_(&t3); |
623 | 0 | tmvbx += t3 - t2; |
624 | 0 | } |
625 | |
|
626 | 0 | step4 = FALSE_; |
627 | | |
628 | | /* %-------------------------------------% |
629 | | | The following is needed for STEP 5. | |
630 | | | Compute the B-norm of OP*v_{j}. | |
631 | | %-------------------------------------% */ |
632 | |
|
633 | 0 | if (*(unsigned char *)bmat == 'G') { |
634 | 0 | wnorm = igraphddot_(n, &resid[1], &c__1, &workd[ipj], &c__1); |
635 | 0 | wnorm = sqrt((abs(wnorm))); |
636 | 0 | } else if (*(unsigned char *)bmat == 'I') { |
637 | 0 | wnorm = igraphdnrm2_(n, &resid[1], &c__1); |
638 | 0 | } |
639 | | |
640 | | /* %-----------------------------------------% |
641 | | | Compute the j-th residual corresponding | |
642 | | | to the j step factorization. | |
643 | | | Use Classical Gram Schmidt and compute: | |
644 | | | w_{j} <- V_{j}^T * B * OP * v_{j} | |
645 | | | r_{j} <- OP*v_{j} - V_{j} * w_{j} | |
646 | | %-----------------------------------------% |
647 | | |
648 | | |
649 | | %------------------------------------------% |
650 | | | Compute the j Fourier coefficients w_{j} | |
651 | | | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | |
652 | | %------------------------------------------% */ |
653 | |
|
654 | 0 | igraphdgemv_("T", n, &j, &c_b25, &v[v_offset], ldv, &workd[ipj], &c__1, &c_b47, |
655 | 0 | &h__[j * h_dim1 + 1], &c__1); |
656 | | |
657 | | /* %--------------------------------------% |
658 | | | Orthogonalize r_{j} against V_{j}. | |
659 | | | RESID contains OP*v_{j}. See STEP 3. | |
660 | | %--------------------------------------% */ |
661 | |
|
662 | 0 | igraphdgemv_("N", n, &j, &c_b50, &v[v_offset], ldv, &h__[j * h_dim1 + 1], &c__1, |
663 | 0 | &c_b25, &resid[1], &c__1); |
664 | |
|
665 | 0 | if (j > 1) { |
666 | 0 | h__[j + (j - 1) * h_dim1] = betaj; |
667 | 0 | } |
668 | |
|
669 | 0 | igraphsecond_(&t4); |
670 | |
|
671 | 0 | orth1 = TRUE_; |
672 | |
|
673 | 0 | igraphsecond_(&t2); |
674 | 0 | if (*(unsigned char *)bmat == 'G') { |
675 | 0 | ++nbx; |
676 | 0 | igraphdcopy_(n, &resid[1], &c__1, &workd[irj], &c__1); |
677 | 0 | ipntr[1] = irj; |
678 | 0 | ipntr[2] = ipj; |
679 | 0 | *ido = 2; |
680 | | |
681 | | /* %----------------------------------% |
682 | | | Exit in order to compute B*r_{j} | |
683 | | %----------------------------------% */ |
684 | |
|
685 | 0 | goto L9000; |
686 | 0 | } else if (*(unsigned char *)bmat == 'I') { |
687 | 0 | igraphdcopy_(n, &resid[1], &c__1, &workd[ipj], &c__1); |
688 | 0 | } |
689 | 0 | L70: |
690 | | |
691 | | /* %---------------------------------------------------% |
692 | | | Back from reverse communication if ORTH1 = .true. | |
693 | | | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | |
694 | | %---------------------------------------------------% */ |
695 | |
|
696 | 0 | if (*(unsigned char *)bmat == 'G') { |
697 | 0 | igraphsecond_(&t3); |
698 | 0 | tmvbx += t3 - t2; |
699 | 0 | } |
700 | |
|
701 | 0 | orth1 = FALSE_; |
702 | | |
703 | | /* %------------------------------% |
704 | | | Compute the B-norm of r_{j}. | |
705 | | %------------------------------% */ |
706 | |
|
707 | 0 | if (*(unsigned char *)bmat == 'G') { |
708 | 0 | *rnorm = igraphddot_(n, &resid[1], &c__1, &workd[ipj], &c__1); |
709 | 0 | *rnorm = sqrt((abs(*rnorm))); |
710 | 0 | } else if (*(unsigned char *)bmat == 'I') { |
711 | 0 | *rnorm = igraphdnrm2_(n, &resid[1], &c__1); |
712 | 0 | } |
713 | | |
714 | | /* %-----------------------------------------------------------% |
715 | | | STEP 5: Re-orthogonalization / Iterative refinement phase | |
716 | | | Maximum NITER_ITREF tries. | |
717 | | | | |
718 | | | s = V_{j}^T * B * r_{j} | |
719 | | | r_{j} = r_{j} - V_{j}*s | |
720 | | | alphaj = alphaj + s_{j} | |
721 | | | | |
722 | | | The stopping criteria used for iterative refinement is | |
723 | | | discussed in Parlett's book SEP, page 107 and in Gragg & | |
724 | | | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | |
725 | | | Determine if we need to correct the residual. The goal is | |
726 | | | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | |
727 | | | The following test determines whether the sine of the | |
728 | | | angle between OP*x and the computed residual is less | |
729 | | | than or equal to 0.717. | |
730 | | %-----------------------------------------------------------% */ |
731 | |
|
732 | 0 | if (*rnorm > wnorm * .717f) { |
733 | 0 | goto L100; |
734 | 0 | } |
735 | 0 | iter = 0; |
736 | 0 | ++nrorth; |
737 | | |
738 | | /* %---------------------------------------------------% |
739 | | | Enter the Iterative refinement phase. If further | |
740 | | | refinement is necessary, loop back here. The loop | |
741 | | | variable is ITER. Perform a step of Classical | |
742 | | | Gram-Schmidt using all the Arnoldi vectors V_{j} | |
743 | | %---------------------------------------------------% */ |
744 | |
|
745 | 0 | L80: |
746 | |
|
747 | 0 | if (msglvl > 2) { |
748 | 0 | xtemp[0] = wnorm; |
749 | 0 | xtemp[1] = *rnorm; |
750 | 0 | igraphdvout_(&logfil, &c__2, xtemp, &ndigit, "_naitr: re-orthonalization; " |
751 | 0 | "wnorm and rnorm are", (ftnlen)47); |
752 | 0 | igraphdvout_(&logfil, &j, &h__[j * h_dim1 + 1], &ndigit, "_naitr: j-th col" |
753 | 0 | "umn of H", (ftnlen)24); |
754 | 0 | } |
755 | | |
756 | | /* %----------------------------------------------------% |
757 | | | Compute V_{j}^T * B * r_{j}. | |
758 | | | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | |
759 | | %----------------------------------------------------% */ |
760 | |
|
761 | 0 | igraphdgemv_("T", n, &j, &c_b25, &v[v_offset], ldv, &workd[ipj], &c__1, &c_b47, |
762 | 0 | &workd[irj], &c__1); |
763 | | |
764 | | /* %---------------------------------------------% |
765 | | | Compute the correction to the residual: | |
766 | | | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | |
767 | | | The correction to H is v(:,1:J)*H(1:J,1:J) | |
768 | | | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | |
769 | | %---------------------------------------------% */ |
770 | |
|
771 | 0 | igraphdgemv_("N", n, &j, &c_b50, &v[v_offset], ldv, &workd[irj], &c__1, &c_b25, |
772 | 0 | &resid[1], &c__1); |
773 | 0 | igraphdaxpy_(&j, &c_b25, &workd[irj], &c__1, &h__[j * h_dim1 + 1], &c__1); |
774 | |
|
775 | 0 | orth2 = TRUE_; |
776 | 0 | igraphsecond_(&t2); |
777 | 0 | if (*(unsigned char *)bmat == 'G') { |
778 | 0 | ++nbx; |
779 | 0 | igraphdcopy_(n, &resid[1], &c__1, &workd[irj], &c__1); |
780 | 0 | ipntr[1] = irj; |
781 | 0 | ipntr[2] = ipj; |
782 | 0 | *ido = 2; |
783 | | |
784 | | /* %-----------------------------------% |
785 | | | Exit in order to compute B*r_{j}. | |
786 | | | r_{j} is the corrected residual. | |
787 | | %-----------------------------------% */ |
788 | |
|
789 | 0 | goto L9000; |
790 | 0 | } else if (*(unsigned char *)bmat == 'I') { |
791 | 0 | igraphdcopy_(n, &resid[1], &c__1, &workd[ipj], &c__1); |
792 | 0 | } |
793 | 0 | L90: |
794 | | |
795 | | /* %---------------------------------------------------% |
796 | | | Back from reverse communication if ORTH2 = .true. | |
797 | | %---------------------------------------------------% */ |
798 | |
|
799 | 0 | if (*(unsigned char *)bmat == 'G') { |
800 | 0 | igraphsecond_(&t3); |
801 | 0 | tmvbx += t3 - t2; |
802 | 0 | } |
803 | | |
804 | | /* %-----------------------------------------------------% |
805 | | | Compute the B-norm of the corrected residual r_{j}. | |
806 | | %-----------------------------------------------------% */ |
807 | |
|
808 | 0 | if (*(unsigned char *)bmat == 'G') { |
809 | 0 | rnorm1 = igraphddot_(n, &resid[1], &c__1, &workd[ipj], &c__1); |
810 | 0 | rnorm1 = sqrt((abs(rnorm1))); |
811 | 0 | } else if (*(unsigned char *)bmat == 'I') { |
812 | 0 | rnorm1 = igraphdnrm2_(n, &resid[1], &c__1); |
813 | 0 | } |
814 | |
|
815 | 0 | if (msglvl > 0 && iter > 0) { |
816 | 0 | igraphivout_(&logfil, &c__1, &j, &ndigit, "_naitr: Iterative refinement fo" |
817 | 0 | "r Arnoldi residual", (ftnlen)49); |
818 | 0 | if (msglvl > 2) { |
819 | 0 | xtemp[0] = *rnorm; |
820 | 0 | xtemp[1] = rnorm1; |
821 | 0 | igraphdvout_(&logfil, &c__2, xtemp, &ndigit, "_naitr: iterative refine" |
822 | 0 | "ment ; rnorm and rnorm1 are", (ftnlen)51); |
823 | 0 | } |
824 | 0 | } |
825 | | |
826 | | /* %-----------------------------------------% |
827 | | | Determine if we need to perform another | |
828 | | | step of re-orthogonalization. | |
829 | | %-----------------------------------------% */ |
830 | |
|
831 | 0 | if (rnorm1 > *rnorm * .717f) { |
832 | | |
833 | | /* %---------------------------------------% |
834 | | | No need for further refinement. | |
835 | | | The cosine of the angle between the | |
836 | | | corrected residual vector and the old | |
837 | | | residual vector is greater than 0.717 | |
838 | | | In other words the corrected residual | |
839 | | | and the old residual vector share an | |
840 | | | angle of less than arcCOS(0.717) | |
841 | | %---------------------------------------% */ |
842 | |
|
843 | 0 | *rnorm = rnorm1; |
844 | |
|
845 | 0 | } else { |
846 | | |
847 | | /* %-------------------------------------------% |
848 | | | Another step of iterative refinement step | |
849 | | | is required. NITREF is used by stat.h | |
850 | | %-------------------------------------------% */ |
851 | |
|
852 | 0 | ++nitref; |
853 | 0 | *rnorm = rnorm1; |
854 | 0 | ++iter; |
855 | 0 | if (iter <= 1) { |
856 | 0 | goto L80; |
857 | 0 | } |
858 | | |
859 | | /* %-------------------------------------------------% |
860 | | | Otherwise RESID is numerically in the span of V | |
861 | | %-------------------------------------------------% */ |
862 | | |
863 | 0 | i__1 = *n; |
864 | 0 | for (jj = 1; jj <= i__1; ++jj) { |
865 | 0 | resid[jj] = 0.; |
866 | | /* L95: */ |
867 | 0 | } |
868 | 0 | *rnorm = 0.; |
869 | 0 | } |
870 | | |
871 | | /* %----------------------------------------------% |
872 | | | Branch here directly if iterative refinement | |
873 | | | wasn't necessary or after at most NITER_REF | |
874 | | | steps of iterative refinement. | |
875 | | %----------------------------------------------% */ |
876 | | |
877 | 0 | L100: |
878 | |
|
879 | 0 | rstart = FALSE_; |
880 | 0 | orth2 = FALSE_; |
881 | |
|
882 | 0 | igraphsecond_(&t5); |
883 | 0 | titref += t5 - t4; |
884 | | |
885 | | /* %------------------------------------% |
886 | | | STEP 6: Update j = j+1; Continue | |
887 | | %------------------------------------% */ |
888 | |
|
889 | 0 | ++j; |
890 | 0 | if (j > *k + *np) { |
891 | 0 | igraphsecond_(&t1); |
892 | 0 | tnaitr += t1 - t0; |
893 | 0 | *ido = 99; |
894 | 0 | i__1 = *k + *np - 1; |
895 | 0 | for (i__ = max(1,*k); i__ <= i__1; ++i__) { |
896 | | |
897 | | /* %--------------------------------------------% |
898 | | | Check for splitting and deflation. | |
899 | | | Use a standard test as in the QR algorithm | |
900 | | | REFERENCE: LAPACK subroutine dlahqr | |
901 | | %--------------------------------------------% */ |
902 | |
|
903 | 0 | tst1 = (d__1 = h__[i__ + i__ * h_dim1], abs(d__1)) + (d__2 = h__[ |
904 | 0 | i__ + 1 + (i__ + 1) * h_dim1], abs(d__2)); |
905 | 0 | if (tst1 == 0.) { |
906 | 0 | i__2 = *k + *np; |
907 | 0 | tst1 = igraphdlanhs_("1", &i__2, &h__[h_offset], ldh, &workd[*n + 1] |
908 | 0 | ); |
909 | 0 | } |
910 | | /* Computing MAX */ |
911 | 0 | d__2 = ulp * tst1; |
912 | 0 | if ((d__1 = h__[i__ + 1 + i__ * h_dim1], abs(d__1)) <= max(d__2, |
913 | 0 | smlnum)) { |
914 | 0 | h__[i__ + 1 + i__ * h_dim1] = 0.; |
915 | 0 | } |
916 | | /* L110: */ |
917 | 0 | } |
918 | |
|
919 | 0 | if (msglvl > 2) { |
920 | 0 | i__1 = *k + *np; |
921 | 0 | i__2 = *k + *np; |
922 | 0 | igraphdmout_(&logfil, &i__1, &i__2, &h__[h_offset], ldh, &ndigit, "_na" |
923 | 0 | "itr: Final upper Hessenberg matrix H of order K+NP", ( |
924 | 0 | ftnlen)53); |
925 | 0 | } |
926 | |
|
927 | 0 | goto L9000; |
928 | 0 | } |
929 | | |
930 | | /* %--------------------------------------------------------% |
931 | | | Loop back to extend the factorization by another step. | |
932 | | %--------------------------------------------------------% */ |
933 | | |
934 | 0 | goto L1000; |
935 | | |
936 | | /* %---------------------------------------------------------------% |
937 | | | | |
938 | | | E N D O F M A I N I T E R A T I O N L O O P | |
939 | | | | |
940 | | %---------------------------------------------------------------% */ |
941 | | |
942 | 0 | L9000: |
943 | 0 | return 0; |
944 | | |
945 | | /* %---------------% |
946 | | | End of dnaitr | |
947 | | %---------------% */ |
948 | |
|
949 | 0 | } /* igraphdnaitr_ */ |
950 | | |