LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches

◆ ssytrf_aa()

subroutine ssytrf_aa ( character uplo,
integer n,
real, dimension( lda, * ) a,
integer lda,
integer, dimension( * ) ipiv,
real, dimension( * ) work,
integer lwork,
integer info )

SSYTRF_AA

Download SSYTRF_AA + dependencies [TGZ] [ZIP] [TXT]

Purpose:
!>
!> SSYTRF_AA computes the factorization of a real symmetric matrix A
!> using the Aasen's algorithm.  The form of the factorization is
!>
!>    A = U**T*T*U  or  A = L*T*L**T
!>
!> where U (or L) is a product of permutation and unit upper (lower)
!> triangular matrices, and T is a symmetric tridiagonal matrix.
!>
!> This is the blocked version of the algorithm, calling Level 3 BLAS.
!> 
Parameters
[in]UPLO
!>          UPLO is CHARACTER*1
!>          = 'U':  Upper triangle of A is stored;
!>          = 'L':  Lower triangle of A is stored.
!> 
[in]N
!>          N is INTEGER
!>          The order of the matrix A.  N >= 0.
!> 
[in,out]A
!>          A is REAL array, dimension (LDA,N)
!>          On entry, the symmetric matrix A.  If UPLO = 'U', the leading
!>          N-by-N upper triangular part of A contains the upper
!>          triangular part of the matrix A, and the strictly lower
!>          triangular part of A is not referenced.  If UPLO = 'L', the
!>          leading N-by-N lower triangular part of A contains the lower
!>          triangular part of the matrix A, and the strictly upper
!>          triangular part of A is not referenced.
!>
!>          On exit, the tridiagonal matrix is stored in the diagonals
!>          and the subdiagonals of A just below (or above) the diagonals,
!>          and L is stored below (or above) the subdiagonals, when UPLO
!>          is 'L' (or 'U').
!> 
[in]LDA
!>          LDA is INTEGER
!>          The leading dimension of the array A.  LDA >= max(1,N).
!> 
[out]IPIV
!>          IPIV is INTEGER array, dimension (N)
!>          On exit, it contains the details of the interchanges, i.e.,
!>          the row and column k of A were interchanged with the
!>          row and column IPIV(k).
!> 
[out]WORK
!>          WORK is REAL array, dimension (MAX(1,LWORK))
!>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
!> 
[in]LWORK
!>          LWORK is INTEGER
!>          The length of WORK.
!>          LWORK >= 1, if N <= 1, and LWORK >= 2*N, otherwise.
!>          For optimum performance LWORK >= N*(1+NB), where NB is
!>          the optimal blocksize, returned by ILAENV.
!>
!>          If LWORK = -1, then a workspace query is assumed; the routine
!>          only calculates the optimal size of the WORK array, returns
!>          this value as the first entry of the WORK array, and no error
!>          message related to LWORK is issued by XERBLA.
!> 
[out]INFO
!>          INFO is INTEGER
!>          = 0:  successful exit
!>          < 0:  if INFO = -i, the i-th argument had an illegal value.
!> 
Author
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.

Definition at line 131 of file ssytrf_aa.f.

133*
134* -- LAPACK computational routine --
135* -- LAPACK is a software package provided by Univ. of Tennessee, --
136* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
137*
138 IMPLICIT NONE
139*
140* .. Scalar Arguments ..
141 CHARACTER UPLO
142 INTEGER N, LDA, LWORK, INFO
143* ..
144* .. Array Arguments ..
145 INTEGER IPIV( * )
146 REAL A( LDA, * ), WORK( * )
147* ..
148*
149* =====================================================================
150* .. Parameters ..
151 REAL ZERO, ONE
152 parameter( zero = 0.0e+0, one = 1.0e+0 )
153*
154* .. Local Scalars ..
155 LOGICAL LQUERY, UPPER
156 INTEGER J, LWKMIN, LWKOPT
157 INTEGER NB, MJ, NJ, K1, K2, J1, J2, J3, JB
158 REAL ALPHA
159* ..
160* .. External Functions ..
161 LOGICAL LSAME
162 INTEGER ILAENV
163 REAL SROUNDUP_LWORK
164 EXTERNAL lsame, ilaenv, sroundup_lwork
165* ..
166* .. External Subroutines ..
167 EXTERNAL slasyf_aa, sgemv, sscal, scopy, sswap,
168 $ sgemm,
169 $ xerbla
170* ..
171* .. Intrinsic Functions ..
172 INTRINSIC max
173* ..
174* .. Executable Statements ..
175*
176* Determine the block size
177*
178 nb = ilaenv( 1, 'SSYTRF_AA', uplo, n, -1, -1, -1 )
179*
180* Test the input parameters.
181*
182 info = 0
183 upper = lsame( uplo, 'U' )
184 lquery = ( lwork.EQ.-1 )
185 IF( n.LE.1 ) THEN
186 lwkmin = 1
187 lwkopt = 1
188 ELSE
189 lwkmin = 2*n
190 lwkopt = (nb+1)*n
191 END IF
192*
193 IF( .NOT.upper .AND. .NOT.lsame( uplo, 'L' ) ) THEN
194 info = -1
195 ELSE IF( n.LT.0 ) THEN
196 info = -2
197 ELSE IF( lda.LT.max( 1, n ) ) THEN
198 info = -4
199 ELSE IF( lwork.LT.lwkmin .AND. .NOT.lquery ) THEN
200 info = -7
201 END IF
202*
203 IF( info.EQ.0 ) THEN
204 work( 1 ) = sroundup_lwork( lwkopt )
205 END IF
206*
207 IF( info.NE.0 ) THEN
208 CALL xerbla( 'SSYTRF_AA', -info )
209 RETURN
210 ELSE IF( lquery ) THEN
211 RETURN
212 END IF
213*
214* Quick return
215*
216 IF( n.EQ.0 ) THEN
217 RETURN
218 ENDIF
219 ipiv( 1 ) = 1
220 IF( n.EQ.1 ) THEN
221 RETURN
222 END IF
223*
224* Adjust block size based on the workspace size
225*
226 IF( lwork.LT.((1+nb)*n) ) THEN
227 nb = ( lwork-n ) / n
228 END IF
229*
230 IF( upper ) THEN
231*
232* .....................................................
233* Factorize A as U**T*D*U using the upper triangle of A
234* .....................................................
235*
236* Copy first row A(1, 1:N) into H(1:n) (stored in WORK(1:N))
237*
238 CALL scopy( n, a( 1, 1 ), lda, work( 1 ), 1 )
239*
240* J is the main loop index, increasing from 1 to N in steps of
241* JB, where JB is the number of columns factorized by SLASYF;
242* JB is either NB, or N-J+1 for the last block
243*
244 j = 0
245 10 CONTINUE
246 IF( j.GE.n )
247 $ GO TO 20
248*
249* each step of the main loop
250* J is the last column of the previous panel
251* J1 is the first column of the current panel
252* K1 identifies if the previous column of the panel has been
253* explicitly stored, e.g., K1=1 for the first panel, and
254* K1=0 for the rest
255*
256 j1 = j + 1
257 jb = min( n-j1+1, nb )
258 k1 = max(1, j)-j
259*
260* Panel factorization
261*
262 CALL slasyf_aa( uplo, 2-k1, n-j, jb,
263 $ a( max(1, j), j+1 ), lda,
264 $ ipiv( j+1 ), work, n, work( n*nb+1 ) )
265*
266* Adjust IPIV and apply it back (J-th step picks (J+1)-th pivot)
267*
268 DO j2 = j+2, min(n, j+jb+1)
269 ipiv( j2 ) = ipiv( j2 ) + j
270 IF( (j2.NE.ipiv(j2)) .AND. ((j1-k1).GT.2) ) THEN
271 CALL sswap( j1-k1-2, a( 1, j2 ), 1,
272 $ a( 1, ipiv(j2) ), 1 )
273 END IF
274 END DO
275 j = j + jb
276*
277* Trailing submatrix update, where
278* the row A(J1-1, J2-1:N) stores U(J1, J2+1:N) and
279* WORK stores the current block of the auxiriarly matrix H
280*
281 IF( j.LT.n ) THEN
282*
283* If first panel and JB=1 (NB=1), then nothing to do
284*
285 IF( j1.GT.1 .OR. jb.GT.1 ) THEN
286*
287* Merge rank-1 update with BLAS-3 update
288*
289 alpha = a( j, j+1 )
290 a( j, j+1 ) = one
291 CALL scopy( n-j, a( j-1, j+1 ), lda,
292 $ work( (j+1-j1+1)+jb*n ), 1 )
293 CALL sscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1 )
294*
295* K1 identifies if the previous column of the panel has been
296* explicitly stored, e.g., K1=1 and K2= 0 for the first panel,
297* while K1=0 and K2=1 for the rest
298*
299 IF( j1.GT.1 ) THEN
300*
301* Not first panel
302*
303 k2 = 1
304 ELSE
305*
306* First panel
307*
308 k2 = 0
309*
310* First update skips the first column
311*
312 jb = jb - 1
313 END IF
314*
315 DO j2 = j+1, n, nb
316 nj = min( nb, n-j2+1 )
317*
318* Update (J2, J2) diagonal block with SGEMV
319*
320 j3 = j2
321 DO mj = nj-1, 1, -1
322 CALL sgemv( 'No transpose', mj, jb+1,
323 $ -one, work( j3-j1+1+k1*n ), n,
324 $ a( j1-k2, j3 ), 1,
325 $ one, a( j3, j3 ), lda )
326 j3 = j3 + 1
327 END DO
328*
329* Update off-diagonal block of J2-th block row with SGEMM
330*
331 CALL sgemm( 'Transpose', 'Transpose',
332 $ nj, n-j3+1, jb+1,
333 $ -one, a( j1-k2, j2 ), lda,
334 $ work( j3-j1+1+k1*n ), n,
335 $ one, a( j2, j3 ), lda )
336 END DO
337*
338* Recover T( J, J+1 )
339*
340 a( j, j+1 ) = alpha
341 END IF
342*
343* WORK(J+1, 1) stores H(J+1, 1)
344*
345 CALL scopy( n-j, a( j+1, j+1 ), lda, work( 1 ), 1 )
346 END IF
347 GO TO 10
348 ELSE
349*
350* .....................................................
351* Factorize A as L*D*L**T using the lower triangle of A
352* .....................................................
353*
354* copy first column A(1:N, 1) into H(1:N, 1)
355* (stored in WORK(1:N))
356*
357 CALL scopy( n, a( 1, 1 ), 1, work( 1 ), 1 )
358*
359* J is the main loop index, increasing from 1 to N in steps of
360* JB, where JB is the number of columns factorized by SLASYF;
361* JB is either NB, or N-J+1 for the last block
362*
363 j = 0
364 11 CONTINUE
365 IF( j.GE.n )
366 $ GO TO 20
367*
368* each step of the main loop
369* J is the last column of the previous panel
370* J1 is the first column of the current panel
371* K1 identifies if the previous column of the panel has been
372* explicitly stored, e.g., K1=1 for the first panel, and
373* K1=0 for the rest
374*
375 j1 = j+1
376 jb = min( n-j1+1, nb )
377 k1 = max(1, j)-j
378*
379* Panel factorization
380*
381 CALL slasyf_aa( uplo, 2-k1, n-j, jb,
382 $ a( j+1, max(1, j) ), lda,
383 $ ipiv( j+1 ), work, n, work( n*nb+1 ) )
384*
385* Adjust IPIV and apply it back (J-th step picks (J+1)-th pivot)
386*
387 DO j2 = j+2, min(n, j+jb+1)
388 ipiv( j2 ) = ipiv( j2 ) + j
389 IF( (j2.NE.ipiv(j2)) .AND. ((j1-k1).GT.2) ) THEN
390 CALL sswap( j1-k1-2, a( j2, 1 ), lda,
391 $ a( ipiv(j2), 1 ), lda )
392 END IF
393 END DO
394 j = j + jb
395*
396* Trailing submatrix update, where
397* A(J2+1, J1-1) stores L(J2+1, J1) and
398* WORK(J2+1, 1) stores H(J2+1, 1)
399*
400 IF( j.LT.n ) THEN
401*
402* if first panel and JB=1 (NB=1), then nothing to do
403*
404 IF( j1.GT.1 .OR. jb.GT.1 ) THEN
405*
406* Merge rank-1 update with BLAS-3 update
407*
408 alpha = a( j+1, j )
409 a( j+1, j ) = one
410 CALL scopy( n-j, a( j+1, j-1 ), 1,
411 $ work( (j+1-j1+1)+jb*n ), 1 )
412 CALL sscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1 )
413*
414* K1 identifies if the previous column of the panel has been
415* explicitly stored, e.g., K1=1 and K2= 0 for the first panel,
416* while K1=0 and K2=1 for the rest
417*
418 IF( j1.GT.1 ) THEN
419*
420* Not first panel
421*
422 k2 = 1
423 ELSE
424*
425* First panel
426*
427 k2 = 0
428*
429* First update skips the first column
430*
431 jb = jb - 1
432 END IF
433*
434 DO j2 = j+1, n, nb
435 nj = min( nb, n-j2+1 )
436*
437* Update (J2, J2) diagonal block with SGEMV
438*
439 j3 = j2
440 DO mj = nj-1, 1, -1
441 CALL sgemv( 'No transpose', mj, jb+1,
442 $ -one, work( j3-j1+1+k1*n ), n,
443 $ a( j3, j1-k2 ), lda,
444 $ one, a( j3, j3 ), 1 )
445 j3 = j3 + 1
446 END DO
447*
448* Update off-diagonal block in J2-th block column with SGEMM
449*
450 CALL sgemm( 'No transpose', 'Transpose',
451 $ n-j3+1, nj, jb+1,
452 $ -one, work( j3-j1+1+k1*n ), n,
453 $ a( j2, j1-k2 ), lda,
454 $ one, a( j3, j2 ), lda )
455 END DO
456*
457* Recover T( J+1, J )
458*
459 a( j+1, j ) = alpha
460 END IF
461*
462* WORK(J+1, 1) stores H(J+1, 1)
463*
464 CALL scopy( n-j, a( j+1, j+1 ), 1, work( 1 ), 1 )
465 END IF
466 GO TO 11
467 END IF
468*
469 20 CONTINUE
470*
471 work( 1 ) = sroundup_lwork( lwkopt )
472 RETURN
473*
474* End of SSYTRF_AA
475*
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
Definition scopy.f:82
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
Definition sgemm.f:188
subroutine sgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
SGEMV
Definition sgemv.f:158
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
Definition ilaenv.f:160
subroutine slasyf_aa(uplo, j1, m, nb, a, lda, ipiv, h, ldh, work)
SLASYF_AA
Definition slasyf_aa.f:142
logical function lsame(ca, cb)
LSAME
Definition lsame.f:48
real function sroundup_lwork(lwork)
SROUNDUP_LWORK
subroutine sscal(n, sa, sx, incx)
SSCAL
Definition sscal.f:79
subroutine sswap(n, sx, incx, sy, incy)
SSWAP
Definition sswap.f:82
Here is the call graph for this function:
Here is the caller graph for this function: