LAPACK  3.7.0
LAPACK: Linear Algebra PACKage
dtsqr01.f
Go to the documentation of this file.
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
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 )
178  CALL dgemqr( 'L', 'N', m, m, k, af, m, tquery, tsize, cf, m,
179  $ workquery, -1, info)
180  lwork = max( lwork, int( workquery ) )
181  CALL dgemqr( 'L', 'N', m, n, k, af, m, tquery, tsize, cf, m,
182  $ workquery, -1, info)
183  lwork = max( lwork, int( workquery ) )
184  CALL dgemqr( 'L', 'T', m, n, k, af, m, tquery, tsize, cf, m,
185  $ workquery, -1, info)
186  lwork = max( lwork, int( workquery ) )
187  CALL dgemqr( 'R', 'N', n, m, k, af, m, tquery, tsize, df, n,
188  $ workquery, -1, info)
189  lwork = max( lwork, int( workquery ) )
190  CALL dgemqr( 'R', 'T', n, m, k, af, m, tquery, tsize, df, n,
191  $ workquery, -1, info)
192  lwork = max( lwork, int( workquery ) )
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 )
321  CALL dgemlq( 'R', 'N', n, n, k, af, m, tquery, tsize, q, n,
322  $ workquery, -1, info )
323  lwork = max( lwork, int( workquery ) )
324  CALL dgemlq( 'L', 'N', n, m, k, af, m, tquery, tsize, df, n,
325  $ workquery, -1, info)
326  lwork = max( lwork, int( workquery ) )
327  CALL dgemlq( 'L', 'T', n, m, k, af, m, tquery, tsize, df, n,
328  $ workquery, -1, info)
329  lwork = max( lwork, int( workquery ) )
330  CALL dgemlq( 'R', 'N', m, n, k, af, m, tquery, tsize, cf, m,
331  $ workquery, -1, info)
332  lwork = max( lwork, int( workquery ) )
333  CALL dgemlq( 'R', 'T', m, n, k, af, m, tquery, tsize, cf, m,
334  $ workquery, -1, info)
335  lwork = max( lwork, int( workquery ) )
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
subroutine dlacpy(UPLO, M, N, A, LDA, B, LDB)
DLACPY copies all or part of one two-dimensional array to another.
Definition: dlacpy.f:105
subroutine dgemlq(SIDE, TRANS, M, N, K, A, LDA, T, TSIZE, C, LDC, WORK, LWORK, INFO)
Definition: dgemlq.f:170
subroutine dtsqr01(TSSW, M, N, MB, NB, RESULT)
DTSQR01
Definition: dtsqr01.f:86
subroutine dlarnv(IDIST, ISEED, N, X)
DLARNV returns a vector of random numbers from a uniform or normal distribution.
Definition: dlarnv.f:99
subroutine dgeqr(M, N, A, LDA, T, TSIZE, WORK, LWORK, INFO)
Definition: dgeqr.f:162
subroutine dlaset(UPLO, M, N, ALPHA, BETA, A, LDA)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values...
Definition: dlaset.f:112
subroutine dgemm(TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC)
DGEMM
Definition: dgemm.f:189
subroutine dsyrk(UPLO, TRANS, N, K, ALPHA, A, LDA, BETA, C, LDC)
DSYRK
Definition: dsyrk.f:171
subroutine dgemqr(SIDE, TRANS, M, N, K, A, LDA, T, TSIZE, C, LDC, WORK, LWORK, INFO)
Definition: dgemqr.f:171
subroutine dgelq(M, N, A, LDA, T, TSIZE, WORK, LWORK, INFO)
Definition: dgelq.f:161