Coverage Report

Created: 2023-09-25 06:05

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