1: SUBROUTINE DLAIC1( JOB, J, X, SEST, W, GAMMA, SESTPR, S, C )
2: *
3: * -- LAPACK auxiliary routine (version 3.2) --
4: * -- LAPACK is a software package provided by Univ. of Tennessee, --
5: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
6: * November 2006
7: *
8: * .. Scalar Arguments ..
9: INTEGER J, JOB
10: DOUBLE PRECISION C, GAMMA, S, SEST, SESTPR
11: * ..
12: * .. Array Arguments ..
13: DOUBLE PRECISION W( J ), X( J )
14: * ..
15: *
16: * Purpose
17: * =======
18: *
19: * DLAIC1 applies one step of incremental condition estimation in
20: * its simplest version:
21: *
22: * Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j
23: * lower triangular matrix L, such that
24: * twonorm(L*x) = sest
25: * Then DLAIC1 computes sestpr, s, c such that
26: * the vector
27: * [ s*x ]
28: * xhat = [ c ]
29: * is an approximate singular vector of
30: * [ L 0 ]
31: * Lhat = [ w' gamma ]
32: * in the sense that
33: * twonorm(Lhat*xhat) = sestpr.
34: *
35: * Depending on JOB, an estimate for the largest or smallest singular
36: * value is computed.
37: *
38: * Note that [s c]' and sestpr**2 is an eigenpair of the system
39: *
40: * diag(sest*sest, 0) + [alpha gamma] * [ alpha ]
41: * [ gamma ]
42: *
43: * where alpha = x'*w.
44: *
45: * Arguments
46: * =========
47: *
48: * JOB (input) INTEGER
49: * = 1: an estimate for the largest singular value is computed.
50: * = 2: an estimate for the smallest singular value is computed.
51: *
52: * J (input) INTEGER
53: * Length of X and W
54: *
55: * X (input) DOUBLE PRECISION array, dimension (J)
56: * The j-vector x.
57: *
58: * SEST (input) DOUBLE PRECISION
59: * Estimated singular value of j by j matrix L
60: *
61: * W (input) DOUBLE PRECISION array, dimension (J)
62: * The j-vector w.
63: *
64: * GAMMA (input) DOUBLE PRECISION
65: * The diagonal element gamma.
66: *
67: * SESTPR (output) DOUBLE PRECISION
68: * Estimated singular value of (j+1) by (j+1) matrix Lhat.
69: *
70: * S (output) DOUBLE PRECISION
71: * Sine needed in forming xhat.
72: *
73: * C (output) DOUBLE PRECISION
74: * Cosine needed in forming xhat.
75: *
76: * =====================================================================
77: *
78: * .. Parameters ..
79: DOUBLE PRECISION ZERO, ONE, TWO
80: PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0 )
81: DOUBLE PRECISION HALF, FOUR
82: PARAMETER ( HALF = 0.5D0, FOUR = 4.0D0 )
83: * ..
84: * .. Local Scalars ..
85: DOUBLE PRECISION ABSALP, ABSEST, ABSGAM, ALPHA, B, COSINE, EPS,
86: $ NORMA, S1, S2, SINE, T, TEST, TMP, ZETA1, ZETA2
87: * ..
88: * .. Intrinsic Functions ..
89: INTRINSIC ABS, MAX, SIGN, SQRT
90: * ..
91: * .. External Functions ..
92: DOUBLE PRECISION DDOT, DLAMCH
93: EXTERNAL DDOT, DLAMCH
94: * ..
95: * .. Executable Statements ..
96: *
97: EPS = DLAMCH( 'Epsilon' )
98: ALPHA = DDOT( J, X, 1, W, 1 )
99: *
100: ABSALP = ABS( ALPHA )
101: ABSGAM = ABS( GAMMA )
102: ABSEST = ABS( SEST )
103: *
104: IF( JOB.EQ.1 ) THEN
105: *
106: * Estimating largest singular value
107: *
108: * special cases
109: *
110: IF( SEST.EQ.ZERO ) THEN
111: S1 = MAX( ABSGAM, ABSALP )
112: IF( S1.EQ.ZERO ) THEN
113: S = ZERO
114: C = ONE
115: SESTPR = ZERO
116: ELSE
117: S = ALPHA / S1
118: C = GAMMA / S1
119: TMP = SQRT( S*S+C*C )
120: S = S / TMP
121: C = C / TMP
122: SESTPR = S1*TMP
123: END IF
124: RETURN
125: ELSE IF( ABSGAM.LE.EPS*ABSEST ) THEN
126: S = ONE
127: C = ZERO
128: TMP = MAX( ABSEST, ABSALP )
129: S1 = ABSEST / TMP
130: S2 = ABSALP / TMP
131: SESTPR = TMP*SQRT( S1*S1+S2*S2 )
132: RETURN
133: ELSE IF( ABSALP.LE.EPS*ABSEST ) THEN
134: S1 = ABSGAM
135: S2 = ABSEST
136: IF( S1.LE.S2 ) THEN
137: S = ONE
138: C = ZERO
139: SESTPR = S2
140: ELSE
141: S = ZERO
142: C = ONE
143: SESTPR = S1
144: END IF
145: RETURN
146: ELSE IF( ABSEST.LE.EPS*ABSALP .OR. ABSEST.LE.EPS*ABSGAM ) THEN
147: S1 = ABSGAM
148: S2 = ABSALP
149: IF( S1.LE.S2 ) THEN
150: TMP = S1 / S2
151: S = SQRT( ONE+TMP*TMP )
152: SESTPR = S2*S
153: C = ( GAMMA / S2 ) / S
154: S = SIGN( ONE, ALPHA ) / S
155: ELSE
156: TMP = S2 / S1
157: C = SQRT( ONE+TMP*TMP )
158: SESTPR = S1*C
159: S = ( ALPHA / S1 ) / C
160: C = SIGN( ONE, GAMMA ) / C
161: END IF
162: RETURN
163: ELSE
164: *
165: * normal case
166: *
167: ZETA1 = ALPHA / ABSEST
168: ZETA2 = GAMMA / ABSEST
169: *
170: B = ( ONE-ZETA1*ZETA1-ZETA2*ZETA2 )*HALF
171: C = ZETA1*ZETA1
172: IF( B.GT.ZERO ) THEN
173: T = C / ( B+SQRT( B*B+C ) )
174: ELSE
175: T = SQRT( B*B+C ) - B
176: END IF
177: *
178: SINE = -ZETA1 / T
179: COSINE = -ZETA2 / ( ONE+T )
180: TMP = SQRT( SINE*SINE+COSINE*COSINE )
181: S = SINE / TMP
182: C = COSINE / TMP
183: SESTPR = SQRT( T+ONE )*ABSEST
184: RETURN
185: END IF
186: *
187: ELSE IF( JOB.EQ.2 ) THEN
188: *
189: * Estimating smallest singular value
190: *
191: * special cases
192: *
193: IF( SEST.EQ.ZERO ) THEN
194: SESTPR = ZERO
195: IF( MAX( ABSGAM, ABSALP ).EQ.ZERO ) THEN
196: SINE = ONE
197: COSINE = ZERO
198: ELSE
199: SINE = -GAMMA
200: COSINE = ALPHA
201: END IF
202: S1 = MAX( ABS( SINE ), ABS( COSINE ) )
203: S = SINE / S1
204: C = COSINE / S1
205: TMP = SQRT( S*S+C*C )
206: S = S / TMP
207: C = C / TMP
208: RETURN
209: ELSE IF( ABSGAM.LE.EPS*ABSEST ) THEN
210: S = ZERO
211: C = ONE
212: SESTPR = ABSGAM
213: RETURN
214: ELSE IF( ABSALP.LE.EPS*ABSEST ) THEN
215: S1 = ABSGAM
216: S2 = ABSEST
217: IF( S1.LE.S2 ) THEN
218: S = ZERO
219: C = ONE
220: SESTPR = S1
221: ELSE
222: S = ONE
223: C = ZERO
224: SESTPR = S2
225: END IF
226: RETURN
227: ELSE IF( ABSEST.LE.EPS*ABSALP .OR. ABSEST.LE.EPS*ABSGAM ) THEN
228: S1 = ABSGAM
229: S2 = ABSALP
230: IF( S1.LE.S2 ) THEN
231: TMP = S1 / S2
232: C = SQRT( ONE+TMP*TMP )
233: SESTPR = ABSEST*( TMP / C )
234: S = -( GAMMA / S2 ) / C
235: C = SIGN( ONE, ALPHA ) / C
236: ELSE
237: TMP = S2 / S1
238: S = SQRT( ONE+TMP*TMP )
239: SESTPR = ABSEST / S
240: C = ( ALPHA / S1 ) / S
241: S = -SIGN( ONE, GAMMA ) / S
242: END IF
243: RETURN
244: ELSE
245: *
246: * normal case
247: *
248: ZETA1 = ALPHA / ABSEST
249: ZETA2 = GAMMA / ABSEST
250: *
251: NORMA = MAX( ONE+ZETA1*ZETA1+ABS( ZETA1*ZETA2 ),
252: $ ABS( ZETA1*ZETA2 )+ZETA2*ZETA2 )
253: *
254: * See if root is closer to zero or to ONE
255: *
256: TEST = ONE + TWO*( ZETA1-ZETA2 )*( ZETA1+ZETA2 )
257: IF( TEST.GE.ZERO ) THEN
258: *
259: * root is close to zero, compute directly
260: *
261: B = ( ZETA1*ZETA1+ZETA2*ZETA2+ONE )*HALF
262: C = ZETA2*ZETA2
263: T = C / ( B+SQRT( ABS( B*B-C ) ) )
264: SINE = ZETA1 / ( ONE-T )
265: COSINE = -ZETA2 / T
266: SESTPR = SQRT( T+FOUR*EPS*EPS*NORMA )*ABSEST
267: ELSE
268: *
269: * root is closer to ONE, shift by that amount
270: *
271: B = ( ZETA2*ZETA2+ZETA1*ZETA1-ONE )*HALF
272: C = ZETA1*ZETA1
273: IF( B.GE.ZERO ) THEN
274: T = -C / ( B+SQRT( B*B+C ) )
275: ELSE
276: T = B - SQRT( B*B+C )
277: END IF
278: SINE = -ZETA1 / T
279: COSINE = -ZETA2 / ( ONE+T )
280: SESTPR = SQRT( ONE+T+FOUR*EPS*EPS*NORMA )*ABSEST
281: END IF
282: TMP = SQRT( SINE*SINE+COSINE*COSINE )
283: S = SINE / TMP
284: C = COSINE / TMP
285: RETURN
286: *
287: END IF
288: END IF
289: RETURN
290: *
291: * End of DLAIC1
292: *
293: END
CVSweb interface <joel.bertrand@systella.fr>