119 IMPLICIT NONE
120
121
122
123
124
125
126 INTEGER M, N, MB1, NB1, NB2
127
128 DOUBLE PRECISION RESULT(6)
129
130
131
132
133
134 DOUBLE PRECISION, ALLOCATABLE :: A(:,:), AF(:,:), Q(:,:), R(:,:),
135 $ RWORK(:), WORK( : ), T1(:,:), T2(:,:), DIAG(:),
136 $ C(:,:), CF(:,:), D(:,:), DF(:,:)
137
138
139 DOUBLE PRECISION ONE, ZERO
140 parameter( zero = 0.0d+0, one = 1.0d+0 )
141
142
143 LOGICAL TESTZEROS
144 INTEGER INFO, I, J, K, L, LWORK, NB1_UB, NB2_UB, NRB
145 DOUBLE PRECISION ANORM, EPS, RESID, CNORM, DNORM
146
147
148 INTEGER ISEED( 4 )
149 DOUBLE PRECISION WORKQUERY( 1 )
150
151
152 DOUBLE PRECISION DLAMCH, DLANGE, DLANSY
154
155
158
159
160 INTRINSIC ceiling, dble, max, min
161
162
163 CHARACTER(LEN=32) SRNAMT
164
165
166 COMMON / srmnamc / srnamt
167
168
169 DATA iseed / 1988, 1989, 1990, 1991 /
170
171
172
173 testzeros = .false.
174
176 k = min( m, n )
177 l = max( m, n, 1)
178
179
180
181 ALLOCATE ( a(m,n), af(m,n), q(l,l), r(m,l), rwork(l),
182 $ c(m,n), cf(m,n),
183 $ d(n,m), df(n,m) )
184
185
186
187 DO j = 1, n
188 CALL dlarnv( 2, iseed, m, a( 1, j ) )
189 END DO
190 IF( testzeros ) THEN
191 IF( m.GE.4 ) THEN
192 DO j = 1, n
193 CALL dlarnv( 2, iseed, m/2, a( m/4, j ) )
194 END DO
195 END IF
196 END IF
197 CALL dlacpy(
'Full', m, n, a, m, af, m )
198
199
200
201 nrb = max( 1, ceiling( dble( m - n ) / dble( mb1 - n ) ) )
202
203 ALLOCATE ( t1( nb1, n * nrb ) )
204 ALLOCATE ( t2( nb2, n ) )
205 ALLOCATE ( diag( n ) )
206
207
208
209
210
211 nb1_ub = min( nb1, n)
212
213
214
215 nb2_ub = min( nb2, n)
216
217 CALL dlatsqr( m, n, mb1, nb1_ub, af, m, t1, nb1,
218 $ workquery, -1, info )
219 lwork = int( workquery( 1 ) )
220 CALL dorgtsqr( m, n, mb1, nb1, af, m, t1, nb1, workquery, -1,
221 $ info )
222
223 lwork = max( lwork, int( workquery( 1 ) ) )
224
225
226
227
228 lwork = max( lwork, nb2_ub * n, nb2_ub * m )
229
230 ALLOCATE ( work( lwork ) )
231
232
233
234
235
236
237
238
239 srnamt = 'DLATSQR'
240 CALL dlatsqr( m, n, mb1, nb1_ub, af, m, t1, nb1, work, lwork,
241 $ info )
242
243
244
245 srnamt = 'DLACPY'
246 CALL dlacpy(
'U', n, n, af, m, r, m )
247
248
249
250 srnamt = 'DORGTSQR'
251 CALL dorgtsqr( m, n, mb1, nb1, af, m, t1, nb1, work, lwork,
252 $ info )
253
254
255
256
257 srnamt = 'DORHR_COL'
258 CALL dorhr_col( m, n, nb2, af, m, t2, nb2, diag, info )
259
260
261
262
263
264
265
266
267 srnamt = 'DLACPY'
268 CALL dlacpy(
'U', n, n, r, m, af, m )
269
270 DO i = 1, n
271 IF( diag( i ).EQ.-one ) THEN
272 CALL dscal( n+1-i, -one, af( i, i ), m )
273 END IF
274 END DO
275
276
277
278
279
280
281 CALL dlaset(
'Full', m, m, zero, one, q, m )
282
283 srnamt = 'DGEMQRT'
284 CALL dgemqrt(
'L',
'N', m, m, k, nb2_ub, af, m, t2, nb2, q, m,
285 $ work, info )
286
287
288
289 CALL dlaset(
'Full', m, n, zero, zero, r, m )
290
291 CALL dlacpy(
'Upper', m, n, af, m, r, m )
292
293
294
295
296 CALL dgemm(
'T',
'N', m, n, m, -one, q, m, a, m, one, r, m )
297
298 anorm =
dlange(
'1', m, n, a, m, rwork )
299 resid =
dlange(
'1', m, n, r, m, rwork )
300 IF( anorm.GT.zero ) THEN
301 result( 1 ) = resid / ( eps * max( 1, m ) * anorm )
302 ELSE
303 result( 1 ) = zero
304 END IF
305
306
307
308
309 CALL dlaset(
'Full', m, m, zero, one, r, m )
310 CALL dsyrk(
'U',
'T', m, m, -one, q, m, one, r, m )
311 resid =
dlansy(
'1',
'Upper', m, r, m, rwork )
312 result( 2 ) = resid / ( eps * max( 1, m ) )
313
314
315
316 DO j = 1, n
317 CALL dlarnv( 2, iseed, m, c( 1, j ) )
318 END DO
319 cnorm =
dlange(
'1', m, n, c, m, rwork )
320 CALL dlacpy(
'Full', m, n, c, m, cf, m )
321
322
323
324 srnamt = 'DGEMQRT'
325 CALL dgemqrt(
'L',
'N', m, n, k, nb2_ub, af, m, t2, nb2, cf, m,
326 $ work, info )
327
328
329
330
331 CALL dgemm(
'N',
'N', m, n, m, -one, q, m, c, m, one, cf, m )
332 resid =
dlange(
'1', m, n, cf, m, rwork )
333 IF( cnorm.GT.zero ) THEN
334 result( 3 ) = resid / ( eps * max( 1, m ) * cnorm )
335 ELSE
336 result( 3 ) = zero
337 END IF
338
339
340
341 CALL dlacpy(
'Full', m, n, c, m, cf, m )
342
343
344
345 srnamt = 'DGEMQRT'
346 CALL dgemqrt(
'L',
'T', m, n, k, nb2_ub, af, m, t2, nb2, cf, m,
347 $ work, info )
348
349
350
351
352 CALL dgemm(
'T',
'N', m, n, m, -one, q, m, c, m, one, cf, m )
353 resid =
dlange(
'1', m, n, cf, m, rwork )
354 IF( cnorm.GT.zero ) THEN
355 result( 4 ) = resid / ( eps * max( 1, m ) * cnorm )
356 ELSE
357 result( 4 ) = zero
358 END IF
359
360
361
362 DO j = 1, m
363 CALL dlarnv( 2, iseed, n, d( 1, j ) )
364 END DO
365 dnorm =
dlange(
'1', n, m, d, n, rwork )
366 CALL dlacpy(
'Full', n, m, d, n, df, n )
367
368
369
370 srnamt = 'DGEMQRT'
371 CALL dgemqrt(
'R',
'N', n, m, k, nb2_ub, af, m, t2, nb2, df, n,
372 $ work, info )
373
374
375
376
377 CALL dgemm(
'N',
'N', n, m, m, -one, d, n, q, m, one, df, n )
378 resid =
dlange(
'1', n, m, df, n, rwork )
379 IF( dnorm.GT.zero ) THEN
380 result( 5 ) = resid / ( eps * max( 1, m ) * dnorm )
381 ELSE
382 result( 5 ) = zero
383 END IF
384
385
386
387 CALL dlacpy(
'Full', n, m, d, n, df, n )
388
389
390
391 srnamt = 'DGEMQRT'
392 CALL dgemqrt(
'R',
'T', n, m, k, nb2_ub, af, m, t2, nb2, df, n,
393 $ work, info )
394
395
396
397
398 CALL dgemm(
'N',
'T', n, m, m, -one, d, n, q, m, one, df, n )
399 resid =
dlange(
'1', n, m, df, n, rwork )
400 IF( dnorm.GT.zero ) THEN
401 result( 6 ) = resid / ( eps * max( 1, m ) * dnorm )
402 ELSE
403 result( 6 ) = zero
404 END IF
405
406
407
408 DEALLOCATE ( a, af, q, r, rwork, work, t1, t2, diag,
409 $ c, d, cf, df )
410
411 RETURN
412
413
414
subroutine dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
subroutine dgemqrt(side, trans, m, n, k, nb, v, ldv, t, ldt, c, ldc, work, info)
DGEMQRT
subroutine dsyrk(uplo, trans, n, k, alpha, a, lda, beta, c, ldc)
DSYRK
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
double precision function dlamch(cmach)
DLAMCH
double precision function dlange(norm, m, n, a, lda, work)
DLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
double precision function dlansy(norm, uplo, n, a, lda, work)
DLANSY returns the value of the 1-norm, or the Frobenius norm, or the infinity norm,...
subroutine dlarnv(idist, iseed, n, x)
DLARNV returns a vector of random numbers from a uniform or normal distribution.
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.
subroutine dlatsqr(m, n, mb, nb, a, lda, t, ldt, work, lwork, info)
DLATSQR
subroutine dscal(n, da, dx, incx)
DSCAL
subroutine dorgtsqr(m, n, mb, nb, a, lda, t, ldt, work, lwork, info)
DORGTSQR
subroutine dorhr_col(m, n, nb, a, lda, t, ldt, d, info)
DORHR_COL