Skip to content

Commit 7d15f83

Browse files
kleineLidklyuchinskiy
authored andcommitted
handle and document corner cases of lwork in lapack, double complex precision
1 parent e0d8afb commit 7d15f83

33 files changed

+278
-169
lines changed

SRC/zgebrd.f

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@
122122
*> \param[in] LWORK
123123
*> \verbatim
124124
*> LWORK is INTEGER
125-
*> The length of the array WORK. LWORK >= max(1,M,N).
125+
*> The length of the array WORK.
126+
*> LWORK >= 1, if MIN(M,N) = 0, and LWORK >= MAX(M,N), otherwise.
126127
*> For optimum performance LWORK >= (M+N)*NB, where NB
127128
*> is the optimal blocksize.
128129
*>
@@ -223,8 +224,8 @@ SUBROUTINE ZGEBRD( M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK,
223224
* ..
224225
* .. Local Scalars ..
225226
LOGICAL LQUERY
226-
INTEGER I, IINFO, J, LDWRKX, LDWRKY, LWKOPT, MINMN, NB,
227-
$ NBMIN, NX, WS
227+
INTEGER I, IINFO, J, LDWRKX, LDWRKY, LWKMIN, LWKOPT,
228+
$ MINMN, NB, NBMIN, NX, WS
228229
* ..
229230
* .. External Subroutines ..
230231
EXTERNAL XERBLA, ZGEBD2, ZGEMM, ZLABRD
@@ -241,17 +242,25 @@ SUBROUTINE ZGEBRD( M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK,
241242
* Test the input parameters
242243
*
243244
INFO = 0
244-
NB = MAX( 1, ILAENV( 1, 'ZGEBRD', ' ', M, N, -1, -1 ) )
245-
LWKOPT = ( M+N )*NB
245+
MINMN = MIN( M, N )
246+
IF( MINMN.EQ.0 ) THEN
247+
LWKMIN = 1
248+
LWKOPT = 1
249+
ELSE
250+
LWKMIN = MAX( M, N )
251+
NB = MAX( 1, ILAENV( 1, 'ZGEBRD', ' ', M, N, -1, -1 ) )
252+
LWKOPT = MAX( 1, ( M+N )*NB )
253+
END IF
246254
WORK( 1 ) = DBLE( LWKOPT )
255+
*
247256
LQUERY = ( LWORK.EQ.-1 )
248257
IF( M.LT.0 ) THEN
249258
INFO = -1
250259
ELSE IF( N.LT.0 ) THEN
251260
INFO = -2
252261
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
253262
INFO = -4
254-
ELSE IF( LWORK.LT.MAX( 1, M, N ) .AND. .NOT.LQUERY ) THEN
263+
ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN
255264
INFO = -10
256265
END IF
257266
IF( INFO.LT.0 ) THEN
@@ -263,7 +272,6 @@ SUBROUTINE ZGEBRD( M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK,
263272
*
264273
* Quick return if possible
265274
*
266-
MINMN = MIN( M, N )
267275
IF( MINMN.EQ.0 ) THEN
268276
WORK( 1 ) = 1
269277
RETURN

SRC/zgehrd.f

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
*>
9090
*> \param[out] WORK
9191
*> \verbatim
92-
*> WORK is COMPLEX*16 array, dimension (LWORK)
92+
*> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
9393
*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
9494
*> \endverbatim
9595
*>
@@ -225,8 +225,13 @@ SUBROUTINE ZGEHRD( N, ILO, IHI, A, LDA, TAU, WORK, LWORK, INFO )
225225
*
226226
* Compute the workspace requirements
227227
*
228-
NB = MIN( NBMAX, ILAENV( 1, 'ZGEHRD', ' ', N, ILO, IHI, -1 ) )
229-
LWKOPT = N*NB + TSIZE
228+
IF( N.EQ.0 ) THEN
229+
LWKOPT = 1
230+
ELSE
231+
NB = MIN( NBMAX, ILAENV( 1, 'ZGEHRD', ' ', N, ILO, IHI,
232+
$ -1 ) )
233+
LWKOPT = N*NB + TSIZE
234+
END IF
230235
WORK( 1 ) = LWKOPT
231236
ENDIF
232237
*

SRC/zgelq.f

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
*> \param[in] LWORK
9999
*> \verbatim
100100
*> LWORK is INTEGER
101-
*> The dimension of the array WORK.
101+
*> The dimension of the array WORK. LWORK >= 1.
102102
*> If LWORK = -1 or -2, then a workspace query is assumed. The routine
103103
*> only calculates the sizes of the T and WORK arrays, returns these
104104
*> values as the first entries of the T and WORK arrays, and no error

SRC/zgelqf.f

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
*> \param[in] LWORK
9494
*> \verbatim
9595
*> LWORK is INTEGER
96+
*> LWORK >= 1, if MIN(M,N) = 0, and LWORK >= M, otherwise.
9697
*> The dimension of the array WORK. LWORK >= max(1,M).
9798
*> For optimum performance LWORK >= M*NB, where NB is the
9899
*> optimal blocksize.
@@ -174,29 +175,34 @@ SUBROUTINE ZGELQF( M, N, A, LDA, TAU, WORK, LWORK, INFO )
174175
* Test the input arguments
175176
*
176177
INFO = 0
178+
K = MIN( M, N )
177179
NB = ILAENV( 1, 'ZGELQF', ' ', M, N, -1, -1 )
178-
LWKOPT = M*NB
179-
WORK( 1 ) = LWKOPT
180180
LQUERY = ( LWORK.EQ.-1 )
181181
IF( M.LT.0 ) THEN
182182
INFO = -1
183183
ELSE IF( N.LT.0 ) THEN
184184
INFO = -2
185185
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
186186
INFO = -4
187-
ELSE IF( LWORK.LT.MAX( 1, M ) .AND. .NOT.LQUERY ) THEN
188-
INFO = -7
187+
ELSE IF( .NOT.LQUERY ) THEN
188+
IF( LWORK.LE.0 .OR. ( N.GT.0 .AND. LWORK.LT.MAX( 1, M ) ) )
189+
$ INFO = -7
189190
END IF
190191
IF( INFO.NE.0 ) THEN
191192
CALL XERBLA( 'ZGELQF', -INFO )
192193
RETURN
193194
ELSE IF( LQUERY ) THEN
195+
IF( K.EQ.0 ) THEN
196+
LWKOPT = 1
197+
ELSE
198+
LWKOPT = M*NB
199+
END IF
200+
WORK( 1 ) = LWKOPT
194201
RETURN
195202
END IF
196203
*
197204
* Quick return if possible
198205
*
199-
K = MIN( M, N )
200206
IF( K.EQ.0 ) THEN
201207
WORK( 1 ) = 1
202208
RETURN

SRC/zgemlq.f

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,14 @@
109109
*>
110110
*> \param[out] WORK
111111
*> \verbatim
112-
*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK))
112+
*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK))
113+
*> On exit, if INFO = 0, WORK(1) returns the minimal LWORK.
113114
*> \endverbatim
114115
*>
115116
*> \param[in] LWORK
116117
*> \verbatim
117118
*> LWORK is INTEGER
118-
*> The dimension of the array WORK.
119+
*> The dimension of the array WORK. LWORK >= 1.
119120
*> If LWORK = -1, then a workspace query is assumed. The routine
120121
*> only calculates the size of the WORK array, returns this
121122
*> value as WORK(1), and no error message related to WORK
@@ -186,7 +187,7 @@ SUBROUTINE ZGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE,
186187
* ..
187188
* .. Local Scalars ..
188189
LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY
189-
INTEGER MB, NB, LW, NBLCKS, MN
190+
INTEGER MB, NB, LW, NBLCKS, MN, MINMNK, LWMIN
190191
* ..
191192
* .. External Functions ..
192193
LOGICAL LSAME
@@ -202,7 +203,7 @@ SUBROUTINE ZGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE,
202203
*
203204
* Test the input arguments
204205
*
205-
LQUERY = LWORK.EQ.-1
206+
LQUERY = ( LWORK.EQ.-1 )
206207
NOTRAN = LSAME( TRANS, 'N' )
207208
TRAN = LSAME( TRANS, 'C' )
208209
LEFT = LSAME( SIDE, 'L' )
@@ -217,6 +218,13 @@ SUBROUTINE ZGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE,
217218
LW = M * MB
218219
MN = N
219220
END IF
221+
*
222+
MINMNK = MIN( M, N, K )
223+
IF( MINMNK.EQ.0 ) THEN
224+
LWMIN = 1
225+
ELSE
226+
LWMIN = MAX( 1, LW )
227+
END IF
220228
*
221229
IF( ( NB.GT.K ) .AND. ( MN.GT.K ) ) THEN
222230
IF( MOD( MN - K, NB - K ) .EQ. 0 ) THEN
@@ -245,7 +253,7 @@ SUBROUTINE ZGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE,
245253
INFO = -9
246254
ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
247255
INFO = -11
248-
ELSE IF( ( LWORK.LT.MAX( 1, LW ) ) .AND. ( .NOT.LQUERY ) ) THEN
256+
ELSE IF( ( LWORK.LT.LWMIN ) .AND. ( .NOT.LQUERY ) ) THEN
249257
INFO = -13
250258
END IF
251259
*
@@ -262,7 +270,7 @@ SUBROUTINE ZGEMLQ( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE,
262270
*
263271
* Quick return if possible
264272
*
265-
IF( MIN( M, N, K ).EQ.0 ) THEN
273+
IF( MINMNK.EQ.0 ) THEN
266274
RETURN
267275
END IF
268276
*

SRC/zgemqr.f

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,14 @@
111111
*>
112112
*> \param[out] WORK
113113
*> \verbatim
114-
*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK))
114+
*> (workspace) COMPLEX*16 array, dimension (MAX(1,LWORK))
115+
*> On exit, if INFO = 0, WORK(1) returns the minimal LWORK.
115116
*> \endverbatim
116117
*>
117118
*> \param[in] LWORK
118119
*> \verbatim
119120
*> LWORK is INTEGER
120-
*> The dimension of the array WORK.
121+
*> The dimension of the array WORK. LWORK >= 1.
121122
*> If LWORK = -1, then a workspace query is assumed. The routine
122123
*> only calculates the size of the WORK array, returns this
123124
*> value as WORK(1), and no error message related to WORK
@@ -189,7 +190,7 @@ SUBROUTINE ZGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE,
189190
* ..
190191
* .. Local Scalars ..
191192
LOGICAL LEFT, RIGHT, TRAN, NOTRAN, LQUERY
192-
INTEGER MB, NB, LW, NBLCKS, MN
193+
INTEGER MB, NB, LW, NBLCKS, MN, MINMNK, LWMIN
193194
* ..
194195
* .. External Functions ..
195196
LOGICAL LSAME
@@ -205,7 +206,7 @@ SUBROUTINE ZGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE,
205206
*
206207
* Test the input arguments
207208
*
208-
LQUERY = LWORK.EQ.-1
209+
LQUERY = ( LWORK.EQ.-1 )
209210
NOTRAN = LSAME( TRANS, 'N' )
210211
TRAN = LSAME( TRANS, 'C' )
211212
LEFT = LSAME( SIDE, 'L' )
@@ -220,6 +221,13 @@ SUBROUTINE ZGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE,
220221
LW = MB * NB
221222
MN = N
222223
END IF
224+
*
225+
MINMNK = MIN( M, N, K )
226+
IF( MINMNK.EQ.0 ) THEN
227+
LWMIN = 1
228+
ELSE
229+
LWMIN = MAX( 1, LW )
230+
END IF
223231
*
224232
IF( ( MB.GT.K ) .AND. ( MN.GT.K ) ) THEN
225233
IF( MOD( MN - K, MB - K ).EQ.0 ) THEN
@@ -248,7 +256,7 @@ SUBROUTINE ZGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE,
248256
INFO = -9
249257
ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
250258
INFO = -11
251-
ELSE IF( ( LWORK.LT.MAX( 1, LW ) ) .AND. ( .NOT.LQUERY ) ) THEN
259+
ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THEN
252260
INFO = -13
253261
END IF
254262
*
@@ -265,7 +273,7 @@ SUBROUTINE ZGEMQR( SIDE, TRANS, M, N, K, A, LDA, T, TSIZE,
265273
*
266274
* Quick return if possible
267275
*
268-
IF( MIN( M, N, K ).EQ.0 ) THEN
276+
IF( MINMNK.EQ.0 ) THEN
269277
RETURN
270278
END IF
271279
*

SRC/zgeqlf.f

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@
8888
*> \param[in] LWORK
8989
*> \verbatim
9090
*> LWORK is INTEGER
91-
*> The dimension of the array WORK. LWORK >= max(1,N).
91+
*> The dimension of the array WORK.
92+
*> LWORK >= 1, if MIN(M,N) = 0, and LWORK >= N, otherwise.
9293
*> For optimum performance LWORK >= N*NB, where NB is
9394
*> the optimal blocksize.
9495
*>
@@ -188,8 +189,9 @@ SUBROUTINE ZGEQLF( M, N, A, LDA, TAU, WORK, LWORK, INFO )
188189
END IF
189190
WORK( 1 ) = LWKOPT
190191
*
191-
IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THEN
192-
INFO = -7
192+
IF( .NOT.LQUERY ) THEN
193+
IF( LWORK.LE.0 .OR. ( M.GT.0 .AND. LWORK.LT.MAX( 1, N ) ) )
194+
$ INFO = -7
193195
END IF
194196
END IF
195197
*

SRC/zgeqp3rk.f

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,8 @@
428428
*> \verbatim
429429
*> LWORK is INTEGER
430430
*> The dimension of the array WORK.
431-
*. LWORK >= N+NRHS-1
431+
*> LWORK >= 1, if MIN(M,N) = 0, and
432+
*> LWORK >= N+NRHS-1, otherwise.
432433
*> For optimal performance LWORK >= NB*( N+NRHS+1 ),
433434
*> where NB is the optimal block size for ZGEQP3RK returned
434435
*> by ILAENV. Minimal block size MINNB=2.

SRC/zgeqr.f

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
*> \param[in] LWORK
100100
*> \verbatim
101101
*> LWORK is INTEGER
102-
*> The dimension of the array WORK.
102+
*> The dimension of the array WORK. LWORK >= 1.
103103
*> If LWORK = -1 or -2, then a workspace query is assumed. The routine
104104
*> only calculates the sizes of the T and WORK arrays, returns these
105105
*> values as the first entries of the T and WORK arrays, and no error
@@ -190,7 +190,7 @@ SUBROUTINE ZGEQR( M, N, A, LDA, T, TSIZE, WORK, LWORK,
190190
* ..
191191
* .. Local Scalars ..
192192
LOGICAL LQUERY, LMINWS, MINT, MINW
193-
INTEGER MB, NB, MINTSZ, NBLCKS
193+
INTEGER MB, NB, MINTSZ, NBLCKS, LWMIN, LWREQ
194194
* ..
195195
* .. External Functions ..
196196
LOGICAL LSAME
@@ -246,16 +246,18 @@ SUBROUTINE ZGEQR( M, N, A, LDA, T, TSIZE, WORK, LWORK,
246246
*
247247
* Determine if the workspace size satisfies minimal size
248248
*
249+
LWMIN = MAX( 1, N )
250+
LWREQ = MAX( 1, N*NB )
249251
LMINWS = .FALSE.
250-
IF( ( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) .OR. LWORK.LT.NB*N )
252+
IF( ( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) .OR. LWORK.LT.LWREQ )
251253
$ .AND. ( LWORK.GE.N ) .AND. ( TSIZE.GE.MINTSZ )
252254
$ .AND. ( .NOT.LQUERY ) ) THEN
253255
IF( TSIZE.LT.MAX( 1, NB*N*NBLCKS + 5 ) ) THEN
254256
LMINWS = .TRUE.
255257
NB = 1
256258
MB = M
257259
END IF
258-
IF( LWORK.LT.NB*N ) THEN
260+
IF( LWORK.LT.LWREQ ) THEN
259261
LMINWS = .TRUE.
260262
NB = 1
261263
END IF
@@ -284,9 +286,9 @@ SUBROUTINE ZGEQR( M, N, A, LDA, T, TSIZE, WORK, LWORK,
284286
T( 2 ) = MB
285287
T( 3 ) = NB
286288
IF( MINW ) THEN
287-
WORK( 1 ) = MAX( 1, N )
289+
WORK( 1 ) = LWMIN
288290
ELSE
289-
WORK( 1 ) = MAX( 1, NB*N )
291+
WORK( 1 ) = LWREQ
290292
END IF
291293
END IF
292294
IF( INFO.NE.0 ) THEN
@@ -311,7 +313,7 @@ SUBROUTINE ZGEQR( M, N, A, LDA, T, TSIZE, WORK, LWORK,
311313
$ LWORK, INFO )
312314
END IF
313315
*
314-
WORK( 1 ) = MAX( 1, NB*N )
316+
WORK( 1 ) = LWREQ
315317
*
316318
RETURN
317319
*

0 commit comments

Comments
 (0)