1: SUBROUTINE DOPMTR( SIDE, UPLO, TRANS, M, N, AP, TAU, C, LDC, WORK,
2: $ INFO )
3: *
4: * -- LAPACK routine (version 3.2) --
5: * -- LAPACK is a software package provided by Univ. of Tennessee, --
6: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
7: * November 2006
8: *
9: * .. Scalar Arguments ..
10: CHARACTER SIDE, TRANS, UPLO
11: INTEGER INFO, LDC, M, N
12: * ..
13: * .. Array Arguments ..
14: DOUBLE PRECISION AP( * ), C( LDC, * ), TAU( * ), WORK( * )
15: * ..
16: *
17: * Purpose
18: * =======
19: *
20: * DOPMTR overwrites the general real M-by-N matrix C with
21: *
22: * SIDE = 'L' SIDE = 'R'
23: * TRANS = 'N': Q * C C * Q
24: * TRANS = 'T': Q**T * C C * Q**T
25: *
26: * where Q is a real orthogonal matrix of order nq, with nq = m if
27: * SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of
28: * nq-1 elementary reflectors, as returned by DSPTRD using packed
29: * storage:
30: *
31: * if UPLO = 'U', Q = H(nq-1) . . . H(2) H(1);
32: *
33: * if UPLO = 'L', Q = H(1) H(2) . . . H(nq-1).
34: *
35: * Arguments
36: * =========
37: *
38: * SIDE (input) CHARACTER*1
39: * = 'L': apply Q or Q**T from the Left;
40: * = 'R': apply Q or Q**T from the Right.
41: *
42: * UPLO (input) CHARACTER*1
43: * = 'U': Upper triangular packed storage used in previous
44: * call to DSPTRD;
45: * = 'L': Lower triangular packed storage used in previous
46: * call to DSPTRD.
47: *
48: * TRANS (input) CHARACTER*1
49: * = 'N': No transpose, apply Q;
50: * = 'T': Transpose, apply Q**T.
51: *
52: * M (input) INTEGER
53: * The number of rows of the matrix C. M >= 0.
54: *
55: * N (input) INTEGER
56: * The number of columns of the matrix C. N >= 0.
57: *
58: * AP (input) DOUBLE PRECISION array, dimension
59: * (M*(M+1)/2) if SIDE = 'L'
60: * (N*(N+1)/2) if SIDE = 'R'
61: * The vectors which define the elementary reflectors, as
62: * returned by DSPTRD. AP is modified by the routine but
63: * restored on exit.
64: *
65: * TAU (input) DOUBLE PRECISION array, dimension (M-1) if SIDE = 'L'
66: * or (N-1) if SIDE = 'R'
67: * TAU(i) must contain the scalar factor of the elementary
68: * reflector H(i), as returned by DSPTRD.
69: *
70: * C (input/output) DOUBLE PRECISION array, dimension (LDC,N)
71: * On entry, the M-by-N matrix C.
72: * On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q.
73: *
74: * LDC (input) INTEGER
75: * The leading dimension of the array C. LDC >= max(1,M).
76: *
77: * WORK (workspace) DOUBLE PRECISION array, dimension
78: * (N) if SIDE = 'L'
79: * (M) if SIDE = 'R'
80: *
81: * INFO (output) INTEGER
82: * = 0: successful exit
83: * < 0: if INFO = -i, the i-th argument had an illegal value
84: *
85: * =====================================================================
86: *
87: * .. Parameters ..
88: DOUBLE PRECISION ONE
89: PARAMETER ( ONE = 1.0D+0 )
90: * ..
91: * .. Local Scalars ..
92: LOGICAL FORWRD, LEFT, NOTRAN, UPPER
93: INTEGER I, I1, I2, I3, IC, II, JC, MI, NI, NQ
94: DOUBLE PRECISION AII
95: * ..
96: * .. External Functions ..
97: LOGICAL LSAME
98: EXTERNAL LSAME
99: * ..
100: * .. External Subroutines ..
101: EXTERNAL DLARF, XERBLA
102: * ..
103: * .. Intrinsic Functions ..
104: INTRINSIC MAX
105: * ..
106: * .. Executable Statements ..
107: *
108: * Test the input arguments
109: *
110: INFO = 0
111: LEFT = LSAME( SIDE, 'L' )
112: NOTRAN = LSAME( TRANS, 'N' )
113: UPPER = LSAME( UPLO, 'U' )
114: *
115: * NQ is the order of Q
116: *
117: IF( LEFT ) THEN
118: NQ = M
119: ELSE
120: NQ = N
121: END IF
122: IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN
123: INFO = -1
124: ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
125: INFO = -2
126: ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN
127: INFO = -3
128: ELSE IF( M.LT.0 ) THEN
129: INFO = -4
130: ELSE IF( N.LT.0 ) THEN
131: INFO = -5
132: ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
133: INFO = -9
134: END IF
135: IF( INFO.NE.0 ) THEN
136: CALL XERBLA( 'DOPMTR', -INFO )
137: RETURN
138: END IF
139: *
140: * Quick return if possible
141: *
142: IF( M.EQ.0 .OR. N.EQ.0 )
143: $ RETURN
144: *
145: IF( UPPER ) THEN
146: *
147: * Q was determined by a call to DSPTRD with UPLO = 'U'
148: *
149: FORWRD = ( LEFT .AND. NOTRAN ) .OR.
150: $ ( .NOT.LEFT .AND. .NOT.NOTRAN )
151: *
152: IF( FORWRD ) THEN
153: I1 = 1
154: I2 = NQ - 1
155: I3 = 1
156: II = 2
157: ELSE
158: I1 = NQ - 1
159: I2 = 1
160: I3 = -1
161: II = NQ*( NQ+1 ) / 2 - 1
162: END IF
163: *
164: IF( LEFT ) THEN
165: NI = N
166: ELSE
167: MI = M
168: END IF
169: *
170: DO 10 I = I1, I2, I3
171: IF( LEFT ) THEN
172: *
173: * H(i) is applied to C(1:i,1:n)
174: *
175: MI = I
176: ELSE
177: *
178: * H(i) is applied to C(1:m,1:i)
179: *
180: NI = I
181: END IF
182: *
183: * Apply H(i)
184: *
185: AII = AP( II )
186: AP( II ) = ONE
187: CALL DLARF( SIDE, MI, NI, AP( II-I+1 ), 1, TAU( I ), C, LDC,
188: $ WORK )
189: AP( II ) = AII
190: *
191: IF( FORWRD ) THEN
192: II = II + I + 2
193: ELSE
194: II = II - I - 1
195: END IF
196: 10 CONTINUE
197: ELSE
198: *
199: * Q was determined by a call to DSPTRD with UPLO = 'L'.
200: *
201: FORWRD = ( LEFT .AND. .NOT.NOTRAN ) .OR.
202: $ ( .NOT.LEFT .AND. NOTRAN )
203: *
204: IF( FORWRD ) THEN
205: I1 = 1
206: I2 = NQ - 1
207: I3 = 1
208: II = 2
209: ELSE
210: I1 = NQ - 1
211: I2 = 1
212: I3 = -1
213: II = NQ*( NQ+1 ) / 2 - 1
214: END IF
215: *
216: IF( LEFT ) THEN
217: NI = N
218: JC = 1
219: ELSE
220: MI = M
221: IC = 1
222: END IF
223: *
224: DO 20 I = I1, I2, I3
225: AII = AP( II )
226: AP( II ) = ONE
227: IF( LEFT ) THEN
228: *
229: * H(i) is applied to C(i+1:m,1:n)
230: *
231: MI = M - I
232: IC = I + 1
233: ELSE
234: *
235: * H(i) is applied to C(1:m,i+1:n)
236: *
237: NI = N - I
238: JC = I + 1
239: END IF
240: *
241: * Apply H(i)
242: *
243: CALL DLARF( SIDE, MI, NI, AP( II ), 1, TAU( I ),
244: $ C( IC, JC ), LDC, WORK )
245: AP( II ) = AII
246: *
247: IF( FORWRD ) THEN
248: II = II + NQ - I + 1
249: ELSE
250: II = II - NQ + I - 2
251: END IF
252: 20 CONTINUE
253: END IF
254: RETURN
255: *
256: * End of DOPMTR
257: *
258: END
CVSweb interface <joel.bertrand@systella.fr>