~ubuntu-branches/ubuntu/karmic/python-scipy/karmic

« back to all changes in this revision

Viewing changes to Lib/linalg/iterative/GMRESREVCOM.f.src

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T. Chen (new)
  • Date: 2005-03-16 02:15:29 UTC
  • Revision ID: james.westby@ubuntu.com-20050316021529-xrjlowsejs0cijig
Tags: upstream-0.3.2
ImportĀ upstreamĀ versionĀ 0.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
*
 
2
      SUBROUTINE <_c>GMRESREVCOM(N, B, X, RESTRT, WORK, LDW, WORK2,
 
3
     $                  LDW2, ITER, RESID, INFO, NDX1, NDX2, SCLR1, 
 
4
     $                  SCLR2, IJOB)
 
5
*
 
6
*  -- Iterative template routine --
 
7
*     Univ. of Tennessee and Oak Ridge National Laboratory
 
8
*     October 1, 1993
 
9
*     Details of this algorithm are described in "Templates for the
 
10
*     Solution of Linear Systems: Building Blocks for Iterative
 
11
*     Methods", Barrett, Berry, Chan, Demmel, Donato, Dongarra,
 
12
*     EiITERkhout, Pozo, Romine, and van der Vorst, SIAM Publications,
 
13
*     1993. (ftp netlib2.cs.utk.edu; cd linalg; get templates.ps).
 
14
*
 
15
*     .. Scalar Arguments ..
 
16
      INTEGER            N, RESTRT, LDW, LDW2, ITER, INFO
 
17
      <rt=real,double precision,real,double precision>  RESID
 
18
      INTEGER            NDX1, NDX2
 
19
      <_t>   SCLR1, SCLR2
 
20
      INTEGER            IJOB
 
21
*     ..
 
22
*     .. Array Arguments ..
 
23
      <_t>   B( * ), X( * ), WORK( LDW,* ), WORK2( LDW2,* )
 
24
*     ..
 
25
*
 
26
*  Purpose
 
27
*  =======
 
28
*
 
29
*  GMRES solves the linear system Ax = b using the
 
30
*  Generalized Minimal Residual iterative method with preconditioning.
 
31
*
 
32
*  Arguments
 
33
*  =========
 
34
*
 
35
*  N       (input) INTEGER. 
 
36
*          On entry, the dimension of the matrix.
 
37
*          Unchanged on exit.
 
38
 
39
*  B       (input) DOUBLE PRECISION array, dimension N.
 
40
*          On entry, right hand side vector B.
 
41
*          Unchanged on exit.
 
42
*
 
43
*  X       (input/output) DOUBLE PRECISION array, dimension N.
 
44
*          On input, the initial guess; on exit, the iterated solution.
 
45
*
 
46
*  RESTRT  (input) INTEGER
 
47
*          Restart parameter, .ls. = N. This parameter controls the amount
 
48
*          of memory required for matrix WORK2.
 
49
*
 
50
*  WORK    (workspace) DOUBLE PRECISION array, dimension (LDW,6+restrt).
 
51
*          Note that if the initial guess is the zero vector, then 
 
52
*          storing the initial residual is not necessary.
 
53
*
 
54
*  LDW     (input) INTEGER
 
55
*          The leading dimension of the array WORK. LDW .gt. = max(1,N).
 
56
*
 
57
*  WORK2   (workspace) DOUBLE PRECISION array, dimension (LDW2,2*RESTRT+2).
 
58
*          This workspace is used for constructing and storing the
 
59
*          upper Hessenberg matrix. The two extra columns are used to
 
60
*          store the Givens rotation matrices.
 
61
*
 
62
*  LDW2    (input) INTEGER
 
63
*          The leading dimension of the array WORK2.
 
64
*          LDW2 .gt. = max(2,RESTRT+1).
 
65
*
 
66
*  ITER    (input/output) INTEGER
 
67
*          On input, the maximum iterations to be performed.
 
68
*          On output, actual number of iterations performed.
 
69
*
 
70
*  RESID   (input/output) DOUBLE PRECISION
 
71
*          On input, the allowable error tolerance.
 
72
*          On ouput, the norm of the residual vector if solution
 
73
*          approximated to tolerance, otherwise reset to input
 
74
*          tolerance.
 
75
*
 
76
*  INFO    (output) INTEGER
 
77
*          =  0:  successful exit
 
78
*          =  1:  maximum number of iterations performed;
 
79
*                 convergence not achieved.
 
80
*            -5: Erroneous NDX1/NDX2 in INIT call.
 
81
*            -6: Erroneous RLBL.
 
82
*
 
83
*  NDX1    (input/output) INTEGER. 
 
84
*  NDX2    On entry in INIT call contain indices required by interface
 
85
*          level for stopping test.
 
86
*          All other times, used as output, to indicate indices into
 
87
*          WORK[] for the MATVEC, PSOLVE done by the interface level.
 
88
*
 
89
*  SCLR1   (output) DOUBLE PRECISION.
 
90
*  SCLR2   Used to pass the scalars used in MATVEC. Scalars are reqd because
 
91
*          original routines use dgemv.
 
92
*
 
93
*  IJOB    (input/output) INTEGER. 
 
94
*          Used to communicate job code between the two levels.
 
95
*
 
96
*  ============================================================
 
97
*
 
98
*     .. Parameters ..
 
99
      <rt>    ZERO, ONE
 
100
      PARAMETER         ( ZERO = 0.0D+0, ONE = 1.0D+0 )
 
101
      INTEGER             OFSET
 
102
      PARAMETER         ( OFSET = 1000 )
 
103
*     ..
 
104
*     .. Local Scalars ..
 
105
      INTEGER             I, MAXIT, AV, GIV, H, R, S, V, W, Y,
 
106
     $                    NEED1, NEED2
 
107
      <_t>  <xdot=sdot,ddot,cdotc,zdotc>
 
108
      <_t>  toz
 
109
      <rt>    BNRM2, RNORM, TOL,  
 
110
     $     <rc=s,d,sc,dz>NRM2,
 
111
     $     <rc>APPROXRES
 
112
 
 
113
*
 
114
*     indicates where to resume from. Only valid when IJOB = 2!
 
115
      INTEGER RLBL
 
116
*
 
117
*     saving all.
 
118
      SAVE
 
119
*
 
120
*     ..
 
121
*     .. External Routines ..
 
122
      EXTERNAL     <_c>AXPY, <_c>COPY, <xdot>, <rc>NRM2, <_c>SCAL
 
123
*     ..
 
124
*     .. Executable Statements ..
 
125
*
 
126
* Entry point, so test IJOB
 
127
      IF (IJOB .eq. 1) THEN
 
128
         GOTO 1
 
129
      ELSEIF (IJOB .eq. 2) THEN
 
130
*        here we do resumption handling
 
131
         IF (RLBL .eq. 2) GOTO 2
 
132
         IF (RLBL .eq. 3) GOTO 3
 
133
         IF (RLBL .eq. 4) GOTO 4
 
134
         IF (RLBL .eq. 5) GOTO 5
 
135
         IF (RLBL .eq. 6) GOTO 6
 
136
         IF (RLBL .eq. 7) GOTO 7
 
137
*        if neither of these, then error
 
138
         INFO = -6
 
139
         GOTO 200
 
140
      ENDIF
 
141
*
 
142
* init.
 
143
*****************
 
144
 1    CONTINUE
 
145
*****************
 
146
*
 
147
      INFO = 0
 
148
      MAXIT = ITER
 
149
      TOL   = RESID
 
150
*
 
151
*     Alias workspace columns.
 
152
*
 
153
      R   = 1
 
154
      S   = 2
 
155
      W   = 3
 
156
      Y   = 4
 
157
      AV  = 5
 
158
      V   = 6
 
159
*
 
160
      H   = 1
 
161
      GIV = H + RESTRT
 
162
*
 
163
*     Check if caller will need indexing info.
 
164
*
 
165
      IF( NDX1.NE.-1 ) THEN
 
166
         IF( NDX1.EQ.1 ) THEN
 
167
            NEED1 = ((R - 1) * LDW) + 1
 
168
         ELSEIF( NDX1.EQ.2 ) THEN
 
169
            NEED1 = ((S - 1) * LDW) + 1
 
170
         ELSEIF( NDX1.EQ.3 ) THEN
 
171
            NEED1 = ((W - 1) * LDW) + 1
 
172
         ELSEIF( NDX1.EQ.4 ) THEN
 
173
            NEED1 = ((Y - 1) * LDW) + 1
 
174
         ELSEIF( NDX1.EQ.5 ) THEN
 
175
            NEED1 = ((AV - 1) * LDW) + 1
 
176
         ELSEIF( NDX1.EQ.6 ) THEN
 
177
            NEED1 = ((V - 1) * LDW) + 1
 
178
         ELSEIF( ( NDX1.GT.V*OFSET ) .AND.
 
179
     $           ( NDX1.LE.V*OFSET+RESTRT ) ) THEN
 
180
            NEED1 = ((NDX1-V*OFSET - 1) * LDW) + 1
 
181
         ELSEIF( ( NDX1.GT.GIV*OFSET ) .AND.
 
182
     $           ( NDX1.LE.GIV*OFSET+RESTRT ) ) THEN
 
183
            NEED1 = ((NDX1-GIV*OFSET - 1) * LDW) + 1
 
184
         ELSE
 
185
*           report error
 
186
            INFO = -5
 
187
            GO TO 100
 
188
         ENDIF
 
189
      ELSE
 
190
         NEED1 = NDX1
 
191
      ENDIF
 
192
*
 
193
      IF( NDX2.NE.-1 ) THEN
 
194
         IF( NDX2.EQ.1 ) THEN
 
195
            NEED2 = ((R - 1) * LDW) + 1
 
196
         ELSEIF( NDX2.EQ.2 ) THEN
 
197
            NEED2 = ((S - 1) * LDW) + 1
 
198
         ELSEIF( NDX2.EQ.3 ) THEN
 
199
            NEED2 = ((W - 1) * LDW) + 1
 
200
         ELSEIF( NDX2.EQ.4 ) THEN
 
201
            NEED2 = ((Y - 1) * LDW) + 1
 
202
         ELSEIF( NDX2.EQ.5 ) THEN
 
203
            NEED2 = ((AV - 1) * LDW) + 1
 
204
         ELSEIF( NDX2.EQ.6 ) THEN
 
205
            NEED2 = ((V - 1) * LDW) + 1
 
206
         ELSEIF( ( NDX2.GT.V*OFSET ) .AND.
 
207
     $           ( NDX2.LE.V*OFSET+RESTRT ) ) THEN
 
208
            NEED2 = ((NDX2-V*OFSET - 1) * LDW) + 1
 
209
         ELSEIF( ( NDX2.GT.GIV*OFSET ) .AND.
 
210
     $           ( NDX2.LE.GIV*OFSET+RESTRT ) ) THEN
 
211
            NEED2 = ((NDX2-GIV*OFSET - 1) * LDW) + 1
 
212
         ELSE
 
213
*           report error
 
214
            INFO = -5
 
215
            GO TO 100
 
216
         ENDIF
 
217
      ELSE
 
218
         NEED2 = NDX2
 
219
      ENDIF
 
220
*
 
221
*     Set initial residual.
 
222
*
 
223
      CALL <_c>COPY( N, B, 1, WORK(1,R), 1 )
 
224
      IF ( <rc>NRM2( N, X, 1 ).NE.ZERO ) THEN
 
225
*********CALL MATVEC( -ONE, X, ONE, WORK(1,R) )
 
226
*        Note: using X directly
 
227
         SCLR1 = -ONE
 
228
         SCLR2 = ONE
 
229
         NDX1 = -1
 
230
         NDX2 = ((R - 1) * LDW) + 1
 
231
*
 
232
*        Prepare for resumption & return
 
233
         RLBL = 2
 
234
         IJOB = 1
 
235
         RETURN
 
236
*
 
237
*****************
 
238
 2       CONTINUE
 
239
*****************
 
240
*
 
241
         IF ( <rc>NRM2( N, WORK(1,R), 1 ).LT.TOL ) GO TO 200
 
242
      ENDIF
 
243
      BNRM2 = <rc>NRM2( N, B, 1 )
 
244
      IF ( BNRM2.EQ.ZERO ) BNRM2 = ONE
 
245
*
 
246
      ITER = 0
 
247
   10 CONTINUE
 
248
*
 
249
         ITER = ITER + 1
 
250
*
 
251
*        Construct the first column of V, and initialize S to the
 
252
*        elementary vector E1 scaled by RNORM.
 
253
*
 
254
*********CALL PSOLVE( WORK( 1,V ), WORK( 1,R ) )
 
255
*
 
256
         NDX1 = ((V - 1) * LDW) + 1
 
257
         NDX2 = ((R - 1) * LDW) + 1
 
258
*        Prepare for return & return
 
259
         RLBL = 3
 
260
         IJOB = 2
 
261
         RETURN
 
262
*
 
263
*****************
 
264
 3       CONTINUE
 
265
*****************
 
266
*
 
267
         RNORM = <rc>NRM2( N, WORK( 1,V ), 1 )
 
268
         toz = ONE/RNORM
 
269
         CALL <_c>SCAL( N, toz, WORK( 1,V ), 1 )
 
270
         CALL <_c>ELEMVEC( 1, N, RNORM, WORK( 1,S ) )
 
271
*
 
272
*         DO 50 I = 1, RESTRT
 
273
         i = 1
 
274
 49      if (i.gt.restrt) go to 50
 
275
************CALL MATVEC( ONE, WORK( 1,V+I-1 ), ZERO, WORK( 1,AV ) )
 
276
*
 
277
         NDX1 = ((V+I-1 - 1) * LDW) + 1
 
278
         NDX2 = ((AV    - 1) * LDW) + 1
 
279
*        Prepare for return & return
 
280
         SCLR1 = ONE
 
281
         SCLR2 = ZERO
 
282
         RLBL = 4
 
283
         IJOB = 3
 
284
         RETURN
 
285
*
 
286
*****************
 
287
 4       CONTINUE
 
288
*****************
 
289
*
 
290
*********CALL PSOLVE( WORK( 1,W ), WORK( 1,AV ) )
 
291
*
 
292
         NDX1 = ((W  - 1) * LDW) + 1
 
293
         NDX2 = ((AV - 1) * LDW) + 1
 
294
*        Prepare for return & return
 
295
         RLBL = 5
 
296
         IJOB = 2
 
297
         RETURN
 
298
*
 
299
*****************
 
300
 5       CONTINUE
 
301
*****************
 
302
*
 
303
*           Construct I-th column of H so that it is orthnormal to 
 
304
*           the previous I-1 columns.
 
305
*
 
306
            CALL <_c>ORTHOH( I, N, WORK2( 1,I+H-1 ), WORK( 1,V ), LDW,
 
307
     $                   WORK( 1,W ) )
 
308
*
 
309
            IF ( I.GT.0 )
 
310
*
 
311
*              Apply Givens rotations to the I-th column of H. This
 
312
*              effectively reduces the Hessenberg matrix to upper
 
313
*              triangular form during the RESTRT iterations.
 
314
*
 
315
     $         CALL <_c>APPLYGIVENS(I, WORK2( 1,I+H-1 ), WORK2( 1,GIV ),
 
316
     $                           LDW2 )
 
317
*
 
318
*           Approxiyate residual norm. Check tolerance. If okay, compute
 
319
*           final approximation vector X and quit.
 
320
*
 
321
            RESID = <rc>APPROXRES( I, WORK2( 1,I+H-1 ), WORK( 1,S ),
 
322
     $                         WORK2( 1,GIV ), LDW2 ) / BNRM2
 
323
            IF ( RESID.LE.TOL ) THEN
 
324
               CALL <_c>UPDATE(I, N, X, WORK2( 1,H ), LDW2, 
 
325
     $                     WORK(1,Y), WORK(1,S), WORK( 1,V ), LDW)
 
326
               GO TO 200
 
327
            ENDIF
 
328
            i = i + 1
 
329
            go to 49
 
330
   50    CONTINUE
 
331
         i = restrt
 
332
*
 
333
*        Compute current solution vector X.
 
334
*
 
335
         CALL <_c>UPDATE(RESTRT, N, X, WORK2( 1,H ), LDW2,
 
336
     $               WORK(1,Y), WORK( 1,S ), WORK( 1,V ), LDW )
 
337
*
 
338
*        Compute residual vector R, find norm,
 
339
*        then check for tolerance.
 
340
*
 
341
         CALL <_c>COPY( N, B, 1, WORK( 1,R ), 1 )
 
342
*********CALL MATVEC( -ONE, X, ONE, WORK( 1,R ) )
 
343
*
 
344
         NDX1 = -1
 
345
         NDX2 = ((R - 1) * LDW) + 1
 
346
*        Prepare for return & return
 
347
         SCLR1 = -ONE
 
348
         SCLR2 = ONE
 
349
         RLBL = 6
 
350
         IJOB = 1
 
351
         RETURN
 
352
*
 
353
*****************
 
354
 6       CONTINUE
 
355
*****************
 
356
*
 
357
         WORK( I+1,S ) = <rc>NRM2( N, WORK( 1,R ), 1 )
 
358
*
 
359
*********RESID = WORK( I+1,S ) / BNRM2
 
360
*********IF ( RESID.LE.TOL  ) GO TO 200
 
361
*
 
362
         NDX1 = NEED1
 
363
         NDX2 = NEED2
 
364
*        Prepare for resumption & return
 
365
         RLBL = 7
 
366
         IJOB = 4
 
367
         RETURN
 
368
*
 
369
*****************
 
370
 7       CONTINUE
 
371
*****************
 
372
         IF( INFO.EQ.1 ) GO TO 200
 
373
*
 
374
         IF ( ITER.EQ.MAXIT ) THEN
 
375
            INFO = 1
 
376
            GO TO 100
 
377
         ENDIF
 
378
*
 
379
         GO TO 10
 
380
*
 
381
  100 CONTINUE
 
382
*
 
383
*     Iteration fails.
 
384
*
 
385
      RLBL = -1
 
386
      IJOB = -1
 
387
      RETURN
 
388
*
 
389
  200 CONTINUE
 
390
*
 
391
*     Iteration successful; return.
 
392
*
 
393
      INFO = 0
 
394
      RLBL = -1
 
395
      IJOB = -1
 
396
 
 
397
      RETURN
 
398
*
 
399
*     End of GMRESREVCOM
 
400
*
 
401
      END SUBROUTINE <_c>GMRESREVCOM
 
402
*
 
403
*     =========================================================
 
404
      SUBROUTINE <_c>ORTHOH( I, N, H, V, LDV, W )
 
405
*
 
406
      INTEGER            I, N, LDV
 
407
      <_t>   H( * ), W( * ), V( LDV,* )
 
408
*
 
409
*     Construct the I-th column of the upper Hessenberg matrix H
 
410
*     using the Gram-Schmidt process on V and W.
 
411
*
 
412
      INTEGER            K
 
413
      <rt=real,double precision,real,double precision>    
 
414
     $     <rc=s,d,sc,dz>NRM2, ONE
 
415
      PARAMETER        ( ONE = 1.0D+0 )
 
416
      <_t>    <xdot=sdot,ddot,cdotc,zdotc>
 
417
      EXTERNAL         <_c>AXPY, <_c>COPY, <xdot>, <rc>NRM2, <_c>SCAL
 
418
*
 
419
      DO 10 K = 1, I
 
420
         H( K ) = <xdot>( N, V( 1,K ), 1, W, 1 )
 
421
         CALL <_c>AXPY( N, -H( K ), V( 1,K ), 1, W, 1 )
 
422
   10 CONTINUE
 
423
      H( I+1 ) = <rc>NRM2( N, W, 1 )
 
424
      CALL <_c>COPY( N, W, 1, V( 1,I+1 ), 1 )
 
425
      CALL <_c>SCAL( N, ONE / H( I+1 ), V( 1,I+1 ), 1 )
 
426
*
 
427
      RETURN
 
428
*
 
429
      END SUBROUTINE <_c>ORTHOH
 
430
*     =========================================================
 
431
      SUBROUTINE <_c>APPLYGIVENS( I, H, GIVENS, LDG )
 
432
*
 
433
      INTEGER            I, LDG
 
434
      <_t>   H( * ), GIVENS( LDG,* )
 
435
*
 
436
*     This routine applies a sequence of I-1 Givens rotations to
 
437
*     the I-th column of H. The Givens parameters are stored, so that
 
438
*     the first I-2 Givens rotation matrices are known. The I-1st
 
439
*     Givens rotation is computed using BLAS 1 routine DROTG. Each
 
440
*     rotation is applied to the 2x1 vector [H( J ), H( J+1 )]',
 
441
*     which results in H( J+1 ) = 0.
 
442
*
 
443
      INTEGER            J
 
444
*      DOUBLE PRECISION   TEMP
 
445
      EXTERNAL           <_c>ROTG
 
446
*
 
447
*     .. Executable Statements ..
 
448
*
 
449
*     Construct I-1st rotation matrix.
 
450
*
 
451
*     CALL <_c>ROTG( H( I ), H( I+1 ), GIVENS( I,1 ), GIVENS( I,2 ) )
 
452
*      CALL <_c>GETGIV( H( I ), H( I+1 ), GIVENS( I,1 ), GIVENS( I,2 ) )
 
453
*
 
454
*     Apply 1,...,I-1st rotation matrices to the I-th column of H.
 
455
*
 
456
      DO 10 J = 1, I-1
 
457
         CALL <_c>ROTVEC(H( J ), H( J+1 ), GIVENS( J,1 ), GIVENS( J,2 ))
 
458
*        TEMP     =  GIVENS( J,1 ) * H( J ) + GIVENS( J,2 ) * H( J+1 ) 
 
459
*        H( J+1 ) = -GIVENS( J,2 ) * H( J ) + GIVENS( J,1 ) * H( J+1 )
 
460
*        H( J ) = TEMP
 
461
 10   CONTINUE
 
462
      call <_c>getgiv( H( I ), H( I+1 ), GIVENS( I,1 ), GIVENS( I,2 ) )
 
463
      call <_c>rotvec( H( I ), H( I+1 ), GIVENS( I,1 ), GIVENS( I,2 ) )
 
464
*
 
465
      RETURN
 
466
*
 
467
      END SUBROUTINE <_c>APPLYGIVENS
 
468
*
 
469
*     ===============================================================
 
470
      <rt=real,double precision,real,double precision>
 
471
     $     FUNCTION <rc=s,d,sc,dz>APPROXRES( I, H, S, GIVENS, LDG )
 
472
*
 
473
      INTEGER            I, LDG
 
474
      <_t>   H( * ), S( * ), GIVENS( LDG,* )
 
475
*
 
476
*     This func allows the user to approximate the residual
 
477
*     using an updating scheme involving Givens rotations. The
 
478
*     rotation matrix is formed using [H( I ),H( I+1 )]' with the
 
479
*     intent of zeroing H( I+1 ), but here is applied to the 2x1
 
480
*     vector [S(I), S(I+1)]'.
 
481
*
 
482
      INTRINSIC          ABS
 
483
      EXTERNAL           <_c>ROTG
 
484
*
 
485
*     .. Executable Statements ..
 
486
*
 
487
*     CALL <_c>ROTG( H( I ), H( I+1 ), GIVENS( I,1 ), GIVENS( I,2 ) )
 
488
*      CALL <_c>GETGIV( H( I ), H( I+1 ), GIVENS( I,1 ), GIVENS( I,2 ) )
 
489
      CALL <_c>ROTVEC( S( I ), S( I+1 ), GIVENS( I,1 ), GIVENS( I,2 ) )
 
490
*
 
491
      <rc>APPROXRES = ABS( S( I+1 ) )
 
492
*
 
493
      RETURN
 
494
*
 
495
      END FUNCTION <rc>APPROXRES
 
496
*     ===============================================================
 
497
      SUBROUTINE <_c>UPDATE( I, N, X, H, LDH, Y, S, V, LDV )
 
498
*
 
499
      INTEGER            N, I, J, LDH, LDV
 
500
      <_t>   X( * ), Y( * ), S( * ), H( LDH,* ), V( LDV,* )
 
501
      EXTERNAL           <_c>AXPY, <_c>COPY, <_c>TRSV
 
502
*
 
503
*     Solve H*y = s for upper triangualar H.
 
504
*
 
505
      CALL <_c>COPY( I, S, 1, Y, 1 )
 
506
      CALL <_c>TRSV( 'UPPER', 'NOTRANS', 'NONUNIT', I, H, LDH, Y, 1 )
 
507
*
 
508
*     Compute current solution vector X.
 
509
*
 
510
      DO 10 J = 1, I
 
511
         CALL <_c>AXPY( N, Y( J ), V( 1,J ), 1, X, 1 )
 
512
   10 CONTINUE
 
513
*
 
514
      RETURN
 
515
*
 
516
      END SUBROUTINE <_c>UPDATE
 
517
*
 
518
*     ===============================================================
 
519
      SUBROUTINE <_c>GETGIV( A, B, C, S )
 
520
*
 
521
      <_t>   A, B, C, S, TEMP, ZERO, ONE
 
522
      PARAMETER  ( 
 
523
     $     ZERO = 0.0, 
 
524
     $     ONE = 1.0 )
 
525
*
 
526
      IF ( ABS( B ).EQ.ZERO ) THEN
 
527
         C = ONE
 
528
         S = ZERO
 
529
      ELSE IF ( ABS( B ).GT.ABS( A ) ) THEN
 
530
         TEMP = -A / B
 
531
         S = ONE / SQRT( ONE + abs(TEMP)**2 )
 
532
         C = TEMP * S
 
533
*         S = b / SQRT( abs(a)**2 + abs(b)**2 )
 
534
*         C = -a / SQRT( abs(a)**2 + abs(b)**2 )
 
535
      ELSE
 
536
         TEMP = -B / A
 
537
         C = ONE / SQRT( ONE + abs(TEMP)**2 )
 
538
         S = TEMP * C
 
539
*         S = -b / SQRT( abs(a)**2 + abs(b)**2 )
 
540
*         C = a / SQRT( abs(a)**2 + abs(b)**2 )
 
541
      ENDIF
 
542
*
 
543
      RETURN
 
544
*
 
545
      END SUBROUTINE <_c>GETGIV
 
546
*
 
547
*     ================================================================
 
548
      SUBROUTINE <_c>ROTVEC( X, Y, C, S )
 
549
*
 
550
      <_t>   X, Y, C, S, TEMP
 
551
 
 
552
*
 
553
      TEMP = <co= , ,conjg,conjg>(C) * X - <co>(S) * Y
 
554
      Y    = S * X + C * Y
 
555
      X    = TEMP
 
556
*
 
557
      RETURN
 
558
*
 
559
      END SUBROUTINE <_c>ROTVEC
 
560
*
 
561
*     ===============================================================
 
562
      SUBROUTINE <_c>ELEMVEC( I, N, ALPHA, E )
 
563
*
 
564
*     Construct the I-th elementary vector E, scaled by ALPHA.
 
565
*
 
566
      INTEGER            I, J, N
 
567
      <_t>   ALPHA, E( * )
 
568
*
 
569
*     .. Parameters ..
 
570
      <rt=real,double precision,real,double precision>   ZERO
 
571
      PARAMETER        ( ZERO = 0.0D+0 )
 
572
*
 
573
      DO 10 J = 1, N
 
574
         E( J ) = ZERO
 
575
   10 CONTINUE
 
576
      E( I ) = ALPHA
 
577
*
 
578
      RETURN
 
579
*
 
580
      END SUBROUTINE <_c>ELEMVEC
 
581