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.

ccsdts.f 18 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. *> \brief \b CCSDTS
  2. *
  3. * =========== DOCUMENTATION ===========
  4. *
  5. * Online html documentation available at
  6. * http://www.netlib.org/lapack/explore-html/
  7. *
  8. * Definition:
  9. * ===========
  10. *
  11. * SUBROUTINE CCSDTS( M, P, Q, X, XF, LDX, U1, LDU1, U2, LDU2, V1T,
  12. * LDV1T, V2T, LDV2T, THETA, IWORK, WORK, LWORK,
  13. * RWORK, RESULT )
  14. *
  15. * .. Scalar Arguments ..
  16. * INTEGER LDX, LDU1, LDU2, LDV1T, LDV2T, LWORK, M, P, Q
  17. * ..
  18. * .. Array Arguments ..
  19. * INTEGER IWORK( * )
  20. * REAL RESULT( 15 ), RWORK( * ), THETA( * )
  21. * COMPLEX U1( LDU1, * ), U2( LDU2, * ), V1T( LDV1T, * ),
  22. * $ V2T( LDV2T, * ), WORK( LWORK ), X( LDX, * ),
  23. * $ XF( LDX, * )
  24. * ..
  25. *
  26. *
  27. *> \par Purpose:
  28. * =============
  29. *>
  30. *> \verbatim
  31. *>
  32. *> CCSDTS tests CUNCSD, which, given an M-by-M partitioned unitary
  33. *> matrix X,
  34. *> Q M-Q
  35. *> X = [ X11 X12 ] P ,
  36. *> [ X21 X22 ] M-P
  37. *>
  38. *> computes the CSD
  39. *>
  40. *> [ U1 ]**T * [ X11 X12 ] * [ V1 ]
  41. *> [ U2 ] [ X21 X22 ] [ V2 ]
  42. *>
  43. *> [ I 0 0 | 0 0 0 ]
  44. *> [ 0 C 0 | 0 -S 0 ]
  45. *> [ 0 0 0 | 0 0 -I ]
  46. *> = [---------------------] = [ D11 D12 ] .
  47. *> [ 0 0 0 | I 0 0 ] [ D21 D22 ]
  48. *> [ 0 S 0 | 0 C 0 ]
  49. *> [ 0 0 I | 0 0 0 ]
  50. *>
  51. *> and also SORCSD2BY1, which, given
  52. *> Q
  53. *> [ X11 ] P ,
  54. *> [ X21 ] M-P
  55. *>
  56. *> computes the 2-by-1 CSD
  57. *>
  58. *> [ I 0 0 ]
  59. *> [ 0 C 0 ]
  60. *> [ 0 0 0 ]
  61. *> [ U1 ]**T * [ X11 ] * V1 = [----------] = [ D11 ] ,
  62. *> [ U2 ] [ X21 ] [ 0 0 0 ] [ D21 ]
  63. *> [ 0 S 0 ]
  64. *> [ 0 0 I ]
  65. *> \endverbatim
  66. *
  67. * Arguments:
  68. * ==========
  69. *
  70. *> \param[in] M
  71. *> \verbatim
  72. *> M is INTEGER
  73. *> The number of rows of the matrix X. M >= 0.
  74. *> \endverbatim
  75. *>
  76. *> \param[in] P
  77. *> \verbatim
  78. *> P is INTEGER
  79. *> The number of rows of the matrix X11. P >= 0.
  80. *> \endverbatim
  81. *>
  82. *> \param[in] Q
  83. *> \verbatim
  84. *> Q is INTEGER
  85. *> The number of columns of the matrix X11. Q >= 0.
  86. *> \endverbatim
  87. *>
  88. *> \param[in] X
  89. *> \verbatim
  90. *> X is COMPLEX array, dimension (LDX,M)
  91. *> The M-by-M matrix X.
  92. *> \endverbatim
  93. *>
  94. *> \param[out] XF
  95. *> \verbatim
  96. *> XF is COMPLEX array, dimension (LDX,M)
  97. *> Details of the CSD of X, as returned by CUNCSD;
  98. *> see CUNCSD for further details.
  99. *> \endverbatim
  100. *>
  101. *> \param[in] LDX
  102. *> \verbatim
  103. *> LDX is INTEGER
  104. *> The leading dimension of the arrays X and XF.
  105. *> LDX >= max( 1,M ).
  106. *> \endverbatim
  107. *>
  108. *> \param[out] U1
  109. *> \verbatim
  110. *> U1 is COMPLEX array, dimension(LDU1,P)
  111. *> The P-by-P unitary matrix U1.
  112. *> \endverbatim
  113. *>
  114. *> \param[in] LDU1
  115. *> \verbatim
  116. *> LDU1 is INTEGER
  117. *> The leading dimension of the array U1. LDU >= max(1,P).
  118. *> \endverbatim
  119. *>
  120. *> \param[out] U2
  121. *> \verbatim
  122. *> U2 is COMPLEX array, dimension(LDU2,M-P)
  123. *> The (M-P)-by-(M-P) unitary matrix U2.
  124. *> \endverbatim
  125. *>
  126. *> \param[in] LDU2
  127. *> \verbatim
  128. *> LDU2 is INTEGER
  129. *> The leading dimension of the array U2. LDU >= max(1,M-P).
  130. *> \endverbatim
  131. *>
  132. *> \param[out] V1T
  133. *> \verbatim
  134. *> V1T is COMPLEX array, dimension(LDV1T,Q)
  135. *> The Q-by-Q unitary matrix V1T.
  136. *> \endverbatim
  137. *>
  138. *> \param[in] LDV1T
  139. *> \verbatim
  140. *> LDV1T is INTEGER
  141. *> The leading dimension of the array V1T. LDV1T >=
  142. *> max(1,Q).
  143. *> \endverbatim
  144. *>
  145. *> \param[out] V2T
  146. *> \verbatim
  147. *> V2T is COMPLEX array, dimension(LDV2T,M-Q)
  148. *> The (M-Q)-by-(M-Q) unitary matrix V2T.
  149. *> \endverbatim
  150. *>
  151. *> \param[in] LDV2T
  152. *> \verbatim
  153. *> LDV2T is INTEGER
  154. *> The leading dimension of the array V2T. LDV2T >=
  155. *> max(1,M-Q).
  156. *> \endverbatim
  157. *>
  158. *> \param[out] THETA
  159. *> \verbatim
  160. *> THETA is REAL array, dimension MIN(P,M-P,Q,M-Q)
  161. *> The CS values of X; the essentially diagonal matrices C and
  162. *> S are constructed from THETA; see subroutine CUNCSD for
  163. *> details.
  164. *> \endverbatim
  165. *>
  166. *> \param[out] IWORK
  167. *> \verbatim
  168. *> IWORK is INTEGER array, dimension (M)
  169. *> \endverbatim
  170. *>
  171. *> \param[out] WORK
  172. *> \verbatim
  173. *> WORK is COMPLEX array, dimension (LWORK)
  174. *> \endverbatim
  175. *>
  176. *> \param[in] LWORK
  177. *> \verbatim
  178. *> LWORK is INTEGER
  179. *> The dimension of the array WORK
  180. *> \endverbatim
  181. *>
  182. *> \param[out] RWORK
  183. *> \verbatim
  184. *> RWORK is REAL array
  185. *> \endverbatim
  186. *>
  187. *> \param[out] RESULT
  188. *> \verbatim
  189. *> RESULT is REAL array, dimension (15)
  190. *> The test ratios:
  191. *> First, the 2-by-2 CSD:
  192. *> RESULT(1) = norm( U1'*X11*V1 - D11 ) / ( MAX(1,P,Q)*EPS2 )
  193. *> RESULT(2) = norm( U1'*X12*V2 - D12 ) / ( MAX(1,P,M-Q)*EPS2 )
  194. *> RESULT(3) = norm( U2'*X21*V1 - D21 ) / ( MAX(1,M-P,Q)*EPS2 )
  195. *> RESULT(4) = norm( U2'*X22*V2 - D22 ) / ( MAX(1,M-P,M-Q)*EPS2 )
  196. *> RESULT(5) = norm( I - U1'*U1 ) / ( MAX(1,P)*ULP )
  197. *> RESULT(6) = norm( I - U2'*U2 ) / ( MAX(1,M-P)*ULP )
  198. *> RESULT(7) = norm( I - V1T'*V1T ) / ( MAX(1,Q)*ULP )
  199. *> RESULT(8) = norm( I - V2T'*V2T ) / ( MAX(1,M-Q)*ULP )
  200. *> RESULT(9) = 0 if THETA is in increasing order and
  201. *> all angles are in [0,pi/2];
  202. *> = ULPINV otherwise.
  203. *> Then, the 2-by-1 CSD:
  204. *> RESULT(10) = norm( U1'*X11*V1 - D11 ) / ( MAX(1,P,Q)*EPS2 )
  205. *> RESULT(11) = norm( U2'*X21*V1 - D21 ) / ( MAX(1,M-P,Q)*EPS2 )
  206. *> RESULT(12) = norm( I - U1'*U1 ) / ( MAX(1,P)*ULP )
  207. *> RESULT(13) = norm( I - U2'*U2 ) / ( MAX(1,M-P)*ULP )
  208. *> RESULT(14) = norm( I - V1T'*V1T ) / ( MAX(1,Q)*ULP )
  209. *> RESULT(15) = 0 if THETA is in increasing order and
  210. *> all angles are in [0,pi/2];
  211. *> = ULPINV otherwise.
  212. *> ( EPS2 = MAX( norm( I - X'*X ) / M, ULP ). )
  213. *> \endverbatim
  214. *
  215. * Authors:
  216. * ========
  217. *
  218. *> \author Univ. of Tennessee
  219. *> \author Univ. of California Berkeley
  220. *> \author Univ. of Colorado Denver
  221. *> \author NAG Ltd.
  222. *
  223. *> \date December 2016
  224. *
  225. *> \ingroup complex_eig
  226. *
  227. * =====================================================================
  228. SUBROUTINE CCSDTS( M, P, Q, X, XF, LDX, U1, LDU1, U2, LDU2, V1T,
  229. $ LDV1T, V2T, LDV2T, THETA, IWORK, WORK, LWORK,
  230. $ RWORK, RESULT )
  231. *
  232. * -- LAPACK test routine (version 3.7.0) --
  233. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  234. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  235. * December 2016
  236. *
  237. * .. Scalar Arguments ..
  238. INTEGER LDX, LDU1, LDU2, LDV1T, LDV2T, LWORK, M, P, Q
  239. * ..
  240. * .. Array Arguments ..
  241. INTEGER IWORK( * )
  242. REAL RESULT( 15 ), RWORK( * ), THETA( * )
  243. COMPLEX U1( LDU1, * ), U2( LDU2, * ), V1T( LDV1T, * ),
  244. $ V2T( LDV2T, * ), WORK( LWORK ), X( LDX, * ),
  245. $ XF( LDX, * )
  246. * ..
  247. *
  248. * =====================================================================
  249. *
  250. * .. Parameters ..
  251. REAL PIOVER2, REALONE, REALZERO
  252. PARAMETER ( PIOVER2 = 1.57079632679489662E0,
  253. $ REALONE = 1.0E0, REALZERO = 0.0E0 )
  254. COMPLEX ZERO, ONE
  255. PARAMETER ( ZERO = (0.0E0,0.0E0), ONE = (1.0E0,0.0E0) )
  256. * ..
  257. * .. Local Scalars ..
  258. INTEGER I, INFO, R
  259. REAL EPS2, RESID, ULP, ULPINV
  260. * ..
  261. * .. External Functions ..
  262. REAL SLAMCH, CLANGE, CLANHE
  263. EXTERNAL SLAMCH, CLANGE, CLANHE
  264. * ..
  265. * .. External Subroutines ..
  266. EXTERNAL CGEMM, CHERK, CLACPY, CLASET, CUNCSD,
  267. $ CUNCSD2BY1
  268. * ..
  269. * .. Intrinsic Functions ..
  270. INTRINSIC CMPLX, COS, MAX, MIN, REAL, SIN
  271. * ..
  272. * .. Executable Statements ..
  273. *
  274. ULP = SLAMCH( 'Precision' )
  275. ULPINV = REALONE / ULP
  276. *
  277. * The first half of the routine checks the 2-by-2 CSD
  278. *
  279. CALL CLASET( 'Full', M, M, ZERO, ONE, WORK, LDX )
  280. CALL CHERK( 'Upper', 'Conjugate transpose', M, M, -REALONE,
  281. $ X, LDX, REALONE, WORK, LDX )
  282. IF (M.GT.0) THEN
  283. EPS2 = MAX( ULP,
  284. $ CLANGE( '1', M, M, WORK, LDX, RWORK ) / REAL( M ) )
  285. ELSE
  286. EPS2 = ULP
  287. END IF
  288. R = MIN( P, M-P, Q, M-Q )
  289. *
  290. * Copy the matrix X to the array XF.
  291. *
  292. CALL CLACPY( 'Full', M, M, X, LDX, XF, LDX )
  293. *
  294. * Compute the CSD
  295. *
  296. CALL CUNCSD( 'Y', 'Y', 'Y', 'Y', 'N', 'D', M, P, Q, XF(1,1), LDX,
  297. $ XF(1,Q+1), LDX, XF(P+1,1), LDX, XF(P+1,Q+1), LDX,
  298. $ THETA, U1, LDU1, U2, LDU2, V1T, LDV1T, V2T, LDV2T,
  299. $ WORK, LWORK, RWORK, 17*(R+2), IWORK, INFO )
  300. *
  301. * Compute XF := diag(U1,U2)'*X*diag(V1,V2) - [D11 D12; D21 D22]
  302. *
  303. CALL CLACPY( 'Full', M, M, X, LDX, XF, LDX )
  304. *
  305. CALL CGEMM( 'No transpose', 'Conjugate transpose', P, Q, Q, ONE,
  306. $ XF, LDX, V1T, LDV1T, ZERO, WORK, LDX )
  307. *
  308. CALL CGEMM( 'Conjugate transpose', 'No transpose', P, Q, P, ONE,
  309. $ U1, LDU1, WORK, LDX, ZERO, XF, LDX )
  310. *
  311. DO I = 1, MIN(P,Q)-R
  312. XF(I,I) = XF(I,I) - ONE
  313. END DO
  314. DO I = 1, R
  315. XF(MIN(P,Q)-R+I,MIN(P,Q)-R+I) =
  316. $ XF(MIN(P,Q)-R+I,MIN(P,Q)-R+I) - CMPLX( COS(THETA(I)),
  317. $ 0.0E0 )
  318. END DO
  319. *
  320. CALL CGEMM( 'No transpose', 'Conjugate transpose', P, M-Q, M-Q,
  321. $ ONE, XF(1,Q+1), LDX, V2T, LDV2T, ZERO, WORK, LDX )
  322. *
  323. CALL CGEMM( 'Conjugate transpose', 'No transpose', P, M-Q, P,
  324. $ ONE, U1, LDU1, WORK, LDX, ZERO, XF(1,Q+1), LDX )
  325. *
  326. DO I = 1, MIN(P,M-Q)-R
  327. XF(P-I+1,M-I+1) = XF(P-I+1,M-I+1) + ONE
  328. END DO
  329. DO I = 1, R
  330. XF(P-(MIN(P,M-Q)-R)+1-I,M-(MIN(P,M-Q)-R)+1-I) =
  331. $ XF(P-(MIN(P,M-Q)-R)+1-I,M-(MIN(P,M-Q)-R)+1-I) +
  332. $ CMPLX( SIN(THETA(R-I+1)), 0.0E0 )
  333. END DO
  334. *
  335. CALL CGEMM( 'No transpose', 'Conjugate transpose', M-P, Q, Q, ONE,
  336. $ XF(P+1,1), LDX, V1T, LDV1T, ZERO, WORK, LDX )
  337. *
  338. CALL CGEMM( 'Conjugate transpose', 'No transpose', M-P, Q, M-P,
  339. $ ONE, U2, LDU2, WORK, LDX, ZERO, XF(P+1,1), LDX )
  340. *
  341. DO I = 1, MIN(M-P,Q)-R
  342. XF(M-I+1,Q-I+1) = XF(M-I+1,Q-I+1) - ONE
  343. END DO
  344. DO I = 1, R
  345. XF(M-(MIN(M-P,Q)-R)+1-I,Q-(MIN(M-P,Q)-R)+1-I) =
  346. $ XF(M-(MIN(M-P,Q)-R)+1-I,Q-(MIN(M-P,Q)-R)+1-I) -
  347. $ CMPLX( SIN(THETA(R-I+1)), 0.0E0 )
  348. END DO
  349. *
  350. CALL CGEMM( 'No transpose', 'Conjugate transpose', M-P, M-Q, M-Q,
  351. $ ONE, XF(P+1,Q+1), LDX, V2T, LDV2T, ZERO, WORK, LDX )
  352. *
  353. CALL CGEMM( 'Conjugate transpose', 'No transpose', M-P, M-Q, M-P,
  354. $ ONE, U2, LDU2, WORK, LDX, ZERO, XF(P+1,Q+1), LDX )
  355. *
  356. DO I = 1, MIN(M-P,M-Q)-R
  357. XF(P+I,Q+I) = XF(P+I,Q+I) - ONE
  358. END DO
  359. DO I = 1, R
  360. XF(P+(MIN(M-P,M-Q)-R)+I,Q+(MIN(M-P,M-Q)-R)+I) =
  361. $ XF(P+(MIN(M-P,M-Q)-R)+I,Q+(MIN(M-P,M-Q)-R)+I) -
  362. $ CMPLX( COS(THETA(I)), 0.0E0 )
  363. END DO
  364. *
  365. * Compute norm( U1'*X11*V1 - D11 ) / ( MAX(1,P,Q)*EPS2 ) .
  366. *
  367. RESID = CLANGE( '1', P, Q, XF, LDX, RWORK )
  368. RESULT( 1 ) = ( RESID / REAL(MAX(1,P,Q)) ) / EPS2
  369. *
  370. * Compute norm( U1'*X12*V2 - D12 ) / ( MAX(1,P,M-Q)*EPS2 ) .
  371. *
  372. RESID = CLANGE( '1', P, M-Q, XF(1,Q+1), LDX, RWORK )
  373. RESULT( 2 ) = ( RESID / REAL(MAX(1,P,M-Q)) ) / EPS2
  374. *
  375. * Compute norm( U2'*X21*V1 - D21 ) / ( MAX(1,M-P,Q)*EPS2 ) .
  376. *
  377. RESID = CLANGE( '1', M-P, Q, XF(P+1,1), LDX, RWORK )
  378. RESULT( 3 ) = ( RESID / REAL(MAX(1,M-P,Q)) ) / EPS2
  379. *
  380. * Compute norm( U2'*X22*V2 - D22 ) / ( MAX(1,M-P,M-Q)*EPS2 ) .
  381. *
  382. RESID = CLANGE( '1', M-P, M-Q, XF(P+1,Q+1), LDX, RWORK )
  383. RESULT( 4 ) = ( RESID / REAL(MAX(1,M-P,M-Q)) ) / EPS2
  384. *
  385. * Compute I - U1'*U1
  386. *
  387. CALL CLASET( 'Full', P, P, ZERO, ONE, WORK, LDU1 )
  388. CALL CHERK( 'Upper', 'Conjugate transpose', P, P, -REALONE,
  389. $ U1, LDU1, REALONE, WORK, LDU1 )
  390. *
  391. * Compute norm( I - U'*U ) / ( MAX(1,P) * ULP ) .
  392. *
  393. RESID = CLANHE( '1', 'Upper', P, WORK, LDU1, RWORK )
  394. RESULT( 5 ) = ( RESID / REAL(MAX(1,P)) ) / ULP
  395. *
  396. * Compute I - U2'*U2
  397. *
  398. CALL CLASET( 'Full', M-P, M-P, ZERO, ONE, WORK, LDU2 )
  399. CALL CHERK( 'Upper', 'Conjugate transpose', M-P, M-P, -REALONE,
  400. $ U2, LDU2, REALONE, WORK, LDU2 )
  401. *
  402. * Compute norm( I - U2'*U2 ) / ( MAX(1,M-P) * ULP ) .
  403. *
  404. RESID = CLANHE( '1', 'Upper', M-P, WORK, LDU2, RWORK )
  405. RESULT( 6 ) = ( RESID / REAL(MAX(1,M-P)) ) / ULP
  406. *
  407. * Compute I - V1T*V1T'
  408. *
  409. CALL CLASET( 'Full', Q, Q, ZERO, ONE, WORK, LDV1T )
  410. CALL CHERK( 'Upper', 'No transpose', Q, Q, -REALONE,
  411. $ V1T, LDV1T, REALONE, WORK, LDV1T )
  412. *
  413. * Compute norm( I - V1T*V1T' ) / ( MAX(1,Q) * ULP ) .
  414. *
  415. RESID = CLANHE( '1', 'Upper', Q, WORK, LDV1T, RWORK )
  416. RESULT( 7 ) = ( RESID / REAL(MAX(1,Q)) ) / ULP
  417. *
  418. * Compute I - V2T*V2T'
  419. *
  420. CALL CLASET( 'Full', M-Q, M-Q, ZERO, ONE, WORK, LDV2T )
  421. CALL CHERK( 'Upper', 'No transpose', M-Q, M-Q, -REALONE,
  422. $ V2T, LDV2T, REALONE, WORK, LDV2T )
  423. *
  424. * Compute norm( I - V2T*V2T' ) / ( MAX(1,M-Q) * ULP ) .
  425. *
  426. RESID = CLANHE( '1', 'Upper', M-Q, WORK, LDV2T, RWORK )
  427. RESULT( 8 ) = ( RESID / REAL(MAX(1,M-Q)) ) / ULP
  428. *
  429. * Check sorting
  430. *
  431. RESULT( 9 ) = REALZERO
  432. DO I = 1, R
  433. IF( THETA(I).LT.REALZERO .OR. THETA(I).GT.PIOVER2 ) THEN
  434. RESULT( 9 ) = ULPINV
  435. END IF
  436. IF( I.GT.1) THEN
  437. IF ( THETA(I).LT.THETA(I-1) ) THEN
  438. RESULT( 9 ) = ULPINV
  439. END IF
  440. END IF
  441. END DO
  442. *
  443. * The second half of the routine checks the 2-by-1 CSD
  444. *
  445. CALL CLASET( 'Full', Q, Q, ZERO, ONE, WORK, LDX )
  446. CALL CHERK( 'Upper', 'Conjugate transpose', Q, M, -REALONE,
  447. $ X, LDX, REALONE, WORK, LDX )
  448. IF (M.GT.0) THEN
  449. EPS2 = MAX( ULP,
  450. $ CLANGE( '1', Q, Q, WORK, LDX, RWORK ) / REAL( M ) )
  451. ELSE
  452. EPS2 = ULP
  453. END IF
  454. R = MIN( P, M-P, Q, M-Q )
  455. *
  456. * Copy the matrix X to the array XF.
  457. *
  458. CALL CLACPY( 'Full', M, Q, X, LDX, XF, LDX )
  459. *
  460. * Compute the CSD
  461. *
  462. CALL CUNCSD2BY1( 'Y', 'Y', 'Y', M, P, Q, XF(1,1), LDX, XF(P+1,1),
  463. $ LDX, THETA, U1, LDU1, U2, LDU2, V1T, LDV1T, WORK,
  464. $ LWORK, RWORK, 17*(R+2), IWORK, INFO )
  465. *
  466. * Compute [X11;X21] := diag(U1,U2)'*[X11;X21]*V1 - [D11;D21]
  467. *
  468. CALL CGEMM( 'No transpose', 'Conjugate transpose', P, Q, Q, ONE,
  469. $ X, LDX, V1T, LDV1T, ZERO, WORK, LDX )
  470. *
  471. CALL CGEMM( 'Conjugate transpose', 'No transpose', P, Q, P, ONE,
  472. $ U1, LDU1, WORK, LDX, ZERO, X, LDX )
  473. *
  474. DO I = 1, MIN(P,Q)-R
  475. X(I,I) = X(I,I) - ONE
  476. END DO
  477. DO I = 1, R
  478. X(MIN(P,Q)-R+I,MIN(P,Q)-R+I) =
  479. $ X(MIN(P,Q)-R+I,MIN(P,Q)-R+I) - CMPLX( COS(THETA(I)),
  480. $ 0.0E0 )
  481. END DO
  482. *
  483. CALL CGEMM( 'No transpose', 'Conjugate transpose', M-P, Q, Q, ONE,
  484. $ X(P+1,1), LDX, V1T, LDV1T, ZERO, WORK, LDX )
  485. *
  486. CALL CGEMM( 'Conjugate transpose', 'No transpose', M-P, Q, M-P,
  487. $ ONE, U2, LDU2, WORK, LDX, ZERO, X(P+1,1), LDX )
  488. *
  489. DO I = 1, MIN(M-P,Q)-R
  490. X(M-I+1,Q-I+1) = X(M-I+1,Q-I+1) - ONE
  491. END DO
  492. DO I = 1, R
  493. X(M-(MIN(M-P,Q)-R)+1-I,Q-(MIN(M-P,Q)-R)+1-I) =
  494. $ X(M-(MIN(M-P,Q)-R)+1-I,Q-(MIN(M-P,Q)-R)+1-I) -
  495. $ CMPLX( SIN(THETA(R-I+1)), 0.0E0 )
  496. END DO
  497. *
  498. * Compute norm( U1'*X11*V1 - D11 ) / ( MAX(1,P,Q)*EPS2 ) .
  499. *
  500. RESID = CLANGE( '1', P, Q, X, LDX, RWORK )
  501. RESULT( 10 ) = ( RESID / REAL(MAX(1,P,Q)) ) / EPS2
  502. *
  503. * Compute norm( U2'*X21*V1 - D21 ) / ( MAX(1,M-P,Q)*EPS2 ) .
  504. *
  505. RESID = CLANGE( '1', M-P, Q, X(P+1,1), LDX, RWORK )
  506. RESULT( 11 ) = ( RESID / REAL(MAX(1,M-P,Q)) ) / EPS2
  507. *
  508. * Compute I - U1'*U1
  509. *
  510. CALL CLASET( 'Full', P, P, ZERO, ONE, WORK, LDU1 )
  511. CALL CHERK( 'Upper', 'Conjugate transpose', P, P, -REALONE,
  512. $ U1, LDU1, REALONE, WORK, LDU1 )
  513. *
  514. * Compute norm( I - U1'*U1 ) / ( MAX(1,P) * ULP ) .
  515. *
  516. RESID = CLANHE( '1', 'Upper', P, WORK, LDU1, RWORK )
  517. RESULT( 12 ) = ( RESID / REAL(MAX(1,P)) ) / ULP
  518. *
  519. * Compute I - U2'*U2
  520. *
  521. CALL CLASET( 'Full', M-P, M-P, ZERO, ONE, WORK, LDU2 )
  522. CALL CHERK( 'Upper', 'Conjugate transpose', M-P, M-P, -REALONE,
  523. $ U2, LDU2, REALONE, WORK, LDU2 )
  524. *
  525. * Compute norm( I - U2'*U2 ) / ( MAX(1,M-P) * ULP ) .
  526. *
  527. RESID = CLANHE( '1', 'Upper', M-P, WORK, LDU2, RWORK )
  528. RESULT( 13 ) = ( RESID / REAL(MAX(1,M-P)) ) / ULP
  529. *
  530. * Compute I - V1T*V1T'
  531. *
  532. CALL CLASET( 'Full', Q, Q, ZERO, ONE, WORK, LDV1T )
  533. CALL CHERK( 'Upper', 'No transpose', Q, Q, -REALONE,
  534. $ V1T, LDV1T, REALONE, WORK, LDV1T )
  535. *
  536. * Compute norm( I - V1T*V1T' ) / ( MAX(1,Q) * ULP ) .
  537. *
  538. RESID = CLANHE( '1', 'Upper', Q, WORK, LDV1T, RWORK )
  539. RESULT( 14 ) = ( RESID / REAL(MAX(1,Q)) ) / ULP
  540. *
  541. * Check sorting
  542. *
  543. RESULT( 15 ) = REALZERO
  544. DO I = 1, R
  545. IF( THETA(I).LT.REALZERO .OR. THETA(I).GT.PIOVER2 ) THEN
  546. RESULT( 15 ) = ULPINV
  547. END IF
  548. IF( I.GT.1) THEN
  549. IF ( THETA(I).LT.THETA(I-1) ) THEN
  550. RESULT( 15 ) = ULPINV
  551. END IF
  552. END IF
  553. END DO
  554. *
  555. RETURN
  556. *
  557. * End of CCSDTS
  558. *
  559. END