1       DOUBLE PRECISION FUNCTION DQRT14( TRANS, M, N, NRHS, A, LDA, X,
  2      $                 LDX, WORK, LWORK )
  3 *
  4 *  -- LAPACK test routine (version 3.1) --
  5 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
  6 *     November 2006
  7 *
  8 *     .. Scalar Arguments ..
  9       CHARACTER          TRANS
 10       INTEGER            LDA, LDX, LWORK, M, N, NRHS
 11 *     ..
 12 *     .. Array Arguments ..
 13       DOUBLE PRECISION   A( LDA, * ), WORK( LWORK ), X( LDX, * )
 14 *     ..
 15 *
 16 *  Purpose
 17 *  =======
 18 *
 19 *  DQRT14 checks whether X is in the row space of A or A'.  It does so
 20 *  by scaling both X and A such that their norms are in the range
 21 *  [sqrt(eps), 1/sqrt(eps)], then computing a QR factorization of [A,X]
 22 *  (if TRANS = 'T') or an LQ factorization of [A',X]' (if TRANS = 'N'),
 23 *  and returning the norm of the trailing triangle, scaled by
 24 *  MAX(M,N,NRHS)*eps.
 25 *
 26 *  Arguments
 27 *  =========
 28 *
 29 *  TRANS   (input) CHARACTER*1
 30 *          = 'N':  No transpose, check for X in the row space of A
 31 *          = 'T':  Transpose, check for X in the row space of A'.
 32 *
 33 *  M       (input) INTEGER
 34 *          The number of rows of the matrix A.
 35 *
 36 *  N       (input) INTEGER
 37 *          The number of columns of the matrix A.
 38 *
 39 *  NRHS    (input) INTEGER
 40 *          The number of right hand sides, i.e., the number of columns
 41 *          of X.
 42 *
 43 *  A       (input) DOUBLE PRECISION array, dimension (LDA,N)
 44 *          The M-by-N matrix A.
 45 *
 46 *  LDA     (input) INTEGER
 47 *          The leading dimension of the array A.
 48 *
 49 *  X       (input) DOUBLE PRECISION array, dimension (LDX,NRHS)
 50 *          If TRANS = 'N', the N-by-NRHS matrix X.
 51 *          IF TRANS = 'T', the M-by-NRHS matrix X.
 52 *
 53 *  LDX     (input) INTEGER
 54 *          The leading dimension of the array X.
 55 *
 56 *  WORK    (workspace) DOUBLE PRECISION array dimension (LWORK)
 57 *
 58 *  LWORK   (input) INTEGER
 59 *          length of workspace array required
 60 *          If TRANS = 'N', LWORK >= (M+NRHS)*(N+2);
 61 *          if TRANS = 'T', LWORK >= (N+NRHS)*(M+2).
 62 *
 63 *  =====================================================================
 64 *
 65 *     .. Parameters ..
 66       DOUBLE PRECISION   ZERO, ONE
 67       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )
 68 *     ..
 69 *     .. Local Scalars ..
 70       LOGICAL            TPSD
 71       INTEGER            I, INFO, J, LDWORK
 72       DOUBLE PRECISION   ANRM, ERR, XNRM
 73 *     ..
 74 *     .. Local Arrays ..
 75       DOUBLE PRECISION   RWORK( 1 )
 76 *     ..
 77 *     .. External Functions ..
 78       LOGICAL            LSAME
 79       DOUBLE PRECISION   DLAMCH, DLANGE
 80       EXTERNAL           LSAME, DLAMCH, DLANGE
 81 *     ..
 82 *     .. External Subroutines ..
 83       EXTERNAL           DGELQ2, DGEQR2, DLACPY, DLASCL, XERBLA
 84 *     ..
 85 *     .. Intrinsic Functions ..
 86       INTRINSIC          ABSDBLEMAXMIN
 87 *     ..
 88 *     .. Executable Statements ..
 89 *
 90       DQRT14 = ZERO
 91       IF( LSAME( TRANS, 'N' ) ) THEN
 92          LDWORK = M + NRHS
 93          TPSD = .FALSE.
 94          IF( LWORK.LT.( M+NRHS )*( N+2 ) ) THEN
 95             CALL XERBLA( 'DQRT14'10 )
 96             RETURN
 97          ELSE IF( N.LE.0 .OR. NRHS.LE.0 ) THEN
 98             RETURN
 99          END IF
100       ELSE IF( LSAME( TRANS, 'T' ) ) THEN
101          LDWORK = M
102          TPSD = .TRUE.
103          IF( LWORK.LT.( N+NRHS )*( M+2 ) ) THEN
104             CALL XERBLA( 'DQRT14'10 )
105             RETURN
106          ELSE IF( M.LE.0 .OR. NRHS.LE.0 ) THEN
107             RETURN
108          END IF
109       ELSE
110          CALL XERBLA( 'DQRT14'1 )
111          RETURN
112       END IF
113 *
114 *     Copy and scale A
115 *
116       CALL DLACPY( 'All', M, N, A, LDA, WORK, LDWORK )
117       ANRM = DLANGE( 'M', M, N, WORK, LDWORK, RWORK )
118       IF( ANRM.NE.ZERO )
119      $   CALL DLASCL( 'G'00, ANRM, ONE, M, N, WORK, LDWORK, INFO )
120 *
121 *     Copy X or X' into the right place and scale it
122 *
123       IF( TPSD ) THEN
124 *
125 *        Copy X into columns n+1:n+nrhs of work
126 *
127          CALL DLACPY( 'All', M, NRHS, X, LDX, WORK( N*LDWORK+1 ),
128      $                LDWORK )
129          XNRM = DLANGE( 'M', M, NRHS, WORK( N*LDWORK+1 ), LDWORK,
130      $          RWORK )
131          IF( XNRM.NE.ZERO )
132      $      CALL DLASCL( 'G'00, XNRM, ONE, M, NRHS,
133      $                   WORK( N*LDWORK+1 ), LDWORK, INFO )
134          ANRM = DLANGE( 'One-norm', M, N+NRHS, WORK, LDWORK, RWORK )
135 *
136 *        Compute QR factorization of X
137 *
138          CALL DGEQR2( M, N+NRHS, WORK, LDWORK,
139      $                WORK( LDWORK*( N+NRHS )+1 ),
140      $                WORK( LDWORK*( N+NRHS )+MIN( M, N+NRHS )+1 ),
141      $                INFO )
142 *
143 *        Compute largest entry in upper triangle of
144 *        work(n+1:m,n+1:n+nrhs)
145 *
146          ERR = ZERO
147          DO 20 J = N + 1, N + NRHS
148             DO 10 I = N + 1MIN( M, J )
149                ERR = MAX( ERR, ABS( WORK( I+( J-1 )*M ) ) )
150    10       CONTINUE
151    20    CONTINUE
152 *
153       ELSE
154 *
155 *        Copy X' into rows m+1:m+nrhs of work
156 *
157          DO 40 I = 1, N
158             DO 30 J = 1, NRHS
159                WORK( M+J+( I-1 )*LDWORK ) = X( I, J )
160    30       CONTINUE
161    40    CONTINUE
162 *
163          XNRM = DLANGE( 'M', NRHS, N, WORK( M+1 ), LDWORK, RWORK )
164          IF( XNRM.NE.ZERO )
165      $      CALL DLASCL( 'G'00, XNRM, ONE, NRHS, N, WORK( M+1 ),
166      $                   LDWORK, INFO )
167 *
168 *        Compute LQ factorization of work
169 *
170          CALL DGELQ2( LDWORK, N, WORK, LDWORK, WORK( LDWORK*N+1 ),
171      $                WORK( LDWORK*( N+1 )+1 ), INFO )
172 *
173 *        Compute largest entry in lower triangle in
174 *        work(m+1:m+nrhs,m+1:n)
175 *
176          ERR = ZERO
177          DO 60 J = M + 1, N
178             DO 50 I = J, LDWORK
179                ERR = MAX( ERR, ABS( WORK( I+( J-1 )*LDWORK ) ) )
180    50       CONTINUE
181    60    CONTINUE
182 *
183       END IF
184 *
185       DQRT14 = ERR / ( DBLEMAX( M, N, NRHS ) )*DLAMCH( 'Epsilon' ) )
186 *
187       RETURN
188 *
189 *     End of DQRT14
190 *
191       END