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.

dlaqr5.f 40 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  1. ! Copyright (c) 2013-2016, The OpenBLAS Project
  2. ! All rights reserved.
  3. ! Redistribution and use in source and binary forms, with or without
  4. ! modification, are permitted provided that the following conditions are
  5. ! met:
  6. ! 1. Redistributions of source code must retain the above copyright
  7. ! notice, this list of conditions and the following disclaimer.
  8. ! 2. Redistributions in binary form must reproduce the above copyright
  9. ! notice, this list of conditions and the following disclaimer in
  10. ! the documentation and/or other materials provided with the
  11. ! distribution.
  12. ! 3. Neither the name of the OpenBLAS project nor the names of
  13. ! its contributors may be used to endorse or promote products
  14. ! derived from this software without specific prior written permission.
  15. ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. ! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. ! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. ! ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBLAS PROJECT OR CONTRIBUTORS BE
  19. ! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. ! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. ! SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. ! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. ! OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  24. ! USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. *> \brief \b DLAQR5 performs a single small-bulge multi-shift QR sweep.
  26. *
  27. * =========== DOCUMENTATION ===========
  28. *
  29. * Online html documentation available at
  30. * http://www.netlib.org/lapack/explore-html/
  31. *
  32. *> \htmlonly
  33. *> Download DLAQR5 + dependencies
  34. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlaqr5.f">
  35. *> [TGZ]</a>
  36. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlaqr5.f">
  37. *> [ZIP]</a>
  38. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlaqr5.f">
  39. *> [TXT]</a>
  40. *> \endhtmlonly
  41. *
  42. * Definition:
  43. * ===========
  44. *
  45. * SUBROUTINE DLAQR5( WANTT, WANTZ, KACC22, N, KTOP, KBOT, NSHFTS,
  46. * SR, SI, H, LDH, ILOZ, IHIZ, Z, LDZ, V, LDV, U,
  47. * LDU, NV, WV, LDWV, NH, WH, LDWH )
  48. *
  49. * .. Scalar Arguments ..
  50. * INTEGER IHIZ, ILOZ, KACC22, KBOT, KTOP, LDH, LDU, LDV,
  51. * $ LDWH, LDWV, LDZ, N, NH, NSHFTS, NV
  52. * LOGICAL WANTT, WANTZ
  53. * ..
  54. * .. Array Arguments ..
  55. * DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), U( LDU, * ),
  56. * $ V( LDV, * ), WH( LDWH, * ), WV( LDWV, * ),
  57. * $ Z( LDZ, * )
  58. * ..
  59. *
  60. *
  61. *> \par Purpose:
  62. * =============
  63. *>
  64. *> \verbatim
  65. *>
  66. *> DLAQR5, called by DLAQR0, performs a
  67. *> single small-bulge multi-shift QR sweep.
  68. *> \endverbatim
  69. *
  70. * Arguments:
  71. * ==========
  72. *
  73. *> \param[in] WANTT
  74. *> \verbatim
  75. *> WANTT is logical scalar
  76. *> WANTT = .true. if the quasi-triangular Schur factor
  77. *> is being computed. WANTT is set to .false. otherwise.
  78. *> \endverbatim
  79. *>
  80. *> \param[in] WANTZ
  81. *> \verbatim
  82. *> WANTZ is logical scalar
  83. *> WANTZ = .true. if the orthogonal Schur factor is being
  84. *> computed. WANTZ is set to .false. otherwise.
  85. *> \endverbatim
  86. *>
  87. *> \param[in] KACC22
  88. *> \verbatim
  89. *> KACC22 is integer with value 0, 1, or 2.
  90. *> Specifies the computation mode of far-from-diagonal
  91. *> orthogonal updates.
  92. *> = 0: DLAQR5 does not accumulate reflections and does not
  93. *> use matrix-matrix multiply to update far-from-diagonal
  94. *> matrix entries.
  95. *> = 1: DLAQR5 accumulates reflections and uses matrix-matrix
  96. *> multiply to update the far-from-diagonal matrix entries.
  97. *> = 2: DLAQR5 accumulates reflections, uses matrix-matrix
  98. *> multiply to update the far-from-diagonal matrix entries,
  99. *> and takes advantage of 2-by-2 block structure during
  100. *> matrix multiplies.
  101. *> \endverbatim
  102. *>
  103. *> \param[in] N
  104. *> \verbatim
  105. *> N is integer scalar
  106. *> N is the order of the Hessenberg matrix H upon which this
  107. *> subroutine operates.
  108. *> \endverbatim
  109. *>
  110. *> \param[in] KTOP
  111. *> \verbatim
  112. *> KTOP is integer scalar
  113. *> \endverbatim
  114. *>
  115. *> \param[in] KBOT
  116. *> \verbatim
  117. *> KBOT is integer scalar
  118. *> These are the first and last rows and columns of an
  119. *> isolated diagonal block upon which the QR sweep is to be
  120. *> applied. It is assumed without a check that
  121. *> either KTOP = 1 or H(KTOP,KTOP-1) = 0
  122. *> and
  123. *> either KBOT = N or H(KBOT+1,KBOT) = 0.
  124. *> \endverbatim
  125. *>
  126. *> \param[in] NSHFTS
  127. *> \verbatim
  128. *> NSHFTS is integer scalar
  129. *> NSHFTS gives the number of simultaneous shifts. NSHFTS
  130. *> must be positive and even.
  131. *> \endverbatim
  132. *>
  133. *> \param[in,out] SR
  134. *> \verbatim
  135. *> SR is DOUBLE PRECISION array of size (NSHFTS)
  136. *> \endverbatim
  137. *>
  138. *> \param[in,out] SI
  139. *> \verbatim
  140. *> SI is DOUBLE PRECISION array of size (NSHFTS)
  141. *> SR contains the real parts and SI contains the imaginary
  142. *> parts of the NSHFTS shifts of origin that define the
  143. *> multi-shift QR sweep. On output SR and SI may be
  144. *> reordered.
  145. *> \endverbatim
  146. *>
  147. *> \param[in,out] H
  148. *> \verbatim
  149. *> H is DOUBLE PRECISION array of size (LDH,N)
  150. *> On input H contains a Hessenberg matrix. On output a
  151. *> multi-shift QR sweep with shifts SR(J)+i*SI(J) is applied
  152. *> to the isolated diagonal block in rows and columns KTOP
  153. *> through KBOT.
  154. *> \endverbatim
  155. *>
  156. *> \param[in] LDH
  157. *> \verbatim
  158. *> LDH is integer scalar
  159. *> LDH is the leading dimension of H just as declared in the
  160. *> calling procedure. LDH.GE.MAX(1,N).
  161. *> \endverbatim
  162. *>
  163. *> \param[in] ILOZ
  164. *> \verbatim
  165. *> ILOZ is INTEGER
  166. *> \endverbatim
  167. *>
  168. *> \param[in] IHIZ
  169. *> \verbatim
  170. *> IHIZ is INTEGER
  171. *> Specify the rows of Z to which transformations must be
  172. *> applied if WANTZ is .TRUE.. 1 .LE. ILOZ .LE. IHIZ .LE. N
  173. *> \endverbatim
  174. *>
  175. *> \param[in,out] Z
  176. *> \verbatim
  177. *> Z is DOUBLE PRECISION array of size (LDZ,IHI)
  178. *> If WANTZ = .TRUE., then the QR Sweep orthogonal
  179. *> similarity transformation is accumulated into
  180. *> Z(ILOZ:IHIZ,ILO:IHI) from the right.
  181. *> If WANTZ = .FALSE., then Z is unreferenced.
  182. *> \endverbatim
  183. *>
  184. *> \param[in] LDZ
  185. *> \verbatim
  186. *> LDZ is integer scalar
  187. *> LDA is the leading dimension of Z just as declared in
  188. *> the calling procedure. LDZ.GE.N.
  189. *> \endverbatim
  190. *>
  191. *> \param[out] V
  192. *> \verbatim
  193. *> V is DOUBLE PRECISION array of size (LDV,NSHFTS/2)
  194. *> \endverbatim
  195. *>
  196. *> \param[in] LDV
  197. *> \verbatim
  198. *> LDV is integer scalar
  199. *> LDV is the leading dimension of V as declared in the
  200. *> calling procedure. LDV.GE.3.
  201. *> \endverbatim
  202. *>
  203. *> \param[out] U
  204. *> \verbatim
  205. *> U is DOUBLE PRECISION array of size
  206. *> (LDU,3*NSHFTS-3)
  207. *> \endverbatim
  208. *>
  209. *> \param[in] LDU
  210. *> \verbatim
  211. *> LDU is integer scalar
  212. *> LDU is the leading dimension of U just as declared in the
  213. *> in the calling subroutine. LDU.GE.3*NSHFTS-3.
  214. *> \endverbatim
  215. *>
  216. *> \param[in] NH
  217. *> \verbatim
  218. *> NH is integer scalar
  219. *> NH is the number of columns in array WH available for
  220. *> workspace. NH.GE.1.
  221. *> \endverbatim
  222. *>
  223. *> \param[out] WH
  224. *> \verbatim
  225. *> WH is DOUBLE PRECISION array of size (LDWH,NH)
  226. *> \endverbatim
  227. *>
  228. *> \param[in] LDWH
  229. *> \verbatim
  230. *> LDWH is integer scalar
  231. *> Leading dimension of WH just as declared in the
  232. *> calling procedure. LDWH.GE.3*NSHFTS-3.
  233. *> \endverbatim
  234. *>
  235. *> \param[in] NV
  236. *> \verbatim
  237. *> NV is integer scalar
  238. *> NV is the number of rows in WV agailable for workspace.
  239. *> NV.GE.1.
  240. *> \endverbatim
  241. *>
  242. *> \param[out] WV
  243. *> \verbatim
  244. *> WV is DOUBLE PRECISION array of size
  245. *> (LDWV,3*NSHFTS-3)
  246. *> \endverbatim
  247. *>
  248. *> \param[in] LDWV
  249. *> \verbatim
  250. *> LDWV is integer scalar
  251. *> LDWV is the leading dimension of WV as declared in the
  252. *> in the calling subroutine. LDWV.GE.NV.
  253. *> \endverbatim
  254. *
  255. * Authors:
  256. * ========
  257. *
  258. *> \author Univ. of Tennessee
  259. *> \author Univ. of California Berkeley
  260. *> \author Univ. of Colorado Denver
  261. *> \author NAG Ltd.
  262. *
  263. *> \date September 2012
  264. *
  265. *> \ingroup doubleOTHERauxiliary
  266. *
  267. *> \par Contributors:
  268. * ==================
  269. *>
  270. *> Karen Braman and Ralph Byers, Department of Mathematics,
  271. *> University of Kansas, USA
  272. *
  273. *> \par References:
  274. * ================
  275. *>
  276. *> K. Braman, R. Byers and R. Mathias, The Multi-Shift QR
  277. *> Algorithm Part I: Maintaining Well Focused Shifts, and Level 3
  278. *> Performance, SIAM Journal of Matrix Analysis, volume 23, pages
  279. *> 929--947, 2002.
  280. *>
  281. * =====================================================================
  282. SUBROUTINE DLAQR5( WANTT, WANTZ, KACC22, N, KTOP, KBOT, NSHFTS,
  283. $ SR, SI, H, LDH, ILOZ, IHIZ, Z, LDZ, V, LDV, U,
  284. $ LDU, NV, WV, LDWV, NH, WH, LDWH )
  285. *
  286. * -- LAPACK auxiliary routine (version 3.4.2) --
  287. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  288. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  289. * September 2012
  290. *
  291. * .. Scalar Arguments ..
  292. INTEGER IHIZ, ILOZ, KACC22, KBOT, KTOP, LDH, LDU, LDV,
  293. $ LDWH, LDWV, LDZ, N, NH, NSHFTS, NV
  294. LOGICAL WANTT, WANTZ
  295. * ..
  296. * .. Array Arguments ..
  297. DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), U( LDU, * ),
  298. $ V( LDV, * ), WH( LDWH, * ), WV( LDWV, * ),
  299. $ Z( LDZ, * )
  300. * ..
  301. *
  302. * ================================================================
  303. * .. Parameters ..
  304. DOUBLE PRECISION ZERO, ONE
  305. PARAMETER ( ZERO = 0.0d0, ONE = 1.0d0 )
  306. * ..
  307. * .. Local Scalars ..
  308. DOUBLE PRECISION ALPHA, BETA, H11, H12, H21, H22, REFSUM,
  309. $ SAFMAX, SAFMIN, SCL, SMLNUM, SWAP, TST1, TST2,
  310. $ ULP
  311. INTEGER I, I2, I4, INCOL, J, J2, J4, JBOT, JCOL, JLEN,
  312. $ JROW, JTOP, K, K1, KDU, KMS, KNZ, KRCOL, KZS,
  313. $ M, M22, MBOT, MEND, MSTART, MTOP, NBMPS, NDCOL,
  314. $ NS, NU
  315. LOGICAL ACCUM, BLK22, BMP22
  316. * ..
  317. * .. External Functions ..
  318. DOUBLE PRECISION DLAMCH
  319. EXTERNAL DLAMCH
  320. * ..
  321. * .. Intrinsic Functions ..
  322. *
  323. INTRINSIC ABS, DBLE, MAX, MIN, MOD
  324. * ..
  325. * .. Local Arrays ..
  326. DOUBLE PRECISION VT( 3 )
  327. * temp scalars
  328. DOUBLE PRECISION tempv1, tempv2, tempv3,
  329. $ tempv4, tempv5, tempv6,
  330. $ temph1, temph2, temph3,
  331. $ temph4, temph5, temph6,
  332. $ tempz1, tempz2, tempz3,
  333. $ tempz4, tempz5, tempz6,
  334. $ tempu1, tempu2, tempu3,
  335. $ tempu4, tempu5, tempu6,
  336. $ REFSU1
  337. INTEGER JBEGIN, M1
  338. * ..
  339. * .. External Subroutines ..
  340. EXTERNAL DGEMM, DLABAD, DLACPY, DLAQR1, DLARFG, DLASET,
  341. $ DTRMM
  342. * ..
  343. * .. Executable Statements ..
  344. *
  345. * ==== If there are no shifts, then there is nothing to do. ====
  346. *
  347. IF( NSHFTS.LT.2 )
  348. $ RETURN
  349. *
  350. * ==== If the active block is empty or 1-by-1, then there
  351. * . is nothing to do. ====
  352. *
  353. IF( KTOP.GE.KBOT )
  354. $ RETURN
  355. *
  356. * ==== Shuffle shifts into pairs of real shifts and pairs
  357. * . of complex conjugate shifts assuming complex
  358. * . conjugate shifts are already adjacent to one
  359. * . another. ====
  360. *
  361. DO 10 I = 1, NSHFTS - 2, 2
  362. IF( SI( I ).NE.-SI( I+1 ) ) THEN
  363. *
  364. SWAP = SR( I )
  365. SR( I ) = SR( I+1 )
  366. SR( I+1 ) = SR( I+2 )
  367. SR( I+2 ) = SWAP
  368. *
  369. SWAP = SI( I )
  370. SI( I ) = SI( I+1 )
  371. SI( I+1 ) = SI( I+2 )
  372. SI( I+2 ) = SWAP
  373. END IF
  374. 10 CONTINUE
  375. *
  376. * ==== NSHFTS is supposed to be even, but if it is odd,
  377. * . then simply reduce it by one. The shuffle above
  378. * . ensures that the dropped shift is real and that
  379. * . the remaining shifts are paired. ====
  380. *
  381. NS = NSHFTS - MOD( NSHFTS, 2 )
  382. *
  383. * ==== Machine constants for deflation ====
  384. *
  385. SAFMIN = DLAMCH( 'SAFE MINIMUM' )
  386. SAFMAX = ONE / SAFMIN
  387. CALL DLABAD( SAFMIN, SAFMAX )
  388. ULP = DLAMCH( 'PRECISION' )
  389. SMLNUM = SAFMIN*( DBLE( N ) / ULP )
  390. *
  391. * ==== Use accumulated reflections to update far-from-diagonal
  392. * . entries ? ====
  393. *
  394. ACCUM = ( KACC22.EQ.1 ) .OR. ( KACC22.EQ.2 )
  395. *
  396. * ==== If so, exploit the 2-by-2 block structure? ====
  397. *
  398. BLK22 = ( NS.GT.2 ) .AND. ( KACC22.EQ.2 )
  399. *
  400. * ==== clear trash ====
  401. *
  402. IF( KTOP+2.LE.KBOT )
  403. $ H( KTOP+2, KTOP ) = ZERO
  404. *
  405. * ==== NBMPS = number of 2-shift bulges in the chain ====
  406. *
  407. NBMPS = NS / 2
  408. *
  409. * ==== KDU = width of slab ====
  410. *
  411. KDU = 6*NBMPS - 3
  412. *
  413. * ==== Create and chase chains of NBMPS bulges ====
  414. *
  415. DO 220 INCOL = 3*( 1-NBMPS ) + KTOP - 1, KBOT - 2, 3*NBMPS - 2
  416. NDCOL = INCOL + KDU
  417. IF( ACCUM )
  418. $ CALL DLASET( 'ALL', KDU, KDU, ZERO, ONE, U, LDU )
  419. *
  420. * ==== Near-the-diagonal bulge chase. The following loop
  421. * . performs the near-the-diagonal part of a small bulge
  422. * . multi-shift QR sweep. Each 6*NBMPS-2 column diagonal
  423. * . chunk extends from column INCOL to column NDCOL
  424. * . (including both column INCOL and column NDCOL). The
  425. * . following loop chases a 3*NBMPS column long chain of
  426. * . NBMPS bulges 3*NBMPS-2 columns to the right. (INCOL
  427. * . may be less than KTOP and and NDCOL may be greater than
  428. * . KBOT indicating phantom columns from which to chase
  429. * . bulges before they are actually introduced or to which
  430. * . to chase bulges beyond column KBOT.) ====
  431. *
  432. DO 150 KRCOL = INCOL, MIN( INCOL+3*NBMPS-3, KBOT-2 )
  433. *
  434. * ==== Bulges number MTOP to MBOT are active double implicit
  435. * . shift bulges. There may or may not also be small
  436. * . 2-by-2 bulge, if there is room. The inactive bulges
  437. * . (if any) must wait until the active bulges have moved
  438. * . down the diagonal to make room. The phantom matrix
  439. * . paradigm described above helps keep track. ====
  440. *
  441. MTOP = MAX( 1, ( ( KTOP-1 )-KRCOL+2 ) / 3+1 )
  442. MBOT = MIN( NBMPS, ( KBOT-KRCOL ) / 3 )
  443. M22 = MBOT + 1
  444. BMP22 = ( MBOT.LT.NBMPS ) .AND. ( KRCOL+3*( M22-1 ) ).EQ.
  445. $ ( KBOT-2 )
  446. *
  447. * ==== Generate reflections to chase the chain right
  448. * . one column. (The minimum value of K is KTOP-1.) ====
  449. *
  450. DO 20 M = MTOP, MBOT
  451. K = KRCOL + 3*( M-1 )
  452. IF( K.EQ.KTOP-1 ) THEN
  453. CALL DLAQR1( 3, H( KTOP, KTOP ), LDH, SR( 2*M-1 ),
  454. $ SI( 2*M-1 ), SR( 2*M ), SI( 2*M ),
  455. $ V( 1, M ) )
  456. ALPHA = V( 1, M )
  457. CALL DLARFG( 3, ALPHA, V( 2, M ), 1, V( 1, M ) )
  458. ELSE
  459. BETA = H( K+1, K )
  460. V( 2, M ) = H( K+2, K )
  461. V( 3, M ) = H( K+3, K )
  462. CALL DLARFG( 3, BETA, V( 2, M ), 1, V( 1, M ) )
  463. *
  464. * ==== A Bulge may collapse because of vigilant
  465. * . deflation or destructive underflow. In the
  466. * . underflow case, try the two-small-subdiagonals
  467. * . trick to try to reinflate the bulge. ====
  468. *
  469. IF( H( K+3, K ).NE.ZERO .OR. H( K+3, K+1 ).NE.
  470. $ ZERO .OR. H( K+3, K+2 ).EQ.ZERO ) THEN
  471. *
  472. * ==== Typical case: not collapsed (yet). ====
  473. *
  474. H( K+1, K ) = BETA
  475. H( K+2, K ) = ZERO
  476. H( K+3, K ) = ZERO
  477. ELSE
  478. *
  479. * ==== Atypical case: collapsed. Attempt to
  480. * . reintroduce ignoring H(K+1,K) and H(K+2,K).
  481. * . If the fill resulting from the new
  482. * . reflector is too large, then abandon it.
  483. * . Otherwise, use the new one. ====
  484. *
  485. CALL DLAQR1( 3, H( K+1, K+1 ), LDH, SR( 2*M-1 ),
  486. $ SI( 2*M-1 ), SR( 2*M ), SI( 2*M ),
  487. $ VT )
  488. ALPHA = VT( 1 )
  489. CALL DLARFG( 3, ALPHA, VT( 2 ), 1, VT( 1 ) )
  490. REFSUM = VT( 1 )*( H( K+1, K )+VT( 2 )*
  491. $ H( K+2, K ) )
  492. *
  493. IF( ABS( H( K+2, K )-REFSUM*VT( 2 ) )+
  494. $ ABS( REFSUM*VT( 3 ) ).GT.ULP*
  495. $ ( ABS( H( K, K ) )+ABS( H( K+1,
  496. $ K+1 ) )+ABS( H( K+2, K+2 ) ) ) ) THEN
  497. *
  498. * ==== Starting a new bulge here would
  499. * . create non-negligible fill. Use
  500. * . the old one with trepidation. ====
  501. *
  502. H( K+1, K ) = BETA
  503. H( K+2, K ) = ZERO
  504. H( K+3, K ) = ZERO
  505. ELSE
  506. *
  507. * ==== Stating a new bulge here would
  508. * . create only negligible fill.
  509. * . Replace the old reflector with
  510. * . the new one. ====
  511. *
  512. H( K+1, K ) = H( K+1, K ) - REFSUM
  513. H( K+2, K ) = ZERO
  514. H( K+3, K ) = ZERO
  515. V( 1, M ) = VT( 1 )
  516. V( 2, M ) = VT( 2 )
  517. V( 3, M ) = VT( 3 )
  518. END IF
  519. END IF
  520. END IF
  521. 20 CONTINUE
  522. *
  523. * ==== Generate a 2-by-2 reflection, if needed. ====
  524. *
  525. K = KRCOL + 3*( M22-1 )
  526. IF( BMP22 ) THEN
  527. IF( K.EQ.KTOP-1 ) THEN
  528. CALL DLAQR1( 2, H( K+1, K+1 ), LDH, SR( 2*M22-1 ),
  529. $ SI( 2*M22-1 ), SR( 2*M22 ), SI( 2*M22 ),
  530. $ V( 1, M22 ) )
  531. BETA = V( 1, M22 )
  532. CALL DLARFG( 2, BETA, V( 2, M22 ), 1, V( 1, M22 ) )
  533. ELSE
  534. BETA = H( K+1, K )
  535. V( 2, M22 ) = H( K+2, K )
  536. CALL DLARFG( 2, BETA, V( 2, M22 ), 1, V( 1, M22 ) )
  537. H( K+1, K ) = BETA
  538. H( K+2, K ) = ZERO
  539. END IF
  540. END IF
  541. *
  542. * ==== Multiply H by reflections from the left ====
  543. *
  544. IF( ACCUM ) THEN
  545. JBOT = MIN( NDCOL, KBOT )
  546. ELSE IF( WANTT ) THEN
  547. JBOT = N
  548. ELSE
  549. JBOT = KBOT
  550. END IF
  551. DO 40 J = MAX( KTOP, KRCOL ), JBOT
  552. MEND = MIN( MBOT, ( J-KRCOL+2 ) / 3 )
  553. DO 30 M = MTOP, MEND
  554. M1 = M -1
  555. tempv1 = V( 1, M )
  556. K = KRCOL + 2*M1
  557. tempv2 = V( 2, M )
  558. K = K + M1
  559. tempv3 = V( 3, M )
  560. temph1 = H( K+1, J )
  561. temph2 = H( K+2, J )
  562. temph3 = H( K+3, J )
  563. REFSUM = tempv1*( temph1+tempv2*
  564. $ temph2+tempv3*temph3 )
  565. H( K+1, J ) = temph1 - REFSUM
  566. H( K+2, J ) = temph2 - REFSUM*tempv2
  567. H( K+3, J ) = temph3 - REFSUM*tempv3
  568. 30 CONTINUE
  569. 40 CONTINUE
  570. IF( BMP22 ) THEN
  571. K = KRCOL + 3*( M22-1 )
  572. DO 50 J = MAX( K+1, KTOP ), JBOT
  573. REFSUM = V( 1, M22 )*( H( K+1, J )+V( 2, M22 )*
  574. $ H( K+2, J ) )
  575. H( K+1, J ) = H( K+1, J ) - REFSUM
  576. H( K+2, J ) = H( K+2, J ) - REFSUM*V( 2, M22 )
  577. 50 CONTINUE
  578. END IF
  579. *
  580. * ==== Multiply H by reflections from the right.
  581. * . Delay filling in the last row until the
  582. * . vigilant deflation check is complete. ====
  583. *
  584. IF( ACCUM ) THEN
  585. JTOP = MAX( KTOP, INCOL )
  586. ELSE IF( WANTT ) THEN
  587. JTOP = 1
  588. ELSE
  589. JTOP = KTOP
  590. END IF
  591. DO 90 M = MTOP, MBOT
  592. IF( V( 1, M ).NE.ZERO ) THEN
  593. tempv1 = V( 1, M )
  594. tempv2 = V( 2, M )
  595. tempv3 = V( 3, M )
  596. K = KRCOL + 3*( M-1 )
  597. JBEGIN = JTOP
  598. IF ( MOD( MIN( KBOT, K+3 )-JTOP+1, 2).GT.0 ) THEN
  599. J = JBEGIN
  600. temph1 = H( J, K+1 )
  601. temph2 = H( J, K+2 )
  602. temph3 = H( J, K+3 )
  603. REFSUM = tempv1* ( temph1+tempv2*temph2+
  604. $ tempv3*temph3 )
  605. H( J, K+1 ) = temph1 - REFSUM
  606. H( J, K+2 ) = temph2 - REFSUM*tempv2
  607. H( J, K+3 ) = temph3 - REFSUM*tempv3
  608. JBEGIN = JBEGIN + 1
  609. END IF
  610. DO 60 J = JBEGIN, MIN( KBOT, K+3 ), 2
  611. temph1 = H( J, K+1 )
  612. temph4 = H( J+1, K+1 )
  613. temph2 = H( J, K+2 )
  614. temph5 = H( J+1, K+2 )
  615. temph3 = H( J, K+3 )
  616. temph6 = H( J+1, K+3 )
  617. REFSUM = tempv1* ( temph1+tempv2*temph2+
  618. $ tempv3*temph3 )
  619. REFSU1 = tempv1* ( temph4+tempv2*temph5+
  620. $ tempv3*temph6 )
  621. H( J, K+1 ) = temph1 - REFSUM
  622. H( J+1, K+1 ) = temph4 - REFSU1
  623. H( J, K+2 ) = temph2 - REFSUM*tempv2
  624. H( J+1, K+2 ) = temph5 - REFSU1*tempv2
  625. H( J, K+3 ) = temph3 - REFSUM*tempv3
  626. H( J+1, K+3 ) = temph6 - REFSU1*tempv3
  627. 60 CONTINUE
  628. *
  629. IF( ACCUM ) THEN
  630. *
  631. * ==== Accumulate U. (If necessary, update Z later
  632. * . with with an efficient matrix-matrix
  633. * . multiply.) ====
  634. *
  635. KMS = K - INCOL
  636. JBEGIN=MAX( 1, KTOP-INCOL )
  637. IF ( MOD(KDU-JBEGIN+1,2).GT.0 ) THEN
  638. J = JBEGIN
  639. tempu1 = U( J, KMS+1 )
  640. tempu2 = U( J, KMS+2 )
  641. tempu3 = U( J, KMS+3 )
  642. REFSUM = tempv1* ( tempu1+tempv2*tempu2+
  643. $ tempv3*tempu3 )
  644. U( J, KMS+1 ) = tempu1 - REFSUM
  645. U( J, KMS+2 ) = tempu2 - REFSUM*tempv2
  646. U( J, KMS+3 ) = tempu3 - REFSUM*tempv3
  647. JBEGIN = JBEGIN + 1
  648. END IF
  649. DO 70 J = JBEGIN, KDU , 2
  650. tempu1 = U( J, KMS+1 )
  651. tempu4 = U( J+1, KMS+1 )
  652. tempu2 = U( J, KMS+2 )
  653. tempu5 = U( J+1, KMS+2 )
  654. tempu3 = U( J, KMS+3 )
  655. tempu6 = U( J+1, KMS+3 )
  656. REFSUM = tempv1* ( tempu1+tempv2*tempu2+
  657. $ tempv3*tempu3 )
  658. REFSU1 = tempv1* ( tempu4+tempv2*tempu5+
  659. $ tempv3*tempu6 )
  660. U( J, KMS+1 ) = tempu1 - REFSUM
  661. U( J+1, KMS+1 ) = tempu4 - REFSU1
  662. U( J, KMS+2 ) = tempu2 - REFSUM*tempv2
  663. U( J+1, KMS+2 ) = tempu5 - REFSU1*tempv2
  664. U( J, KMS+3 ) = tempu3 - REFSUM*tempv3
  665. U( J+1, KMS+3 ) = tempu6 - REFSU1*tempv3
  666. 70 CONTINUE
  667. ELSE IF( WANTZ ) THEN
  668. *
  669. * ==== U is not accumulated, so update Z
  670. * . now by multiplying by reflections
  671. * . from the right. ====
  672. *
  673. JBEGIN = ILOZ
  674. IF ( MOD(IHIZ-ILOZ+1,2).GT.0 ) THEN
  675. J = JBEGIN
  676. tempz1 = Z( J, K+1 )
  677. tempz2 = Z( J, K+2 )
  678. tempz3 = Z( J, K+3 )
  679. REFSUM = tempv1* ( tempz1+tempv2*tempz2+
  680. $ tempv3*tempz3 )
  681. Z( J, K+1 ) = tempz1 - REFSUM
  682. Z( J, K+2 ) = tempz2 - REFSUM*tempv2
  683. Z( J, K+3 ) = tempz3 - REFSUM*tempv3
  684. JBEGIN = JBEGIN + 1
  685. END IF
  686. DO 80 J = JBEGIN, IHIZ, 2
  687. tempz1 = Z( J, K+1 )
  688. tempz4 = Z( J+1, K+1 )
  689. tempz2 = Z( J, K+2 )
  690. tempz5 = Z( J+1, K+2 )
  691. tempz3 = Z( J, K+3 )
  692. tempz6 = Z( J+1, K+3 )
  693. REFSUM = tempv1* ( tempz1+tempv2*tempz2+
  694. $ tempv3*tempz3 )
  695. REFSU1 = tempv1* ( tempz4+tempv2*tempz5+
  696. $ tempv3*tempz6 )
  697. Z( J, K+1 ) = tempz1 - REFSUM
  698. Z( J, K+2 ) = tempz2 - REFSUM*tempv2
  699. Z( J, K+3 ) = tempz3 - REFSUM*tempv3
  700. Z( J+1, K+1 ) = tempz4 - REFSU1
  701. Z( J+1, K+2 ) = tempz5 - REFSU1*tempv2
  702. Z( J+1, K+3 ) = tempz6 - REFSU1*tempv3
  703. 80 CONTINUE
  704. END IF
  705. END IF
  706. 90 CONTINUE
  707. *
  708. * ==== Special case: 2-by-2 reflection (if needed) ====
  709. *
  710. K = KRCOL + 3*( M22-1 )
  711. IF( BMP22 ) THEN
  712. IF ( V( 1, M22 ).NE.ZERO ) THEN
  713. DO 100 J = JTOP, MIN( KBOT, K+3 )
  714. REFSUM = V( 1, M22 )*( H( J, K+1 )+V( 2, M22 )*
  715. $ H( J, K+2 ) )
  716. H( J, K+1 ) = H( J, K+1 ) - REFSUM
  717. H( J, K+2 ) = H( J, K+2 ) - REFSUM*V( 2, M22 )
  718. 100 CONTINUE
  719. *
  720. IF( ACCUM ) THEN
  721. KMS = K - INCOL
  722. DO 110 J = MAX( 1, KTOP-INCOL ), KDU
  723. REFSUM = V( 1, M22 )*( U( J, KMS+1 )+
  724. $ V( 2, M22 )*U( J, KMS+2 ) )
  725. U( J, KMS+1 ) = U( J, KMS+1 ) - REFSUM
  726. U( J, KMS+2 ) = U( J, KMS+2 ) -
  727. $ REFSUM*V( 2, M22 )
  728. 110 CONTINUE
  729. ELSE IF( WANTZ ) THEN
  730. DO 120 J = ILOZ, IHIZ
  731. REFSUM = V( 1, M22 )*( Z( J, K+1 )+V( 2, M22 )*
  732. $ Z( J, K+2 ) )
  733. Z( J, K+1 ) = Z( J, K+1 ) - REFSUM
  734. Z( J, K+2 ) = Z( J, K+2 ) - REFSUM*V( 2, M22 )
  735. 120 CONTINUE
  736. END IF
  737. END IF
  738. END IF
  739. *
  740. * ==== Vigilant deflation check ====
  741. *
  742. MSTART = MTOP
  743. IF( KRCOL+3*( MSTART-1 ).LT.KTOP )
  744. $ MSTART = MSTART + 1
  745. MEND = MBOT
  746. IF( BMP22 )
  747. $ MEND = MEND + 1
  748. IF( KRCOL.EQ.KBOT-2 )
  749. $ MEND = MEND + 1
  750. DO 130 M = MSTART, MEND
  751. K = MIN( KBOT-1, KRCOL+3*( M-1 ) )
  752. *
  753. * ==== The following convergence test requires that
  754. * . the tradition small-compared-to-nearby-diagonals
  755. * . criterion and the Ahues & Tisseur (LAWN 122, 1997)
  756. * . criteria both be satisfied. The latter improves
  757. * . accuracy in some examples. Falling back on an
  758. * . alternate convergence criterion when TST1 or TST2
  759. * . is zero (as done here) is traditional but probably
  760. * . unnecessary. ====
  761. *
  762. IF( H( K+1, K ).NE.ZERO ) THEN
  763. TST1 = ABS( H( K, K ) ) + ABS( H( K+1, K+1 ) )
  764. IF( TST1.EQ.ZERO ) THEN
  765. IF( K.GE.KTOP+1 )
  766. $ TST1 = TST1 + ABS( H( K, K-1 ) )
  767. IF( K.GE.KTOP+2 )
  768. $ TST1 = TST1 + ABS( H( K, K-2 ) )
  769. IF( K.GE.KTOP+3 )
  770. $ TST1 = TST1 + ABS( H( K, K-3 ) )
  771. IF( K.LE.KBOT-2 )
  772. $ TST1 = TST1 + ABS( H( K+2, K+1 ) )
  773. IF( K.LE.KBOT-3 )
  774. $ TST1 = TST1 + ABS( H( K+3, K+1 ) )
  775. IF( K.LE.KBOT-4 )
  776. $ TST1 = TST1 + ABS( H( K+4, K+1 ) )
  777. END IF
  778. IF( ABS( H( K+1, K ) ).LE.MAX( SMLNUM, ULP*TST1 ) )
  779. $ THEN
  780. H12 = MAX( ABS( H( K+1, K ) ), ABS( H( K, K+1 ) ) )
  781. H21 = MIN( ABS( H( K+1, K ) ), ABS( H( K, K+1 ) ) )
  782. H11 = MAX( ABS( H( K+1, K+1 ) ),
  783. $ ABS( H( K, K )-H( K+1, K+1 ) ) )
  784. H22 = MIN( ABS( H( K+1, K+1 ) ),
  785. $ ABS( H( K, K )-H( K+1, K+1 ) ) )
  786. SCL = H11 + H12
  787. TST2 = H22*( H11 / SCL )
  788. *
  789. IF( TST2.EQ.ZERO .OR. H21*( H12 / SCL ).LE.
  790. $ MAX( SMLNUM, ULP*TST2 ) )H( K+1, K ) = ZERO
  791. END IF
  792. END IF
  793. 130 CONTINUE
  794. *
  795. * ==== Fill in the last row of each bulge. ====
  796. *
  797. MEND = MIN( NBMPS, ( KBOT-KRCOL-1 ) / 3 )
  798. DO 140 M = MTOP, MEND
  799. K = KRCOL + 3*( M-1 )
  800. REFSUM = V( 1, M )*V( 3, M )*H( K+4, K+3 )
  801. H( K+4, K+1 ) = -REFSUM
  802. H( K+4, K+2 ) = -REFSUM*V( 2, M )
  803. H( K+4, K+3 ) = H( K+4, K+3 ) - REFSUM*V( 3, M )
  804. 140 CONTINUE
  805. *
  806. * ==== End of near-the-diagonal bulge chase. ====
  807. *
  808. 150 CONTINUE
  809. *
  810. * ==== Use U (if accumulated) to update far-from-diagonal
  811. * . entries in H. If required, use U to update Z as
  812. * . well. ====
  813. *
  814. IF( ACCUM ) THEN
  815. IF( WANTT ) THEN
  816. JTOP = 1
  817. JBOT = N
  818. ELSE
  819. JTOP = KTOP
  820. JBOT = KBOT
  821. END IF
  822. IF( ( .NOT.BLK22 ) .OR. ( INCOL.LT.KTOP ) .OR.
  823. $ ( NDCOL.GT.KBOT ) .OR. ( NS.LE.2 ) ) THEN
  824. *
  825. * ==== Updates not exploiting the 2-by-2 block
  826. * . structure of U. K1 and NU keep track of
  827. * . the location and size of U in the special
  828. * . cases of introducing bulges and chasing
  829. * . bulges off the bottom. In these special
  830. * . cases and in case the number of shifts
  831. * . is NS = 2, there is no 2-by-2 block
  832. * . structure to exploit. ====
  833. *
  834. K1 = MAX( 1, KTOP-INCOL )
  835. NU = ( KDU-MAX( 0, NDCOL-KBOT ) ) - K1 + 1
  836. *
  837. * ==== Horizontal Multiply ====
  838. *
  839. DO 160 JCOL = MIN( NDCOL, KBOT ) + 1, JBOT, NH
  840. JLEN = MIN( NH, JBOT-JCOL+1 )
  841. CALL DGEMM( 'C', 'N', NU, JLEN, NU, ONE, U( K1, K1 ),
  842. $ LDU, H( INCOL+K1, JCOL ), LDH, ZERO, WH,
  843. $ LDWH )
  844. CALL DLACPY( 'ALL', NU, JLEN, WH, LDWH,
  845. $ H( INCOL+K1, JCOL ), LDH )
  846. 160 CONTINUE
  847. *
  848. * ==== Vertical multiply ====
  849. *
  850. DO 170 JROW = JTOP, MAX( KTOP, INCOL ) - 1, NV
  851. JLEN = MIN( NV, MAX( KTOP, INCOL )-JROW )
  852. CALL DGEMM( 'N', 'N', JLEN, NU, NU, ONE,
  853. $ H( JROW, INCOL+K1 ), LDH, U( K1, K1 ),
  854. $ LDU, ZERO, WV, LDWV )
  855. CALL DLACPY( 'ALL', JLEN, NU, WV, LDWV,
  856. $ H( JROW, INCOL+K1 ), LDH )
  857. 170 CONTINUE
  858. *
  859. * ==== Z multiply (also vertical) ====
  860. *
  861. IF( WANTZ ) THEN
  862. DO 180 JROW = ILOZ, IHIZ, NV
  863. JLEN = MIN( NV, IHIZ-JROW+1 )
  864. CALL DGEMM( 'N', 'N', JLEN, NU, NU, ONE,
  865. $ Z( JROW, INCOL+K1 ), LDZ, U( K1, K1 ),
  866. $ LDU, ZERO, WV, LDWV )
  867. CALL DLACPY( 'ALL', JLEN, NU, WV, LDWV,
  868. $ Z( JROW, INCOL+K1 ), LDZ )
  869. 180 CONTINUE
  870. END IF
  871. ELSE
  872. *
  873. * ==== Updates exploiting U's 2-by-2 block structure.
  874. * . (I2, I4, J2, J4 are the last rows and columns
  875. * . of the blocks.) ====
  876. *
  877. I2 = ( KDU+1 ) / 2
  878. I4 = KDU
  879. J2 = I4 - I2
  880. J4 = KDU
  881. *
  882. * ==== KZS and KNZ deal with the band of zeros
  883. * . along the diagonal of one of the triangular
  884. * . blocks. ====
  885. *
  886. KZS = ( J4-J2 ) - ( NS+1 )
  887. KNZ = NS + 1
  888. *
  889. * ==== Horizontal multiply ====
  890. *
  891. DO 190 JCOL = MIN( NDCOL, KBOT ) + 1, JBOT, NH
  892. JLEN = MIN( NH, JBOT-JCOL+1 )
  893. *
  894. * ==== Copy bottom of H to top+KZS of scratch ====
  895. * (The first KZS rows get multiplied by zero.) ====
  896. *
  897. CALL DLACPY( 'ALL', KNZ, JLEN, H( INCOL+1+J2, JCOL ),
  898. $ LDH, WH( KZS+1, 1 ), LDWH )
  899. *
  900. * ==== Multiply by U21**T ====
  901. *
  902. CALL DLASET( 'ALL', KZS, JLEN, ZERO, ZERO, WH, LDWH )
  903. CALL DTRMM( 'L', 'U', 'C', 'N', KNZ, JLEN, ONE,
  904. $ U( J2+1, 1+KZS ), LDU, WH( KZS+1, 1 ),
  905. $ LDWH )
  906. *
  907. * ==== Multiply top of H by U11**T ====
  908. *
  909. CALL DGEMM( 'C', 'N', I2, JLEN, J2, ONE, U, LDU,
  910. $ H( INCOL+1, JCOL ), LDH, ONE, WH, LDWH )
  911. *
  912. * ==== Copy top of H to bottom of WH ====
  913. *
  914. CALL DLACPY( 'ALL', J2, JLEN, H( INCOL+1, JCOL ), LDH,
  915. $ WH( I2+1, 1 ), LDWH )
  916. *
  917. * ==== Multiply by U21**T ====
  918. *
  919. CALL DTRMM( 'L', 'L', 'C', 'N', J2, JLEN, ONE,
  920. $ U( 1, I2+1 ), LDU, WH( I2+1, 1 ), LDWH )
  921. *
  922. * ==== Multiply by U22 ====
  923. *
  924. CALL DGEMM( 'C', 'N', I4-I2, JLEN, J4-J2, ONE,
  925. $ U( J2+1, I2+1 ), LDU,
  926. $ H( INCOL+1+J2, JCOL ), LDH, ONE,
  927. $ WH( I2+1, 1 ), LDWH )
  928. *
  929. * ==== Copy it back ====
  930. *
  931. CALL DLACPY( 'ALL', KDU, JLEN, WH, LDWH,
  932. $ H( INCOL+1, JCOL ), LDH )
  933. 190 CONTINUE
  934. *
  935. * ==== Vertical multiply ====
  936. *
  937. DO 200 JROW = JTOP, MAX( INCOL, KTOP ) - 1, NV
  938. JLEN = MIN( NV, MAX( INCOL, KTOP )-JROW )
  939. *
  940. * ==== Copy right of H to scratch (the first KZS
  941. * . columns get multiplied by zero) ====
  942. *
  943. CALL DLACPY( 'ALL', JLEN, KNZ, H( JROW, INCOL+1+J2 ),
  944. $ LDH, WV( 1, 1+KZS ), LDWV )
  945. *
  946. * ==== Multiply by U21 ====
  947. *
  948. CALL DLASET( 'ALL', JLEN, KZS, ZERO, ZERO, WV, LDWV )
  949. CALL DTRMM( 'R', 'U', 'N', 'N', JLEN, KNZ, ONE,
  950. $ U( J2+1, 1+KZS ), LDU, WV( 1, 1+KZS ),
  951. $ LDWV )
  952. *
  953. * ==== Multiply by U11 ====
  954. *
  955. CALL DGEMM( 'N', 'N', JLEN, I2, J2, ONE,
  956. $ H( JROW, INCOL+1 ), LDH, U, LDU, ONE, WV,
  957. $ LDWV )
  958. *
  959. * ==== Copy left of H to right of scratch ====
  960. *
  961. CALL DLACPY( 'ALL', JLEN, J2, H( JROW, INCOL+1 ), LDH,
  962. $ WV( 1, 1+I2 ), LDWV )
  963. *
  964. * ==== Multiply by U21 ====
  965. *
  966. CALL DTRMM( 'R', 'L', 'N', 'N', JLEN, I4-I2, ONE,
  967. $ U( 1, I2+1 ), LDU, WV( 1, 1+I2 ), LDWV )
  968. *
  969. * ==== Multiply by U22 ====
  970. *
  971. CALL DGEMM( 'N', 'N', JLEN, I4-I2, J4-J2, ONE,
  972. $ H( JROW, INCOL+1+J2 ), LDH,
  973. $ U( J2+1, I2+1 ), LDU, ONE, WV( 1, 1+I2 ),
  974. $ LDWV )
  975. *
  976. * ==== Copy it back ====
  977. *
  978. CALL DLACPY( 'ALL', JLEN, KDU, WV, LDWV,
  979. $ H( JROW, INCOL+1 ), LDH )
  980. 200 CONTINUE
  981. *
  982. * ==== Multiply Z (also vertical) ====
  983. *
  984. IF( WANTZ ) THEN
  985. DO 210 JROW = ILOZ, IHIZ, NV
  986. JLEN = MIN( NV, IHIZ-JROW+1 )
  987. *
  988. * ==== Copy right of Z to left of scratch (first
  989. * . KZS columns get multiplied by zero) ====
  990. *
  991. CALL DLACPY( 'ALL', JLEN, KNZ,
  992. $ Z( JROW, INCOL+1+J2 ), LDZ,
  993. $ WV( 1, 1+KZS ), LDWV )
  994. *
  995. * ==== Multiply by U12 ====
  996. *
  997. CALL DLASET( 'ALL', JLEN, KZS, ZERO, ZERO, WV,
  998. $ LDWV )
  999. CALL DTRMM( 'R', 'U', 'N', 'N', JLEN, KNZ, ONE,
  1000. $ U( J2+1, 1+KZS ), LDU, WV( 1, 1+KZS ),
  1001. $ LDWV )
  1002. *
  1003. * ==== Multiply by U11 ====
  1004. *
  1005. CALL DGEMM( 'N', 'N', JLEN, I2, J2, ONE,
  1006. $ Z( JROW, INCOL+1 ), LDZ, U, LDU, ONE,
  1007. $ WV, LDWV )
  1008. *
  1009. * ==== Copy left of Z to right of scratch ====
  1010. *
  1011. CALL DLACPY( 'ALL', JLEN, J2, Z( JROW, INCOL+1 ),
  1012. $ LDZ, WV( 1, 1+I2 ), LDWV )
  1013. *
  1014. * ==== Multiply by U21 ====
  1015. *
  1016. CALL DTRMM( 'R', 'L', 'N', 'N', JLEN, I4-I2, ONE,
  1017. $ U( 1, I2+1 ), LDU, WV( 1, 1+I2 ),
  1018. $ LDWV )
  1019. *
  1020. * ==== Multiply by U22 ====
  1021. *
  1022. CALL DGEMM( 'N', 'N', JLEN, I4-I2, J4-J2, ONE,
  1023. $ Z( JROW, INCOL+1+J2 ), LDZ,
  1024. $ U( J2+1, I2+1 ), LDU, ONE,
  1025. $ WV( 1, 1+I2 ), LDWV )
  1026. *
  1027. * ==== Copy the result back to Z ====
  1028. *
  1029. CALL DLACPY( 'ALL', JLEN, KDU, WV, LDWV,
  1030. $ Z( JROW, INCOL+1 ), LDZ )
  1031. 210 CONTINUE
  1032. END IF
  1033. END IF
  1034. END IF
  1035. 220 CONTINUE
  1036. *
  1037. * ==== End of DLAQR5 ====
  1038. *
  1039. END