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.

dtsqr01.f 13 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. *> \brief \b DTSQR01
  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 DTSQR01(TSSW, M,N, MB, NB, RESULT)
  12. *
  13. * .. Scalar Arguments ..
  14. * INTEGER M, N, MB
  15. * .. Return values ..
  16. * DOUBLE PRECISION RESULT(6)
  17. *
  18. *
  19. *> \par Purpose:
  20. * =============
  21. *>
  22. *> \verbatim
  23. *>
  24. *> DTSQR01 tests DGEQR , DGELQ, DGEMLQ and DGEMQR.
  25. *> \endverbatim
  26. *
  27. * Arguments:
  28. * ==========
  29. *
  30. *> \param[in] TSSW
  31. *> \verbatim
  32. *> TSSW is CHARACTER
  33. *> 'TS' for testing tall skinny QR
  34. *> and anything else for testing short wide LQ
  35. *> \endverbatim
  36. *> \param[in] M
  37. *> \verbatim
  38. *> M is INTEGER
  39. *> Number of rows in test matrix.
  40. *> \endverbatim
  41. *>
  42. *> \param[in] N
  43. *> \verbatim
  44. *> N is INTEGER
  45. *> Number of columns in test matrix.
  46. *> \endverbatim
  47. *> \param[in] MB
  48. *> \verbatim
  49. *> MB is INTEGER
  50. *> Number of row in row block in test matrix.
  51. *> \endverbatim
  52. *>
  53. *> \param[in] NB
  54. *> \verbatim
  55. *> NB is INTEGER
  56. *> Number of columns in column block test matrix.
  57. *> \endverbatim
  58. *>
  59. *> \param[out] RESULT
  60. *> \verbatim
  61. *> RESULT is DOUBLE PRECISION array, dimension (6)
  62. *> Results of each of the six tests below.
  63. *>
  64. *> RESULT(1) = | A - Q R | or | A - L Q |
  65. *> RESULT(2) = | I - Q^H Q | or | I - Q Q^H |
  66. *> RESULT(3) = | Q C - Q C |
  67. *> RESULT(4) = | Q^H C - Q^H C |
  68. *> RESULT(5) = | C Q - C Q |
  69. *> RESULT(6) = | C Q^H - C Q^H |
  70. *> \endverbatim
  71. *
  72. * Authors:
  73. * ========
  74. *
  75. *> \author Univ. of Tennessee
  76. *> \author Univ. of California Berkeley
  77. *> \author Univ. of Colorado Denver
  78. *> \author NAG Ltd.
  79. *
  80. *> \date April 2012
  81. *
  82. *> \ingroup double_lin
  83. *
  84. * =====================================================================
  85. SUBROUTINE DTSQR01(TSSW, M, N, MB, NB, RESULT)
  86. IMPLICIT NONE
  87. *
  88. * -- LAPACK test routine (version 3.7.0) --
  89. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  90. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  91. * April 2012
  92. *
  93. * .. Scalar Arguments ..
  94. CHARACTER TSSW
  95. INTEGER M, N, MB, NB
  96. * .. Return values ..
  97. DOUBLE PRECISION RESULT(6)
  98. *
  99. * =====================================================================
  100. *
  101. * ..
  102. * .. Local allocatable arrays
  103. DOUBLE PRECISION, ALLOCATABLE :: AF(:,:), Q(:,:),
  104. $ R(:,:), RWORK(:), WORK( : ), T(:),
  105. $ CF(:,:), DF(:,:), A(:,:), C(:,:), D(:,:), LQ(:,:)
  106. *
  107. * .. Parameters ..
  108. DOUBLE PRECISION ONE, ZERO
  109. PARAMETER( ZERO = 0.0, ONE = 1.0 )
  110. * ..
  111. * .. Local Scalars ..
  112. LOGICAL TESTZEROS, TS
  113. INTEGER INFO, J, K, L, LWORK, TSIZE, MNB
  114. DOUBLE PRECISION ANORM, EPS, RESID, CNORM, DNORM
  115. * ..
  116. * .. Local Arrays ..
  117. INTEGER ISEED( 4 )
  118. DOUBLE PRECISION TQUERY( 5 ), WORKQUERY( 1 )
  119. * ..
  120. * .. External Functions ..
  121. DOUBLE PRECISION DLAMCH, DLANGE, DLANSY
  122. LOGICAL LSAME
  123. INTEGER ILAENV
  124. EXTERNAL DLAMCH, DLANGE, DLANSY, LSAME, ILAENV
  125. * ..
  126. * .. Intrinsic Functions ..
  127. INTRINSIC MAX, MIN
  128. * .. Scalars in Common ..
  129. CHARACTER*32 srnamt
  130. * ..
  131. * .. Common blocks ..
  132. COMMON / srnamc / srnamt
  133. * ..
  134. * .. Data statements ..
  135. DATA ISEED / 1988, 1989, 1990, 1991 /
  136. *
  137. * TEST TALL SKINNY OR SHORT WIDE
  138. *
  139. TS = LSAME(TSSW, 'TS')
  140. *
  141. * TEST MATRICES WITH HALF OF MATRIX BEING ZEROS
  142. *
  143. TESTZEROS = .FALSE.
  144. *
  145. EPS = DLAMCH( 'Epsilon' )
  146. K = MIN(M,N)
  147. L = MAX(M,N,1)
  148. MNB = MAX ( MB, NB)
  149. LWORK = MAX(3,L)*MNB
  150. *
  151. * Dynamically allocate local arrays
  152. *
  153. ALLOCATE ( A(M,N), AF(M,N), Q(L,L), R(M,L), RWORK(L),
  154. $ C(M,N), CF(M,N),
  155. $ D(N,M), DF(N,M), LQ(L,N) )
  156. *
  157. * Put random numbers into A and copy to AF
  158. *
  159. DO J=1,N
  160. CALL DLARNV( 2, ISEED, M, A( 1, J ) )
  161. END DO
  162. IF (TESTZEROS) THEN
  163. IF (M.GE.4) THEN
  164. DO J=1,N
  165. CALL DLARNV( 2, ISEED, M/2, A( M/4, J ) )
  166. END DO
  167. END IF
  168. END IF
  169. CALL DLACPY( 'Full', M, N, A, M, AF, M )
  170. *
  171. IF (TS) THEN
  172. *
  173. * Factor the matrix A in the array AF.
  174. *
  175. CALL DGEQR( M, N, AF, M, TQUERY, -1, WORKQUERY, -1, INFO )
  176. TSIZE = INT( TQUERY( 1 ) )
  177. LWORK = INT( WORKQUERY( 1 ) )
  178. CALL DGEMQR( 'L', 'N', M, M, K, AF, M, TQUERY, TSIZE, CF, M,
  179. $ WORKQUERY, -1, INFO)
  180. LWORK = MAX( LWORK, INT( WORKQUERY( 1 ) ) )
  181. CALL DGEMQR( 'L', 'N', M, N, K, AF, M, TQUERY, TSIZE, CF, M,
  182. $ WORKQUERY, -1, INFO)
  183. LWORK = MAX( LWORK, INT( WORKQUERY( 1 ) ) )
  184. CALL DGEMQR( 'L', 'T', M, N, K, AF, M, TQUERY, TSIZE, CF, M,
  185. $ WORKQUERY, -1, INFO)
  186. LWORK = MAX( LWORK, INT( WORKQUERY( 1 ) ) )
  187. CALL DGEMQR( 'R', 'N', N, M, K, AF, M, TQUERY, TSIZE, DF, N,
  188. $ WORKQUERY, -1, INFO)
  189. LWORK = MAX( LWORK, INT( WORKQUERY( 1 ) ) )
  190. CALL DGEMQR( 'R', 'T', N, M, K, AF, M, TQUERY, TSIZE, DF, N,
  191. $ WORKQUERY, -1, INFO)
  192. LWORK = MAX( LWORK, INT( WORKQUERY( 1 ) ) )
  193. ALLOCATE ( T( TSIZE ) )
  194. ALLOCATE ( WORK( LWORK ) )
  195. srnamt = 'DGEQR'
  196. CALL DGEQR( M, N, AF, M, T, TSIZE, WORK, LWORK, INFO )
  197. *
  198. * Generate the m-by-m matrix Q
  199. *
  200. CALL DLASET( 'Full', M, M, ZERO, ONE, Q, M )
  201. srnamt = 'DGEMQR'
  202. CALL DGEMQR( 'L', 'N', M, M, K, AF, M, T, TSIZE, Q, M,
  203. $ WORK, LWORK, INFO )
  204. *
  205. * Copy R
  206. *
  207. CALL DLASET( 'Full', M, N, ZERO, ZERO, R, M )
  208. CALL DLACPY( 'Upper', M, N, AF, M, R, M )
  209. *
  210. * Compute |R - Q'*A| / |A| and store in RESULT(1)
  211. *
  212. CALL DGEMM( 'T', 'N', M, N, M, -ONE, Q, M, A, M, ONE, R, M )
  213. ANORM = DLANGE( '1', M, N, A, M, RWORK )
  214. RESID = DLANGE( '1', M, N, R, M, RWORK )
  215. IF( ANORM.GT.ZERO ) THEN
  216. RESULT( 1 ) = RESID / (EPS*MAX(1,M)*ANORM)
  217. ELSE
  218. RESULT( 1 ) = ZERO
  219. END IF
  220. *
  221. * Compute |I - Q'*Q| and store in RESULT(2)
  222. *
  223. CALL DLASET( 'Full', M, M, ZERO, ONE, R, M )
  224. CALL DSYRK( 'U', 'C', M, M, -ONE, Q, M, ONE, R, M )
  225. RESID = DLANSY( '1', 'Upper', M, R, M, RWORK )
  226. RESULT( 2 ) = RESID / (EPS*MAX(1,M))
  227. *
  228. * Generate random m-by-n matrix C and a copy CF
  229. *
  230. DO J=1,N
  231. CALL DLARNV( 2, ISEED, M, C( 1, J ) )
  232. END DO
  233. CNORM = DLANGE( '1', M, N, C, M, RWORK)
  234. CALL DLACPY( 'Full', M, N, C, M, CF, M )
  235. *
  236. * Apply Q to C as Q*C
  237. *
  238. srnamt = 'DGEMQR'
  239. CALL DGEMQR( 'L', 'N', M, N, K, AF, M, T, TSIZE, CF, M,
  240. $ WORK, LWORK, INFO)
  241. *
  242. * Compute |Q*C - Q*C| / |C|
  243. *
  244. CALL DGEMM( 'N', 'N', M, N, M, -ONE, Q, M, C, M, ONE, CF, M )
  245. RESID = DLANGE( '1', M, N, CF, M, RWORK )
  246. IF( CNORM.GT.ZERO ) THEN
  247. RESULT( 3 ) = RESID / (EPS*MAX(1,M)*CNORM)
  248. ELSE
  249. RESULT( 3 ) = ZERO
  250. END IF
  251. *
  252. * Copy C into CF again
  253. *
  254. CALL DLACPY( 'Full', M, N, C, M, CF, M )
  255. *
  256. * Apply Q to C as QT*C
  257. *
  258. srnamt = 'DGEMQR'
  259. CALL DGEMQR( 'L', 'T', M, N, K, AF, M, T, TSIZE, CF, M,
  260. $ WORK, LWORK, INFO)
  261. *
  262. * Compute |QT*C - QT*C| / |C|
  263. *
  264. CALL DGEMM( 'T', 'N', M, N, M, -ONE, Q, M, C, M, ONE, CF, M )
  265. RESID = DLANGE( '1', M, N, CF, M, RWORK )
  266. IF( CNORM.GT.ZERO ) THEN
  267. RESULT( 4 ) = RESID / (EPS*MAX(1,M)*CNORM)
  268. ELSE
  269. RESULT( 4 ) = ZERO
  270. END IF
  271. *
  272. * Generate random n-by-m matrix D and a copy DF
  273. *
  274. DO J=1,M
  275. CALL DLARNV( 2, ISEED, N, D( 1, J ) )
  276. END DO
  277. DNORM = DLANGE( '1', N, M, D, N, RWORK)
  278. CALL DLACPY( 'Full', N, M, D, N, DF, N )
  279. *
  280. * Apply Q to D as D*Q
  281. *
  282. srnamt = 'DGEMQR'
  283. CALL DGEMQR( 'R', 'N', N, M, K, AF, M, T, TSIZE, DF, N,
  284. $ WORK, LWORK, INFO)
  285. *
  286. * Compute |D*Q - D*Q| / |D|
  287. *
  288. CALL DGEMM( 'N', 'N', N, M, M, -ONE, D, N, Q, M, ONE, DF, N )
  289. RESID = DLANGE( '1', N, M, DF, N, RWORK )
  290. IF( DNORM.GT.ZERO ) THEN
  291. RESULT( 5 ) = RESID / (EPS*MAX(1,M)*DNORM)
  292. ELSE
  293. RESULT( 5 ) = ZERO
  294. END IF
  295. *
  296. * Copy D into DF again
  297. *
  298. CALL DLACPY( 'Full', N, M, D, N, DF, N )
  299. *
  300. * Apply Q to D as D*QT
  301. *
  302. CALL DGEMQR( 'R', 'T', N, M, K, AF, M, T, TSIZE, DF, N,
  303. $ WORK, LWORK, INFO)
  304. *
  305. * Compute |D*QT - D*QT| / |D|
  306. *
  307. CALL DGEMM( 'N', 'T', N, M, M, -ONE, D, N, Q, M, ONE, DF, N )
  308. RESID = DLANGE( '1', N, M, DF, N, RWORK )
  309. IF( CNORM.GT.ZERO ) THEN
  310. RESULT( 6 ) = RESID / (EPS*MAX(1,M)*DNORM)
  311. ELSE
  312. RESULT( 6 ) = ZERO
  313. END IF
  314. *
  315. * Short and wide
  316. *
  317. ELSE
  318. CALL DGELQ( M, N, AF, M, TQUERY, -1, WORKQUERY, -1, INFO )
  319. TSIZE = INT( TQUERY( 1 ) )
  320. LWORK = INT( WORKQUERY( 1 ) )
  321. CALL DGEMLQ( 'R', 'N', N, N, K, AF, M, TQUERY, TSIZE, Q, N,
  322. $ WORKQUERY, -1, INFO )
  323. LWORK = MAX( LWORK, INT( WORKQUERY( 1 ) ) )
  324. CALL DGEMLQ( 'L', 'N', N, M, K, AF, M, TQUERY, TSIZE, DF, N,
  325. $ WORKQUERY, -1, INFO)
  326. LWORK = MAX( LWORK, INT( WORKQUERY( 1 ) ) )
  327. CALL DGEMLQ( 'L', 'T', N, M, K, AF, M, TQUERY, TSIZE, DF, N,
  328. $ WORKQUERY, -1, INFO)
  329. LWORK = MAX( LWORK, INT( WORKQUERY( 1 ) ) )
  330. CALL DGEMLQ( 'R', 'N', M, N, K, AF, M, TQUERY, TSIZE, CF, M,
  331. $ WORKQUERY, -1, INFO)
  332. LWORK = MAX( LWORK, INT( WORKQUERY( 1 ) ) )
  333. CALL DGEMLQ( 'R', 'T', M, N, K, AF, M, TQUERY, TSIZE, CF, M,
  334. $ WORKQUERY, -1, INFO)
  335. LWORK = MAX( LWORK, INT( WORKQUERY( 1 ) ) )
  336. ALLOCATE ( T( TSIZE ) )
  337. ALLOCATE ( WORK( LWORK ) )
  338. srnamt = 'DGELQ'
  339. CALL DGELQ( M, N, AF, M, T, TSIZE, WORK, LWORK, INFO )
  340. *
  341. *
  342. * Generate the n-by-n matrix Q
  343. *
  344. CALL DLASET( 'Full', N, N, ZERO, ONE, Q, N )
  345. srnamt = 'DGEMLQ'
  346. CALL DGEMLQ( 'R', 'N', N, N, K, AF, M, T, TSIZE, Q, N,
  347. $ WORK, LWORK, INFO )
  348. *
  349. * Copy R
  350. *
  351. CALL DLASET( 'Full', M, N, ZERO, ZERO, LQ, L )
  352. CALL DLACPY( 'Lower', M, N, AF, M, LQ, L )
  353. *
  354. * Compute |L - A*Q'| / |A| and store in RESULT(1)
  355. *
  356. CALL DGEMM( 'N', 'T', M, N, N, -ONE, A, M, Q, N, ONE, LQ, L )
  357. ANORM = DLANGE( '1', M, N, A, M, RWORK )
  358. RESID = DLANGE( '1', M, N, LQ, L, RWORK )
  359. IF( ANORM.GT.ZERO ) THEN
  360. RESULT( 1 ) = RESID / (EPS*MAX(1,N)*ANORM)
  361. ELSE
  362. RESULT( 1 ) = ZERO
  363. END IF
  364. *
  365. * Compute |I - Q'*Q| and store in RESULT(2)
  366. *
  367. CALL DLASET( 'Full', N, N, ZERO, ONE, LQ, L )
  368. CALL DSYRK( 'U', 'C', N, N, -ONE, Q, N, ONE, LQ, L )
  369. RESID = DLANSY( '1', 'Upper', N, LQ, L, RWORK )
  370. RESULT( 2 ) = RESID / (EPS*MAX(1,N))
  371. *
  372. * Generate random m-by-n matrix C and a copy CF
  373. *
  374. DO J=1,M
  375. CALL DLARNV( 2, ISEED, N, D( 1, J ) )
  376. END DO
  377. DNORM = DLANGE( '1', N, M, D, N, RWORK)
  378. CALL DLACPY( 'Full', N, M, D, N, DF, N )
  379. *
  380. * Apply Q to C as Q*C
  381. *
  382. CALL DGEMLQ( 'L', 'N', N, M, K, AF, M, T, TSIZE, DF, N,
  383. $ WORK, LWORK, INFO)
  384. *
  385. * Compute |Q*D - Q*D| / |D|
  386. *
  387. CALL DGEMM( 'N', 'N', N, M, N, -ONE, Q, N, D, N, ONE, DF, N )
  388. RESID = DLANGE( '1', N, M, DF, N, RWORK )
  389. IF( DNORM.GT.ZERO ) THEN
  390. RESULT( 3 ) = RESID / (EPS*MAX(1,N)*DNORM)
  391. ELSE
  392. RESULT( 3 ) = ZERO
  393. END IF
  394. *
  395. * Copy D into DF again
  396. *
  397. CALL DLACPY( 'Full', N, M, D, N, DF, N )
  398. *
  399. * Apply Q to D as QT*D
  400. *
  401. CALL DGEMLQ( 'L', 'T', N, M, K, AF, M, T, TSIZE, DF, N,
  402. $ WORK, LWORK, INFO)
  403. *
  404. * Compute |QT*D - QT*D| / |D|
  405. *
  406. CALL DGEMM( 'T', 'N', N, M, N, -ONE, Q, N, D, N, ONE, DF, N )
  407. RESID = DLANGE( '1', N, M, DF, N, RWORK )
  408. IF( DNORM.GT.ZERO ) THEN
  409. RESULT( 4 ) = RESID / (EPS*MAX(1,N)*DNORM)
  410. ELSE
  411. RESULT( 4 ) = ZERO
  412. END IF
  413. *
  414. * Generate random n-by-m matrix D and a copy DF
  415. *
  416. DO J=1,N
  417. CALL DLARNV( 2, ISEED, M, C( 1, J ) )
  418. END DO
  419. CNORM = DLANGE( '1', M, N, C, M, RWORK)
  420. CALL DLACPY( 'Full', M, N, C, M, CF, M )
  421. *
  422. * Apply Q to C as C*Q
  423. *
  424. CALL DGEMLQ( 'R', 'N', M, N, K, AF, M, T, TSIZE, CF, M,
  425. $ WORK, LWORK, INFO)
  426. *
  427. * Compute |C*Q - C*Q| / |C|
  428. *
  429. CALL DGEMM( 'N', 'N', M, N, N, -ONE, C, M, Q, N, ONE, CF, M )
  430. RESID = DLANGE( '1', N, M, DF, N, RWORK )
  431. IF( CNORM.GT.ZERO ) THEN
  432. RESULT( 5 ) = RESID / (EPS*MAX(1,N)*CNORM)
  433. ELSE
  434. RESULT( 5 ) = ZERO
  435. END IF
  436. *
  437. * Copy C into CF again
  438. *
  439. CALL DLACPY( 'Full', M, N, C, M, CF, M )
  440. *
  441. * Apply Q to D as D*QT
  442. *
  443. CALL DGEMLQ( 'R', 'T', M, N, K, AF, M, T, TSIZE, CF, M,
  444. $ WORK, LWORK, INFO)
  445. *
  446. * Compute |C*QT - C*QT| / |C|
  447. *
  448. CALL DGEMM( 'N', 'T', M, N, N, -ONE, C, M, Q, N, ONE, CF, M )
  449. RESID = DLANGE( '1', M, N, CF, M, RWORK )
  450. IF( CNORM.GT.ZERO ) THEN
  451. RESULT( 6 ) = RESID / (EPS*MAX(1,N)*CNORM)
  452. ELSE
  453. RESULT( 6 ) = ZERO
  454. END IF
  455. *
  456. END IF
  457. *
  458. * Deallocate all arrays
  459. *
  460. DEALLOCATE ( A, AF, Q, R, RWORK, WORK, T, C, D, CF, DF)
  461. *
  462. RETURN
  463. END