You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

dsytf2_rk.f 29 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  1. *> \brief \b DSYTF2_RK computes the factorization of a real symmetric indefinite matrix using the bounded Bunch-Kaufman (rook) diagonal pivoting method (BLAS2 unblocked algorithm).
  2. *
  3. * =========== DOCUMENTATION ===========
  4. *
  5. * Online html documentation available at
  6. * http://www.netlib.org/lapack/explore-html/
  7. *
  8. *> \htmlonly
  9. *> Download DSYTF2_RK + dependencies
  10. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dsytf2_rk.f">
  11. *> [TGZ]</a>
  12. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dsytf2_rk.f">
  13. *> [ZIP]</a>
  14. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsytf2_rk.f">
  15. *> [TXT]</a>
  16. *> \endhtmlonly
  17. *
  18. * Definition:
  19. * ===========
  20. *
  21. * SUBROUTINE DSYTF2_RK( UPLO, N, A, LDA, E, IPIV, INFO )
  22. *
  23. * .. Scalar Arguments ..
  24. * CHARACTER UPLO
  25. * INTEGER INFO, LDA, N
  26. * ..
  27. * .. Array Arguments ..
  28. * INTEGER IPIV( * )
  29. * DOUBLE PRECISION A( LDA, * ), E ( * )
  30. * ..
  31. *
  32. *
  33. *> \par Purpose:
  34. * =============
  35. *>
  36. *> \verbatim
  37. *> DSYTF2_RK computes the factorization of a real symmetric matrix A
  38. *> using the bounded Bunch-Kaufman (rook) diagonal pivoting method:
  39. *>
  40. *> A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T),
  41. *>
  42. *> where U (or L) is unit upper (or lower) triangular matrix,
  43. *> U**T (or L**T) is the transpose of U (or L), P is a permutation
  44. *> matrix, P**T is the transpose of P, and D is symmetric and block
  45. *> diagonal with 1-by-1 and 2-by-2 diagonal blocks.
  46. *>
  47. *> This is the unblocked version of the algorithm, calling Level 2 BLAS.
  48. *> For more information see Further Details section.
  49. *> \endverbatim
  50. *
  51. * Arguments:
  52. * ==========
  53. *
  54. *> \param[in] UPLO
  55. *> \verbatim
  56. *> UPLO is CHARACTER*1
  57. *> Specifies whether the upper or lower triangular part of the
  58. *> symmetric matrix A is stored:
  59. *> = 'U': Upper triangular
  60. *> = 'L': Lower triangular
  61. *> \endverbatim
  62. *>
  63. *> \param[in] N
  64. *> \verbatim
  65. *> N is INTEGER
  66. *> The order of the matrix A. N >= 0.
  67. *> \endverbatim
  68. *>
  69. *> \param[in,out] A
  70. *> \verbatim
  71. *> A is DOUBLE PRECISION array, dimension (LDA,N)
  72. *> On entry, the symmetric matrix A.
  73. *> If UPLO = 'U': the leading N-by-N upper triangular part
  74. *> of A contains the upper triangular part of the matrix A,
  75. *> and the strictly lower triangular part of A is not
  76. *> referenced.
  77. *>
  78. *> If UPLO = 'L': the leading N-by-N lower triangular part
  79. *> of A contains the lower triangular part of the matrix A,
  80. *> and the strictly upper triangular part of A is not
  81. *> referenced.
  82. *>
  83. *> On exit, contains:
  84. *> a) ONLY diagonal elements of the symmetric block diagonal
  85. *> matrix D on the diagonal of A, i.e. D(k,k) = A(k,k);
  86. *> (superdiagonal (or subdiagonal) elements of D
  87. *> are stored on exit in array E), and
  88. *> b) If UPLO = 'U': factor U in the superdiagonal part of A.
  89. *> If UPLO = 'L': factor L in the subdiagonal part of A.
  90. *> \endverbatim
  91. *>
  92. *> \param[in] LDA
  93. *> \verbatim
  94. *> LDA is INTEGER
  95. *> The leading dimension of the array A. LDA >= max(1,N).
  96. *> \endverbatim
  97. *>
  98. *> \param[out] E
  99. *> \verbatim
  100. *> E is DOUBLE PRECISION array, dimension (N)
  101. *> On exit, contains the superdiagonal (or subdiagonal)
  102. *> elements of the symmetric block diagonal matrix D
  103. *> with 1-by-1 or 2-by-2 diagonal blocks, where
  104. *> If UPLO = 'U': E(i) = D(i-1,i), i=2:N, E(1) is set to 0;
  105. *> If UPLO = 'L': E(i) = D(i+1,i), i=1:N-1, E(N) is set to 0.
  106. *>
  107. *> NOTE: For 1-by-1 diagonal block D(k), where
  108. *> 1 <= k <= N, the element E(k) is set to 0 in both
  109. *> UPLO = 'U' or UPLO = 'L' cases.
  110. *> \endverbatim
  111. *>
  112. *> \param[out] IPIV
  113. *> \verbatim
  114. *> IPIV is INTEGER array, dimension (N)
  115. *> IPIV describes the permutation matrix P in the factorization
  116. *> of matrix A as follows. The absolute value of IPIV(k)
  117. *> represents the index of row and column that were
  118. *> interchanged with the k-th row and column. The value of UPLO
  119. *> describes the order in which the interchanges were applied.
  120. *> Also, the sign of IPIV represents the block structure of
  121. *> the symmetric block diagonal matrix D with 1-by-1 or 2-by-2
  122. *> diagonal blocks which correspond to 1 or 2 interchanges
  123. *> at each factorization step. For more info see Further
  124. *> Details section.
  125. *>
  126. *> If UPLO = 'U',
  127. *> ( in factorization order, k decreases from N to 1 ):
  128. *> a) A single positive entry IPIV(k) > 0 means:
  129. *> D(k,k) is a 1-by-1 diagonal block.
  130. *> If IPIV(k) != k, rows and columns k and IPIV(k) were
  131. *> interchanged in the matrix A(1:N,1:N);
  132. *> If IPIV(k) = k, no interchange occurred.
  133. *>
  134. *> b) A pair of consecutive negative entries
  135. *> IPIV(k) < 0 and IPIV(k-1) < 0 means:
  136. *> D(k-1:k,k-1:k) is a 2-by-2 diagonal block.
  137. *> (NOTE: negative entries in IPIV appear ONLY in pairs).
  138. *> 1) If -IPIV(k) != k, rows and columns
  139. *> k and -IPIV(k) were interchanged
  140. *> in the matrix A(1:N,1:N).
  141. *> If -IPIV(k) = k, no interchange occurred.
  142. *> 2) If -IPIV(k-1) != k-1, rows and columns
  143. *> k-1 and -IPIV(k-1) were interchanged
  144. *> in the matrix A(1:N,1:N).
  145. *> If -IPIV(k-1) = k-1, no interchange occurred.
  146. *>
  147. *> c) In both cases a) and b), always ABS( IPIV(k) ) <= k.
  148. *>
  149. *> d) NOTE: Any entry IPIV(k) is always NONZERO on output.
  150. *>
  151. *> If UPLO = 'L',
  152. *> ( in factorization order, k increases from 1 to N ):
  153. *> a) A single positive entry IPIV(k) > 0 means:
  154. *> D(k,k) is a 1-by-1 diagonal block.
  155. *> If IPIV(k) != k, rows and columns k and IPIV(k) were
  156. *> interchanged in the matrix A(1:N,1:N).
  157. *> If IPIV(k) = k, no interchange occurred.
  158. *>
  159. *> b) A pair of consecutive negative entries
  160. *> IPIV(k) < 0 and IPIV(k+1) < 0 means:
  161. *> D(k:k+1,k:k+1) is a 2-by-2 diagonal block.
  162. *> (NOTE: negative entries in IPIV appear ONLY in pairs).
  163. *> 1) If -IPIV(k) != k, rows and columns
  164. *> k and -IPIV(k) were interchanged
  165. *> in the matrix A(1:N,1:N).
  166. *> If -IPIV(k) = k, no interchange occurred.
  167. *> 2) If -IPIV(k+1) != k+1, rows and columns
  168. *> k-1 and -IPIV(k-1) were interchanged
  169. *> in the matrix A(1:N,1:N).
  170. *> If -IPIV(k+1) = k+1, no interchange occurred.
  171. *>
  172. *> c) In both cases a) and b), always ABS( IPIV(k) ) >= k.
  173. *>
  174. *> d) NOTE: Any entry IPIV(k) is always NONZERO on output.
  175. *> \endverbatim
  176. *>
  177. *> \param[out] INFO
  178. *> \verbatim
  179. *> INFO is INTEGER
  180. *> = 0: successful exit
  181. *>
  182. *> < 0: If INFO = -k, the k-th argument had an illegal value
  183. *>
  184. *> > 0: If INFO = k, the matrix A is singular, because:
  185. *> If UPLO = 'U': column k in the upper
  186. *> triangular part of A contains all zeros.
  187. *> If UPLO = 'L': column k in the lower
  188. *> triangular part of A contains all zeros.
  189. *>
  190. *> Therefore D(k,k) is exactly zero, and superdiagonal
  191. *> elements of column k of U (or subdiagonal elements of
  192. *> column k of L ) are all zeros. The factorization has
  193. *> been completed, but the block diagonal matrix D is
  194. *> exactly singular, and division by zero will occur if
  195. *> it is used to solve a system of equations.
  196. *>
  197. *> NOTE: INFO only stores the first occurrence of
  198. *> a singularity, any subsequent occurrence of singularity
  199. *> is not stored in INFO even though the factorization
  200. *> always completes.
  201. *> \endverbatim
  202. *
  203. * Authors:
  204. * ========
  205. *
  206. *> \author Univ. of Tennessee
  207. *> \author Univ. of California Berkeley
  208. *> \author Univ. of Colorado Denver
  209. *> \author NAG Ltd.
  210. *
  211. *> \date December 2016
  212. *
  213. *> \ingroup doubleSYcomputational
  214. *
  215. *> \par Further Details:
  216. * =====================
  217. *>
  218. *> \verbatim
  219. *> TODO: put further details
  220. *> \endverbatim
  221. *
  222. *> \par Contributors:
  223. * ==================
  224. *>
  225. *> \verbatim
  226. *>
  227. *> December 2016, Igor Kozachenko,
  228. *> Computer Science Division,
  229. *> University of California, Berkeley
  230. *>
  231. *> September 2007, Sven Hammarling, Nicholas J. Higham, Craig Lucas,
  232. *> School of Mathematics,
  233. *> University of Manchester
  234. *>
  235. *> 01-01-96 - Based on modifications by
  236. *> J. Lewis, Boeing Computer Services Company
  237. *> A. Petitet, Computer Science Dept.,
  238. *> Univ. of Tenn., Knoxville abd , USA
  239. *> \endverbatim
  240. *
  241. * =====================================================================
  242. SUBROUTINE DSYTF2_RK( UPLO, N, A, LDA, E, IPIV, INFO )
  243. *
  244. * -- LAPACK computational routine (version 3.7.0) --
  245. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  246. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  247. * December 2016
  248. *
  249. * .. Scalar Arguments ..
  250. CHARACTER UPLO
  251. INTEGER INFO, LDA, N
  252. * ..
  253. * .. Array Arguments ..
  254. INTEGER IPIV( * )
  255. DOUBLE PRECISION A( LDA, * ), E( * )
  256. * ..
  257. *
  258. * =====================================================================
  259. *
  260. * .. Parameters ..
  261. DOUBLE PRECISION ZERO, ONE
  262. PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
  263. DOUBLE PRECISION EIGHT, SEVTEN
  264. PARAMETER ( EIGHT = 8.0D+0, SEVTEN = 17.0D+0 )
  265. * ..
  266. * .. Local Scalars ..
  267. LOGICAL UPPER, DONE
  268. INTEGER I, IMAX, J, JMAX, ITEMP, K, KK, KP, KSTEP,
  269. $ P, II
  270. DOUBLE PRECISION ABSAKK, ALPHA, COLMAX, D11, D12, D21, D22,
  271. $ ROWMAX, DTEMP, T, WK, WKM1, WKP1, SFMIN
  272. * ..
  273. * .. External Functions ..
  274. LOGICAL LSAME
  275. INTEGER IDAMAX
  276. DOUBLE PRECISION DLAMCH
  277. EXTERNAL LSAME, IDAMAX, DLAMCH
  278. * ..
  279. * .. External Subroutines ..
  280. EXTERNAL DSCAL, DSWAP, DSYR, XERBLA
  281. * ..
  282. * .. Intrinsic Functions ..
  283. INTRINSIC ABS, MAX, SQRT
  284. * ..
  285. * .. Executable Statements ..
  286. *
  287. * Test the input parameters.
  288. *
  289. INFO = 0
  290. UPPER = LSAME( UPLO, 'U' )
  291. IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
  292. INFO = -1
  293. ELSE IF( N.LT.0 ) THEN
  294. INFO = -2
  295. ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
  296. INFO = -4
  297. END IF
  298. IF( INFO.NE.0 ) THEN
  299. CALL XERBLA( 'DSYTF2_RK', -INFO )
  300. RETURN
  301. END IF
  302. *
  303. * Initialize ALPHA for use in choosing pivot block size.
  304. *
  305. ALPHA = ( ONE+SQRT( SEVTEN ) ) / EIGHT
  306. *
  307. * Compute machine safe minimum
  308. *
  309. SFMIN = DLAMCH( 'S' )
  310. *
  311. IF( UPPER ) THEN
  312. *
  313. * Factorize A as U*D*U**T using the upper triangle of A
  314. *
  315. * Initialize the first entry of array E, where superdiagonal
  316. * elements of D are stored
  317. *
  318. E( 1 ) = ZERO
  319. *
  320. * K is the main loop index, decreasing from N to 1 in steps of
  321. * 1 or 2
  322. *
  323. K = N
  324. 10 CONTINUE
  325. *
  326. * If K < 1, exit from loop
  327. *
  328. IF( K.LT.1 )
  329. $ GO TO 34
  330. KSTEP = 1
  331. P = K
  332. *
  333. * Determine rows and columns to be interchanged and whether
  334. * a 1-by-1 or 2-by-2 pivot block will be used
  335. *
  336. ABSAKK = ABS( A( K, K ) )
  337. *
  338. * IMAX is the row-index of the largest off-diagonal element in
  339. * column K, and COLMAX is its absolute value.
  340. * Determine both COLMAX and IMAX.
  341. *
  342. IF( K.GT.1 ) THEN
  343. IMAX = IDAMAX( K-1, A( 1, K ), 1 )
  344. COLMAX = ABS( A( IMAX, K ) )
  345. ELSE
  346. COLMAX = ZERO
  347. END IF
  348. *
  349. IF( (MAX( ABSAKK, COLMAX ).EQ.ZERO) ) THEN
  350. *
  351. * Column K is zero or underflow: set INFO and continue
  352. *
  353. IF( INFO.EQ.0 )
  354. $ INFO = K
  355. KP = K
  356. *
  357. * Set E( K ) to zero
  358. *
  359. IF( K.GT.1 )
  360. $ E( K ) = ZERO
  361. *
  362. ELSE
  363. *
  364. * Test for interchange
  365. *
  366. * Equivalent to testing for (used to handle NaN and Inf)
  367. * ABSAKK.GE.ALPHA*COLMAX
  368. *
  369. IF( .NOT.( ABSAKK.LT.ALPHA*COLMAX ) ) THEN
  370. *
  371. * no interchange,
  372. * use 1-by-1 pivot block
  373. *
  374. KP = K
  375. ELSE
  376. *
  377. DONE = .FALSE.
  378. *
  379. * Loop until pivot found
  380. *
  381. 12 CONTINUE
  382. *
  383. * Begin pivot search loop body
  384. *
  385. * JMAX is the column-index of the largest off-diagonal
  386. * element in row IMAX, and ROWMAX is its absolute value.
  387. * Determine both ROWMAX and JMAX.
  388. *
  389. IF( IMAX.NE.K ) THEN
  390. JMAX = IMAX + IDAMAX( K-IMAX, A( IMAX, IMAX+1 ),
  391. $ LDA )
  392. ROWMAX = ABS( A( IMAX, JMAX ) )
  393. ELSE
  394. ROWMAX = ZERO
  395. END IF
  396. *
  397. IF( IMAX.GT.1 ) THEN
  398. ITEMP = IDAMAX( IMAX-1, A( 1, IMAX ), 1 )
  399. DTEMP = ABS( A( ITEMP, IMAX ) )
  400. IF( DTEMP.GT.ROWMAX ) THEN
  401. ROWMAX = DTEMP
  402. JMAX = ITEMP
  403. END IF
  404. END IF
  405. *
  406. * Equivalent to testing for (used to handle NaN and Inf)
  407. * ABS( A( IMAX, IMAX ) ).GE.ALPHA*ROWMAX
  408. *
  409. IF( .NOT.( ABS( A( IMAX, IMAX ) ).LT.ALPHA*ROWMAX ) )
  410. $ THEN
  411. *
  412. * interchange rows and columns K and IMAX,
  413. * use 1-by-1 pivot block
  414. *
  415. KP = IMAX
  416. DONE = .TRUE.
  417. *
  418. * Equivalent to testing for ROWMAX .EQ. COLMAX,
  419. * used to handle NaN and Inf
  420. *
  421. ELSE IF( ( P.EQ.JMAX ).OR.( ROWMAX.LE.COLMAX ) ) THEN
  422. *
  423. * interchange rows and columns K+1 and IMAX,
  424. * use 2-by-2 pivot block
  425. *
  426. KP = IMAX
  427. KSTEP = 2
  428. DONE = .TRUE.
  429. ELSE
  430. *
  431. * Pivot NOT found, set variables and repeat
  432. *
  433. P = IMAX
  434. COLMAX = ROWMAX
  435. IMAX = JMAX
  436. END IF
  437. *
  438. * End pivot search loop body
  439. *
  440. IF( .NOT. DONE ) GOTO 12
  441. *
  442. END IF
  443. *
  444. * Swap TWO rows and TWO columns
  445. *
  446. * First swap
  447. *
  448. IF( ( KSTEP.EQ.2 ) .AND. ( P.NE.K ) ) THEN
  449. *
  450. * Interchange rows and column K and P in the leading
  451. * submatrix A(1:k,1:k) if we have a 2-by-2 pivot
  452. *
  453. IF( P.GT.1 )
  454. $ CALL DSWAP( P-1, A( 1, K ), 1, A( 1, P ), 1 )
  455. IF( P.LT.(K-1) )
  456. $ CALL DSWAP( K-P-1, A( P+1, K ), 1, A( P, P+1 ),
  457. $ LDA )
  458. T = A( K, K )
  459. A( K, K ) = A( P, P )
  460. A( P, P ) = T
  461. *
  462. * Convert upper triangle of A into U form by applying
  463. * the interchanges in columns k+1:N.
  464. *
  465. IF( K.LT.N )
  466. $ CALL DSWAP( N-K, A( K, K+1 ), LDA, A( P, K+1 ), LDA )
  467. *
  468. END IF
  469. *
  470. * Second swap
  471. *
  472. KK = K - KSTEP + 1
  473. IF( KP.NE.KK ) THEN
  474. *
  475. * Interchange rows and columns KK and KP in the leading
  476. * submatrix A(1:k,1:k)
  477. *
  478. IF( KP.GT.1 )
  479. $ CALL DSWAP( KP-1, A( 1, KK ), 1, A( 1, KP ), 1 )
  480. IF( ( KK.GT.1 ) .AND. ( KP.LT.(KK-1) ) )
  481. $ CALL DSWAP( KK-KP-1, A( KP+1, KK ), 1, A( KP, KP+1 ),
  482. $ LDA )
  483. T = A( KK, KK )
  484. A( KK, KK ) = A( KP, KP )
  485. A( KP, KP ) = T
  486. IF( KSTEP.EQ.2 ) THEN
  487. T = A( K-1, K )
  488. A( K-1, K ) = A( KP, K )
  489. A( KP, K ) = T
  490. END IF
  491. *
  492. * Convert upper triangle of A into U form by applying
  493. * the interchanges in columns k+1:N.
  494. *
  495. IF( K.LT.N )
  496. $ CALL DSWAP( N-K, A( KK, K+1 ), LDA, A( KP, K+1 ),
  497. $ LDA )
  498. *
  499. END IF
  500. *
  501. * Update the leading submatrix
  502. *
  503. IF( KSTEP.EQ.1 ) THEN
  504. *
  505. * 1-by-1 pivot block D(k): column k now holds
  506. *
  507. * W(k) = U(k)*D(k)
  508. *
  509. * where U(k) is the k-th column of U
  510. *
  511. IF( K.GT.1 ) THEN
  512. *
  513. * Perform a rank-1 update of A(1:k-1,1:k-1) and
  514. * store U(k) in column k
  515. *
  516. IF( ABS( A( K, K ) ).GE.SFMIN ) THEN
  517. *
  518. * Perform a rank-1 update of A(1:k-1,1:k-1) as
  519. * A := A - U(k)*D(k)*U(k)**T
  520. * = A - W(k)*1/D(k)*W(k)**T
  521. *
  522. D11 = ONE / A( K, K )
  523. CALL DSYR( UPLO, K-1, -D11, A( 1, K ), 1, A, LDA )
  524. *
  525. * Store U(k) in column k
  526. *
  527. CALL DSCAL( K-1, D11, A( 1, K ), 1 )
  528. ELSE
  529. *
  530. * Store L(k) in column K
  531. *
  532. D11 = A( K, K )
  533. DO 16 II = 1, K - 1
  534. A( II, K ) = A( II, K ) / D11
  535. 16 CONTINUE
  536. *
  537. * Perform a rank-1 update of A(k+1:n,k+1:n) as
  538. * A := A - U(k)*D(k)*U(k)**T
  539. * = A - W(k)*(1/D(k))*W(k)**T
  540. * = A - (W(k)/D(k))*(D(k))*(W(k)/D(K))**T
  541. *
  542. CALL DSYR( UPLO, K-1, -D11, A( 1, K ), 1, A, LDA )
  543. END IF
  544. *
  545. * Store the superdiagonal element of D in array E
  546. *
  547. E( K ) = ZERO
  548. *
  549. END IF
  550. *
  551. ELSE
  552. *
  553. * 2-by-2 pivot block D(k): columns k and k-1 now hold
  554. *
  555. * ( W(k-1) W(k) ) = ( U(k-1) U(k) )*D(k)
  556. *
  557. * where U(k) and U(k-1) are the k-th and (k-1)-th columns
  558. * of U
  559. *
  560. * Perform a rank-2 update of A(1:k-2,1:k-2) as
  561. *
  562. * A := A - ( U(k-1) U(k) )*D(k)*( U(k-1) U(k) )**T
  563. * = A - ( ( A(k-1)A(k) )*inv(D(k)) ) * ( A(k-1)A(k) )**T
  564. *
  565. * and store L(k) and L(k+1) in columns k and k+1
  566. *
  567. IF( K.GT.2 ) THEN
  568. *
  569. D12 = A( K-1, K )
  570. D22 = A( K-1, K-1 ) / D12
  571. D11 = A( K, K ) / D12
  572. T = ONE / ( D11*D22-ONE )
  573. *
  574. DO 30 J = K - 2, 1, -1
  575. *
  576. WKM1 = T*( D11*A( J, K-1 )-A( J, K ) )
  577. WK = T*( D22*A( J, K )-A( J, K-1 ) )
  578. *
  579. DO 20 I = J, 1, -1
  580. A( I, J ) = A( I, J ) - (A( I, K ) / D12 )*WK -
  581. $ ( A( I, K-1 ) / D12 )*WKM1
  582. 20 CONTINUE
  583. *
  584. * Store U(k) and U(k-1) in cols k and k-1 for row J
  585. *
  586. A( J, K ) = WK / D12
  587. A( J, K-1 ) = WKM1 / D12
  588. *
  589. 30 CONTINUE
  590. *
  591. END IF
  592. *
  593. * Copy superdiagonal elements of D(K) to E(K) and
  594. * ZERO out superdiagonal entry of A
  595. *
  596. E( K ) = A( K-1, K )
  597. E( K-1 ) = ZERO
  598. A( K-1, K ) = ZERO
  599. *
  600. END IF
  601. *
  602. * End column K is nonsingular
  603. *
  604. END IF
  605. *
  606. * Store details of the interchanges in IPIV
  607. *
  608. IF( KSTEP.EQ.1 ) THEN
  609. IPIV( K ) = KP
  610. ELSE
  611. IPIV( K ) = -P
  612. IPIV( K-1 ) = -KP
  613. END IF
  614. *
  615. * Decrease K and return to the start of the main loop
  616. *
  617. K = K - KSTEP
  618. GO TO 10
  619. *
  620. 34 CONTINUE
  621. *
  622. ELSE
  623. *
  624. * Factorize A as L*D*L**T using the lower triangle of A
  625. *
  626. * Initialize the unused last entry of the subdiagonal array E.
  627. *
  628. E( N ) = ZERO
  629. *
  630. * K is the main loop index, increasing from 1 to N in steps of
  631. * 1 or 2
  632. *
  633. K = 1
  634. 40 CONTINUE
  635. *
  636. * If K > N, exit from loop
  637. *
  638. IF( K.GT.N )
  639. $ GO TO 64
  640. KSTEP = 1
  641. P = K
  642. *
  643. * Determine rows and columns to be interchanged and whether
  644. * a 1-by-1 or 2-by-2 pivot block will be used
  645. *
  646. ABSAKK = ABS( A( K, K ) )
  647. *
  648. * IMAX is the row-index of the largest off-diagonal element in
  649. * column K, and COLMAX is its absolute value.
  650. * Determine both COLMAX and IMAX.
  651. *
  652. IF( K.LT.N ) THEN
  653. IMAX = K + IDAMAX( N-K, A( K+1, K ), 1 )
  654. COLMAX = ABS( A( IMAX, K ) )
  655. ELSE
  656. COLMAX = ZERO
  657. END IF
  658. *
  659. IF( ( MAX( ABSAKK, COLMAX ).EQ.ZERO ) ) THEN
  660. *
  661. * Column K is zero or underflow: set INFO and continue
  662. *
  663. IF( INFO.EQ.0 )
  664. $ INFO = K
  665. KP = K
  666. *
  667. * Set E( K ) to zero
  668. *
  669. IF( K.LT.N )
  670. $ E( K ) = ZERO
  671. *
  672. ELSE
  673. *
  674. * Test for interchange
  675. *
  676. * Equivalent to testing for (used to handle NaN and Inf)
  677. * ABSAKK.GE.ALPHA*COLMAX
  678. *
  679. IF( .NOT.( ABSAKK.LT.ALPHA*COLMAX ) ) THEN
  680. *
  681. * no interchange, use 1-by-1 pivot block
  682. *
  683. KP = K
  684. *
  685. ELSE
  686. *
  687. DONE = .FALSE.
  688. *
  689. * Loop until pivot found
  690. *
  691. 42 CONTINUE
  692. *
  693. * Begin pivot search loop body
  694. *
  695. * JMAX is the column-index of the largest off-diagonal
  696. * element in row IMAX, and ROWMAX is its absolute value.
  697. * Determine both ROWMAX and JMAX.
  698. *
  699. IF( IMAX.NE.K ) THEN
  700. JMAX = K - 1 + IDAMAX( IMAX-K, A( IMAX, K ), LDA )
  701. ROWMAX = ABS( A( IMAX, JMAX ) )
  702. ELSE
  703. ROWMAX = ZERO
  704. END IF
  705. *
  706. IF( IMAX.LT.N ) THEN
  707. ITEMP = IMAX + IDAMAX( N-IMAX, A( IMAX+1, IMAX ),
  708. $ 1 )
  709. DTEMP = ABS( A( ITEMP, IMAX ) )
  710. IF( DTEMP.GT.ROWMAX ) THEN
  711. ROWMAX = DTEMP
  712. JMAX = ITEMP
  713. END IF
  714. END IF
  715. *
  716. * Equivalent to testing for (used to handle NaN and Inf)
  717. * ABS( A( IMAX, IMAX ) ).GE.ALPHA*ROWMAX
  718. *
  719. IF( .NOT.( ABS( A( IMAX, IMAX ) ).LT.ALPHA*ROWMAX ) )
  720. $ THEN
  721. *
  722. * interchange rows and columns K and IMAX,
  723. * use 1-by-1 pivot block
  724. *
  725. KP = IMAX
  726. DONE = .TRUE.
  727. *
  728. * Equivalent to testing for ROWMAX .EQ. COLMAX,
  729. * used to handle NaN and Inf
  730. *
  731. ELSE IF( ( P.EQ.JMAX ).OR.( ROWMAX.LE.COLMAX ) ) THEN
  732. *
  733. * interchange rows and columns K+1 and IMAX,
  734. * use 2-by-2 pivot block
  735. *
  736. KP = IMAX
  737. KSTEP = 2
  738. DONE = .TRUE.
  739. ELSE
  740. *
  741. * Pivot NOT found, set variables and repeat
  742. *
  743. P = IMAX
  744. COLMAX = ROWMAX
  745. IMAX = JMAX
  746. END IF
  747. *
  748. * End pivot search loop body
  749. *
  750. IF( .NOT. DONE ) GOTO 42
  751. *
  752. END IF
  753. *
  754. * Swap TWO rows and TWO columns
  755. *
  756. * First swap
  757. *
  758. IF( ( KSTEP.EQ.2 ) .AND. ( P.NE.K ) ) THEN
  759. *
  760. * Interchange rows and column K and P in the trailing
  761. * submatrix A(k:n,k:n) if we have a 2-by-2 pivot
  762. *
  763. IF( P.LT.N )
  764. $ CALL DSWAP( N-P, A( P+1, K ), 1, A( P+1, P ), 1 )
  765. IF( P.GT.(K+1) )
  766. $ CALL DSWAP( P-K-1, A( K+1, K ), 1, A( P, K+1 ), LDA )
  767. T = A( K, K )
  768. A( K, K ) = A( P, P )
  769. A( P, P ) = T
  770. *
  771. * Convert lower triangle of A into L form by applying
  772. * the interchanges in columns 1:k-1.
  773. *
  774. IF ( K.GT.1 )
  775. $ CALL DSWAP( K-1, A( K, 1 ), LDA, A( P, 1 ), LDA )
  776. *
  777. END IF
  778. *
  779. * Second swap
  780. *
  781. KK = K + KSTEP - 1
  782. IF( KP.NE.KK ) THEN
  783. *
  784. * Interchange rows and columns KK and KP in the trailing
  785. * submatrix A(k:n,k:n)
  786. *
  787. IF( KP.LT.N )
  788. $ CALL DSWAP( N-KP, A( KP+1, KK ), 1, A( KP+1, KP ), 1 )
  789. IF( ( KK.LT.N ) .AND. ( KP.GT.(KK+1) ) )
  790. $ CALL DSWAP( KP-KK-1, A( KK+1, KK ), 1, A( KP, KK+1 ),
  791. $ LDA )
  792. T = A( KK, KK )
  793. A( KK, KK ) = A( KP, KP )
  794. A( KP, KP ) = T
  795. IF( KSTEP.EQ.2 ) THEN
  796. T = A( K+1, K )
  797. A( K+1, K ) = A( KP, K )
  798. A( KP, K ) = T
  799. END IF
  800. *
  801. * Convert lower triangle of A into L form by applying
  802. * the interchanges in columns 1:k-1.
  803. *
  804. IF ( K.GT.1 )
  805. $ CALL DSWAP( K-1, A( KK, 1 ), LDA, A( KP, 1 ), LDA )
  806. *
  807. END IF
  808. *
  809. * Update the trailing submatrix
  810. *
  811. IF( KSTEP.EQ.1 ) THEN
  812. *
  813. * 1-by-1 pivot block D(k): column k now holds
  814. *
  815. * W(k) = L(k)*D(k)
  816. *
  817. * where L(k) is the k-th column of L
  818. *
  819. IF( K.LT.N ) THEN
  820. *
  821. * Perform a rank-1 update of A(k+1:n,k+1:n) and
  822. * store L(k) in column k
  823. *
  824. IF( ABS( A( K, K ) ).GE.SFMIN ) THEN
  825. *
  826. * Perform a rank-1 update of A(k+1:n,k+1:n) as
  827. * A := A - L(k)*D(k)*L(k)**T
  828. * = A - W(k)*(1/D(k))*W(k)**T
  829. *
  830. D11 = ONE / A( K, K )
  831. CALL DSYR( UPLO, N-K, -D11, A( K+1, K ), 1,
  832. $ A( K+1, K+1 ), LDA )
  833. *
  834. * Store L(k) in column k
  835. *
  836. CALL DSCAL( N-K, D11, A( K+1, K ), 1 )
  837. ELSE
  838. *
  839. * Store L(k) in column k
  840. *
  841. D11 = A( K, K )
  842. DO 46 II = K + 1, N
  843. A( II, K ) = A( II, K ) / D11
  844. 46 CONTINUE
  845. *
  846. * Perform a rank-1 update of A(k+1:n,k+1:n) as
  847. * A := A - L(k)*D(k)*L(k)**T
  848. * = A - W(k)*(1/D(k))*W(k)**T
  849. * = A - (W(k)/D(k))*(D(k))*(W(k)/D(K))**T
  850. *
  851. CALL DSYR( UPLO, N-K, -D11, A( K+1, K ), 1,
  852. $ A( K+1, K+1 ), LDA )
  853. END IF
  854. *
  855. * Store the subdiagonal element of D in array E
  856. *
  857. E( K ) = ZERO
  858. *
  859. END IF
  860. *
  861. ELSE
  862. *
  863. * 2-by-2 pivot block D(k): columns k and k+1 now hold
  864. *
  865. * ( W(k) W(k+1) ) = ( L(k) L(k+1) )*D(k)
  866. *
  867. * where L(k) and L(k+1) are the k-th and (k+1)-th columns
  868. * of L
  869. *
  870. *
  871. * Perform a rank-2 update of A(k+2:n,k+2:n) as
  872. *
  873. * A := A - ( L(k) L(k+1) ) * D(k) * ( L(k) L(k+1) )**T
  874. * = A - ( ( A(k)A(k+1) )*inv(D(k) ) * ( A(k)A(k+1) )**T
  875. *
  876. * and store L(k) and L(k+1) in columns k and k+1
  877. *
  878. IF( K.LT.N-1 ) THEN
  879. *
  880. D21 = A( K+1, K )
  881. D11 = A( K+1, K+1 ) / D21
  882. D22 = A( K, K ) / D21
  883. T = ONE / ( D11*D22-ONE )
  884. *
  885. DO 60 J = K + 2, N
  886. *
  887. * Compute D21 * ( W(k)W(k+1) ) * inv(D(k)) for row J
  888. *
  889. WK = T*( D11*A( J, K )-A( J, K+1 ) )
  890. WKP1 = T*( D22*A( J, K+1 )-A( J, K ) )
  891. *
  892. * Perform a rank-2 update of A(k+2:n,k+2:n)
  893. *
  894. DO 50 I = J, N
  895. A( I, J ) = A( I, J ) - ( A( I, K ) / D21 )*WK -
  896. $ ( A( I, K+1 ) / D21 )*WKP1
  897. 50 CONTINUE
  898. *
  899. * Store L(k) and L(k+1) in cols k and k+1 for row J
  900. *
  901. A( J, K ) = WK / D21
  902. A( J, K+1 ) = WKP1 / D21
  903. *
  904. 60 CONTINUE
  905. *
  906. END IF
  907. *
  908. * Copy subdiagonal elements of D(K) to E(K) and
  909. * ZERO out subdiagonal entry of A
  910. *
  911. E( K ) = A( K+1, K )
  912. E( K+1 ) = ZERO
  913. A( K+1, K ) = ZERO
  914. *
  915. END IF
  916. *
  917. * End column K is nonsingular
  918. *
  919. END IF
  920. *
  921. * Store details of the interchanges in IPIV
  922. *
  923. IF( KSTEP.EQ.1 ) THEN
  924. IPIV( K ) = KP
  925. ELSE
  926. IPIV( K ) = -P
  927. IPIV( K+1 ) = -KP
  928. END IF
  929. *
  930. * Increase K and return to the start of the main loop
  931. *
  932. K = K + KSTEP
  933. GO TO 40
  934. *
  935. 64 CONTINUE
  936. *
  937. END IF
  938. *
  939. RETURN
  940. *
  941. * End of DSYTF2_RK
  942. *
  943. END