118
119
120
121
122
123
124 CHARACTER UPLO
125 INTEGER INFO, LDA, N, NB
126
127
128 INTEGER IPIV( * )
129 DOUBLE PRECISION A( LDA, * ), WORK( N+NB+1,* )
130
131
132
133
134
135 DOUBLE PRECISION ONE, ZERO
136 parameter( one = 1.0d+0, zero = 0.0d+0 )
137
138
139 LOGICAL UPPER
140 INTEGER I, IINFO, IP, K, CUT, NNB
141 INTEGER COUNT
142 INTEGER J, U11, INVD
143
144 DOUBLE PRECISION AK, AKKP1, AKP1, D, T
145 DOUBLE PRECISION U01_I_J, U01_IP1_J
146 DOUBLE PRECISION U11_I_J, U11_IP1_J
147
148
149 LOGICAL LSAME
151
152
155
156
157 INTRINSIC max
158
159
160
161
162
163 info = 0
164 upper =
lsame( uplo,
'U' )
165 IF( .NOT.upper .AND. .NOT.
lsame( uplo,
'L' ) )
THEN
166 info = -1
167 ELSE IF( n.LT.0 ) THEN
168 info = -2
169 ELSE IF( lda.LT.max( 1, n ) ) THEN
170 info = -4
171 END IF
172
173
174
175
176 IF( info.NE.0 ) THEN
177 CALL xerbla(
'DSYTRI2X', -info )
178 RETURN
179 END IF
180 IF( n.EQ.0 )
181 $ RETURN
182
183
184
185
186 CALL dsyconv( uplo,
'C', n, a, lda, ipiv, work, iinfo )
187
188
189
190 IF( upper ) THEN
191
192
193
194 DO info = n, 1, -1
195 IF( ipiv( info ).GT.0 .AND. a( info, info ).EQ.zero )
196 $ RETURN
197 END DO
198 ELSE
199
200
201
202 DO info = 1, n
203 IF( ipiv( info ).GT.0 .AND. a( info, info ).EQ.zero )
204 $ RETURN
205 END DO
206 END IF
207 info = 0
208
209
210
211
212
213
214 u11 = n
215
216
217 invd = nb+2
218
219 IF( upper ) THEN
220
221
222
223 CALL dtrtri( uplo,
'U', n, a, lda, info )
224
225
226
227 k=1
228 DO WHILE ( k .LE. n )
229 IF( ipiv( k ).GT.0 ) THEN
230
231 work(k,invd) = one / a( k, k )
232 work(k,invd+1) = 0
233 k=k+1
234 ELSE
235
236 t = work(k+1,1)
237 ak = a( k, k ) / t
238 akp1 = a( k+1, k+1 ) / t
239 akkp1 = work(k+1,1) / t
240 d = t*( ak*akp1-one )
241 work(k,invd) = akp1 / d
242 work(k+1,invd+1) = ak / d
243 work(k,invd+1) = -akkp1 / d
244 work(k+1,invd) = -akkp1 / d
245 k=k+2
246 END IF
247 END DO
248
249
250
251
252
253 cut=n
254 DO WHILE (cut .GT. 0)
255 nnb=nb
256 IF (cut .LE. nnb) THEN
257 nnb=cut
258 ELSE
259 count = 0
260
261 DO i=cut+1-nnb,cut
262 IF (ipiv(i) .LT. 0) count=count+1
263 END DO
264
265 IF (mod(count,2) .EQ. 1) nnb=nnb+1
266 END IF
267
268 cut=cut-nnb
269
270
271
272 DO i=1,cut
273 DO j=1,nnb
274 work(i,j)=a(i,cut+j)
275 END DO
276 END DO
277
278
279
280 DO i=1,nnb
281 work(u11+i,i)=one
282 DO j=1,i-1
283 work(u11+i,j)=zero
284 END DO
285 DO j=i+1,nnb
286 work(u11+i,j)=a(cut+i,cut+j)
287 END DO
288 END DO
289
290
291
292 i=1
293 DO WHILE (i .LE. cut)
294 IF (ipiv(i) > 0) THEN
295 DO j=1,nnb
296 work(i,j)=work(i,invd)*work(i,j)
297 END DO
298 i=i+1
299 ELSE
300 DO j=1,nnb
301 u01_i_j = work(i,j)
302 u01_ip1_j = work(i+1,j)
303 work(i,j)=work(i,invd)*u01_i_j+
304 $ work(i,invd+1)*u01_ip1_j
305 work(i+1,j)=work(i+1,invd)*u01_i_j+
306 $ work(i+1,invd+1)*u01_ip1_j
307 END DO
308 i=i+2
309 END IF
310 END DO
311
312
313
314 i=1
315 DO WHILE (i .LE. nnb)
316 IF (ipiv(cut+i) > 0) THEN
317 DO j=i,nnb
318 work(u11+i,j)=work(cut+i,invd)*work(u11+i,j)
319 END DO
320 i=i+1
321 ELSE
322 DO j=i,nnb
323 u11_i_j = work(u11+i,j)
324 u11_ip1_j = work(u11+i+1,j)
325 work(u11+i,j)=work(cut+i,invd)*work(u11+i,j) +
326 $ work(cut+i,invd+1)*work(u11+i+1,j)
327 work(u11+i+1,j)=work(cut+i+1,invd)*u11_i_j+
328 $ work(cut+i+1,invd+1)*u11_ip1_j
329 END DO
330 i=i+2
331 END IF
332 END DO
333
334
335
336 CALL dtrmm(
'L',
'U',
'T',
'U',nnb, nnb,
337 $ one,a(cut+1,cut+1),lda,work(u11+1,1),n+nb+1)
338
339 DO i=1,nnb
340 DO j=i,nnb
341 a(cut+i,cut+j)=work(u11+i,j)
342 END DO
343 END DO
344
345
346
347 CALL dgemm(
'T',
'N',nnb,nnb,cut,one,a(1,cut+1),lda,
348 $ work,n+nb+1, zero, work(u11+1,1), n+nb+1)
349
350
351
352
353 DO i=1,nnb
354 DO j=i,nnb
355 a(cut+i,cut+j)=a(cut+i,cut+j)+work(u11+i,j)
356 END DO
357 END DO
358
359
360
361 CALL dtrmm(
'L',uplo,
'T',
'U',cut, nnb,
362 $ one,a,lda,work,n+nb+1)
363
364
365
366
367 DO i=1,cut
368 DO j=1,nnb
369 a(i,cut+j)=work(i,j)
370 END DO
371 END DO
372
373
374
375 END DO
376
377
378
379 i=1
380 DO WHILE ( i .LE. n )
381 IF( ipiv(i) .GT. 0 ) THEN
382 ip=ipiv(i)
383 IF (i .LT. ip)
CALL dsyswapr( uplo, n, a, lda, i ,
384 $ ip )
385 IF (i .GT. ip)
CALL dsyswapr( uplo, n, a, lda, ip ,
386 $ i )
387 ELSE
388 ip=-ipiv(i)
389 i=i+1
390 IF ( (i-1) .LT. ip)
391 $
CALL dsyswapr( uplo, n, a, lda, i-1 ,ip )
392 IF ( (i-1) .GT. ip)
393 $
CALL dsyswapr( uplo, n, a, lda, ip ,i-1 )
394 ENDIF
395 i=i+1
396 END DO
397 ELSE
398
399
400
401
402
403 CALL dtrtri( uplo,
'U', n, a, lda, info )
404
405
406
407 k=n
408 DO WHILE ( k .GE. 1 )
409 IF( ipiv( k ).GT.0 ) THEN
410
411 work(k,invd) = one / a( k, k )
412 work(k,invd+1) = 0
413 k=k-1
414 ELSE
415
416 t = work(k-1,1)
417 ak = a( k-1, k-1 ) / t
418 akp1 = a( k, k ) / t
419 akkp1 = work(k-1,1) / t
420 d = t*( ak*akp1-one )
421 work(k-1,invd) = akp1 / d
422 work(k,invd) = ak / d
423 work(k,invd+1) = -akkp1 / d
424 work(k-1,invd+1) = -akkp1 / d
425 k=k-2
426 END IF
427 END DO
428
429
430
431
432
433 cut=0
434 DO WHILE (cut .LT. n)
435 nnb=nb
436 IF (cut + nnb .GT. n) THEN
437 nnb=n-cut
438 ELSE
439 count = 0
440
441 DO i=cut+1,cut+nnb
442 IF (ipiv(i) .LT. 0) count=count+1
443 END DO
444
445 IF (mod(count,2) .EQ. 1) nnb=nnb+1
446 END IF
447
448 DO i=1,n-cut-nnb
449 DO j=1,nnb
450 work(i,j)=a(cut+nnb+i,cut+j)
451 END DO
452 END DO
453
454 DO i=1,nnb
455 work(u11+i,i)=one
456 DO j=i+1,nnb
457 work(u11+i,j)=zero
458 END DO
459 DO j=1,i-1
460 work(u11+i,j)=a(cut+i,cut+j)
461 END DO
462 END DO
463
464
465
466 i=n-cut-nnb
467 DO WHILE (i .GE. 1)
468 IF (ipiv(cut+nnb+i) > 0) THEN
469 DO j=1,nnb
470 work(i,j)=work(cut+nnb+i,invd)*work(i,j)
471 END DO
472 i=i-1
473 ELSE
474 DO j=1,nnb
475 u01_i_j = work(i,j)
476 u01_ip1_j = work(i-1,j)
477 work(i,j)=work(cut+nnb+i,invd)*u01_i_j+
478 $ work(cut+nnb+i,invd+1)*u01_ip1_j
479 work(i-1,j)=work(cut+nnb+i-1,invd+1)*u01_i_j+
480 $ work(cut+nnb+i-1,invd)*u01_ip1_j
481 END DO
482 i=i-2
483 END IF
484 END DO
485
486
487
488 i=nnb
489 DO WHILE (i .GE. 1)
490 IF (ipiv(cut+i) > 0) THEN
491 DO j=1,nnb
492 work(u11+i,j)=work(cut+i,invd)*work(u11+i,j)
493 END DO
494 i=i-1
495 ELSE
496 DO j=1,nnb
497 u11_i_j = work(u11+i,j)
498 u11_ip1_j = work(u11+i-1,j)
499 work(u11+i,j)=work(cut+i,invd)*work(u11+i,j) +
500 $ work(cut+i,invd+1)*u11_ip1_j
501 work(u11+i-1,j)=work(cut+i-1,invd+1)*u11_i_j+
502 $ work(cut+i-1,invd)*u11_ip1_j
503 END DO
504 i=i-2
505 END IF
506 END DO
507
508
509
510 CALL dtrmm(
'L',uplo,
'T',
'U',nnb, nnb,
511 $ one,a(cut+1,cut+1),lda,work(u11+1,1),n+nb+1)
512
513
514 DO i=1,nnb
515 DO j=1,i
516 a(cut+i,cut+j)=work(u11+i,j)
517 END DO
518 END DO
519
520 IF ( (cut+nnb) .LT. n ) THEN
521
522
523
524 CALL dgemm(
'T',
'N',nnb,nnb,n-nnb-cut,one,a(cut+nnb+1,cut+1)
525 $ ,lda,work,n+nb+1, zero, work(u11+1,1), n+nb+1)
526
527
528
529
530 DO i=1,nnb
531 DO j=1,i
532 a(cut+i,cut+j)=a(cut+i,cut+j)+work(u11+i,j)
533 END DO
534 END DO
535
536
537
538 CALL dtrmm(
'L',uplo,
'T',
'U', n-nnb-cut, nnb,
539 $ one,a(cut+nnb+1,cut+nnb+1),lda,work,n+nb+1)
540
541
542
543 DO i=1,n-cut-nnb
544 DO j=1,nnb
545 a(cut+nnb+i,cut+j)=work(i,j)
546 END DO
547 END DO
548
549 ELSE
550
551
552
553 DO i=1,nnb
554 DO j=1,i
555 a(cut+i,cut+j)=work(u11+i,j)
556 END DO
557 END DO
558 END IF
559
560
561
562 cut=cut+nnb
563 END DO
564
565
566
567 i=n
568 DO WHILE ( i .GE. 1 )
569 IF( ipiv(i) .GT. 0 ) THEN
570 ip=ipiv(i)
571 IF (i .LT. ip)
CALL dsyswapr( uplo, n, a, lda, i ,
572 $ ip )
573 IF (i .GT. ip)
CALL dsyswapr( uplo, n, a, lda, ip ,
574 $ i )
575 ELSE
576 ip=-ipiv(i)
577 IF ( i .LT. ip)
CALL dsyswapr( uplo, n, a, lda, i ,
578 $ ip )
579 IF ( i .GT. ip)
CALL dsyswapr( uplo, n, a, lda, ip,
580 $ i )
581 i=i-1
582 ENDIF
583 i=i-1
584 END DO
585 END IF
586
587 RETURN
588
589
590
subroutine xerbla(srname, info)
subroutine dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
subroutine dsyswapr(uplo, n, a, lda, i1, i2)
DSYSWAPR applies an elementary permutation on the rows and columns of a symmetric matrix.
logical function lsame(ca, cb)
LSAME
subroutine dsyconv(uplo, way, n, a, lda, ipiv, e, info)
DSYCONV
subroutine dtrmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
DTRMM
subroutine dtrtri(uplo, diag, n, a, lda, info)
DTRTRI