41
41
* > with respect to the columns of
42
42
* > Q = [ Q1 ] .
43
43
* > [ Q2 ]
44
- * > The columns of Q must be orthonormal.
44
+ * > The Euclidean norm of X must be one and the columns of Q must be
45
+ * > orthonormal. The orthogonalized vector will be zero if and only if it
46
+ * > lies entirely in the range of Q.
45
47
* >
46
- * > If the projection is zero according to Kahan's "twice is enough"
47
- * > criterion, then the zero vector is returned.
48
+ * > The projection is computed with at most two iterations of the
49
+ * > classical Gram-Schmidt algorithm, see
50
+ * > * L. Giraud, J. Langou, M. Rozložník. "On the round-off error
51
+ * > analysis of the Gram-Schmidt algorithm with reorthogonalization."
52
+ * > 2002. CERFACS Technical Report No. TR/PA/02/33. URL:
53
+ * > https://www.cerfacs.fr/algor/reports/2002/TR_PA_02_33.pdf
48
54
* >
49
55
* >\endverbatim
50
56
*
@@ -167,16 +173,19 @@ SUBROUTINE ZUNBDB6( M1, M2, N, X1, INCX1, X2, INCX2, Q1, LDQ1, Q2,
167
173
* =====================================================================
168
174
*
169
175
* .. Parameters ..
170
- DOUBLE PRECISION ALPHASQ , REALONE, REALZERO
171
- PARAMETER ( ALPHASQ = 0.01D0 , REALONE = 1.0D0 ,
176
+ DOUBLE PRECISION ALPHA , REALONE, REALZERO
177
+ PARAMETER ( ALPHA = 0.01D0 , REALONE = 1.0D0 ,
172
178
$ REALZERO = 0.0D0 )
173
179
COMPLEX * 16 NEGONE, ONE, ZERO
174
180
PARAMETER ( NEGONE = (- 1.0D0 ,0.0D0 ), ONE = (1.0D0 ,0.0D0 ),
175
181
$ ZERO = (0.0D0 ,0.0D0 ) )
176
182
* ..
177
183
* .. Local Scalars ..
178
- INTEGER I
179
- DOUBLE PRECISION NORMSQ1, NORMSQ2, SCL1, SCL2, SSQ1, SSQ2
184
+ INTEGER I, IX
185
+ DOUBLE PRECISION EPS, NORM, NORM_NEW, SCL, SSQ
186
+ * ..
187
+ * .. External Functions ..
188
+ REAL DLAMCH
180
189
* ..
181
190
* .. External Subroutines ..
182
191
EXTERNAL ZGEMV, ZLASSQ, XERBLA
@@ -211,17 +220,17 @@ SUBROUTINE ZUNBDB6( M1, M2, N, X1, INCX1, X2, INCX2, Q1, LDQ1, Q2,
211
220
CALL XERBLA( ' ZUNBDB6' , - INFO )
212
221
RETURN
213
222
END IF
223
+ *
224
+ EPS = DLAMCH( ' Precision' )
214
225
*
215
226
* First, project X onto the orthogonal complement of Q's column
216
227
* space
217
228
*
218
- SCL1 = REALZERO
219
- SSQ1 = REALONE
220
- CALL ZLASSQ( M1, X1, INCX1, SCL1, SSQ1 )
221
- SCL2 = REALZERO
222
- SSQ2 = REALONE
223
- CALL ZLASSQ( M2, X2, INCX2, SCL2, SSQ2 )
224
- NORMSQ1 = SCL1** 2 * SSQ1 + SCL2** 2 * SSQ2
229
+ * Christoph Conrads: In debugging mode the norm should be computed
230
+ * and an assertion added comparing the norm with one. Alas, Fortran
231
+ * never made it into 1989 when assert() was introduced into the C
232
+ * programming language.
233
+ NORM = REALONE
225
234
*
226
235
IF ( M1 .EQ. 0 ) THEN
227
236
DO I = 1 , N
@@ -239,27 +248,31 @@ SUBROUTINE ZUNBDB6( M1, M2, N, X1, INCX1, X2, INCX2, Q1, LDQ1, Q2,
239
248
CALL ZGEMV( ' N' , M2, N, NEGONE, Q2, LDQ2, WORK, 1 , ONE, X2,
240
249
$ INCX2 )
241
250
*
242
- SCL1 = REALZERO
243
- SSQ1 = REALONE
244
- CALL ZLASSQ( M1, X1, INCX1, SCL1, SSQ1 )
245
- SCL2 = REALZERO
246
- SSQ2 = REALONE
247
- CALL ZLASSQ( M2, X2, INCX2, SCL2, SSQ2 )
248
- NORMSQ2 = SCL1** 2 * SSQ1 + SCL2** 2 * SSQ2
251
+ SCL = REALZERO
252
+ SSQ = REALZERO
253
+ CALL ZLASSQ( M1, X1, INCX1, SCL, SSQ )
254
+ CALL ZLASSQ( M2, X2, INCX2, SCL, SSQ )
255
+ NORM_NEW = SCL * SQRT (SSQ)
249
256
*
250
257
* If projection is sufficiently large in norm, then stop.
251
258
* If projection is zero, then stop.
252
259
* Otherwise, project again.
253
260
*
254
- IF ( NORMSQ2 .GE. ALPHASQ * NORMSQ1 ) THEN
261
+ IF ( NORM_NEW .GE. ALPHA * NORM ) THEN
255
262
RETURN
256
263
END IF
257
264
*
258
- IF ( NORMSQ2 .EQ. ZERO ) THEN
265
+ IF ( NORMSQ2 .LE. N * EPS * NORM ) THEN
266
+ DO IX = 1 , 1 + (M1-1 )* INCX1, INCX1
267
+ X1( IX ) = ZERO
268
+ END DO
269
+ DO IX = 1 , 1 + (M2-1 )* INCX2, INCX2
270
+ X2( IX ) = ZERO
271
+ END DO
259
272
RETURN
260
273
END IF
261
274
*
262
- NORMSQ1 = NORMSQ2
275
+ NORM = NORM_NEW
263
276
*
264
277
DO I = 1 , N
265
278
WORK(I) = ZERO
@@ -281,24 +294,22 @@ SUBROUTINE ZUNBDB6( M1, M2, N, X1, INCX1, X2, INCX2, Q1, LDQ1, Q2,
281
294
CALL ZGEMV( ' N' , M2, N, NEGONE, Q2, LDQ2, WORK, 1 , ONE, X2,
282
295
$ INCX2 )
283
296
*
284
- SCL1 = REALZERO
285
- SSQ1 = REALONE
286
- CALL ZLASSQ( M1, X1, INCX1, SCL1, SSQ1 )
287
- SCL2 = REALZERO
288
- SSQ2 = REALONE
289
- CALL ZLASSQ( M1, X1, INCX1, SCL1, SSQ1 )
290
- NORMSQ2 = SCL1** 2 * SSQ1 + SCL2** 2 * SSQ2
297
+ SCL = REALZERO
298
+ SSQ = REALZERO
299
+ CALL ZLASSQ( M1, X1, INCX1, SCL, SSQ )
300
+ CALL ZLASSQ( M2, X2, INCX2, SCL, SSQ )
301
+ NORM_NEW = SCL * SQRT (SSQ)
291
302
*
292
303
* If second projection is sufficiently large in norm, then do
293
304
* nothing more. Alternatively, if it shrunk significantly, then
294
305
* truncate it to zero.
295
306
*
296
- IF ( NORMSQ2 .LT. ALPHASQ * NORMSQ1 ) THEN
297
- DO I = 1 , M1
298
- X1(I ) = ZERO
307
+ IF ( NORM_NEW .LT. ALPHA * NORM ) THEN
308
+ DO IX = 1 , 1 + (M1 -1 ) * INCX1, INCX1
309
+ X1(IX ) = ZERO
299
310
END DO
300
- DO I = 1 , M2
301
- X2(I ) = ZERO
311
+ DO IX = 1 , 1 + (M2 -1 ) * INCX2, INCX2
312
+ X2(IX ) = ZERO
302
313
END DO
303
314
END IF
304
315
*
@@ -307,4 +318,3 @@ SUBROUTINE ZUNBDB6( M1, M2, N, X1, INCX1, X2, INCX2, Q1, LDQ1, Q2,
307
318
* End of ZUNBDB6
308
319
*
309
320
END
310
-
0 commit comments