~ubuntu-branches/ubuntu/lucid/igraph/lucid

« back to all changes in this revision

Viewing changes to src/arpack/dnaitr.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Malaterre
  • Date: 2009-11-16 18:12:42 UTC
  • Revision ID: james.westby@ubuntu.com-20091116181242-mzv9p5fz9uj57xd1
Tags: upstream-0.5.3
ImportĀ upstreamĀ versionĀ 0.5.3

Show diffs side-by-side

added added

removed removed

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