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