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