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.

zlarft.f 20 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. *> \brief \b ZLARFT forms the triangular factor T of a block reflector H = I - vtvH
  2. *
  3. * =========== DOCUMENTATION ===========
  4. *
  5. * Online html documentation available at
  6. * http://www.netlib.org/lapack/explore-html/
  7. *
  8. *> \htmlonly
  9. *> Download ZLARFT + dependencies
  10. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zlarft.f">
  11. *> [TGZ]</a>
  12. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zlarft.f">
  13. *> [ZIP]</a>
  14. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlarft.f">
  15. *> [TXT]</a>
  16. *> \endhtmlonly
  17. *
  18. * Definition:
  19. * ===========
  20. *
  21. * RECURSIVE SUBROUTINE ZLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )
  22. *
  23. * .. Scalar Arguments ..
  24. * CHARACTER DIRECT, STOREV
  25. * INTEGER K, LDT, LDV, N
  26. * ..
  27. * .. Array Arguments ..
  28. * COMPLEX*16 T( LDT, * ), TAU( * ), V( LDV, * )
  29. * ..
  30. *
  31. *
  32. *> \par Purpose:
  33. * =============
  34. *>
  35. *> \verbatim
  36. *>
  37. *> ZLARFT forms the triangular factor T of a complex block reflector H
  38. *> of order n, which is defined as a product of k elementary reflectors.
  39. *>
  40. *> If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular;
  41. *>
  42. *> If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular.
  43. *>
  44. *> If STOREV = 'C', the vector which defines the elementary reflector
  45. *> H(i) is stored in the i-th column of the array V, and
  46. *>
  47. *> H = I - V * T * V**H
  48. *>
  49. *> If STOREV = 'R', the vector which defines the elementary reflector
  50. *> H(i) is stored in the i-th row of the array V, and
  51. *>
  52. *> H = I - V**H * T * V
  53. *> \endverbatim
  54. *
  55. * Arguments:
  56. * ==========
  57. *
  58. *> \param[in] DIRECT
  59. *> \verbatim
  60. *> DIRECT is CHARACTER*1
  61. *> Specifies the order in which the elementary reflectors are
  62. *> multiplied to form the block reflector:
  63. *> = 'F': H = H(1) H(2) . . . H(k) (Forward)
  64. *> = 'B': H = H(k) . . . H(2) H(1) (Backward)
  65. *> \endverbatim
  66. *>
  67. *> \param[in] STOREV
  68. *> \verbatim
  69. *> STOREV is CHARACTER*1
  70. *> Specifies how the vectors which define the elementary
  71. *> reflectors are stored (see also Further Details):
  72. *> = 'C': columnwise
  73. *> = 'R': rowwise
  74. *> \endverbatim
  75. *>
  76. *> \param[in] N
  77. *> \verbatim
  78. *> N is INTEGER
  79. *> The order of the block reflector H. N >= 0.
  80. *> \endverbatim
  81. *>
  82. *> \param[in] K
  83. *> \verbatim
  84. *> K is INTEGER
  85. *> The order of the triangular factor T (= the number of
  86. *> elementary reflectors). K >= 1.
  87. *> \endverbatim
  88. *>
  89. *> \param[in] V
  90. *> \verbatim
  91. *> V is COMPLEX*16 array, dimension
  92. *> (LDV,K) if STOREV = 'C'
  93. *> (LDV,N) if STOREV = 'R'
  94. *> The matrix V. See further details.
  95. *> \endverbatim
  96. *>
  97. *> \param[in] LDV
  98. *> \verbatim
  99. *> LDV is INTEGER
  100. *> The leading dimension of the array V.
  101. *> If STOREV = 'C', LDV >= max(1,N); if STOREV = 'R', LDV >= K.
  102. *> \endverbatim
  103. *>
  104. *> \param[in] TAU
  105. *> \verbatim
  106. *> TAU is COMPLEX*16 array, dimension (K)
  107. *> TAU(i) must contain the scalar factor of the elementary
  108. *> reflector H(i).
  109. *> \endverbatim
  110. *>
  111. *> \param[out] T
  112. *> \verbatim
  113. *> T is COMPLEX*16 array, dimension (LDT,K)
  114. *> The k by k triangular factor T of the block reflector.
  115. *> If DIRECT = 'F', T is upper triangular; if DIRECT = 'B', T is
  116. *> lower triangular. The rest of the array is not used.
  117. *> \endverbatim
  118. *>
  119. *> \param[in] LDT
  120. *> \verbatim
  121. *> LDT is INTEGER
  122. *> The leading dimension of the array T. LDT >= K.
  123. *> \endverbatim
  124. *
  125. * Authors:
  126. * ========
  127. *
  128. *> \author Univ. of Tennessee
  129. *> \author Univ. of California Berkeley
  130. *> \author Univ. of Colorado Denver
  131. *> \author NAG Ltd.
  132. *
  133. *> \ingroup larft
  134. *
  135. *> \par Further Details:
  136. * =====================
  137. *>
  138. *> \verbatim
  139. *>
  140. *> The shape of the matrix V and the storage of the vectors which define
  141. *> the H(i) is best illustrated by the following example with n = 5 and
  142. *> k = 3. The elements equal to 1 are not stored.
  143. *>
  144. *> DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
  145. *>
  146. *> V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
  147. *> ( v1 1 ) ( 1 v2 v2 v2 )
  148. *> ( v1 v2 1 ) ( 1 v3 v3 )
  149. *> ( v1 v2 v3 )
  150. *> ( v1 v2 v3 )
  151. *>
  152. *> DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
  153. *>
  154. *> V = ( v1 v2 v3 ) V = ( v1 v1 1 )
  155. *> ( v1 v2 v3 ) ( v2 v2 v2 1 )
  156. *> ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
  157. *> ( 1 v3 )
  158. *> ( 1 )
  159. *> \endverbatim
  160. *>
  161. * =====================================================================
  162. RECURSIVE SUBROUTINE ZLARFT( DIRECT, STOREV, N, K, V, LDV,
  163. $ TAU, T, LDT )
  164. *
  165. * -- LAPACK auxiliary routine --
  166. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  167. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  168. *
  169. * .. Scalar Arguments
  170. *
  171. CHARACTER DIRECT, STOREV
  172. INTEGER K, LDT, LDV, N
  173. * ..
  174. * .. Array Arguments ..
  175. *
  176. COMPLEX*16 T( LDT, * ), TAU( * ), V( LDV, * )
  177. * ..
  178. *
  179. * .. Parameters ..
  180. *
  181. COMPLEX*16 ONE, NEG_ONE, ZERO
  182. PARAMETER(ONE=1.0D+0, ZERO = 0.0D+0, NEG_ONE=-1.0D+0)
  183. *
  184. * .. Local Scalars ..
  185. *
  186. INTEGER I,J,L
  187. LOGICAL QR,LQ,QL,DIRF,COLV
  188. *
  189. * .. External Subroutines ..
  190. *
  191. EXTERNAL ZTRMM,ZGEMM,ZLACPY
  192. *
  193. * .. External Functions..
  194. *
  195. LOGICAL LSAME
  196. EXTERNAL LSAME
  197. *
  198. * .. Intrinsic Functions..
  199. *
  200. INTRINSIC CONJG
  201. *
  202. * The general scheme used is inspired by the approach inside DGEQRT3
  203. * which was (at the time of writing this code):
  204. * Based on the algorithm of Elmroth and Gustavson,
  205. * IBM J. Res. Develop. Vol 44 No. 4 July 2000.
  206. * ..
  207. * .. Executable Statements ..
  208. *
  209. * Quick return if possible
  210. *
  211. IF(N.EQ.0.OR.K.EQ.0) THEN
  212. RETURN
  213. END IF
  214. *
  215. * Base case
  216. *
  217. IF(N.EQ.1.OR.K.EQ.1) THEN
  218. T(1,1) = TAU(1)
  219. RETURN
  220. END IF
  221. *
  222. * Beginning of executable statements
  223. *
  224. L = K / 2
  225. *
  226. * Determine what kind of Q we need to compute
  227. * We assume that if the user doesn't provide 'F' for DIRECT,
  228. * then they meant to provide 'B' and if they don't provide
  229. * 'C' for STOREV, then they meant to provide 'R'
  230. *
  231. DIRF = LSAME(DIRECT,'F')
  232. COLV = LSAME(STOREV,'C')
  233. *
  234. * QR happens when we have forward direction in column storage
  235. *
  236. QR = DIRF.AND.COLV
  237. *
  238. * LQ happens when we have forward direction in row storage
  239. *
  240. LQ = DIRF.AND.(.NOT.COLV)
  241. *
  242. * QL happens when we have backward direction in column storage
  243. *
  244. QL = (.NOT.DIRF).AND.COLV
  245. *
  246. * The last case is RQ. Due to how we structured this, if the
  247. * above 3 are false, then RQ must be true, so we never store
  248. * this
  249. * RQ happens when we have backward direction in row storage
  250. * RQ = (.NOT.DIRF).AND.(.NOT.COLV)
  251. *
  252. IF(QR) THEN
  253. *
  254. * Break V apart into 6 components
  255. *
  256. * V = |---------------|
  257. * |V_{1,1} 0 |
  258. * |V_{2,1} V_{2,2}|
  259. * |V_{3,1} V_{3,2}|
  260. * |---------------|
  261. *
  262. * V_{1,1}\in\C^{l,l} unit lower triangular
  263. * V_{2,1}\in\C^{k-l,l} rectangular
  264. * V_{3,1}\in\C^{n-k,l} rectangular
  265. *
  266. * V_{2,2}\in\C^{k-l,k-l} unit lower triangular
  267. * V_{3,2}\in\C^{n-k,k-l} rectangular
  268. *
  269. * We will construct the T matrix
  270. * T = |---------------|
  271. * |T_{1,1} T_{1,2}|
  272. * |0 T_{2,2}|
  273. * |---------------|
  274. *
  275. * T is the triangular factor obtained from block reflectors.
  276. * To motivate the structure, assume we have already computed T_{1,1}
  277. * and T_{2,2}. Then collect the associated reflectors in V_1 and V_2
  278. *
  279. * T_{1,1}\in\C^{l, l} upper triangular
  280. * T_{2,2}\in\C^{k-l, k-l} upper triangular
  281. * T_{1,2}\in\C^{l, k-l} rectangular
  282. *
  283. * Where l = floor(k/2)
  284. *
  285. * Then, consider the product:
  286. *
  287. * (I - V_1*T_{1,1}*V_1')*(I - V_2*T_{2,2}*V_2')
  288. * = I - V_1*T_{1,1}*V_1' - V_2*T_{2,2}*V_2' + V_1*T_{1,1}*V_1'*V_2*T_{2,2}*V_2'
  289. *
  290. * Define T_{1,2} = -T_{1,1}*V_1'*V_2*T_{2,2}
  291. *
  292. * Then, we can define the matrix V as
  293. * V = |-------|
  294. * |V_1 V_2|
  295. * |-------|
  296. *
  297. * So, our product is equivalent to the matrix product
  298. * I - V*T*V'
  299. * This means, we can compute T_{1,1} and T_{2,2}, then use this information
  300. * to compute T_{1,2}
  301. *
  302. * Compute T_{1,1} recursively
  303. *
  304. CALL ZLARFT(DIRECT, STOREV, N, L, V, LDV, TAU, T, LDT)
  305. *
  306. * Compute T_{2,2} recursively
  307. *
  308. CALL ZLARFT(DIRECT, STOREV, N-L, K-L, V(L+1, L+1), LDV,
  309. $ TAU(L+1), T(L+1, L+1), LDT)
  310. *
  311. * Compute T_{1,2}
  312. * T_{1,2} = V_{2,1}'
  313. *
  314. DO J = 1, L
  315. DO I = 1, K-L
  316. T(J, L+I) = CONJG(V(L+I, J))
  317. END DO
  318. END DO
  319. *
  320. * T_{1,2} = T_{1,2}*V_{2,2}
  321. *
  322. CALL ZTRMM('Right', 'Lower', 'No transpose', 'Unit', L,
  323. $ K-L, ONE, V(L+1, L+1), LDV, T(1, L+1), LDT)
  324. *
  325. * T_{1,2} = V_{3,1}'*V_{3,2} + T_{1,2}
  326. * Note: We assume K <= N, and GEMM will do nothing if N=K
  327. *
  328. CALL ZGEMM('Conjugate', 'No transpose', L, K-L, N-K, ONE,
  329. $ V(K+1, 1), LDV, V(K+1, L+1), LDV, ONE,
  330. $ T(1, L+1), LDT)
  331. *
  332. * At this point, we have that T_{1,2} = V_1'*V_2
  333. * All that is left is to pre and post multiply by -T_{1,1} and T_{2,2}
  334. * respectively.
  335. *
  336. * T_{1,2} = -T_{1,1}*T_{1,2}
  337. *
  338. CALL ZTRMM('Left', 'Upper', 'No transpose', 'Non-unit', L,
  339. $ K-L, NEG_ONE, T, LDT, T(1, L+1), LDT)
  340. *
  341. * T_{1,2} = T_{1,2}*T_{2,2}
  342. *
  343. CALL ZTRMM('Right', 'Upper', 'No transpose', 'Non-unit', L,
  344. $ K-L, ONE, T(L+1, L+1), LDT, T(1, L+1), LDT)
  345. ELSE IF(LQ) THEN
  346. *
  347. * Break V apart into 6 components
  348. *
  349. * V = |----------------------|
  350. * |V_{1,1} V_{1,2} V{1,3}|
  351. * |0 V_{2,2} V{2,3}|
  352. * |----------------------|
  353. *
  354. * V_{1,1}\in\C^{l,l} unit upper triangular
  355. * V_{1,2}\in\C^{l,k-l} rectangular
  356. * V_{1,3}\in\C^{l,n-k} rectangular
  357. *
  358. * V_{2,2}\in\C^{k-l,k-l} unit upper triangular
  359. * V_{2,3}\in\C^{k-l,n-k} rectangular
  360. *
  361. * Where l = floor(k/2)
  362. *
  363. * We will construct the T matrix
  364. * T = |---------------|
  365. * |T_{1,1} T_{1,2}|
  366. * |0 T_{2,2}|
  367. * |---------------|
  368. *
  369. * T is the triangular factor obtained from block reflectors.
  370. * To motivate the structure, assume we have already computed T_{1,1}
  371. * and T_{2,2}. Then collect the associated reflectors in V_1 and V_2
  372. *
  373. * T_{1,1}\in\C^{l, l} upper triangular
  374. * T_{2,2}\in\C^{k-l, k-l} upper triangular
  375. * T_{1,2}\in\C^{l, k-l} rectangular
  376. *
  377. * Then, consider the product:
  378. *
  379. * (I - V_1'*T_{1,1}*V_1)*(I - V_2'*T_{2,2}*V_2)
  380. * = I - V_1'*T_{1,1}*V_1 - V_2'*T_{2,2}*V_2 + V_1'*T_{1,1}*V_1*V_2'*T_{2,2}*V_2
  381. *
  382. * Define T_{1,2} = -T_{1,1}*V_1*V_2'*T_{2,2}
  383. *
  384. * Then, we can define the matrix V as
  385. * V = |---|
  386. * |V_1|
  387. * |V_2|
  388. * |---|
  389. *
  390. * So, our product is equivalent to the matrix product
  391. * I - V'*T*V
  392. * This means, we can compute T_{1,1} and T_{2,2}, then use this information
  393. * to compute T_{1,2}
  394. *
  395. * Compute T_{1,1} recursively
  396. *
  397. CALL ZLARFT(DIRECT, STOREV, N, L, V, LDV, TAU, T, LDT)
  398. *
  399. * Compute T_{2,2} recursively
  400. *
  401. CALL ZLARFT(DIRECT, STOREV, N-L, K-L, V(L+1, L+1), LDV,
  402. $ TAU(L+1), T(L+1, L+1), LDT)
  403. *
  404. * Compute T_{1,2}
  405. * T_{1,2} = V_{1,2}
  406. *
  407. CALL ZLACPY('All', L, K-L, V(1, L+1), LDV, T(1, L+1), LDT)
  408. *
  409. * T_{1,2} = T_{1,2}*V_{2,2}'
  410. *
  411. CALL ZTRMM('Right', 'Upper', 'Conjugate', 'Unit', L, K-L,
  412. $ ONE, V(L+1, L+1), LDV, T(1, L+1), LDT)
  413. *
  414. * T_{1,2} = V_{1,3}*V_{2,3}' + T_{1,2}
  415. * Note: We assume K <= N, and GEMM will do nothing if N=K
  416. *
  417. CALL ZGEMM('No transpose', 'Conjugate', L, K-L, N-K, ONE,
  418. $ V(1, K+1), LDV, V(L+1, K+1), LDV, ONE,
  419. $ T(1, L+1), LDT)
  420. *
  421. * At this point, we have that T_{1,2} = V_1*V_2'
  422. * All that is left is to pre and post multiply by -T_{1,1} and T_{2,2}
  423. * respectively.
  424. *
  425. * T_{1,2} = -T_{1,1}*T_{1,2}
  426. *
  427. CALL ZTRMM('Left', 'Upper', 'No transpose', 'Non-unit', L,
  428. $ K-L, NEG_ONE, T, LDT, T(1, L+1), LDT)
  429. *
  430. * T_{1,2} = T_{1,2}*T_{2,2}
  431. *
  432. CALL ZTRMM('Right', 'Upper', 'No transpose', 'Non-unit', L,
  433. $ K-L, ONE, T(L+1, L+1), LDT, T(1, L+1), LDT)
  434. ELSE IF(QL) THEN
  435. *
  436. * Break V apart into 6 components
  437. *
  438. * V = |---------------|
  439. * |V_{1,1} V_{1,2}|
  440. * |V_{2,1} V_{2,2}|
  441. * |0 V_{3,2}|
  442. * |---------------|
  443. *
  444. * V_{1,1}\in\C^{n-k,k-l} rectangular
  445. * V_{2,1}\in\C^{k-l,k-l} unit upper triangular
  446. *
  447. * V_{1,2}\in\C^{n-k,l} rectangular
  448. * V_{2,2}\in\C^{k-l,l} rectangular
  449. * V_{3,2}\in\C^{l,l} unit upper triangular
  450. *
  451. * We will construct the T matrix
  452. * T = |---------------|
  453. * |T_{1,1} 0 |
  454. * |T_{2,1} T_{2,2}|
  455. * |---------------|
  456. *
  457. * T is the triangular factor obtained from block reflectors.
  458. * To motivate the structure, assume we have already computed T_{1,1}
  459. * and T_{2,2}. Then collect the associated reflectors in V_1 and V_2
  460. *
  461. * T_{1,1}\in\C^{k-l, k-l} non-unit lower triangular
  462. * T_{2,2}\in\C^{l, l} non-unit lower triangular
  463. * T_{2,1}\in\C^{k-l, l} rectangular
  464. *
  465. * Where l = floor(k/2)
  466. *
  467. * Then, consider the product:
  468. *
  469. * (I - V_2*T_{2,2}*V_2')*(I - V_1*T_{1,1}*V_1')
  470. * = I - V_2*T_{2,2}*V_2' - V_1*T_{1,1}*V_1' + V_2*T_{2,2}*V_2'*V_1*T_{1,1}*V_1'
  471. *
  472. * Define T_{2,1} = -T_{2,2}*V_2'*V_1*T_{1,1}
  473. *
  474. * Then, we can define the matrix V as
  475. * V = |-------|
  476. * |V_1 V_2|
  477. * |-------|
  478. *
  479. * So, our product is equivalent to the matrix product
  480. * I - V*T*V'
  481. * This means, we can compute T_{1,1} and T_{2,2}, then use this information
  482. * to compute T_{2,1}
  483. *
  484. * Compute T_{1,1} recursively
  485. *
  486. CALL ZLARFT(DIRECT, STOREV, N-L, K-L, V, LDV, TAU, T, LDT)
  487. *
  488. * Compute T_{2,2} recursively
  489. *
  490. CALL ZLARFT(DIRECT, STOREV, N, L, V(1, K-L+1), LDV,
  491. $ TAU(K-L+1), T(K-L+1, K-L+1), LDT)
  492. *
  493. * Compute T_{2,1}
  494. * T_{2,1} = V_{2,2}'
  495. *
  496. DO J = 1, K-L
  497. DO I = 1, L
  498. T(K-L+I, J) = CONJG(V(N-K+J, K-L+I))
  499. END DO
  500. END DO
  501. *
  502. * T_{2,1} = T_{2,1}*V_{2,1}
  503. *
  504. CALL ZTRMM('Right', 'Upper', 'No transpose', 'Unit', L,
  505. $ K-L, ONE, V(N-K+1, 1), LDV, T(K-L+1, 1), LDT)
  506. *
  507. * T_{2,1} = V_{2,2}'*V_{2,1} + T_{2,1}
  508. * Note: We assume K <= N, and GEMM will do nothing if N=K
  509. *
  510. CALL ZGEMM('Conjugate', 'No transpose', L, K-L, N-K, ONE,
  511. $ V(1, K-L+1), LDV, V, LDV, ONE, T(K-L+1, 1),
  512. $ LDT)
  513. *
  514. * At this point, we have that T_{2,1} = V_2'*V_1
  515. * All that is left is to pre and post multiply by -T_{2,2} and T_{1,1}
  516. * respectively.
  517. *
  518. * T_{2,1} = -T_{2,2}*T_{2,1}
  519. *
  520. CALL ZTRMM('Left', 'Lower', 'No transpose', 'Non-unit', L,
  521. $ K-L, NEG_ONE, T(K-L+1, K-L+1), LDT,
  522. $ T(K-L+1, 1), LDT)
  523. *
  524. * T_{2,1} = T_{2,1}*T_{1,1}
  525. *
  526. CALL ZTRMM('Right', 'Lower', 'No transpose', 'Non-unit', L,
  527. $ K-L, ONE, T, LDT, T(K-L+1, 1), LDT)
  528. ELSE
  529. *
  530. * Else means RQ case
  531. *
  532. * Break V apart into 6 components
  533. *
  534. * V = |-----------------------|
  535. * |V_{1,1} V_{1,2} 0 |
  536. * |V_{2,1} V_{2,2} V_{2,3}|
  537. * |-----------------------|
  538. *
  539. * V_{1,1}\in\C^{k-l,n-k} rectangular
  540. * V_{1,2}\in\C^{k-l,k-l} unit lower triangular
  541. *
  542. * V_{2,1}\in\C^{l,n-k} rectangular
  543. * V_{2,2}\in\C^{l,k-l} rectangular
  544. * V_{2,3}\in\C^{l,l} unit lower triangular
  545. *
  546. * We will construct the T matrix
  547. * T = |---------------|
  548. * |T_{1,1} 0 |
  549. * |T_{2,1} T_{2,2}|
  550. * |---------------|
  551. *
  552. * T is the triangular factor obtained from block reflectors.
  553. * To motivate the structure, assume we have already computed T_{1,1}
  554. * and T_{2,2}. Then collect the associated reflectors in V_1 and V_2
  555. *
  556. * T_{1,1}\in\C^{k-l, k-l} non-unit lower triangular
  557. * T_{2,2}\in\C^{l, l} non-unit lower triangular
  558. * T_{2,1}\in\C^{k-l, l} rectangular
  559. *
  560. * Where l = floor(k/2)
  561. *
  562. * Then, consider the product:
  563. *
  564. * (I - V_2'*T_{2,2}*V_2)*(I - V_1'*T_{1,1}*V_1)
  565. * = I - V_2'*T_{2,2}*V_2 - V_1'*T_{1,1}*V_1 + V_2'*T_{2,2}*V_2*V_1'*T_{1,1}*V_1
  566. *
  567. * Define T_{2,1} = -T_{2,2}*V_2*V_1'*T_{1,1}
  568. *
  569. * Then, we can define the matrix V as
  570. * V = |---|
  571. * |V_1|
  572. * |V_2|
  573. * |---|
  574. *
  575. * So, our product is equivalent to the matrix product
  576. * I - V'*T*V
  577. * This means, we can compute T_{1,1} and T_{2,2}, then use this information
  578. * to compute T_{2,1}
  579. *
  580. * Compute T_{1,1} recursively
  581. *
  582. CALL ZLARFT(DIRECT, STOREV, N-L, K-L, V, LDV, TAU, T, LDT)
  583. *
  584. * Compute T_{2,2} recursively
  585. *
  586. CALL ZLARFT(DIRECT, STOREV, N, L, V(K-L+1, 1), LDV,
  587. $ TAU(K-L+1), T(K-L+1, K-L+1), LDT)
  588. *
  589. * Compute T_{2,1}
  590. * T_{2,1} = V_{2,2}
  591. *
  592. CALL ZLACPY('All', L, K-L, V(K-L+1, N-K+1), LDV,
  593. $ T(K-L+1, 1), LDT)
  594. *
  595. * T_{2,1} = T_{2,1}*V_{1,2}'
  596. *
  597. CALL ZTRMM('Right', 'Lower', 'Conjugate', 'Unit', L, K-L,
  598. $ ONE, V(1, N-K+1), LDV, T(K-L+1, 1), LDT)
  599. *
  600. * T_{2,1} = V_{2,1}*V_{1,1}' + T_{2,1}
  601. * Note: We assume K <= N, and GEMM will do nothing if N=K
  602. *
  603. CALL ZGEMM('No transpose', 'Conjugate', L, K-L, N-K, ONE,
  604. $ V(K-L+1, 1), LDV, V, LDV, ONE, T(K-L+1, 1),
  605. $ LDT)
  606. *
  607. * At this point, we have that T_{2,1} = V_2*V_1'
  608. * All that is left is to pre and post multiply by -T_{2,2} and T_{1,1}
  609. * respectively.
  610. *
  611. * T_{2,1} = -T_{2,2}*T_{2,1}
  612. *
  613. CALL ZTRMM('Left', 'Lower', 'No tranpose', 'Non-unit', L,
  614. $ K-L, NEG_ONE, T(K-L+1, K-L+1), LDT,
  615. $ T(K-L+1, 1), LDT)
  616. *
  617. * T_{2,1} = T_{2,1}*T_{1,1}
  618. *
  619. CALL ZTRMM('Right', 'Lower', 'No tranpose', 'Non-unit', L,
  620. $ K-L, ONE, T, LDT, T(K-L+1, 1), LDT)
  621. END IF
  622. END SUBROUTINE