Coverage Report

Created: 2023-06-07 06:06

/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