1: *> \brief <b> DGGLSE solves overdetermined or underdetermined systems for OTHER matrices</b>
2: *
3: * =========== DOCUMENTATION ===========
4: *
5: * Online html documentation available at
6: * http://www.netlib.org/lapack/explore-html/
7: *
8: *> \htmlonly
9: *> Download DGGLSE + dependencies
10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dgglse.f">
11: *> [TGZ]</a>
12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dgglse.f">
13: *> [ZIP]</a>
14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgglse.f">
15: *> [TXT]</a>
16: *> \endhtmlonly
17: *
18: * Definition:
19: * ===========
20: *
21: * SUBROUTINE DGGLSE( M, N, P, A, LDA, B, LDB, C, D, X, WORK, LWORK,
22: * INFO )
23: *
24: * .. Scalar Arguments ..
25: * INTEGER INFO, LDA, LDB, LWORK, M, N, P
26: * ..
27: * .. Array Arguments ..
28: * DOUBLE PRECISION A( LDA, * ), B( LDB, * ), C( * ), D( * ),
29: * $ WORK( * ), X( * )
30: * ..
31: *
32: *
33: *> \par Purpose:
34: * =============
35: *>
36: *> \verbatim
37: *>
38: *> DGGLSE solves the linear equality-constrained least squares (LSE)
39: *> problem:
40: *>
41: *> minimize || c - A*x ||_2 subject to B*x = d
42: *>
43: *> where A is an M-by-N matrix, B is a P-by-N matrix, c is a given
44: *> M-vector, and d is a given P-vector. It is assumed that
45: *> P <= N <= M+P, and
46: *>
47: *> rank(B) = P and rank( (A) ) = N.
48: *> ( (B) )
49: *>
50: *> These conditions ensure that the LSE problem has a unique solution,
51: *> which is obtained using a generalized RQ factorization of the
52: *> matrices (B, A) given by
53: *>
54: *> B = (0 R)*Q, A = Z*T*Q.
55: *> \endverbatim
56: *
57: * Arguments:
58: * ==========
59: *
60: *> \param[in] M
61: *> \verbatim
62: *> M is INTEGER
63: *> The number of rows of the matrix A. M >= 0.
64: *> \endverbatim
65: *>
66: *> \param[in] N
67: *> \verbatim
68: *> N is INTEGER
69: *> The number of columns of the matrices A and B. N >= 0.
70: *> \endverbatim
71: *>
72: *> \param[in] P
73: *> \verbatim
74: *> P is INTEGER
75: *> The number of rows of the matrix B. 0 <= P <= N <= M+P.
76: *> \endverbatim
77: *>
78: *> \param[in,out] A
79: *> \verbatim
80: *> A is DOUBLE PRECISION array, dimension (LDA,N)
81: *> On entry, the M-by-N matrix A.
82: *> On exit, the elements on and above the diagonal of the array
83: *> contain the min(M,N)-by-N upper trapezoidal matrix T.
84: *> \endverbatim
85: *>
86: *> \param[in] LDA
87: *> \verbatim
88: *> LDA is INTEGER
89: *> The leading dimension of the array A. LDA >= max(1,M).
90: *> \endverbatim
91: *>
92: *> \param[in,out] B
93: *> \verbatim
94: *> B is DOUBLE PRECISION array, dimension (LDB,N)
95: *> On entry, the P-by-N matrix B.
96: *> On exit, the upper triangle of the subarray B(1:P,N-P+1:N)
97: *> contains the P-by-P upper triangular matrix R.
98: *> \endverbatim
99: *>
100: *> \param[in] LDB
101: *> \verbatim
102: *> LDB is INTEGER
103: *> The leading dimension of the array B. LDB >= max(1,P).
104: *> \endverbatim
105: *>
106: *> \param[in,out] C
107: *> \verbatim
108: *> C is DOUBLE PRECISION array, dimension (M)
109: *> On entry, C contains the right hand side vector for the
110: *> least squares part of the LSE problem.
111: *> On exit, the residual sum of squares for the solution
112: *> is given by the sum of squares of elements N-P+1 to M of
113: *> vector C.
114: *> \endverbatim
115: *>
116: *> \param[in,out] D
117: *> \verbatim
118: *> D is DOUBLE PRECISION array, dimension (P)
119: *> On entry, D contains the right hand side vector for the
120: *> constrained equation.
121: *> On exit, D is destroyed.
122: *> \endverbatim
123: *>
124: *> \param[out] X
125: *> \verbatim
126: *> X is DOUBLE PRECISION array, dimension (N)
127: *> On exit, X is the solution of the LSE problem.
128: *> \endverbatim
129: *>
130: *> \param[out] WORK
131: *> \verbatim
132: *> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
133: *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
134: *> \endverbatim
135: *>
136: *> \param[in] LWORK
137: *> \verbatim
138: *> LWORK is INTEGER
139: *> The dimension of the array WORK. LWORK >= max(1,M+N+P).
140: *> For optimum performance LWORK >= P+min(M,N)+max(M,N)*NB,
141: *> where NB is an upper bound for the optimal blocksizes for
142: *> DGEQRF, SGERQF, DORMQR and SORMRQ.
143: *>
144: *> If LWORK = -1, then a workspace query is assumed; the routine
145: *> only calculates the optimal size of the WORK array, returns
146: *> this value as the first entry of the WORK array, and no error
147: *> message related to LWORK is issued by XERBLA.
148: *> \endverbatim
149: *>
150: *> \param[out] INFO
151: *> \verbatim
152: *> INFO is INTEGER
153: *> = 0: successful exit.
154: *> < 0: if INFO = -i, the i-th argument had an illegal value.
155: *> = 1: the upper triangular factor R associated with B in the
156: *> generalized RQ factorization of the pair (B, A) is
157: *> singular, so that rank(B) < P; the least squares
158: *> solution could not be computed.
159: *> = 2: the (N-P) by (N-P) part of the upper trapezoidal factor
160: *> T associated with A in the generalized RQ factorization
161: *> of the pair (B, A) is singular, so that
162: *> rank( (A) ) < N; the least squares solution could not
163: *> ( (B) )
164: *> be computed.
165: *> \endverbatim
166: *
167: * Authors:
168: * ========
169: *
170: *> \author Univ. of Tennessee
171: *> \author Univ. of California Berkeley
172: *> \author Univ. of Colorado Denver
173: *> \author NAG Ltd.
174: *
175: *> \date November 2011
176: *
177: *> \ingroup doubleOTHERsolve
178: *
179: * =====================================================================
180: SUBROUTINE DGGLSE( M, N, P, A, LDA, B, LDB, C, D, X, WORK, LWORK,
181: $ INFO )
182: *
183: * -- LAPACK driver routine (version 3.4.0) --
184: * -- LAPACK is a software package provided by Univ. of Tennessee, --
185: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
186: * November 2011
187: *
188: * .. Scalar Arguments ..
189: INTEGER INFO, LDA, LDB, LWORK, M, N, P
190: * ..
191: * .. Array Arguments ..
192: DOUBLE PRECISION A( LDA, * ), B( LDB, * ), C( * ), D( * ),
193: $ WORK( * ), X( * )
194: * ..
195: *
196: * =====================================================================
197: *
198: * .. Parameters ..
199: DOUBLE PRECISION ONE
200: PARAMETER ( ONE = 1.0D+0 )
201: * ..
202: * .. Local Scalars ..
203: LOGICAL LQUERY
204: INTEGER LOPT, LWKMIN, LWKOPT, MN, NB, NB1, NB2, NB3,
205: $ NB4, NR
206: * ..
207: * .. External Subroutines ..
208: EXTERNAL DAXPY, DCOPY, DGEMV, DGGRQF, DORMQR, DORMRQ,
209: $ DTRMV, DTRTRS, XERBLA
210: * ..
211: * .. External Functions ..
212: INTEGER ILAENV
213: EXTERNAL ILAENV
214: * ..
215: * .. Intrinsic Functions ..
216: INTRINSIC INT, MAX, MIN
217: * ..
218: * .. Executable Statements ..
219: *
220: * Test the input parameters
221: *
222: INFO = 0
223: MN = MIN( M, N )
224: LQUERY = ( LWORK.EQ.-1 )
225: IF( M.LT.0 ) THEN
226: INFO = -1
227: ELSE IF( N.LT.0 ) THEN
228: INFO = -2
229: ELSE IF( P.LT.0 .OR. P.GT.N .OR. P.LT.N-M ) THEN
230: INFO = -3
231: ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
232: INFO = -5
233: ELSE IF( LDB.LT.MAX( 1, P ) ) THEN
234: INFO = -7
235: END IF
236: *
237: * Calculate workspace
238: *
239: IF( INFO.EQ.0) THEN
240: IF( N.EQ.0 ) THEN
241: LWKMIN = 1
242: LWKOPT = 1
243: ELSE
244: NB1 = ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
245: NB2 = ILAENV( 1, 'DGERQF', ' ', M, N, -1, -1 )
246: NB3 = ILAENV( 1, 'DORMQR', ' ', M, N, P, -1 )
247: NB4 = ILAENV( 1, 'DORMRQ', ' ', M, N, P, -1 )
248: NB = MAX( NB1, NB2, NB3, NB4 )
249: LWKMIN = M + N + P
250: LWKOPT = P + MN + MAX( M, N )*NB
251: END IF
252: WORK( 1 ) = LWKOPT
253: *
254: IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN
255: INFO = -12
256: END IF
257: END IF
258: *
259: IF( INFO.NE.0 ) THEN
260: CALL XERBLA( 'DGGLSE', -INFO )
261: RETURN
262: ELSE IF( LQUERY ) THEN
263: RETURN
264: END IF
265: *
266: * Quick return if possible
267: *
268: IF( N.EQ.0 )
269: $ RETURN
270: *
271: * Compute the GRQ factorization of matrices B and A:
272: *
273: * B*Q**T = ( 0 T12 ) P Z**T*A*Q**T = ( R11 R12 ) N-P
274: * N-P P ( 0 R22 ) M+P-N
275: * N-P P
276: *
277: * where T12 and R11 are upper triangular, and Q and Z are
278: * orthogonal.
279: *
280: CALL DGGRQF( P, M, N, B, LDB, WORK, A, LDA, WORK( P+1 ),
281: $ WORK( P+MN+1 ), LWORK-P-MN, INFO )
282: LOPT = WORK( P+MN+1 )
283: *
284: * Update c = Z**T *c = ( c1 ) N-P
285: * ( c2 ) M+P-N
286: *
287: CALL DORMQR( 'Left', 'Transpose', M, 1, MN, A, LDA, WORK( P+1 ),
288: $ C, MAX( 1, M ), WORK( P+MN+1 ), LWORK-P-MN, INFO )
289: LOPT = MAX( LOPT, INT( WORK( P+MN+1 ) ) )
290: *
291: * Solve T12*x2 = d for x2
292: *
293: IF( P.GT.0 ) THEN
294: CALL DTRTRS( 'Upper', 'No transpose', 'Non-unit', P, 1,
295: $ B( 1, N-P+1 ), LDB, D, P, INFO )
296: *
297: IF( INFO.GT.0 ) THEN
298: INFO = 1
299: RETURN
300: END IF
301: *
302: * Put the solution in X
303: *
304: CALL DCOPY( P, D, 1, X( N-P+1 ), 1 )
305: *
306: * Update c1
307: *
308: CALL DGEMV( 'No transpose', N-P, P, -ONE, A( 1, N-P+1 ), LDA,
309: $ D, 1, ONE, C, 1 )
310: END IF
311: *
312: * Solve R11*x1 = c1 for x1
313: *
314: IF( N.GT.P ) THEN
315: CALL DTRTRS( 'Upper', 'No transpose', 'Non-unit', N-P, 1,
316: $ A, LDA, C, N-P, INFO )
317: *
318: IF( INFO.GT.0 ) THEN
319: INFO = 2
320: RETURN
321: END IF
322: *
323: * Put the solutions in X
324: *
325: CALL DCOPY( N-P, C, 1, X, 1 )
326: END IF
327: *
328: * Compute the residual vector:
329: *
330: IF( M.LT.N ) THEN
331: NR = M + P - N
332: IF( NR.GT.0 )
333: $ CALL DGEMV( 'No transpose', NR, N-M, -ONE, A( N-P+1, M+1 ),
334: $ LDA, D( NR+1 ), 1, ONE, C( N-P+1 ), 1 )
335: ELSE
336: NR = P
337: END IF
338: IF( NR.GT.0 ) THEN
339: CALL DTRMV( 'Upper', 'No transpose', 'Non unit', NR,
340: $ A( N-P+1, N-P+1 ), LDA, D, 1 )
341: CALL DAXPY( NR, -ONE, D, 1, C( N-P+1 ), 1 )
342: END IF
343: *
344: * Backward transformation x = Q**T*x
345: *
346: CALL DORMRQ( 'Left', 'Transpose', N, 1, P, B, LDB, WORK( 1 ), X,
347: $ N, WORK( P+MN+1 ), LWORK-P-MN, INFO )
348: WORK( 1 ) = P + MN + MAX( LOPT, INT( WORK( P+MN+1 ) ) )
349: *
350: RETURN
351: *
352: * End of DGGLSE
353: *
354: END
CVSweb interface <joel.bertrand@systella.fr>