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.

csytf2_rk.f 30 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. *> \brief \b CSYTF2_RK computes the factorization of a complex 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 CSYTF2_RK + dependencies
  10. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/csytf2_rk.f">
  11. *> [TGZ]</a>
  12. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/csytf2_rk.f">
  13. *> [ZIP]</a>
  14. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csytf2_rk.f">
  15. *> [TXT]</a>
  16. *> \endhtmlonly
  17. *
  18. * Definition:
  19. * ===========
  20. *
  21. * SUBROUTINE CSYTF2_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. * COMPLEX A( LDA, * ), E ( * )
  30. * ..
  31. *
  32. *
  33. *> \par Purpose:
  34. * =============
  35. *>
  36. *> \verbatim
  37. *> CSYTF2_RK computes the factorization of a complex 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 COMPLEX 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 COMPLEX 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. *> \ingroup complexSYcomputational
  212. *
  213. *> \par Further Details:
  214. * =====================
  215. *>
  216. *> \verbatim
  217. *> TODO: put further details
  218. *> \endverbatim
  219. *
  220. *> \par Contributors:
  221. * ==================
  222. *>
  223. *> \verbatim
  224. *>
  225. *> December 2016, Igor Kozachenko,
  226. *> Computer Science Division,
  227. *> University of California, Berkeley
  228. *>
  229. *> September 2007, Sven Hammarling, Nicholas J. Higham, Craig Lucas,
  230. *> School of Mathematics,
  231. *> University of Manchester
  232. *>
  233. *> 01-01-96 - Based on modifications by
  234. *> J. Lewis, Boeing Computer Services Company
  235. *> A. Petitet, Computer Science Dept.,
  236. *> Univ. of Tenn., Knoxville abd , USA
  237. *> \endverbatim
  238. *
  239. * =====================================================================
  240. SUBROUTINE CSYTF2_RK( UPLO, N, A, LDA, E, IPIV, INFO )
  241. *
  242. * -- LAPACK computational routine --
  243. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  244. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  245. *
  246. * .. Scalar Arguments ..
  247. CHARACTER UPLO
  248. INTEGER INFO, LDA, N
  249. * ..
  250. * .. Array Arguments ..
  251. INTEGER IPIV( * )
  252. COMPLEX A( LDA, * ), E( * )
  253. * ..
  254. *
  255. * =====================================================================
  256. *
  257. * .. Parameters ..
  258. REAL ZERO, ONE
  259. PARAMETER ( ZERO = 0.0E+0, ONE = 1.0E+0 )
  260. REAL EIGHT, SEVTEN
  261. PARAMETER ( EIGHT = 8.0E+0, SEVTEN = 17.0E+0 )
  262. COMPLEX CONE, CZERO
  263. PARAMETER ( CONE = ( 1.0E+0, 0.0E+0 ),
  264. $ CZERO = ( 0.0E+0, 0.0E+0 ) )
  265. * ..
  266. * .. Local Scalars ..
  267. LOGICAL UPPER, DONE
  268. INTEGER I, IMAX, J, JMAX, ITEMP, K, KK, KP, KSTEP,
  269. $ P, II
  270. REAL ABSAKK, ALPHA, COLMAX, ROWMAX, STEMP, SFMIN
  271. COMPLEX D11, D12, D21, D22, T, WK, WKM1, WKP1, Z
  272. * ..
  273. * .. External Functions ..
  274. LOGICAL LSAME
  275. INTEGER ICAMAX
  276. REAL SLAMCH
  277. EXTERNAL LSAME, ICAMAX, SLAMCH
  278. * ..
  279. * .. External Subroutines ..
  280. EXTERNAL CSCAL, CSWAP, CSYR, XERBLA
  281. * ..
  282. * .. Intrinsic Functions ..
  283. INTRINSIC ABS, MAX, SQRT, AIMAG, REAL
  284. * ..
  285. * .. Statement Functions ..
  286. REAL CABS1
  287. * ..
  288. * .. Statement Function definitions ..
  289. CABS1( Z ) = ABS( REAL( Z ) ) + ABS( AIMAG( Z ) )
  290. * ..
  291. * .. Executable Statements ..
  292. *
  293. * Test the input parameters.
  294. *
  295. INFO = 0
  296. UPPER = LSAME( UPLO, 'U' )
  297. IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
  298. INFO = -1
  299. ELSE IF( N.LT.0 ) THEN
  300. INFO = -2
  301. ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
  302. INFO = -4
  303. END IF
  304. IF( INFO.NE.0 ) THEN
  305. CALL XERBLA( 'CSYTF2_RK', -INFO )
  306. RETURN
  307. END IF
  308. *
  309. * Initialize ALPHA for use in choosing pivot block size.
  310. *
  311. ALPHA = ( ONE+SQRT( SEVTEN ) ) / EIGHT
  312. *
  313. * Compute machine safe minimum
  314. *
  315. SFMIN = SLAMCH( 'S' )
  316. *
  317. IF( UPPER ) THEN
  318. *
  319. * Factorize A as U*D*U**T using the upper triangle of A
  320. *
  321. * Initialize the first entry of array E, where superdiagonal
  322. * elements of D are stored
  323. *
  324. E( 1 ) = CZERO
  325. *
  326. * K is the main loop index, decreasing from N to 1 in steps of
  327. * 1 or 2
  328. *
  329. K = N
  330. 10 CONTINUE
  331. *
  332. * If K < 1, exit from loop
  333. *
  334. IF( K.LT.1 )
  335. $ GO TO 34
  336. KSTEP = 1
  337. P = K
  338. *
  339. * Determine rows and columns to be interchanged and whether
  340. * a 1-by-1 or 2-by-2 pivot block will be used
  341. *
  342. ABSAKK = CABS1( A( K, K ) )
  343. *
  344. * IMAX is the row-index of the largest off-diagonal element in
  345. * column K, and COLMAX is its absolute value.
  346. * Determine both COLMAX and IMAX.
  347. *
  348. IF( K.GT.1 ) THEN
  349. IMAX = ICAMAX( K-1, A( 1, K ), 1 )
  350. COLMAX = CABS1( A( IMAX, K ) )
  351. ELSE
  352. COLMAX = ZERO
  353. END IF
  354. *
  355. IF( (MAX( ABSAKK, COLMAX ).EQ.ZERO) ) THEN
  356. *
  357. * Column K is zero or underflow: set INFO and continue
  358. *
  359. IF( INFO.EQ.0 )
  360. $ INFO = K
  361. KP = K
  362. *
  363. * Set E( K ) to zero
  364. *
  365. IF( K.GT.1 )
  366. $ E( K ) = CZERO
  367. *
  368. ELSE
  369. *
  370. * Test for interchange
  371. *
  372. * Equivalent to testing for (used to handle NaN and Inf)
  373. * ABSAKK.GE.ALPHA*COLMAX
  374. *
  375. IF( .NOT.( ABSAKK.LT.ALPHA*COLMAX ) ) THEN
  376. *
  377. * no interchange,
  378. * use 1-by-1 pivot block
  379. *
  380. KP = K
  381. ELSE
  382. *
  383. DONE = .FALSE.
  384. *
  385. * Loop until pivot found
  386. *
  387. 12 CONTINUE
  388. *
  389. * Begin pivot search loop body
  390. *
  391. * JMAX is the column-index of the largest off-diagonal
  392. * element in row IMAX, and ROWMAX is its absolute value.
  393. * Determine both ROWMAX and JMAX.
  394. *
  395. IF( IMAX.NE.K ) THEN
  396. JMAX = IMAX + ICAMAX( K-IMAX, A( IMAX, IMAX+1 ),
  397. $ LDA )
  398. ROWMAX = CABS1( A( IMAX, JMAX ) )
  399. ELSE
  400. ROWMAX = ZERO
  401. END IF
  402. *
  403. IF( IMAX.GT.1 ) THEN
  404. ITEMP = ICAMAX( IMAX-1, A( 1, IMAX ), 1 )
  405. STEMP = CABS1( A( ITEMP, IMAX ) )
  406. IF( STEMP.GT.ROWMAX ) THEN
  407. ROWMAX = STEMP
  408. JMAX = ITEMP
  409. END IF
  410. END IF
  411. *
  412. * Equivalent to testing for (used to handle NaN and Inf)
  413. * ABS( A( IMAX, IMAX ) ).GE.ALPHA*ROWMAX
  414. *
  415. IF( .NOT.( CABS1( A( IMAX, IMAX ) ).LT.ALPHA*ROWMAX ))
  416. $ THEN
  417. *
  418. * interchange rows and columns K and IMAX,
  419. * use 1-by-1 pivot block
  420. *
  421. KP = IMAX
  422. DONE = .TRUE.
  423. *
  424. * Equivalent to testing for ROWMAX .EQ. COLMAX,
  425. * used to handle NaN and Inf
  426. *
  427. ELSE IF( ( P.EQ.JMAX ).OR.( ROWMAX.LE.COLMAX ) ) THEN
  428. *
  429. * interchange rows and columns K+1 and IMAX,
  430. * use 2-by-2 pivot block
  431. *
  432. KP = IMAX
  433. KSTEP = 2
  434. DONE = .TRUE.
  435. ELSE
  436. *
  437. * Pivot NOT found, set variables and repeat
  438. *
  439. P = IMAX
  440. COLMAX = ROWMAX
  441. IMAX = JMAX
  442. END IF
  443. *
  444. * End pivot search loop body
  445. *
  446. IF( .NOT. DONE ) GOTO 12
  447. *
  448. END IF
  449. *
  450. * Swap TWO rows and TWO columns
  451. *
  452. * First swap
  453. *
  454. IF( ( KSTEP.EQ.2 ) .AND. ( P.NE.K ) ) THEN
  455. *
  456. * Interchange rows and column K and P in the leading
  457. * submatrix A(1:k,1:k) if we have a 2-by-2 pivot
  458. *
  459. IF( P.GT.1 )
  460. $ CALL CSWAP( P-1, A( 1, K ), 1, A( 1, P ), 1 )
  461. IF( P.LT.(K-1) )
  462. $ CALL CSWAP( K-P-1, A( P+1, K ), 1, A( P, P+1 ),
  463. $ LDA )
  464. T = A( K, K )
  465. A( K, K ) = A( P, P )
  466. A( P, P ) = T
  467. *
  468. * Convert upper triangle of A into U form by applying
  469. * the interchanges in columns k+1:N.
  470. *
  471. IF( K.LT.N )
  472. $ CALL CSWAP( N-K, A( K, K+1 ), LDA, A( P, K+1 ), LDA )
  473. *
  474. END IF
  475. *
  476. * Second swap
  477. *
  478. KK = K - KSTEP + 1
  479. IF( KP.NE.KK ) THEN
  480. *
  481. * Interchange rows and columns KK and KP in the leading
  482. * submatrix A(1:k,1:k)
  483. *
  484. IF( KP.GT.1 )
  485. $ CALL CSWAP( KP-1, A( 1, KK ), 1, A( 1, KP ), 1 )
  486. IF( ( KK.GT.1 ) .AND. ( KP.LT.(KK-1) ) )
  487. $ CALL CSWAP( KK-KP-1, A( KP+1, KK ), 1, A( KP, KP+1 ),
  488. $ LDA )
  489. T = A( KK, KK )
  490. A( KK, KK ) = A( KP, KP )
  491. A( KP, KP ) = T
  492. IF( KSTEP.EQ.2 ) THEN
  493. T = A( K-1, K )
  494. A( K-1, K ) = A( KP, K )
  495. A( KP, K ) = T
  496. END IF
  497. *
  498. * Convert upper triangle of A into U form by applying
  499. * the interchanges in columns k+1:N.
  500. *
  501. IF( K.LT.N )
  502. $ CALL CSWAP( N-K, A( KK, K+1 ), LDA, A( KP, K+1 ),
  503. $ LDA )
  504. *
  505. END IF
  506. *
  507. * Update the leading submatrix
  508. *
  509. IF( KSTEP.EQ.1 ) THEN
  510. *
  511. * 1-by-1 pivot block D(k): column k now holds
  512. *
  513. * W(k) = U(k)*D(k)
  514. *
  515. * where U(k) is the k-th column of U
  516. *
  517. IF( K.GT.1 ) THEN
  518. *
  519. * Perform a rank-1 update of A(1:k-1,1:k-1) and
  520. * store U(k) in column k
  521. *
  522. IF( CABS1( A( K, K ) ).GE.SFMIN ) THEN
  523. *
  524. * Perform a rank-1 update of A(1:k-1,1:k-1) as
  525. * A := A - U(k)*D(k)*U(k)**T
  526. * = A - W(k)*1/D(k)*W(k)**T
  527. *
  528. D11 = CONE / A( K, K )
  529. CALL CSYR( UPLO, K-1, -D11, A( 1, K ), 1, A, LDA )
  530. *
  531. * Store U(k) in column k
  532. *
  533. CALL CSCAL( K-1, D11, A( 1, K ), 1 )
  534. ELSE
  535. *
  536. * Store L(k) in column K
  537. *
  538. D11 = A( K, K )
  539. DO 16 II = 1, K - 1
  540. A( II, K ) = A( II, K ) / D11
  541. 16 CONTINUE
  542. *
  543. * Perform a rank-1 update of A(k+1:n,k+1:n) as
  544. * A := A - U(k)*D(k)*U(k)**T
  545. * = A - W(k)*(1/D(k))*W(k)**T
  546. * = A - (W(k)/D(k))*(D(k))*(W(k)/D(K))**T
  547. *
  548. CALL CSYR( UPLO, K-1, -D11, A( 1, K ), 1, A, LDA )
  549. END IF
  550. *
  551. * Store the superdiagonal element of D in array E
  552. *
  553. E( K ) = CZERO
  554. *
  555. END IF
  556. *
  557. ELSE
  558. *
  559. * 2-by-2 pivot block D(k): columns k and k-1 now hold
  560. *
  561. * ( W(k-1) W(k) ) = ( U(k-1) U(k) )*D(k)
  562. *
  563. * where U(k) and U(k-1) are the k-th and (k-1)-th columns
  564. * of U
  565. *
  566. * Perform a rank-2 update of A(1:k-2,1:k-2) as
  567. *
  568. * A := A - ( U(k-1) U(k) )*D(k)*( U(k-1) U(k) )**T
  569. * = A - ( ( A(k-1)A(k) )*inv(D(k)) ) * ( A(k-1)A(k) )**T
  570. *
  571. * and store L(k) and L(k+1) in columns k and k+1
  572. *
  573. IF( K.GT.2 ) THEN
  574. *
  575. D12 = A( K-1, K )
  576. D22 = A( K-1, K-1 ) / D12
  577. D11 = A( K, K ) / D12
  578. T = CONE / ( D11*D22-CONE )
  579. *
  580. DO 30 J = K - 2, 1, -1
  581. *
  582. WKM1 = T*( D11*A( J, K-1 )-A( J, K ) )
  583. WK = T*( D22*A( J, K )-A( J, K-1 ) )
  584. *
  585. DO 20 I = J, 1, -1
  586. A( I, J ) = A( I, J ) - (A( I, K ) / D12 )*WK -
  587. $ ( A( I, K-1 ) / D12 )*WKM1
  588. 20 CONTINUE
  589. *
  590. * Store U(k) and U(k-1) in cols k and k-1 for row J
  591. *
  592. A( J, K ) = WK / D12
  593. A( J, K-1 ) = WKM1 / D12
  594. *
  595. 30 CONTINUE
  596. *
  597. END IF
  598. *
  599. * Copy superdiagonal elements of D(K) to E(K) and
  600. * ZERO out superdiagonal entry of A
  601. *
  602. E( K ) = A( K-1, K )
  603. E( K-1 ) = CZERO
  604. A( K-1, K ) = CZERO
  605. *
  606. END IF
  607. *
  608. * End column K is nonsingular
  609. *
  610. END IF
  611. *
  612. * Store details of the interchanges in IPIV
  613. *
  614. IF( KSTEP.EQ.1 ) THEN
  615. IPIV( K ) = KP
  616. ELSE
  617. IPIV( K ) = -P
  618. IPIV( K-1 ) = -KP
  619. END IF
  620. *
  621. * Decrease K and return to the start of the main loop
  622. *
  623. K = K - KSTEP
  624. GO TO 10
  625. *
  626. 34 CONTINUE
  627. *
  628. ELSE
  629. *
  630. * Factorize A as L*D*L**T using the lower triangle of A
  631. *
  632. * Initialize the unused last entry of the subdiagonal array E.
  633. *
  634. E( N ) = CZERO
  635. *
  636. * K is the main loop index, increasing from 1 to N in steps of
  637. * 1 or 2
  638. *
  639. K = 1
  640. 40 CONTINUE
  641. *
  642. * If K > N, exit from loop
  643. *
  644. IF( K.GT.N )
  645. $ GO TO 64
  646. KSTEP = 1
  647. P = K
  648. *
  649. * Determine rows and columns to be interchanged and whether
  650. * a 1-by-1 or 2-by-2 pivot block will be used
  651. *
  652. ABSAKK = CABS1( A( K, K ) )
  653. *
  654. * IMAX is the row-index of the largest off-diagonal element in
  655. * column K, and COLMAX is its absolute value.
  656. * Determine both COLMAX and IMAX.
  657. *
  658. IF( K.LT.N ) THEN
  659. IMAX = K + ICAMAX( N-K, A( K+1, K ), 1 )
  660. COLMAX = CABS1( A( IMAX, K ) )
  661. ELSE
  662. COLMAX = ZERO
  663. END IF
  664. *
  665. IF( ( MAX( ABSAKK, COLMAX ).EQ.ZERO ) ) THEN
  666. *
  667. * Column K is zero or underflow: set INFO and continue
  668. *
  669. IF( INFO.EQ.0 )
  670. $ INFO = K
  671. KP = K
  672. *
  673. * Set E( K ) to zero
  674. *
  675. IF( K.LT.N )
  676. $ E( K ) = CZERO
  677. *
  678. ELSE
  679. *
  680. * Test for interchange
  681. *
  682. * Equivalent to testing for (used to handle NaN and Inf)
  683. * ABSAKK.GE.ALPHA*COLMAX
  684. *
  685. IF( .NOT.( ABSAKK.LT.ALPHA*COLMAX ) ) THEN
  686. *
  687. * no interchange, use 1-by-1 pivot block
  688. *
  689. KP = K
  690. *
  691. ELSE
  692. *
  693. DONE = .FALSE.
  694. *
  695. * Loop until pivot found
  696. *
  697. 42 CONTINUE
  698. *
  699. * Begin pivot search loop body
  700. *
  701. * JMAX is the column-index of the largest off-diagonal
  702. * element in row IMAX, and ROWMAX is its absolute value.
  703. * Determine both ROWMAX and JMAX.
  704. *
  705. IF( IMAX.NE.K ) THEN
  706. JMAX = K - 1 + ICAMAX( IMAX-K, A( IMAX, K ), LDA )
  707. ROWMAX = CABS1( A( IMAX, JMAX ) )
  708. ELSE
  709. ROWMAX = ZERO
  710. END IF
  711. *
  712. IF( IMAX.LT.N ) THEN
  713. ITEMP = IMAX + ICAMAX( N-IMAX, A( IMAX+1, IMAX ),
  714. $ 1 )
  715. STEMP = CABS1( A( ITEMP, IMAX ) )
  716. IF( STEMP.GT.ROWMAX ) THEN
  717. ROWMAX = STEMP
  718. JMAX = ITEMP
  719. END IF
  720. END IF
  721. *
  722. * Equivalent to testing for (used to handle NaN and Inf)
  723. * ABS( A( IMAX, IMAX ) ).GE.ALPHA*ROWMAX
  724. *
  725. IF( .NOT.( CABS1( A( IMAX, IMAX ) ).LT.ALPHA*ROWMAX ))
  726. $ THEN
  727. *
  728. * interchange rows and columns K and IMAX,
  729. * use 1-by-1 pivot block
  730. *
  731. KP = IMAX
  732. DONE = .TRUE.
  733. *
  734. * Equivalent to testing for ROWMAX .EQ. COLMAX,
  735. * used to handle NaN and Inf
  736. *
  737. ELSE IF( ( P.EQ.JMAX ).OR.( ROWMAX.LE.COLMAX ) ) THEN
  738. *
  739. * interchange rows and columns K+1 and IMAX,
  740. * use 2-by-2 pivot block
  741. *
  742. KP = IMAX
  743. KSTEP = 2
  744. DONE = .TRUE.
  745. ELSE
  746. *
  747. * Pivot NOT found, set variables and repeat
  748. *
  749. P = IMAX
  750. COLMAX = ROWMAX
  751. IMAX = JMAX
  752. END IF
  753. *
  754. * End pivot search loop body
  755. *
  756. IF( .NOT. DONE ) GOTO 42
  757. *
  758. END IF
  759. *
  760. * Swap TWO rows and TWO columns
  761. *
  762. * First swap
  763. *
  764. IF( ( KSTEP.EQ.2 ) .AND. ( P.NE.K ) ) THEN
  765. *
  766. * Interchange rows and column K and P in the trailing
  767. * submatrix A(k:n,k:n) if we have a 2-by-2 pivot
  768. *
  769. IF( P.LT.N )
  770. $ CALL CSWAP( N-P, A( P+1, K ), 1, A( P+1, P ), 1 )
  771. IF( P.GT.(K+1) )
  772. $ CALL CSWAP( P-K-1, A( K+1, K ), 1, A( P, K+1 ), LDA )
  773. T = A( K, K )
  774. A( K, K ) = A( P, P )
  775. A( P, P ) = T
  776. *
  777. * Convert lower triangle of A into L form by applying
  778. * the interchanges in columns 1:k-1.
  779. *
  780. IF ( K.GT.1 )
  781. $ CALL CSWAP( K-1, A( K, 1 ), LDA, A( P, 1 ), LDA )
  782. *
  783. END IF
  784. *
  785. * Second swap
  786. *
  787. KK = K + KSTEP - 1
  788. IF( KP.NE.KK ) THEN
  789. *
  790. * Interchange rows and columns KK and KP in the trailing
  791. * submatrix A(k:n,k:n)
  792. *
  793. IF( KP.LT.N )
  794. $ CALL CSWAP( N-KP, A( KP+1, KK ), 1, A( KP+1, KP ), 1 )
  795. IF( ( KK.LT.N ) .AND. ( KP.GT.(KK+1) ) )
  796. $ CALL CSWAP( KP-KK-1, A( KK+1, KK ), 1, A( KP, KK+1 ),
  797. $ LDA )
  798. T = A( KK, KK )
  799. A( KK, KK ) = A( KP, KP )
  800. A( KP, KP ) = T
  801. IF( KSTEP.EQ.2 ) THEN
  802. T = A( K+1, K )
  803. A( K+1, K ) = A( KP, K )
  804. A( KP, K ) = T
  805. END IF
  806. *
  807. * Convert lower triangle of A into L form by applying
  808. * the interchanges in columns 1:k-1.
  809. *
  810. IF ( K.GT.1 )
  811. $ CALL CSWAP( K-1, A( KK, 1 ), LDA, A( KP, 1 ), LDA )
  812. *
  813. END IF
  814. *
  815. * Update the trailing submatrix
  816. *
  817. IF( KSTEP.EQ.1 ) THEN
  818. *
  819. * 1-by-1 pivot block D(k): column k now holds
  820. *
  821. * W(k) = L(k)*D(k)
  822. *
  823. * where L(k) is the k-th column of L
  824. *
  825. IF( K.LT.N ) THEN
  826. *
  827. * Perform a rank-1 update of A(k+1:n,k+1:n) and
  828. * store L(k) in column k
  829. *
  830. IF( CABS1( A( K, K ) ).GE.SFMIN ) THEN
  831. *
  832. * Perform a rank-1 update of A(k+1:n,k+1:n) as
  833. * A := A - L(k)*D(k)*L(k)**T
  834. * = A - W(k)*(1/D(k))*W(k)**T
  835. *
  836. D11 = CONE / A( K, K )
  837. CALL CSYR( UPLO, N-K, -D11, A( K+1, K ), 1,
  838. $ A( K+1, K+1 ), LDA )
  839. *
  840. * Store L(k) in column k
  841. *
  842. CALL CSCAL( N-K, D11, A( K+1, K ), 1 )
  843. ELSE
  844. *
  845. * Store L(k) in column k
  846. *
  847. D11 = A( K, K )
  848. DO 46 II = K + 1, N
  849. A( II, K ) = A( II, K ) / D11
  850. 46 CONTINUE
  851. *
  852. * Perform a rank-1 update of A(k+1:n,k+1:n) as
  853. * A := A - L(k)*D(k)*L(k)**T
  854. * = A - W(k)*(1/D(k))*W(k)**T
  855. * = A - (W(k)/D(k))*(D(k))*(W(k)/D(K))**T
  856. *
  857. CALL CSYR( UPLO, N-K, -D11, A( K+1, K ), 1,
  858. $ A( K+1, K+1 ), LDA )
  859. END IF
  860. *
  861. * Store the subdiagonal element of D in array E
  862. *
  863. E( K ) = CZERO
  864. *
  865. END IF
  866. *
  867. ELSE
  868. *
  869. * 2-by-2 pivot block D(k): columns k and k+1 now hold
  870. *
  871. * ( W(k) W(k+1) ) = ( L(k) L(k+1) )*D(k)
  872. *
  873. * where L(k) and L(k+1) are the k-th and (k+1)-th columns
  874. * of L
  875. *
  876. *
  877. * Perform a rank-2 update of A(k+2:n,k+2:n) as
  878. *
  879. * A := A - ( L(k) L(k+1) ) * D(k) * ( L(k) L(k+1) )**T
  880. * = A - ( ( A(k)A(k+1) )*inv(D(k) ) * ( A(k)A(k+1) )**T
  881. *
  882. * and store L(k) and L(k+1) in columns k and k+1
  883. *
  884. IF( K.LT.N-1 ) THEN
  885. *
  886. D21 = A( K+1, K )
  887. D11 = A( K+1, K+1 ) / D21
  888. D22 = A( K, K ) / D21
  889. T = CONE / ( D11*D22-CONE )
  890. *
  891. DO 60 J = K + 2, N
  892. *
  893. * Compute D21 * ( W(k)W(k+1) ) * inv(D(k)) for row J
  894. *
  895. WK = T*( D11*A( J, K )-A( J, K+1 ) )
  896. WKP1 = T*( D22*A( J, K+1 )-A( J, K ) )
  897. *
  898. * Perform a rank-2 update of A(k+2:n,k+2:n)
  899. *
  900. DO 50 I = J, N
  901. A( I, J ) = A( I, J ) - ( A( I, K ) / D21 )*WK -
  902. $ ( A( I, K+1 ) / D21 )*WKP1
  903. 50 CONTINUE
  904. *
  905. * Store L(k) and L(k+1) in cols k and k+1 for row J
  906. *
  907. A( J, K ) = WK / D21
  908. A( J, K+1 ) = WKP1 / D21
  909. *
  910. 60 CONTINUE
  911. *
  912. END IF
  913. *
  914. * Copy subdiagonal elements of D(K) to E(K) and
  915. * ZERO out subdiagonal entry of A
  916. *
  917. E( K ) = A( K+1, K )
  918. E( K+1 ) = CZERO
  919. A( K+1, K ) = CZERO
  920. *
  921. END IF
  922. *
  923. * End column K is nonsingular
  924. *
  925. END IF
  926. *
  927. * Store details of the interchanges in IPIV
  928. *
  929. IF( KSTEP.EQ.1 ) THEN
  930. IPIV( K ) = KP
  931. ELSE
  932. IPIV( K ) = -P
  933. IPIV( K+1 ) = -KP
  934. END IF
  935. *
  936. * Increase K and return to the start of the main loop
  937. *
  938. K = K + KSTEP
  939. GO TO 40
  940. *
  941. 64 CONTINUE
  942. *
  943. END IF
  944. *
  945. RETURN
  946. *
  947. * End of CSYTF2_RK
  948. *
  949. END