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.

slar1v.f 15 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. *> \brief \b SLAR1V computes the (scaled) r-th column of the inverse of the submatrix in rows b1 through bn of the tridiagonal matrix LDLT - λI.
  2. *
  3. * =========== DOCUMENTATION ===========
  4. *
  5. * Online html documentation available at
  6. * http://www.netlib.org/lapack/explore-html/
  7. *
  8. *> \htmlonly
  9. *> Download SLAR1V + dependencies
  10. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slar1v.f">
  11. *> [TGZ]</a>
  12. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slar1v.f">
  13. *> [ZIP]</a>
  14. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slar1v.f">
  15. *> [TXT]</a>
  16. *> \endhtmlonly
  17. *
  18. * Definition:
  19. * ===========
  20. *
  21. * SUBROUTINE SLAR1V( N, B1, BN, LAMBDA, D, L, LD, LLD,
  22. * PIVMIN, GAPTOL, Z, WANTNC, NEGCNT, ZTZ, MINGMA,
  23. * R, ISUPPZ, NRMINV, RESID, RQCORR, WORK )
  24. *
  25. * .. Scalar Arguments ..
  26. * LOGICAL WANTNC
  27. * INTEGER B1, BN, N, NEGCNT, R
  28. * REAL GAPTOL, LAMBDA, MINGMA, NRMINV, PIVMIN, RESID,
  29. * $ RQCORR, ZTZ
  30. * ..
  31. * .. Array Arguments ..
  32. * INTEGER ISUPPZ( * )
  33. * REAL D( * ), L( * ), LD( * ), LLD( * ),
  34. * $ WORK( * )
  35. * REAL Z( * )
  36. * ..
  37. *
  38. *
  39. *> \par Purpose:
  40. * =============
  41. *>
  42. *> \verbatim
  43. *>
  44. *> SLAR1V computes the (scaled) r-th column of the inverse of
  45. *> the sumbmatrix in rows B1 through BN of the tridiagonal matrix
  46. *> L D L**T - sigma I. When sigma is close to an eigenvalue, the
  47. *> computed vector is an accurate eigenvector. Usually, r corresponds
  48. *> to the index where the eigenvector is largest in magnitude.
  49. *> The following steps accomplish this computation :
  50. *> (a) Stationary qd transform, L D L**T - sigma I = L(+) D(+) L(+)**T,
  51. *> (b) Progressive qd transform, L D L**T - sigma I = U(-) D(-) U(-)**T,
  52. *> (c) Computation of the diagonal elements of the inverse of
  53. *> L D L**T - sigma I by combining the above transforms, and choosing
  54. *> r as the index where the diagonal of the inverse is (one of the)
  55. *> largest in magnitude.
  56. *> (d) Computation of the (scaled) r-th column of the inverse using the
  57. *> twisted factorization obtained by combining the top part of the
  58. *> the stationary and the bottom part of the progressive transform.
  59. *> \endverbatim
  60. *
  61. * Arguments:
  62. * ==========
  63. *
  64. *> \param[in] N
  65. *> \verbatim
  66. *> N is INTEGER
  67. *> The order of the matrix L D L**T.
  68. *> \endverbatim
  69. *>
  70. *> \param[in] B1
  71. *> \verbatim
  72. *> B1 is INTEGER
  73. *> First index of the submatrix of L D L**T.
  74. *> \endverbatim
  75. *>
  76. *> \param[in] BN
  77. *> \verbatim
  78. *> BN is INTEGER
  79. *> Last index of the submatrix of L D L**T.
  80. *> \endverbatim
  81. *>
  82. *> \param[in] LAMBDA
  83. *> \verbatim
  84. *> LAMBDA is REAL
  85. *> The shift. In order to compute an accurate eigenvector,
  86. *> LAMBDA should be a good approximation to an eigenvalue
  87. *> of L D L**T.
  88. *> \endverbatim
  89. *>
  90. *> \param[in] L
  91. *> \verbatim
  92. *> L is REAL array, dimension (N-1)
  93. *> The (n-1) subdiagonal elements of the unit bidiagonal matrix
  94. *> L, in elements 1 to N-1.
  95. *> \endverbatim
  96. *>
  97. *> \param[in] D
  98. *> \verbatim
  99. *> D is REAL array, dimension (N)
  100. *> The n diagonal elements of the diagonal matrix D.
  101. *> \endverbatim
  102. *>
  103. *> \param[in] LD
  104. *> \verbatim
  105. *> LD is REAL array, dimension (N-1)
  106. *> The n-1 elements L(i)*D(i).
  107. *> \endverbatim
  108. *>
  109. *> \param[in] LLD
  110. *> \verbatim
  111. *> LLD is REAL array, dimension (N-1)
  112. *> The n-1 elements L(i)*L(i)*D(i).
  113. *> \endverbatim
  114. *>
  115. *> \param[in] PIVMIN
  116. *> \verbatim
  117. *> PIVMIN is REAL
  118. *> The minimum pivot in the Sturm sequence.
  119. *> \endverbatim
  120. *>
  121. *> \param[in] GAPTOL
  122. *> \verbatim
  123. *> GAPTOL is REAL
  124. *> Tolerance that indicates when eigenvector entries are negligible
  125. *> w.r.t. their contribution to the residual.
  126. *> \endverbatim
  127. *>
  128. *> \param[in,out] Z
  129. *> \verbatim
  130. *> Z is REAL array, dimension (N)
  131. *> On input, all entries of Z must be set to 0.
  132. *> On output, Z contains the (scaled) r-th column of the
  133. *> inverse. The scaling is such that Z(R) equals 1.
  134. *> \endverbatim
  135. *>
  136. *> \param[in] WANTNC
  137. *> \verbatim
  138. *> WANTNC is LOGICAL
  139. *> Specifies whether NEGCNT has to be computed.
  140. *> \endverbatim
  141. *>
  142. *> \param[out] NEGCNT
  143. *> \verbatim
  144. *> NEGCNT is INTEGER
  145. *> If WANTNC is .TRUE. then NEGCNT = the number of pivots < pivmin
  146. *> in the matrix factorization L D L**T, and NEGCNT = -1 otherwise.
  147. *> \endverbatim
  148. *>
  149. *> \param[out] ZTZ
  150. *> \verbatim
  151. *> ZTZ is REAL
  152. *> The square of the 2-norm of Z.
  153. *> \endverbatim
  154. *>
  155. *> \param[out] MINGMA
  156. *> \verbatim
  157. *> MINGMA is REAL
  158. *> The reciprocal of the largest (in magnitude) diagonal
  159. *> element of the inverse of L D L**T - sigma I.
  160. *> \endverbatim
  161. *>
  162. *> \param[in,out] R
  163. *> \verbatim
  164. *> R is INTEGER
  165. *> The twist index for the twisted factorization used to
  166. *> compute Z.
  167. *> On input, 0 <= R <= N. If R is input as 0, R is set to
  168. *> the index where (L D L**T - sigma I)^{-1} is largest
  169. *> in magnitude. If 1 <= R <= N, R is unchanged.
  170. *> On output, R contains the twist index used to compute Z.
  171. *> Ideally, R designates the position of the maximum entry in the
  172. *> eigenvector.
  173. *> \endverbatim
  174. *>
  175. *> \param[out] ISUPPZ
  176. *> \verbatim
  177. *> ISUPPZ is INTEGER array, dimension (2)
  178. *> The support of the vector in Z, i.e., the vector Z is
  179. *> nonzero only in elements ISUPPZ(1) through ISUPPZ( 2 ).
  180. *> \endverbatim
  181. *>
  182. *> \param[out] NRMINV
  183. *> \verbatim
  184. *> NRMINV is REAL
  185. *> NRMINV = 1/SQRT( ZTZ )
  186. *> \endverbatim
  187. *>
  188. *> \param[out] RESID
  189. *> \verbatim
  190. *> RESID is REAL
  191. *> The residual of the FP vector.
  192. *> RESID = ABS( MINGMA )/SQRT( ZTZ )
  193. *> \endverbatim
  194. *>
  195. *> \param[out] RQCORR
  196. *> \verbatim
  197. *> RQCORR is REAL
  198. *> The Rayleigh Quotient correction to LAMBDA.
  199. *> RQCORR = MINGMA*TMP
  200. *> \endverbatim
  201. *>
  202. *> \param[out] WORK
  203. *> \verbatim
  204. *> WORK is REAL array, dimension (4*N)
  205. *> \endverbatim
  206. *
  207. * Authors:
  208. * ========
  209. *
  210. *> \author Univ. of Tennessee
  211. *> \author Univ. of California Berkeley
  212. *> \author Univ. of Colorado Denver
  213. *> \author NAG Ltd.
  214. *
  215. *> \date December 2016
  216. *
  217. *> \ingroup realOTHERauxiliary
  218. *
  219. *> \par Contributors:
  220. * ==================
  221. *>
  222. *> Beresford Parlett, University of California, Berkeley, USA \n
  223. *> Jim Demmel, University of California, Berkeley, USA \n
  224. *> Inderjit Dhillon, University of Texas, Austin, USA \n
  225. *> Osni Marques, LBNL/NERSC, USA \n
  226. *> Christof Voemel, University of California, Berkeley, USA
  227. *
  228. * =====================================================================
  229. SUBROUTINE SLAR1V( N, B1, BN, LAMBDA, D, L, LD, LLD,
  230. $ PIVMIN, GAPTOL, Z, WANTNC, NEGCNT, ZTZ, MINGMA,
  231. $ R, ISUPPZ, NRMINV, RESID, RQCORR, WORK )
  232. *
  233. * -- LAPACK auxiliary routine (version 3.7.0) --
  234. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  235. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  236. * December 2016
  237. *
  238. * .. Scalar Arguments ..
  239. LOGICAL WANTNC
  240. INTEGER B1, BN, N, NEGCNT, R
  241. REAL GAPTOL, LAMBDA, MINGMA, NRMINV, PIVMIN, RESID,
  242. $ RQCORR, ZTZ
  243. * ..
  244. * .. Array Arguments ..
  245. INTEGER ISUPPZ( * )
  246. REAL D( * ), L( * ), LD( * ), LLD( * ),
  247. $ WORK( * )
  248. REAL Z( * )
  249. * ..
  250. *
  251. * =====================================================================
  252. *
  253. * .. Parameters ..
  254. REAL ZERO, ONE
  255. PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 )
  256. * ..
  257. * .. Local Scalars ..
  258. LOGICAL SAWNAN1, SAWNAN2
  259. INTEGER I, INDLPL, INDP, INDS, INDUMN, NEG1, NEG2, R1,
  260. $ R2
  261. REAL DMINUS, DPLUS, EPS, S, TMP
  262. * ..
  263. * .. External Functions ..
  264. LOGICAL SISNAN
  265. REAL SLAMCH
  266. EXTERNAL SISNAN, SLAMCH
  267. * ..
  268. * .. Intrinsic Functions ..
  269. INTRINSIC ABS
  270. * ..
  271. * .. Executable Statements ..
  272. *
  273. EPS = SLAMCH( 'Precision' )
  274. IF( R.EQ.0 ) THEN
  275. R1 = B1
  276. R2 = BN
  277. ELSE
  278. R1 = R
  279. R2 = R
  280. END IF
  281. * Storage for LPLUS
  282. INDLPL = 0
  283. * Storage for UMINUS
  284. INDUMN = N
  285. INDS = 2*N + 1
  286. INDP = 3*N + 1
  287. IF( B1.EQ.1 ) THEN
  288. WORK( INDS ) = ZERO
  289. ELSE
  290. WORK( INDS+B1-1 ) = LLD( B1-1 )
  291. END IF
  292. *
  293. * Compute the stationary transform (using the differential form)
  294. * until the index R2.
  295. *
  296. SAWNAN1 = .FALSE.
  297. NEG1 = 0
  298. S = WORK( INDS+B1-1 ) - LAMBDA
  299. DO 50 I = B1, R1 - 1
  300. DPLUS = D( I ) + S
  301. WORK( INDLPL+I ) = LD( I ) / DPLUS
  302. IF(DPLUS.LT.ZERO) NEG1 = NEG1 + 1
  303. WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I )
  304. S = WORK( INDS+I ) - LAMBDA
  305. 50 CONTINUE
  306. SAWNAN1 = SISNAN( S )
  307. IF( SAWNAN1 ) GOTO 60
  308. DO 51 I = R1, R2 - 1
  309. DPLUS = D( I ) + S
  310. WORK( INDLPL+I ) = LD( I ) / DPLUS
  311. WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I )
  312. S = WORK( INDS+I ) - LAMBDA
  313. 51 CONTINUE
  314. SAWNAN1 = SISNAN( S )
  315. *
  316. 60 CONTINUE
  317. IF( SAWNAN1 ) THEN
  318. * Runs a slower version of the above loop if a NaN is detected
  319. NEG1 = 0
  320. S = WORK( INDS+B1-1 ) - LAMBDA
  321. DO 70 I = B1, R1 - 1
  322. DPLUS = D( I ) + S
  323. IF(ABS(DPLUS).LT.PIVMIN) DPLUS = -PIVMIN
  324. WORK( INDLPL+I ) = LD( I ) / DPLUS
  325. IF(DPLUS.LT.ZERO) NEG1 = NEG1 + 1
  326. WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I )
  327. IF( WORK( INDLPL+I ).EQ.ZERO )
  328. $ WORK( INDS+I ) = LLD( I )
  329. S = WORK( INDS+I ) - LAMBDA
  330. 70 CONTINUE
  331. DO 71 I = R1, R2 - 1
  332. DPLUS = D( I ) + S
  333. IF(ABS(DPLUS).LT.PIVMIN) DPLUS = -PIVMIN
  334. WORK( INDLPL+I ) = LD( I ) / DPLUS
  335. WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I )
  336. IF( WORK( INDLPL+I ).EQ.ZERO )
  337. $ WORK( INDS+I ) = LLD( I )
  338. S = WORK( INDS+I ) - LAMBDA
  339. 71 CONTINUE
  340. END IF
  341. *
  342. * Compute the progressive transform (using the differential form)
  343. * until the index R1
  344. *
  345. SAWNAN2 = .FALSE.
  346. NEG2 = 0
  347. WORK( INDP+BN-1 ) = D( BN ) - LAMBDA
  348. DO 80 I = BN - 1, R1, -1
  349. DMINUS = LLD( I ) + WORK( INDP+I )
  350. TMP = D( I ) / DMINUS
  351. IF(DMINUS.LT.ZERO) NEG2 = NEG2 + 1
  352. WORK( INDUMN+I ) = L( I )*TMP
  353. WORK( INDP+I-1 ) = WORK( INDP+I )*TMP - LAMBDA
  354. 80 CONTINUE
  355. TMP = WORK( INDP+R1-1 )
  356. SAWNAN2 = SISNAN( TMP )
  357. IF( SAWNAN2 ) THEN
  358. * Runs a slower version of the above loop if a NaN is detected
  359. NEG2 = 0
  360. DO 100 I = BN-1, R1, -1
  361. DMINUS = LLD( I ) + WORK( INDP+I )
  362. IF(ABS(DMINUS).LT.PIVMIN) DMINUS = -PIVMIN
  363. TMP = D( I ) / DMINUS
  364. IF(DMINUS.LT.ZERO) NEG2 = NEG2 + 1
  365. WORK( INDUMN+I ) = L( I )*TMP
  366. WORK( INDP+I-1 ) = WORK( INDP+I )*TMP - LAMBDA
  367. IF( TMP.EQ.ZERO )
  368. $ WORK( INDP+I-1 ) = D( I ) - LAMBDA
  369. 100 CONTINUE
  370. END IF
  371. *
  372. * Find the index (from R1 to R2) of the largest (in magnitude)
  373. * diagonal element of the inverse
  374. *
  375. MINGMA = WORK( INDS+R1-1 ) + WORK( INDP+R1-1 )
  376. IF( MINGMA.LT.ZERO ) NEG1 = NEG1 + 1
  377. IF( WANTNC ) THEN
  378. NEGCNT = NEG1 + NEG2
  379. ELSE
  380. NEGCNT = -1
  381. ENDIF
  382. IF( ABS(MINGMA).EQ.ZERO )
  383. $ MINGMA = EPS*WORK( INDS+R1-1 )
  384. R = R1
  385. DO 110 I = R1, R2 - 1
  386. TMP = WORK( INDS+I ) + WORK( INDP+I )
  387. IF( TMP.EQ.ZERO )
  388. $ TMP = EPS*WORK( INDS+I )
  389. IF( ABS( TMP ).LE.ABS( MINGMA ) ) THEN
  390. MINGMA = TMP
  391. R = I + 1
  392. END IF
  393. 110 CONTINUE
  394. *
  395. * Compute the FP vector: solve N^T v = e_r
  396. *
  397. ISUPPZ( 1 ) = B1
  398. ISUPPZ( 2 ) = BN
  399. Z( R ) = ONE
  400. ZTZ = ONE
  401. *
  402. * Compute the FP vector upwards from R
  403. *
  404. IF( .NOT.SAWNAN1 .AND. .NOT.SAWNAN2 ) THEN
  405. DO 210 I = R-1, B1, -1
  406. Z( I ) = -( WORK( INDLPL+I )*Z( I+1 ) )
  407. IF( (ABS(Z(I))+ABS(Z(I+1)))* ABS(LD(I)).LT.GAPTOL )
  408. $ THEN
  409. Z( I ) = ZERO
  410. ISUPPZ( 1 ) = I + 1
  411. GOTO 220
  412. ENDIF
  413. ZTZ = ZTZ + Z( I )*Z( I )
  414. 210 CONTINUE
  415. 220 CONTINUE
  416. ELSE
  417. * Run slower loop if NaN occurred.
  418. DO 230 I = R - 1, B1, -1
  419. IF( Z( I+1 ).EQ.ZERO ) THEN
  420. Z( I ) = -( LD( I+1 ) / LD( I ) )*Z( I+2 )
  421. ELSE
  422. Z( I ) = -( WORK( INDLPL+I )*Z( I+1 ) )
  423. END IF
  424. IF( (ABS(Z(I))+ABS(Z(I+1)))* ABS(LD(I)).LT.GAPTOL )
  425. $ THEN
  426. Z( I ) = ZERO
  427. ISUPPZ( 1 ) = I + 1
  428. GO TO 240
  429. END IF
  430. ZTZ = ZTZ + Z( I )*Z( I )
  431. 230 CONTINUE
  432. 240 CONTINUE
  433. ENDIF
  434. * Compute the FP vector downwards from R in blocks of size BLKSIZ
  435. IF( .NOT.SAWNAN1 .AND. .NOT.SAWNAN2 ) THEN
  436. DO 250 I = R, BN-1
  437. Z( I+1 ) = -( WORK( INDUMN+I )*Z( I ) )
  438. IF( (ABS(Z(I))+ABS(Z(I+1)))* ABS(LD(I)).LT.GAPTOL )
  439. $ THEN
  440. Z( I+1 ) = ZERO
  441. ISUPPZ( 2 ) = I
  442. GO TO 260
  443. END IF
  444. ZTZ = ZTZ + Z( I+1 )*Z( I+1 )
  445. 250 CONTINUE
  446. 260 CONTINUE
  447. ELSE
  448. * Run slower loop if NaN occurred.
  449. DO 270 I = R, BN - 1
  450. IF( Z( I ).EQ.ZERO ) THEN
  451. Z( I+1 ) = -( LD( I-1 ) / LD( I ) )*Z( I-1 )
  452. ELSE
  453. Z( I+1 ) = -( WORK( INDUMN+I )*Z( I ) )
  454. END IF
  455. IF( (ABS(Z(I))+ABS(Z(I+1)))* ABS(LD(I)).LT.GAPTOL )
  456. $ THEN
  457. Z( I+1 ) = ZERO
  458. ISUPPZ( 2 ) = I
  459. GO TO 280
  460. END IF
  461. ZTZ = ZTZ + Z( I+1 )*Z( I+1 )
  462. 270 CONTINUE
  463. 280 CONTINUE
  464. END IF
  465. *
  466. * Compute quantities for convergence test
  467. *
  468. TMP = ONE / ZTZ
  469. NRMINV = SQRT( TMP )
  470. RESID = ABS( MINGMA )*NRMINV
  471. RQCORR = MINGMA*TMP
  472. *
  473. *
  474. RETURN
  475. *
  476. * End of SLAR1V
  477. *
  478. END