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.

dlarft.f 20 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. *> \brief \b DLARFT 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 DLARFT + dependencies
  10. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlarft.f">
  11. *> [TGZ]</a>
  12. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlarft.f">
  13. *> [ZIP]</a>
  14. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarft.f">
  15. *> [TXT]</a>
  16. *> \endhtmlonly
  17. *
  18. * Definition:
  19. * ===========
  20. *
  21. * RECURSIVE SUBROUTINE DLARFT( 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. * DOUBLE PRECISION T( LDT, * ), TAU( * ), V( LDV, * )
  29. * ..
  30. *
  31. *
  32. *> \par Purpose:
  33. * =============
  34. *>
  35. *> \verbatim
  36. *>
  37. *> DLARFT forms the triangular factor T of a real 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**T
  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**T * 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 DOUBLE PRECISION 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 DOUBLE PRECISION 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 DOUBLE PRECISION 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 DLARFT( 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. DOUBLE PRECISION T( LDT, * ), TAU( * ), V( LDV, * )
  177. * ..
  178. *
  179. * .. Parameters ..
  180. *
  181. DOUBLE PRECISION 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 DTRMM,DGEMM,DLACPY
  192. *
  193. * .. External Functions..
  194. *
  195. LOGICAL LSAME
  196. EXTERNAL LSAME
  197. *
  198. * The general scheme used is inspired by the approach inside DGEQRT3
  199. * which was (at the time of writing this code):
  200. * Based on the algorithm of Elmroth and Gustavson,
  201. * IBM J. Res. Develop. Vol 44 No. 4 July 2000.
  202. * ..
  203. * .. Executable Statements ..
  204. *
  205. * Quick return if possible
  206. *
  207. IF(N.EQ.0.OR.K.EQ.0) THEN
  208. RETURN
  209. END IF
  210. *
  211. * Base case
  212. *
  213. IF(N.EQ.1.OR.K.EQ.1) THEN
  214. T(1,1) = TAU(1)
  215. RETURN
  216. END IF
  217. *
  218. * Beginning of executable statements
  219. *
  220. L = K / 2
  221. *
  222. * Determine what kind of Q we need to compute
  223. * We assume that if the user doesn't provide 'F' for DIRECT,
  224. * then they meant to provide 'B' and if they don't provide
  225. * 'C' for STOREV, then they meant to provide 'R'
  226. *
  227. DIRF = LSAME(DIRECT,'F')
  228. COLV = LSAME(STOREV,'C')
  229. *
  230. * QR happens when we have forward direction in column storage
  231. *
  232. QR = DIRF.AND.COLV
  233. *
  234. * LQ happens when we have forward direction in row storage
  235. *
  236. LQ = DIRF.AND.(.NOT.COLV)
  237. *
  238. * QL happens when we have backward direction in column storage
  239. *
  240. QL = (.NOT.DIRF).AND.COLV
  241. *
  242. * The last case is RQ. Due to how we structured this, if the
  243. * above 3 are false, then RQ must be true, so we never store
  244. * this
  245. * RQ happens when we have backward direction in row storage
  246. * RQ = (.NOT.DIRF).AND.(.NOT.COLV)
  247. *
  248. IF(QR) THEN
  249. *
  250. * Break V apart into 6 components
  251. *
  252. * V = |---------------|
  253. * |V_{1,1} 0 |
  254. * |V_{2,1} V_{2,2}|
  255. * |V_{3,1} V_{3,2}|
  256. * |---------------|
  257. *
  258. * V_{1,1}\in\R^{l,l} unit lower triangular
  259. * V_{2,1}\in\R^{k-l,l} rectangular
  260. * V_{3,1}\in\R^{n-k,l} rectangular
  261. *
  262. * V_{2,2}\in\R^{k-l,k-l} unit lower triangular
  263. * V_{3,2}\in\R^{n-k,k-l} rectangular
  264. *
  265. * We will construct the T matrix
  266. * T = |---------------|
  267. * |T_{1,1} T_{1,2}|
  268. * |0 T_{2,2}|
  269. * |---------------|
  270. *
  271. * T is the triangular factor obtained from block reflectors.
  272. * To motivate the structure, assume we have already computed T_{1,1}
  273. * and T_{2,2}. Then collect the associated reflectors in V_1 and V_2
  274. *
  275. * T_{1,1}\in\R^{l, l} upper triangular
  276. * T_{2,2}\in\R^{k-l, k-l} upper triangular
  277. * T_{1,2}\in\R^{l, k-l} rectangular
  278. *
  279. * Where l = floor(k/2)
  280. *
  281. * Then, consider the product:
  282. *
  283. * (I - V_1*T_{1,1}*V_1')*(I - V_2*T_{2,2}*V_2')
  284. * = 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'
  285. *
  286. * Define T_{1,2} = -T_{1,1}*V_1'*V_2*T_{2,2}
  287. *
  288. * Then, we can define the matrix V as
  289. * V = |-------|
  290. * |V_1 V_2|
  291. * |-------|
  292. *
  293. * So, our product is equivalent to the matrix product
  294. * I - V*T*V'
  295. * This means, we can compute T_{1,1} and T_{2,2}, then use this information
  296. * to compute T_{1,2}
  297. *
  298. * Compute T_{1,1} recursively
  299. *
  300. CALL DLARFT(DIRECT, STOREV, N, L, V, LDV, TAU, T, LDT)
  301. *
  302. * Compute T_{2,2} recursively
  303. *
  304. CALL DLARFT(DIRECT, STOREV, N-L, K-L, V(L+1, L+1), LDV,
  305. $ TAU(L+1), T(L+1, L+1), LDT)
  306. *
  307. * Compute T_{1,2}
  308. * T_{1,2} = V_{2,1}'
  309. *
  310. DO J = 1, L
  311. DO I = 1, K-L
  312. T(J, L+I) = V(L+I, J)
  313. END DO
  314. END DO
  315. *
  316. * T_{1,2} = T_{1,2}*V_{2,2}
  317. *
  318. CALL DTRMM('Right', 'Lower', 'No transpose', 'Unit', L,
  319. $ K-L, ONE, V(L+1, L+1), LDV, T(1, L+1), LDT)
  320. *
  321. * T_{1,2} = V_{3,1}'*V_{3,2} + T_{1,2}
  322. * Note: We assume K <= N, and GEMM will do nothing if N=K
  323. *
  324. CALL DGEMM('Transpose', 'No transpose', L, K-L, N-K, ONE,
  325. $ V(K+1, 1), LDV, V(K+1, L+1), LDV, ONE,
  326. $ T(1, L+1), LDT)
  327. *
  328. * At this point, we have that T_{1,2} = V_1'*V_2
  329. * All that is left is to pre and post multiply by -T_{1,1} and T_{2,2}
  330. * respectively.
  331. *
  332. * T_{1,2} = -T_{1,1}*T_{1,2}
  333. *
  334. CALL DTRMM('Left', 'Upper', 'No transpose', 'Non-unit', L,
  335. $ K-L, NEG_ONE, T, LDT, T(1, L+1), LDT)
  336. *
  337. * T_{1,2} = T_{1,2}*T_{2,2}
  338. *
  339. CALL DTRMM('Right', 'Upper', 'No transpose', 'Non-unit', L,
  340. $ K-L, ONE, T(L+1, L+1), LDT, T(1, L+1), LDT)
  341. ELSE IF(LQ) THEN
  342. *
  343. * Break V apart into 6 components
  344. *
  345. * V = |----------------------|
  346. * |V_{1,1} V_{1,2} V{1,3}|
  347. * |0 V_{2,2} V{2,3}|
  348. * |----------------------|
  349. *
  350. * V_{1,1}\in\R^{l,l} unit upper triangular
  351. * V_{1,2}\in\R^{l,k-l} rectangular
  352. * V_{1,3}\in\R^{l,n-k} rectangular
  353. *
  354. * V_{2,2}\in\R^{k-l,k-l} unit upper triangular
  355. * V_{2,3}\in\R^{k-l,n-k} rectangular
  356. *
  357. * Where l = floor(k/2)
  358. *
  359. * We will construct the T matrix
  360. * T = |---------------|
  361. * |T_{1,1} T_{1,2}|
  362. * |0 T_{2,2}|
  363. * |---------------|
  364. *
  365. * T is the triangular factor obtained from block reflectors.
  366. * To motivate the structure, assume we have already computed T_{1,1}
  367. * and T_{2,2}. Then collect the associated reflectors in V_1 and V_2
  368. *
  369. * T_{1,1}\in\R^{l, l} upper triangular
  370. * T_{2,2}\in\R^{k-l, k-l} upper triangular
  371. * T_{1,2}\in\R^{l, k-l} rectangular
  372. *
  373. * Then, consider the product:
  374. *
  375. * (I - V_1'*T_{1,1}*V_1)*(I - V_2'*T_{2,2}*V_2)
  376. * = 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
  377. *
  378. * Define T_{1,2} = -T_{1,1}*V_1*V_2'*T_{2,2}
  379. *
  380. * Then, we can define the matrix V as
  381. * V = |---|
  382. * |V_1|
  383. * |V_2|
  384. * |---|
  385. *
  386. * So, our product is equivalent to the matrix product
  387. * I - V'*T*V
  388. * This means, we can compute T_{1,1} and T_{2,2}, then use this information
  389. * to compute T_{1,2}
  390. *
  391. * Compute T_{1,1} recursively
  392. *
  393. CALL DLARFT(DIRECT, STOREV, N, L, V, LDV, TAU, T, LDT)
  394. *
  395. * Compute T_{2,2} recursively
  396. *
  397. CALL DLARFT(DIRECT, STOREV, N-L, K-L, V(L+1, L+1), LDV,
  398. $ TAU(L+1), T(L+1, L+1), LDT)
  399. *
  400. * Compute T_{1,2}
  401. * T_{1,2} = V_{1,2}
  402. *
  403. CALL DLACPY('All', L, K-L, V(1, L+1), LDV, T(1, L+1), LDT)
  404. *
  405. * T_{1,2} = T_{1,2}*V_{2,2}'
  406. *
  407. CALL DTRMM('Right', 'Upper', 'Transpose', 'Unit', L, K-L,
  408. $ ONE, V(L+1, L+1), LDV, T(1, L+1), LDT)
  409. *
  410. * T_{1,2} = V_{1,3}*V_{2,3}' + T_{1,2}
  411. * Note: We assume K <= N, and GEMM will do nothing if N=K
  412. *
  413. CALL DGEMM('No transpose', 'Transpose', L, K-L, N-K, ONE,
  414. $ V(1, K+1), LDV, V(L+1, K+1), LDV, ONE,
  415. $ T(1, L+1), LDT)
  416. *
  417. * At this point, we have that T_{1,2} = V_1*V_2'
  418. * All that is left is to pre and post multiply by -T_{1,1} and T_{2,2}
  419. * respectively.
  420. *
  421. * T_{1,2} = -T_{1,1}*T_{1,2}
  422. *
  423. CALL DTRMM('Left', 'Upper', 'No transpose', 'Non-unit', L,
  424. $ K-L, NEG_ONE, T, LDT, T(1, L+1), LDT)
  425. *
  426. * T_{1,2} = T_{1,2}*T_{2,2}
  427. *
  428. CALL DTRMM('Right', 'Upper', 'No transpose', 'Non-unit', L,
  429. $ K-L, ONE, T(L+1, L+1), LDT, T(1, L+1), LDT)
  430. ELSE IF(QL) THEN
  431. *
  432. * Break V apart into 6 components
  433. *
  434. * V = |---------------|
  435. * |V_{1,1} V_{1,2}|
  436. * |V_{2,1} V_{2,2}|
  437. * |0 V_{3,2}|
  438. * |---------------|
  439. *
  440. * V_{1,1}\in\R^{n-k,k-l} rectangular
  441. * V_{2,1}\in\R^{k-l,k-l} unit upper triangular
  442. *
  443. * V_{1,2}\in\R^{n-k,l} rectangular
  444. * V_{2,2}\in\R^{k-l,l} rectangular
  445. * V_{3,2}\in\R^{l,l} unit upper triangular
  446. *
  447. * We will construct the T matrix
  448. * T = |---------------|
  449. * |T_{1,1} 0 |
  450. * |T_{2,1} T_{2,2}|
  451. * |---------------|
  452. *
  453. * T is the triangular factor obtained from block reflectors.
  454. * To motivate the structure, assume we have already computed T_{1,1}
  455. * and T_{2,2}. Then collect the associated reflectors in V_1 and V_2
  456. *
  457. * T_{1,1}\in\R^{k-l, k-l} non-unit lower triangular
  458. * T_{2,2}\in\R^{l, l} non-unit lower triangular
  459. * T_{2,1}\in\R^{k-l, l} rectangular
  460. *
  461. * Where l = floor(k/2)
  462. *
  463. * Then, consider the product:
  464. *
  465. * (I - V_2*T_{2,2}*V_2')*(I - V_1*T_{1,1}*V_1')
  466. * = 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'
  467. *
  468. * Define T_{2,1} = -T_{2,2}*V_2'*V_1*T_{1,1}
  469. *
  470. * Then, we can define the matrix V as
  471. * V = |-------|
  472. * |V_1 V_2|
  473. * |-------|
  474. *
  475. * So, our product is equivalent to the matrix product
  476. * I - V*T*V'
  477. * This means, we can compute T_{1,1} and T_{2,2}, then use this information
  478. * to compute T_{2,1}
  479. *
  480. * Compute T_{1,1} recursively
  481. *
  482. CALL DLARFT(DIRECT, STOREV, N-L, K-L, V, LDV, TAU, T, LDT)
  483. *
  484. * Compute T_{2,2} recursively
  485. *
  486. CALL DLARFT(DIRECT, STOREV, N, L, V(1, K-L+1), LDV,
  487. $ TAU(K-L+1), T(K-L+1, K-L+1), LDT)
  488. *
  489. * Compute T_{2,1}
  490. * T_{2,1} = V_{2,2}'
  491. *
  492. DO J = 1, K-L
  493. DO I = 1, L
  494. T(K-L+I, J) = V(N-K+J, K-L+I)
  495. END DO
  496. END DO
  497. *
  498. * T_{2,1} = T_{2,1}*V_{2,1}
  499. *
  500. CALL DTRMM('Right', 'Upper', 'No transpose', 'Unit', L,
  501. $ K-L, ONE, V(N-K+1, 1), LDV, T(K-L+1, 1), LDT)
  502. *
  503. * T_{2,1} = V_{2,2}'*V_{2,1} + T_{2,1}
  504. * Note: We assume K <= N, and GEMM will do nothing if N=K
  505. *
  506. CALL DGEMM('Transpose', 'No transpose', L, K-L, N-K, ONE,
  507. $ V(1, K-L+1), LDV, V, LDV, ONE, T(K-L+1, 1),
  508. $ LDT)
  509. *
  510. * At this point, we have that T_{2,1} = V_2'*V_1
  511. * All that is left is to pre and post multiply by -T_{2,2} and T_{1,1}
  512. * respectively.
  513. *
  514. * T_{2,1} = -T_{2,2}*T_{2,1}
  515. *
  516. CALL DTRMM('Left', 'Lower', 'No transpose', 'Non-unit', L,
  517. $ K-L, NEG_ONE, T(K-L+1, K-L+1), LDT,
  518. $ T(K-L+1, 1), LDT)
  519. *
  520. * T_{2,1} = T_{2,1}*T_{1,1}
  521. *
  522. CALL DTRMM('Right', 'Lower', 'No transpose', 'Non-unit', L,
  523. $ K-L, ONE, T, LDT, T(K-L+1, 1), LDT)
  524. ELSE
  525. *
  526. * Else means RQ case
  527. *
  528. * Break V apart into 6 components
  529. *
  530. * V = |-----------------------|
  531. * |V_{1,1} V_{1,2} 0 |
  532. * |V_{2,1} V_{2,2} V_{2,3}|
  533. * |-----------------------|
  534. *
  535. * V_{1,1}\in\R^{k-l,n-k} rectangular
  536. * V_{1,2}\in\R^{k-l,k-l} unit lower triangular
  537. *
  538. * V_{2,1}\in\R^{l,n-k} rectangular
  539. * V_{2,2}\in\R^{l,k-l} rectangular
  540. * V_{2,3}\in\R^{l,l} unit lower triangular
  541. *
  542. * We will construct the T matrix
  543. * T = |---------------|
  544. * |T_{1,1} 0 |
  545. * |T_{2,1} T_{2,2}|
  546. * |---------------|
  547. *
  548. * T is the triangular factor obtained from block reflectors.
  549. * To motivate the structure, assume we have already computed T_{1,1}
  550. * and T_{2,2}. Then collect the associated reflectors in V_1 and V_2
  551. *
  552. * T_{1,1}\in\R^{k-l, k-l} non-unit lower triangular
  553. * T_{2,2}\in\R^{l, l} non-unit lower triangular
  554. * T_{2,1}\in\R^{k-l, l} rectangular
  555. *
  556. * Where l = floor(k/2)
  557. *
  558. * Then, consider the product:
  559. *
  560. * (I - V_2'*T_{2,2}*V_2)*(I - V_1'*T_{1,1}*V_1)
  561. * = 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
  562. *
  563. * Define T_{2,1} = -T_{2,2}*V_2*V_1'*T_{1,1}
  564. *
  565. * Then, we can define the matrix V as
  566. * V = |---|
  567. * |V_1|
  568. * |V_2|
  569. * |---|
  570. *
  571. * So, our product is equivalent to the matrix product
  572. * I - V'*T*V
  573. * This means, we can compute T_{1,1} and T_{2,2}, then use this information
  574. * to compute T_{2,1}
  575. *
  576. * Compute T_{1,1} recursively
  577. *
  578. CALL DLARFT(DIRECT, STOREV, N-L, K-L, V, LDV, TAU, T, LDT)
  579. *
  580. * Compute T_{2,2} recursively
  581. *
  582. CALL DLARFT(DIRECT, STOREV, N, L, V(K-L+1, 1), LDV,
  583. $ TAU(K-L+1), T(K-L+1, K-L+1), LDT)
  584. *
  585. * Compute T_{2,1}
  586. * T_{2,1} = V_{2,2}
  587. *
  588. CALL DLACPY('All', L, K-L, V(K-L+1, N-K+1), LDV,
  589. $ T(K-L+1, 1), LDT)
  590. *
  591. * T_{2,1} = T_{2,1}*V_{1,2}'
  592. *
  593. CALL DTRMM('Right', 'Lower', 'Transpose', 'Unit', L, K-L,
  594. $ ONE, V(1, N-K+1), LDV, T(K-L+1, 1), LDT)
  595. *
  596. * T_{2,1} = V_{2,1}*V_{1,1}' + T_{2,1}
  597. * Note: We assume K <= N, and GEMM will do nothing if N=K
  598. *
  599. CALL DGEMM('No transpose', 'Transpose', L, K-L, N-K, ONE,
  600. $ V(K-L+1, 1), LDV, V, LDV, ONE, T(K-L+1, 1),
  601. $ LDT)
  602. *
  603. * At this point, we have that T_{2,1} = V_2*V_1'
  604. * All that is left is to pre and post multiply by -T_{2,2} and T_{1,1}
  605. * respectively.
  606. *
  607. * T_{2,1} = -T_{2,2}*T_{2,1}
  608. *
  609. CALL DTRMM('Left', 'Lower', 'No tranpose', 'Non-unit', L,
  610. $ K-L, NEG_ONE, T(K-L+1, K-L+1), LDT,
  611. $ T(K-L+1, 1), LDT)
  612. *
  613. * T_{2,1} = T_{2,1}*T_{1,1}
  614. *
  615. CALL DTRMM('Right', 'Lower', 'No tranpose', 'Non-unit', L,
  616. $ K-L, ONE, T, LDT, T(K-L+1, 1), LDT)
  617. END IF
  618. END SUBROUTINE