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

« back to all changes in this revision

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