120 IMPLICIT NONE
121
122
123
124
125
126
127 INTEGER M, N, MB1, NB1, NB2
128
129 DOUBLE PRECISION RESULT(6)
130
131
132
133
134
135 DOUBLE PRECISION, ALLOCATABLE :: A(:,:), AF(:,:), Q(:,:), R(:,:),
136 $ RWORK(:), WORK( : ), T1(:,:), T2(:,:), DIAG(:),
137 $ C(:,:), CF(:,:), D(:,:), DF(:,:)
138
139
140 DOUBLE PRECISION ONE, ZERO
141 parameter( zero = 0.0d+0, one = 1.0d+0 )
142
143
144 LOGICAL TESTZEROS
145 INTEGER INFO, J, K, L, LWORK, NB2_UB, NRB
146 DOUBLE PRECISION ANORM, EPS, RESID, CNORM, DNORM
147
148
149 INTEGER ISEED( 4 )
150 DOUBLE PRECISION WORKQUERY( 1 )
151
152
153 DOUBLE PRECISION DLAMCH, DLANGE, DLANSY
155
156
159
160
161 INTRINSIC ceiling, dble, max, min
162
163
164 CHARACTER(LEN=32) SRNAMT
165
166
167 COMMON / srmnamc / srnamt
168
169
170 DATA iseed / 1988, 1989, 1990, 1991 /
171
172
173
174 testzeros = .false.
175
177 k = min( m, n )
178 l = max( m, n, 1)
179
180
181
182 ALLOCATE ( a(m,n), af(m,n), q(l,l), r(m,l), rwork(l),
183 $ c(m,n), cf(m,n),
184 $ d(n,m), df(n,m) )
185
186
187
188 DO j = 1, n
189 CALL dlarnv( 2, iseed, m, a( 1, j ) )
190 END DO
191 IF( testzeros ) THEN
192 IF( m.GE.4 ) THEN
193 DO j = 1, n
194 CALL dlarnv( 2, iseed, m/2, a( m/4, j ) )
195 END DO
196 END IF
197 END IF
198 CALL dlacpy(
'Full', m, n, a, m, af, m )
199
200
201
202 nrb = max( 1, ceiling( dble( m - n ) / dble( mb1 - n ) ) )
203
204 ALLOCATE ( t1( nb1, n * nrb ) )
205 ALLOCATE ( t2( nb2, n ) )
206 ALLOCATE ( diag( n ) )
207
208
209
210
211
212 nb2_ub = min( nb2, n)
213
214
215 CALL dgetsqrhrt( m, n, mb1, nb1, nb2, af, m, t2, nb2,
216 $ workquery, -1, info )
217
218 lwork = int( workquery( 1 ) )
219
220
221
222
223 lwork = max( lwork, nb2_ub * n, nb2_ub * m )
224
225 ALLOCATE ( work( lwork ) )
226
227
228
229
230
231
232
233
234 srnamt = 'DGETSQRHRT'
235 CALL dgetsqrhrt( m, n, mb1, nb1, nb2, af, m, t2, nb2,
236 $ work, lwork, info )
237
238
239
240
241
242
243 CALL dlaset(
'Full', m, m, zero, one, q, m )
244
245 srnamt = 'DGEMQRT'
246 CALL dgemqrt(
'L',
'N', m, m, k, nb2_ub, af, m, t2, nb2, q, m,
247 $ work, info )
248
249
250
251 CALL dlaset(
'Full', m, n, zero, zero, r, m )
252
253 CALL dlacpy(
'Upper', m, n, af, m, r, m )
254
255
256
257
258 CALL dgemm(
'T',
'N', m, n, m, -one, q, m, a, m, one, r, m )
259
260 anorm =
dlange(
'1', m, n, a, m, rwork )
261 resid =
dlange(
'1', m, n, r, m, rwork )
262 IF( anorm.GT.zero ) THEN
263 result( 1 ) = resid / ( eps * max( 1, m ) * anorm )
264 ELSE
265 result( 1 ) = zero
266 END IF
267
268
269
270
271 CALL dlaset(
'Full', m, m, zero, one, r, m )
272 CALL dsyrk(
'U',
'T', m, m, -one, q, m, one, r, m )
273 resid =
dlansy(
'1',
'Upper', m, r, m, rwork )
274 result( 2 ) = resid / ( eps * max( 1, m ) )
275
276
277
278 DO j = 1, n
279 CALL dlarnv( 2, iseed, m, c( 1, j ) )
280 END DO
281 cnorm =
dlange(
'1', m, n, c, m, rwork )
282 CALL dlacpy(
'Full', m, n, c, m, cf, m )
283
284
285
286 srnamt = 'DGEMQRT'
287 CALL dgemqrt(
'L',
'N', m, n, k, nb2_ub, af, m, t2, nb2, cf, m,
288 $ work, info )
289
290
291
292
293 CALL dgemm(
'N',
'N', m, n, m, -one, q, m, c, m, one, cf, m )
294 resid =
dlange(
'1', m, n, cf, m, rwork )
295 IF( cnorm.GT.zero ) THEN
296 result( 3 ) = resid / ( eps * max( 1, m ) * cnorm )
297 ELSE
298 result( 3 ) = zero
299 END IF
300
301
302
303 CALL dlacpy(
'Full', m, n, c, m, cf, m )
304
305
306
307 srnamt = 'DGEMQRT'
308 CALL dgemqrt(
'L',
'T', m, n, k, nb2_ub, af, m, t2, nb2, cf, m,
309 $ work, info )
310
311
312
313
314 CALL dgemm(
'T',
'N', m, n, m, -one, q, m, c, m, one, cf, m )
315 resid =
dlange(
'1', m, n, cf, m, rwork )
316 IF( cnorm.GT.zero ) THEN
317 result( 4 ) = resid / ( eps * max( 1, m ) * cnorm )
318 ELSE
319 result( 4 ) = zero
320 END IF
321
322
323
324 DO j = 1, m
325 CALL dlarnv( 2, iseed, n, d( 1, j ) )
326 END DO
327 dnorm =
dlange(
'1', n, m, d, n, rwork )
328 CALL dlacpy(
'Full', n, m, d, n, df, n )
329
330
331
332 srnamt = 'DGEMQRT'
333 CALL dgemqrt(
'R',
'N', n, m, k, nb2_ub, af, m, t2, nb2, df, n,
334 $ work, info )
335
336
337
338
339 CALL dgemm(
'N',
'N', n, m, m, -one, d, n, q, m, one, df, n )
340 resid =
dlange(
'1', n, m, df, n, rwork )
341 IF( dnorm.GT.zero ) THEN
342 result( 5 ) = resid / ( eps * max( 1, m ) * dnorm )
343 ELSE
344 result( 5 ) = zero
345 END IF
346
347
348
349 CALL dlacpy(
'Full', n, m, d, n, df, n )
350
351
352
353 srnamt = 'DGEMQRT'
354 CALL dgemqrt(
'R',
'T', n, m, k, nb2_ub, af, m, t2, nb2, df, n,
355 $ work, info )
356
357
358
359
360 CALL dgemm(
'N',
'T', n, m, m, -one, d, n, q, m, one, df, n )
361 resid =
dlange(
'1', n, m, df, n, rwork )
362 IF( dnorm.GT.zero ) THEN
363 result( 6 ) = resid / ( eps * max( 1, m ) * dnorm )
364 ELSE
365 result( 6 ) = zero
366 END IF
367
368
369
370 DEALLOCATE ( a, af, q, r, rwork, work, t1, t2, diag,
371 $ c, d, cf, df )
372
373 RETURN
374
375
376
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 dgetsqrhrt(m, n, mb1, nb1, nb2, a, lda, t, ldt, work, lwork, info)
DGETSQRHRT
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 dscal(n, da, dx, incx)
DSCAL